sgen_card_table_get_card_data (guint8 * data_dest, mword address, mword cards)
{
  gboolean D.17599;
  mword * start;
  mword * dest;
  mword * end;
  mword mask;

  start = sgen_card_table_get_card_address (address);
  dest = data_dest;
  end = data_dest + cards;
  mask = 0;
  goto <D.17451>;
  <D.17450>:
  {
    mword v;

    v = *start;
    *dest = v;
    mask = mask | v;
    *start = 0;
  }
  dest = dest + 4;
  start = start + 4;
  <D.17451>:
  if (dest < end) goto <D.17450>; else goto <D.17452>;
  <D.17452>:
  D.17599 = (gboolean) mask;
  return D.17599;
}


sgen_card_table_get_card_address (mword address)
{
  guint8 * D.17601;
  guint8 * sgen_cardtable.0;
  unsigned int D.17603;

  sgen_cardtable.0 = sgen_cardtable;
  D.17603 = address >> 9;
  D.17601 = sgen_cardtable.0 + D.17603;
  return D.17601;
}


sgen_card_table_align_pointer (void * ptr)
{
  void * D.17605;
  unsigned int ptr.1;
  unsigned int D.17607;

  ptr.1 = (unsigned int) ptr;
  D.17607 = ptr.1 & 4294966784;
  D.17605 = (void *) D.17607;
  return D.17605;
}


sgen_card_table_mark_range (mword address, mword size)
{
  guint8 * D.17609;
  unsigned int D.17610;

  D.17609 = sgen_card_table_get_card_address (address);
  D.17610 = cards_in_range (address, size);
  memset (D.17609, 1, D.17610);
}


cards_in_range (mword address, mword size)
{
  mword iftmp.2;
  unsigned int D.17615;
  mword D.17616;
  unsigned int D.17617;
  unsigned int D.17618;
  unsigned int D.17619;
  mword end;

  if (size != 0) goto <D.17612>; else goto <D.17613>;
  <D.17612>:
  iftmp.2 = size;
  goto <D.17614>;
  <D.17613>:
  iftmp.2 = 1;
  <D.17614>:
  D.17615 = iftmp.2 + address;
  end = D.17615 + 4294967295;
  D.17617 = end >> 9;
  D.17618 = address >> 9;
  D.17619 = D.17617 - D.17618;
  D.17616 = D.17619 + 1;
  return D.17616;
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.17623;
  int D.17628;
  void * D.17630;
  unsigned int D.17631;

  D.17623 = __builtin_constant_p (__len);
  if (D.17623 != 0) goto <D.17624>; else goto <D.17625>;
  <D.17624>:
  if (__len == 0) goto <D.17626>; else goto <D.17627>;
  <D.17626>:
  D.17628 = __builtin_constant_p (__ch);
  if (D.17628 == 0) goto <D.17621>; else goto <D.17629>;
  <D.17629>:
  if (__ch != 0) goto <D.17621>; else goto <D.17622>;
  <D.17621>:
  __warn_memset_zero_len ();
  D.17630 = __dest;
  return D.17630;
  <D.17622>:
  <D.17627>:
  <D.17625>:
  D.17631 = __builtin_object_size (__dest, 0);
  D.17630 = __builtin___memset_chk (__dest, __ch, __len, D.17631);
  return D.17630;
}


sgen_card_table_update_mod_union (guint8 * dest, char * obj, mword obj_size, size_t * out_num_cards)
{
  unsigned int obj.3;
  unsigned int D.17634;
  unsigned int D.17635;
  guint8 * D.17636;
  _Bool D.17637;
  int end_card.4;
  int start_card.5;
  int D.17640;
  guint8 * D.17645;
  guint8 * result;
  guint8 * start_card;
  guint8 * end_card;
  gboolean init;
  size_t num_cards;

  result = dest;
  obj.3 = (unsigned int) obj;
  start_card = sgen_card_table_get_card_address (obj.3);
  obj.3 = (unsigned int) obj;
  D.17634 = obj.3 + obj_size;
  D.17635 = D.17634 + 4294967295;
  D.17636 = sgen_card_table_get_card_address (D.17635);
  end_card = D.17636 + 1;
  D.17637 = dest == 0B;
  init = (gboolean) D.17637;
  end_card.4 = (int) end_card;
  start_card.5 = (int) start_card;
  D.17640 = end_card.4 - start_card.5;
  num_cards = (size_t) D.17640;
  if (init != 0) goto <D.17641>; else goto <D.17642>;
  <D.17641>:
  dest = alloc_mod_union (num_cards);
  result = dest;
  <D.17642>:
  update_mod_union (dest, init, start_card, end_card);
  if (out_num_cards != 0B) goto <D.17643>; else goto <D.17644>;
  <D.17643>:
  *out_num_cards = num_cards;
  <D.17644>:
  D.17645 = result;
  return D.17645;
}


alloc_mod_union (size_t num_cards)
{
  guint8 * D.17647;

  D.17647 = sgen_alloc_internal_dynamic (num_cards, 28, 1);
  return D.17647;
}


update_mod_union (guint8 * dest, gboolean init, guint8 * start_card, guint8 * end_card)
{
  int end_card.6;
  int start_card.7;
  int D.17651;
  sizetype i.8;
  guint8 * D.17656;
  unsigned char D.17657;
  guint8 * D.17658;
  unsigned char D.17659;
  unsigned char D.17660;
  unsigned int i.9;
  size_t num_cards;

  end_card.6 = (int) end_card;
  start_card.7 = (int) start_card;
  D.17651 = end_card.6 - start_card.7;
  num_cards = (size_t) D.17651;
  if (init != 0) goto <D.17652>; else goto <D.17653>;
  <D.17652>:
  memcpy (dest, start_card, num_cards);
  goto <D.17654>;
  <D.17653>:
  {
    int i;

    i = 0;
    goto <D.17489>;
    <D.17488>:
    i.8 = (sizetype) i;
    D.17656 = dest + i.8;
    i.8 = (sizetype) i;
    D.17656 = dest + i.8;
    D.17657 = *D.17656;
    i.8 = (sizetype) i;
    D.17658 = start_card + i.8;
    D.17659 = *D.17658;
    D.17660 = D.17657 | D.17659;
    *D.17656 = D.17660;
    i = i + 1;
    <D.17489>:
    i.9 = (unsigned int) i;
    if (i.9 < num_cards) goto <D.17488>; else goto <D.17490>;
    <D.17490>:
  }
  <D.17654>:
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.17662;
  unsigned int D.17663;

  D.17663 = __builtin_object_size (__dest, 0);
  D.17662 = __builtin___memcpy_chk (__dest, __src, __len, D.17663);
  return D.17662;
}


mono_gc_get_card_table (int * shift_bits, void * * mask)
{
  guint8 * sgen_cardtable.10;
  guint8 * D.17668;

  sgen_cardtable.10 = sgen_cardtable;
  if (sgen_cardtable.10 == 0B) goto <D.17666>; else goto <D.17667>;
  <D.17666>:
  D.17668 = 0B;
  return D.17668;
  <D.17667>:
  *shift_bits = 9;
  *mask = 0B;
  D.17668 = sgen_cardtable;
  return D.17668;
}


mono_gc_card_table_nursery_check ()
{
  gboolean D.17670;
  int D.17671;
  _Bool D.17672;

  D.17671 = major_collector.is_concurrent;
  D.17672 = D.17671 == 0;
  D.17670 = (gboolean) D.17672;
  return D.17670;
}


sgen_cardtable_scan_object (char * obj, mword block_obj_size, guint8 * cards, gboolean mod_union, struct SgenGrayQueue * queue)
{
  unsigned int D.17674;
  unsigned int D.17675;
  void * D.17676;
  unsigned int D.17677;
  int D.17678;
  unsigned char D.17681;
  struct MonoClass * D.17684;
  void * D.17685;
  unsigned int obj.11;
  int card_data.12;
  int card_base.13;
  int D.17692;
  int D.17693;
  sizetype D.17694;
  double[0:] * D.17697;
  int start.14;
  char * D.17702;
  int D.17703;
  int D.17704;
  double[0:] * D.17705;
  int D.17706;
  sizetype D.17707;
  unsigned int D.17708;
  unsigned int D.17709;
  struct SgenObjectOperations * D.17712;
  sizetype elem_size.15;
  struct SgenObjectOperations * D.17715;
  int D.17720;
  _Bool D.17721;
  long int D.17722;
  long int D.17723;
  int D.17724;
  _Bool D.17725;
  long int D.17726;
  long int D.17727;
  guint8 * D.17730;
  int D.17734;
  struct SgenObjectOperations * D.17737;
  void (*<T2b4d>) (char *, struct SgenGrayQueue *) D.17738;
  int D.17740;
  struct SgenObjectOperations * D.17743;
  void (*<T2b4d>) (char *, struct SgenGrayQueue *) D.17744;
  struct MonoVTable * vt;
  struct MonoClass * klass;

  D.17674 = MEM[(mword *)obj];
  D.17675 = D.17674 & 4294967292;
  vt = (struct MonoVTable *) D.17675;
  klass = vt->klass;
  D.17676 = vt->gc_descr;
  D.17677 = (unsigned int) D.17676;
  D.17678 = sgen_gc_descr_has_references (D.17677);
  if (D.17678 == 0) goto <D.17679>; else goto <D.17680>;
  <D.17679>:
  return;
  <D.17680>:
  D.17681 = vt->rank;
  if (D.17681 != 0) goto <D.17682>; else goto <D.17683>;
  <D.17682>:
  {
    guint8 * card_data;
    guint8 * card_base;
    guint8 * card_data_end;
    char * obj_start;
    mword obj_size;
    char * obj_end;
    size_t card_count;
    int extra_idx;
    struct MonoArray * arr;
    mword desc;
    int elem_size;

    obj_start = sgen_card_table_align_pointer (obj);
    obj_size = sgen_par_object_get_size (vt, obj);
    obj_end = obj + obj_size;
    extra_idx = 0;
    arr = obj;
    D.17684 = klass->element_class;
    D.17685 = D.17684->gc_descr;
    desc = (mword) D.17685;
    elem_size = mono_array_element_size (klass);
    if (cards != 0B) goto <D.17686>; else goto <D.17687>;
    <D.17686>:
    card_data = cards;
    goto <D.17688>;
    <D.17687>:
    obj.11 = (unsigned int) obj;
    card_data = sgen_card_table_get_card_address (obj.11);
    <D.17688>:
    card_base = card_data;
    obj.11 = (unsigned int) obj;
    card_count = cards_in_range (obj.11, obj_size);
    card_data_end = card_data + card_count;
    card_data = find_next_card (card_data, card_data_end);
    goto <D.17590>;
    <D.17589>:
    {
      int index;
      int idx;
      char * start;
      char * card_end;
      char * first_elem;
      char * elem;

      card_data.12 = (int) card_data;
      card_base.13 = (int) card_base;
      D.17692 = card_data.12 - card_base.13;
      idx = D.17692 + extra_idx;
      D.17693 = idx * 512;
      D.17694 = (sizetype) D.17693;
      start = obj_start + D.17694;
      card_end = start + 512;
      if (cards == 0B) goto <D.17695>; else goto <D.17696>;
      <D.17695>:
      sgen_card_table_prepare_card_for_scanning (card_data);
      <D.17696>:
      card_end = MIN_EXPR <obj_end, card_end>;
      D.17697 = &arr->vector;
      if (D.17697 >= start) goto <D.17698>; else goto <D.17699>;
      <D.17698>:
      index = 0;
      goto <D.17700>;
      <D.17699>:
      start.14 = (int) start;
      D.17702 = obj + 16;
      D.17703 = (int) D.17702;
      D.17704 = start.14 - D.17703;
      index = D.17704 / elem_size;
      <D.17700>:
      D.17705 = &MEM[(struct MonoArray *)obj].vector;
      D.17706 = elem_size * index;
      D.17707 = (sizetype) D.17706;
      first_elem = D.17705 + D.17707;
      elem = first_elem;
      D.17684 = klass->element_class;
      D.17708 = BIT_FIELD_REF <*D.17684, 32, 160>;
      D.17709 = D.17708 & 8;
      if (D.17709 != 0) goto <D.17710>; else goto <D.17711>;
      <D.17710>:
      {
        void (*ScanVTypeFunc) (char *, mword, struct SgenGrayQueue *) scan_vtype_func;

        D.17712 = sgen_get_current_object_ops ();
        scan_vtype_func = D.17712->scan_vtype;
        goto <D.17581>;
        <D.17580>:
        scan_vtype_func (elem, desc, queue);
        elem_size.15 = (sizetype) elem_size;
        elem = elem + elem_size.15;
        <D.17581>:
        if (elem < card_end) goto <D.17580>; else goto <D.17582>;
        <D.17582>:
      }
      goto <D.17714>;
      <D.17711>:
      {
        void (*CopyOrMarkObjectFunc) (void * *, struct SgenGrayQueue *) copy_func;

        D.17715 = sgen_get_current_object_ops ();
        copy_func = D.17715->copy_or_mark_object;
        goto <D.17587>;
        <D.17586>:
        {
          void * new;
          void * old;

          old = MEM[(void * *)elem];
          if (mod_union != 0) goto <D.17719>; else goto <D.17716>;
          <D.17719>:
          if (old != 0B) goto <D.17717>; else goto <D.17716>;
          <D.17716>:
          D.17720 = sgen_ptr_in_nursery (old);
          D.17721 = D.17720 != 0;
          D.17722 = (long int) D.17721;
          D.17723 = __builtin_expect (D.17722, 0);
          if (D.17723 != 0) goto <D.17717>; else goto <D.17718>;
          <D.17717>:
          copy_func (elem, queue);
          new = MEM[(void * *)elem];
          D.17724 = sgen_ptr_in_nursery (new);
          D.17725 = D.17724 != 0;
          D.17726 = (long int) D.17725;
          D.17727 = __builtin_expect (D.17726, 0);
          if (D.17727 != 0) goto <D.17728>; else goto <D.17729>;
          <D.17728>:
          sgen_add_to_global_remset (elem, new);
          <D.17729>:
          <D.17718>:
        }
        elem = elem + 4;
        <D.17587>:
        if (elem < card_end) goto <D.17586>; else goto <D.17588>;
        <D.17588>:
      }
      <D.17714>:
    }
    D.17730 = card_data + 1;
    card_data = find_next_card (D.17730, card_data_end);
    <D.17590>:
    if (card_data < card_data_end) goto <D.17589>; else goto <D.17591>;
    <D.17591>:
  }
  goto <D.17731>;
  <D.17683>:
  if (cards != 0B) goto <D.17732>; else goto <D.17733>;
  <D.17732>:
  obj.11 = (unsigned int) obj;
  D.17734 = sgen_card_table_is_range_marked (cards, obj.11, block_obj_size);
  if (D.17734 != 0) goto <D.17735>; else goto <D.17736>;
  <D.17735>:
  D.17737 = sgen_get_current_object_ops ();
  D.17738 = D.17737->scan_object;
  D.17738 (obj, queue);
  <D.17736>:
  goto <D.17739>;
  <D.17733>:
  obj.11 = (unsigned int) obj;
  D.17740 = sgen_card_table_region_begin_scanning (obj.11, block_obj_size);
  if (D.17740 != 0) goto <D.17741>; else goto <D.17742>;
  <D.17741>:
  D.17743 = sgen_get_current_object_ops ();
  D.17744 = D.17743->scan_object;
  D.17744 (obj, queue);
  <D.17742>:
  <D.17739>:
  <D.17731>:
}


sgen_gc_descr_has_references (mword desc)
{
  unsigned int D.17746;
  gboolean D.17749;
  unsigned int D.17750;
  unsigned int D.17753;

  D.17746 = desc & 4294901767;
  if (D.17746 == 1) goto <D.17747>; else goto <D.17748>;
  <D.17747>:
  D.17749 = 0;
  return D.17749;
  <D.17748>:
  D.17750 = desc & 49159;
  if (D.17750 == 4) goto <D.17751>; else goto <D.17752>;
  <D.17751>:
  D.17749 = 0;
  return D.17749;
  <D.17752>:
  D.17753 = desc & 7;
  if (D.17753 == 7) goto <D.17754>; else goto <D.17755>;
  <D.17754>:
  D.17749 = 0;
  return D.17749;
  <D.17755>:
  D.17749 = 1;
  return D.17749;
}


sgen_par_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  void * D.17757;
  unsigned int D.17758;
  guint D.17763;
  int D.17764;
  int D.17765;
  unsigned int D.17766;
  unsigned int D.17769;
  int D.17770;
  unsigned int D.17771;
  unsigned int element_size.16;
  unsigned int D.17773;
  unsigned int D.17774;
  struct MonoClass * D.17777;
  unsigned char D.17778;
  unsigned int D.17779;
  unsigned int D.17780;
  mword descr;
  mword type;

  D.17757 = vtable->gc_descr;
  descr = (mword) D.17757;
  type = descr & 7;
  D.17758 = type + 4294967295;
  if (D.17758 <= 1) goto <D.17759>; else goto <D.17760>;
  <D.17759>:
  {
    mword size;

    size = descr & 65528;
    if (size == 0) goto <D.17761>; else goto <D.17762>;
    <D.17761>:
    D.17764 = MEM[(struct MonoString *)o].length;
    D.17765 = D.17764 * 2;
    D.17766 = (unsigned int) D.17765;
    D.17763 = D.17766 + 14;
    return D.17763;
    <D.17762>:
    D.17763 = size;
    return D.17763;
  }
  <D.17760>:
  if (type == 4) goto <D.17767>; else goto <D.17768>;
  <D.17767>:
  {
    int element_size;
    struct MonoArray * array;
    size_t size;

    D.17769 = descr >> 3;
    D.17770 = (int) D.17769;
    element_size = D.17770 & 1023;
    array = o;
    D.17771 = array->max_length;
    element_size.16 = (unsigned int) element_size;
    D.17773 = D.17771 * element_size.16;
    size = D.17773 + 16;
    D.17774 = descr & 8192;
    if (D.17774 != 0) goto <D.17775>; else goto <D.17776>;
    <D.17775>:
    size = size + 3;
    size = size & 4294967292;
    D.17777 = vtable->klass;
    D.17778 = D.17777->rank;
    D.17779 = (unsigned int) D.17778;
    D.17780 = D.17779 * 8;
    size = D.17780 + size;
    <D.17776>:
    D.17763 = size;
    return D.17763;
  }
  <D.17768>:
  D.17763 = slow_object_get_size (vtable, o);
  return D.17763;
}


slow_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  struct MonoClass * D.17782;
  guint D.17785;
  int D.17786;
  int D.17787;
  unsigned int D.17788;
  unsigned char D.17789;
  int D.17792;
  unsigned int D.17793;
  unsigned int D.17794;
  unsigned int D.17795;
  struct MonoArrayBounds * D.17796;
  _Bool D.17797;
  long int D.17798;
  long int D.17799;
  unsigned int D.17802;
  unsigned int D.17803;
  int D.17804;
  struct MonoClass * klass;

  klass = vtable->klass;
  D.17782 = mono_defaults.string_class;
  if (D.17782 == klass) goto <D.17783>; else goto <D.17784>;
  <D.17783>:
  D.17786 = MEM[(struct MonoString *)o].length;
  D.17787 = D.17786 * 2;
  D.17788 = (unsigned int) D.17787;
  D.17785 = D.17788 + 14;
  return D.17785;
  <D.17784>:
  D.17789 = klass->rank;
  if (D.17789 != 0) goto <D.17790>; else goto <D.17791>;
  <D.17790>:
  {
    struct MonoArray * array;
    size_t size;

    array = o;
    D.17792 = klass->sizes.element_size;
    D.17793 = (unsigned int) D.17792;
    D.17794 = array->max_length;
    D.17795 = D.17793 * D.17794;
    size = D.17795 + 16;
    D.17796 = array->bounds;
    D.17797 = D.17796 != 0B;
    D.17798 = (long int) D.17797;
    D.17799 = __builtin_expect (D.17798, 0);
    if (D.17799 != 0) goto <D.17800>; else goto <D.17801>;
    <D.17800>:
    size = size + 3;
    size = size & 4294967292;
    D.17789 = klass->rank;
    D.17802 = (unsigned int) D.17789;
    D.17803 = D.17802 * 8;
    size = D.17803 + size;
    <D.17801>:
    D.17785 = size;
    return D.17785;
  }
  <D.17791>:
  D.17804 = klass->instance_size;
  D.17785 = (guint) D.17804;
  return D.17785;
}


sgen_card_table_prepare_card_for_scanning (guint8 * card)
{
  *card = 0;
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.17806;
  int sgen_nursery_bits.17;
  int D.17808;
  int D.17809;
  unsigned int D.17810;
  unsigned int p.18;
  unsigned int D.17812;
  char * sgen_nursery_start.19;
  unsigned int sgen_nursery_start.20;
  _Bool D.17815;

  sgen_nursery_bits.17 = sgen_nursery_bits;
  D.17808 = 1 << sgen_nursery_bits.17;
  D.17809 = -D.17808;
  D.17810 = (unsigned int) D.17809;
  p.18 = (unsigned int) p;
  D.17812 = D.17810 & p.18;
  sgen_nursery_start.19 = sgen_nursery_start;
  sgen_nursery_start.20 = (unsigned int) sgen_nursery_start.19;
  D.17815 = D.17812 == sgen_nursery_start.20;
  D.17806 = (gboolean) D.17815;
  return D.17806;
}


find_next_card (guint8 * card_data, guint8 * end)
{
  unsigned char D.17817;
  guint8 * D.17820;
  unsigned int card_data.21;
  unsigned int D.17822;
  unsigned int end.22;
  unsigned int D.17827;
  int D.17830;
  sizetype D.17831;
  mword * cards;
  mword * cards_end;
  mword card;

  goto <D.17545>;
  <D.17544>:
  D.17817 = *card_data;
  if (D.17817 != 0) goto <D.17818>; else goto <D.17819>;
  <D.17818>:
  D.17820 = card_data;
  return D.17820;
  <D.17819>:
  card_data = card_data + 1;
  <D.17545>:
  card_data.21 = (unsigned int) card_data;
  D.17822 = card_data.21 & 3;
  if (D.17822 != 0) goto <D.17823>; else goto <D.17546>;
  <D.17823>:
  if (card_data < end) goto <D.17544>; else goto <D.17546>;
  <D.17546>:
  if (card_data == end) goto <D.17824>; else goto <D.17825>;
  <D.17824>:
  D.17820 = end;
  return D.17820;
  <D.17825>:
  cards = card_data;
  end.22 = (unsigned int) end;
  D.17827 = end.22 & 4294967292;
  cards_end = (mword *) D.17827;
  goto <D.17548>;
  <D.17547>:
  card = *cards;
  if (card != 0) goto <D.17828>; else goto <D.17829>;
  <D.17828>:
  D.17830 = find_card_offset (card);
  D.17831 = (sizetype) D.17830;
  D.17820 = cards + D.17831;
  return D.17820;
  <D.17829>:
  cards = cards + 4;
  <D.17548>:
  if (cards < cards_end) goto <D.17547>; else goto <D.17549>;
  <D.17549>:
  card_data = cards_end;
  goto <D.17551>;
  <D.17550>:
  D.17817 = *card_data;
  if (D.17817 != 0) goto <D.17832>; else goto <D.17833>;
  <D.17832>:
  D.17820 = card_data;
  return D.17820;
  <D.17833>:
  card_data = card_data + 1;
  <D.17551>:
  if (card_data < end) goto <D.17550>; else goto <D.17552>;
  <D.17552>:
  D.17820 = end;
  return D.17820;
}


find_card_offset (mword card)
{
  sizetype i.23;
  guint8 * D.17836;
  unsigned char D.17837;
  int D.17840;
  unsigned int i.24;
  int i;
  guint8 * ptr;

  ptr = &card;
  i = 0;
  goto <D.17535>;
  <D.17534>:
  i.23 = (sizetype) i;
  D.17836 = ptr + i.23;
  D.17837 = *D.17836;
  if (D.17837 != 0) goto <D.17838>; else goto <D.17839>;
  <D.17838>:
  D.17840 = i;
  return D.17840;
  <D.17839>:
  i = i + 1;
  <D.17535>:
  i.24 = (unsigned int) i;
  if (i.24 <= 3) goto <D.17534>; else goto <D.17536>;
  <D.17536>:
  D.17840 = 0;
  return D.17840;
}


sgen_card_table_is_range_marked (guint8 * cards, mword address, mword size)
{
  unsigned int D.17843;
  guint8 * cards.25;
  unsigned char D.17845;
  gboolean D.17848;
  guint8 * end;

  D.17843 = cards_in_range (address, size);
  end = cards + D.17843;
  goto <D.17467>;
  <D.17466>:
  cards.25 = cards;
  cards = cards.25 + 1;
  D.17845 = *cards.25;
  if (D.17845 != 0) goto <D.17846>; else goto <D.17847>;
  <D.17846>:
  D.17848 = 1;
  return D.17848;
  <D.17847>:
  <D.17467>:
  if (cards != end) goto <D.17466>; else goto <D.17468>;
  <D.17468>:
  D.17848 = 0;
  return D.17848;
}


sgen_card_table_region_begin_scanning (mword start, mword size)
{
  unsigned int D.17850;
  guint8 * card.26;
  unsigned char D.17852;
  guint8 * D.17855;
  unsigned int D.17856;
  gboolean D.17857;
  gboolean res;
  guint8 * card;
  guint8 * end;

  res = 0;
  card = sgen_card_table_get_card_address (start);
  D.17850 = cards_in_range (start, size);
  end = card + D.17850;
  goto <D.17439>;
  <D.17438>:
  card.26 = card;
  card = card.26 + 1;
  D.17852 = *card.26;
  if (D.17852 != 0) goto <D.17853>; else goto <D.17854>;
  <D.17853>:
  res = 1;
  goto <D.17437>;
  <D.17854>:
  <D.17439>:
  if (card != end) goto <D.17438>; else goto <D.17437>;
  <D.17437>:
  D.17855 = sgen_card_table_get_card_address (start);
  D.17856 = size >> 9;
  memset (D.17855, 0, D.17856);
  D.17857 = res;
  return D.17857;
}


sgen_card_table_init (struct SgenRemeberedSet * remset)
{
  void * sgen_cardtable.27;
  struct SgenMajorCollector * D.17860;
  int need_mod_union.28;

  sgen_cardtable.27 = sgen_alloc_os_memory (8388608, 2, "card table");
  sgen_cardtable = sgen_cardtable.27;
  mono_counters_register ("cardtable major scan time", 519, &major_card_scan_time);
  mono_counters_register ("cardtable los scan time", 519, &los_card_scan_time);
  remset->wbarrier_set_field = sgen_card_table_wbarrier_set_field;
  remset->wbarrier_set_arrayref = sgen_card_table_wbarrier_set_arrayref;
  remset->wbarrier_arrayref_copy = sgen_card_table_wbarrier_arrayref_copy;
  remset->wbarrier_value_copy = sgen_card_table_wbarrier_value_copy;
  remset->wbarrier_object_copy = sgen_card_table_wbarrier_object_copy;
  remset->wbarrier_generic_nostore = sgen_card_table_wbarrier_generic_nostore;
  remset->record_pointer = sgen_card_table_record_pointer;
  remset->finish_scan_remsets = sgen_card_table_finish_scan_remsets;
  remset->finish_minor_collection = sgen_card_table_finish_minor_collection;
  remset->prepare_for_major_collection = sgen_card_table_prepare_for_major_collection;
  remset->find_address = sgen_card_table_find_address;
  remset->find_address_with_cards = sgen_card_table_find_address_with_cards;
  D.17860 = sgen_get_major_collector ();
  need_mod_union.28 = D.17860->is_concurrent;
  need_mod_union = need_mod_union.28;
}


sgen_card_table_find_address_with_cards (char * cards_start, guint8 * cards, char * addr)
{
  gboolean D.17862;
  int addr.29;
  int cards_start.30;
  int D.17865;
  int D.17866;
  sizetype D.17867;
  guint8 * D.17868;
  unsigned char D.17869;

  cards_start = sgen_card_table_align_pointer (cards_start);
  addr.29 = (int) addr;
  cards_start.30 = (int) cards_start;
  D.17865 = addr.29 - cards_start.30;
  D.17866 = D.17865 >> 9;
  D.17867 = (sizetype) D.17866;
  D.17868 = cards + D.17867;
  D.17869 = *D.17868;
  D.17862 = (gboolean) D.17869;
  return D.17862;
}


sgen_card_table_find_address (char * addr)
{
  gboolean D.17871;
  unsigned int addr.31;

  addr.31 = (unsigned int) addr;
  D.17871 = sgen_card_table_address_is_marked (addr.31);
  return D.17871;
}


sgen_card_table_address_is_marked (mword address)
{
  gboolean D.17874;
  guint8 * D.17875;
  unsigned char D.17876;
  _Bool D.17877;

  D.17875 = sgen_card_table_get_card_address (address);
  D.17876 = *D.17875;
  D.17877 = D.17876 != 0;
  D.17874 = (gboolean) D.17877;
  return D.17874;
}


sgen_card_table_prepare_for_major_collection ()
{
  sgen_major_collector_iterate_live_block_ranges (clear_cards);
  sgen_los_iterate_live_block_ranges (clear_cards);
}


clear_cards (mword start, mword size)
{
  guint8 * D.17879;
  unsigned int D.17880;

  D.17879 = sgen_card_table_get_card_address (start);
  D.17880 = cards_in_range (start, size);
  memset (D.17879, 0, D.17880);
}


sgen_card_table_finish_minor_collection ()
{
  sgen_card_tables_collect_stats (0);
}


sgen_card_tables_collect_stats (gboolean begin)
{

}


sgen_card_table_finish_scan_remsets (void * start_nursery, void * end_nursery, struct SgenGrayQueue * queue)
{
  long long int D.17881;
  long long int D.17882;
  int D.17883;
  long long int last_major_scan_time.32;
  long long int major_card_scan_time.33;
  long long int last_major_scan_time.34;
  long long int major_card_scan_time.35;
  long long int D.17888;
  long long int D.17889;
  int D.17890;
  long long int last_los_scan_time.36;
  long long int los_card_scan_time.37;
  long long int last_los_scan_time.38;
  long long int los_card_scan_time.39;
  gint64 atv;
  gint64 btv;

  sgen_card_tables_collect_stats (1);
  atv = mono_100ns_ticks ();
  sgen_major_collector_scan_card_table (queue);
  btv = mono_100ns_ticks ();
  D.17881 = btv - atv;
  D.17882 = D.17881 / 10;
  D.17883 = (int) D.17882;
  last_major_scan_time.32 = (long long int) D.17883;
  last_major_scan_time = last_major_scan_time.32;
  major_card_scan_time.33 = major_card_scan_time;
  last_major_scan_time.34 = last_major_scan_time;
  major_card_scan_time.35 = major_card_scan_time.33 + last_major_scan_time.34;
  major_card_scan_time = major_card_scan_time.35;
  sgen_los_scan_card_table (0, queue);
  atv = mono_100ns_ticks ();
  D.17888 = atv - btv;
  D.17889 = D.17888 / 10;
  D.17890 = (int) D.17889;
  last_los_scan_time.36 = (long long int) D.17890;
  last_los_scan_time = last_los_scan_time.36;
  los_card_scan_time.37 = los_card_scan_time;
  last_los_scan_time.38 = last_los_scan_time;
  los_card_scan_time.39 = los_card_scan_time.37 + last_los_scan_time.38;
  los_card_scan_time = los_card_scan_time.39;
}


sgen_card_table_record_pointer (void * address)
{
  unsigned int address.40;
  guint8 * D.17896;

  address.40 = (unsigned int) address;
  D.17896 = sgen_card_table_get_card_address (address.40);
  *D.17896 = 1;
}


sgen_card_table_wbarrier_generic_nostore (void * ptr)
{
  unsigned int ptr.41;

  ptr.41 = (unsigned int) ptr;
  sgen_card_table_mark_address (ptr.41);
}


sgen_card_table_mark_address (mword address)
{
  guint8 * D.17898;

  D.17898 = sgen_card_table_get_card_address (address);
  *D.17898 = 1;
}


sgen_card_table_wbarrier_object_copy (struct MonoObject * obj, struct MonoObject * src)
{
  struct MonoVTable * D.17899;
  struct MonoClass * D.17900;
  struct SgenThreadInfo * sgen_thread_info.42;
  void * D.17902;
  const void * D.17903;
  unsigned int size.43;
  unsigned int D.17905;
  unsigned int obj.44;
  unsigned int size.45;
  int size;

  D.17899 = obj->vtable;
  D.17900 = D.17899->klass;
  size = D.17900->instance_size;
  sgen_thread_info.42 = sgen_thread_info;
  sgen_thread_info.42->in_critical_region = 1;
  mono_memory_barrier ();
  D.17902 = obj + 8;
  D.17903 = src + 8;
  size.43 = (unsigned int) size;
  D.17905 = size.43 + 4294967288;
  mono_gc_memmove_aligned (D.17902, D.17903, D.17905);
  obj.44 = (unsigned int) obj;
  size.45 = (unsigned int) size;
  sgen_card_table_mark_range (obj.44, size.45);
  mono_memory_barrier ();
  sgen_thread_info.42 = sgen_thread_info;
  sgen_thread_info.42->in_critical_region = 0;
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


sgen_card_table_wbarrier_value_copy (void * dest, void * src, int count, struct MonoClass * klass)
{
  int D.17908;
  unsigned int count.46;
  struct SgenThreadInfo * sgen_thread_info.47;
  unsigned int dest.48;
  size_t element_size;
  size_t size;

  D.17908 = mono_class_value_size (klass, 0B);
  element_size = (size_t) D.17908;
  count.46 = (unsigned int) count;
  size = count.46 * element_size;
  sgen_thread_info.47 = sgen_thread_info;
  sgen_thread_info.47->in_critical_region = 1;
  mono_memory_barrier ();
  mono_gc_memmove_atomic (dest, src, size);
  dest.48 = (unsigned int) dest;
  sgen_card_table_mark_range (dest.48, size);
  mono_memory_barrier ();
  sgen_thread_info.47 = sgen_thread_info;
  sgen_thread_info.47->in_critical_region = 0;
}


sgen_card_table_wbarrier_arrayref_copy (void * dest_ptr, void * src_ptr, int count)
{
  unsigned int count.49;
  unsigned int D.17916;
  void * * D.17917;
  sizetype count.50;
  sizetype D.17920;
  sizetype D.17921;
  int need_mod_union.51;
  int D.17926;
  unsigned int dest.52;
  int D.17931;
  void * * dest;
  void * * src;

  dest = dest_ptr;
  src = src_ptr;
  if (src < dest) goto <D.17914>; else goto <D.17912>;
  <D.17914>:
  count.49 = (unsigned int) count;
  D.17916 = count.49 * 4;
  D.17917 = src + D.17916;
  if (D.17917 > dest) goto <D.17918>; else goto <D.17912>;
  <D.17918>:
  {
    void * * start;

    start = dest;
    count.50 = (sizetype) count;
    D.17920 = count.50 + 1073741823;
    D.17921 = D.17920 * 4;
    dest = dest + D.17921;
    count.50 = (sizetype) count;
    D.17920 = count.50 + 1073741823;
    D.17921 = D.17920 * 4;
    src = src + D.17921;
    goto <D.17407>;
    <D.17406>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.51 = need_mod_union;
      if (need_mod_union.51 != 0) goto <D.17922>; else goto <D.17925>;
      <D.17925>:
      D.17926 = sgen_ptr_in_nursery (value);
      if (D.17926 != 0) goto <D.17922>; else goto <D.17923>;
      <D.17922>:
      dest.52 = (unsigned int) dest;
      sgen_card_table_mark_address (dest.52);
      <D.17923>:
      sgen_dummy_use (value);
    }
    src = src + 4294967292;
    dest = dest + 4294967292;
    <D.17407>:
    if (dest >= start) goto <D.17406>; else goto <D.17408>;
    <D.17408>:
  }
  goto <D.17913>;
  <D.17912>:
  {
    void * * end;

    count.49 = (unsigned int) count;
    D.17916 = count.49 * 4;
    end = dest + D.17916;
    goto <D.17412>;
    <D.17411>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.51 = need_mod_union;
      if (need_mod_union.51 != 0) goto <D.17928>; else goto <D.17930>;
      <D.17930>:
      D.17931 = sgen_ptr_in_nursery (value);
      if (D.17931 != 0) goto <D.17928>; else goto <D.17929>;
      <D.17928>:
      dest.52 = (unsigned int) dest;
      sgen_card_table_mark_address (dest.52);
      <D.17929>:
      sgen_dummy_use (value);
    }
    src = src + 4;
    dest = dest + 4;
    <D.17412>:
    if (dest < end) goto <D.17411>; else goto <D.17413>;
    <D.17413>:
  }
  <D.17913>:
}


sgen_dummy_use (void * v)
{
  __asm__ __volatile__("" : "=r" v : "r" v);
}


sgen_card_table_wbarrier_set_arrayref (struct MonoArray * arr, void * slot_ptr, struct MonoObject * value)
{
  int need_mod_union.53;
  int D.17936;
  unsigned int slot_ptr.54;

  MEM[(void * *)slot_ptr] = value;
  need_mod_union.53 = need_mod_union;
  if (need_mod_union.53 != 0) goto <D.17932>; else goto <D.17935>;
  <D.17935>:
  D.17936 = sgen_ptr_in_nursery (value);
  if (D.17936 != 0) goto <D.17932>; else goto <D.17933>;
  <D.17932>:
  slot_ptr.54 = (unsigned int) slot_ptr;
  sgen_card_table_mark_address (slot_ptr.54);
  <D.17933>:
  sgen_dummy_use (value);
}


sgen_card_table_wbarrier_set_field (struct MonoObject * obj, void * field_ptr, struct MonoObject * value)
{
  int need_mod_union.55;
  int D.17942;
  unsigned int field_ptr.56;

  MEM[(void * *)field_ptr] = value;
  need_mod_union.55 = need_mod_union;
  if (need_mod_union.55 != 0) goto <D.17938>; else goto <D.17941>;
  <D.17941>:
  D.17942 = sgen_ptr_in_nursery (value);
  if (D.17942 != 0) goto <D.17938>; else goto <D.17939>;
  <D.17938>:
  field_ptr.56 = (unsigned int) field_ptr;
  sgen_card_table_mark_address (field_ptr.56);
  <D.17939>:
  sgen_dummy_use (value);
}


