sgen_card_table_get_card_data (guint8 * data_dest, mword address, mword cards)
{
  gboolean D.20184;
  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.20034>;
  <D.20033>:
  {
    mword v;

    v = *start;
    *dest = v;
    mask = mask | v;
    *start = 0;
  }
  dest = dest + 4;
  start = start + 4;
  <D.20034>:
  if (dest < end) goto <D.20033>; else goto <D.20035>;
  <D.20035>:
  D.20184 = (gboolean) mask;
  return D.20184;
}


sgen_card_table_get_card_address (mword address)
{
  guint8 * D.20186;
  guint8 * sgen_cardtable.0;
  unsigned int D.20188;

  sgen_cardtable.0 = sgen_cardtable;
  D.20188 = address >> 9;
  D.20186 = sgen_cardtable.0 + D.20188;
  return D.20186;
}


sgen_card_table_align_pointer (void * ptr)
{
  void * D.20190;
  unsigned int ptr.1;
  unsigned int D.20192;

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


sgen_card_table_mark_range (mword address, mword size)
{
  guint8 * D.20194;
  unsigned int D.20195;

  D.20194 = sgen_card_table_get_card_address (address);
  D.20195 = cards_in_range (address, size);
  memset (D.20194, 1, D.20195);
}


cards_in_range (mword address, mword size)
{
  mword iftmp.2;
  unsigned int D.20200;
  mword D.20201;
  unsigned int D.20202;
  unsigned int D.20203;
  unsigned int D.20204;
  mword end;

  if (size != 0) goto <D.20197>; else goto <D.20198>;
  <D.20197>:
  iftmp.2 = size;
  goto <D.20199>;
  <D.20198>:
  iftmp.2 = 1;
  <D.20199>:
  D.20200 = iftmp.2 + address;
  end = D.20200 + 4294967295;
  D.20202 = end >> 9;
  D.20203 = address >> 9;
  D.20204 = D.20202 - D.20203;
  D.20201 = D.20204 + 1;
  return D.20201;
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.20208;
  int D.20213;
  void * D.20215;
  unsigned int D.20216;

  D.20208 = __builtin_constant_p (__len);
  if (D.20208 != 0) goto <D.20209>; else goto <D.20210>;
  <D.20209>:
  if (__len == 0) goto <D.20211>; else goto <D.20212>;
  <D.20211>:
  D.20213 = __builtin_constant_p (__ch);
  if (D.20213 == 0) goto <D.20206>; else goto <D.20214>;
  <D.20214>:
  if (__ch != 0) goto <D.20206>; else goto <D.20207>;
  <D.20206>:
  __warn_memset_zero_len ();
  D.20215 = __dest;
  return D.20215;
  <D.20207>:
  <D.20212>:
  <D.20210>:
  D.20216 = __builtin_object_size (__dest, 0);
  D.20215 = __builtin___memset_chk (__dest, __ch, __len, D.20216);
  return D.20215;
}


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.20219;
  unsigned int D.20220;
  guint8 * D.20221;
  _Bool D.20222;
  int end_card.4;
  int start_card.5;
  int D.20225;
  guint8 * D.20230;
  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.20219 = obj.3 + obj_size;
  D.20220 = D.20219 + 4294967295;
  D.20221 = sgen_card_table_get_card_address (D.20220);
  end_card = D.20221 + 1;
  D.20222 = dest == 0B;
  init = (gboolean) D.20222;
  end_card.4 = (int) end_card;
  start_card.5 = (int) start_card;
  D.20225 = end_card.4 - start_card.5;
  num_cards = (size_t) D.20225;
  if (init != 0) goto <D.20226>; else goto <D.20227>;
  <D.20226>:
  dest = alloc_mod_union (num_cards);
  result = dest;
  <D.20227>:
  update_mod_union (dest, init, start_card, end_card);
  if (out_num_cards != 0B) goto <D.20228>; else goto <D.20229>;
  <D.20228>:
  *out_num_cards = num_cards;
  <D.20229>:
  D.20230 = result;
  return D.20230;
}


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

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


update_mod_union (guint8 * dest, gboolean init, guint8 * start_card, guint8 * end_card)
{
  int end_card.6;
  int start_card.7;
  int D.20236;
  sizetype i.8;
  guint8 * D.20241;
  unsigned char D.20242;
  guint8 * D.20243;
  unsigned char D.20244;
  unsigned char D.20245;
  unsigned int i.9;
  size_t num_cards;

  end_card.6 = (int) end_card;
  start_card.7 = (int) start_card;
  D.20236 = end_card.6 - start_card.7;
  num_cards = (size_t) D.20236;
  if (init != 0) goto <D.20237>; else goto <D.20238>;
  <D.20237>:
  memcpy (dest, start_card, num_cards);
  goto <D.20239>;
  <D.20238>:
  {
    int i;

    i = 0;
    goto <D.20072>;
    <D.20071>:
    i.8 = (sizetype) i;
    D.20241 = dest + i.8;
    i.8 = (sizetype) i;
    D.20241 = dest + i.8;
    D.20242 = *D.20241;
    i.8 = (sizetype) i;
    D.20243 = start_card + i.8;
    D.20244 = *D.20243;
    D.20245 = D.20242 | D.20244;
    *D.20241 = D.20245;
    i = i + 1;
    <D.20072>:
    i.9 = (unsigned int) i;
    if (i.9 < num_cards) goto <D.20071>; else goto <D.20073>;
    <D.20073>:
  }
  <D.20239>:
}


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

  D.20248 = __builtin_object_size (__dest, 0);
  D.20247 = __builtin___memcpy_chk (__dest, __src, __len, D.20248);
  return D.20247;
}


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

  sgen_cardtable.10 = sgen_cardtable;
  if (sgen_cardtable.10 == 0B) goto <D.20251>; else goto <D.20252>;
  <D.20251>:
  D.20253 = 0B;
  return D.20253;
  <D.20252>:
  *shift_bits = 9;
  *mask = 0B;
  D.20253 = sgen_cardtable;
  return D.20253;
}


mono_gc_card_table_nursery_check ()
{
  gboolean D.20255;
  int D.20256;
  _Bool D.20257;

  D.20256 = major_collector.is_concurrent;
  D.20257 = D.20256 == 0;
  D.20255 = (gboolean) D.20257;
  return D.20255;
}


sgen_cardtable_scan_object (char * obj, mword block_obj_size, guint8 * cards, gboolean mod_union, struct SgenGrayQueue * queue)
{
  unsigned int D.20259;
  unsigned int D.20260;
  void * D.20261;
  unsigned int D.20262;
  int D.20263;
  unsigned char D.20266;
  struct MonoClass * D.20269;
  void * D.20270;
  unsigned int obj.11;
  int card_data.12;
  int card_base.13;
  int D.20277;
  int D.20278;
  sizetype D.20279;
  double[0:] * D.20282;
  int start.14;
  char * D.20287;
  int D.20288;
  int D.20289;
  double[0:] * D.20290;
  int D.20291;
  sizetype D.20292;
  unsigned char D.20293;
  unsigned char D.20294;
  struct SgenObjectOperations * D.20297;
  sizetype elem_size.15;
  struct SgenObjectOperations * D.20300;
  _Bool D.20303;
  _Bool D.20304;
  _Bool D.20305;
  int D.20307;
  _Bool D.20308;
  long int D.20309;
  long int D.20310;
  int D.20311;
  _Bool D.20312;
  long int D.20313;
  long int D.20314;
  guint8 * D.20317;
  int D.20321;
  struct SgenObjectOperations * D.20324;
  void (*<T35be>) (char *, struct SgenGrayQueue *) D.20325;
  int D.20327;
  struct SgenObjectOperations * D.20330;
  void (*<T35be>) (char *, struct SgenGrayQueue *) D.20331;
  struct MonoVTable * vt;
  struct MonoClass * klass;

  D.20259 = MEM[(mword *)obj];
  D.20260 = D.20259 & 4294967292;
  vt = (struct MonoVTable *) D.20260;
  klass = vt->klass;
  D.20261 = vt->gc_descr;
  D.20262 = (unsigned int) D.20261;
  D.20263 = sgen_gc_descr_has_references (D.20262);
  if (D.20263 == 0) goto <D.20264>; else goto <D.20265>;
  <D.20264>:
  return;
  <D.20265>:
  D.20266 = vt->rank;
  if (D.20266 != 0) goto <D.20267>; else goto <D.20268>;
  <D.20267>:
  {
    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.20269 = klass->element_class;
    D.20270 = D.20269->gc_descr;
    desc = (mword) D.20270;
    elem_size = mono_array_element_size (klass);
    if (cards != 0B) goto <D.20271>; else goto <D.20272>;
    <D.20271>:
    card_data = cards;
    goto <D.20273>;
    <D.20272>:
    obj.11 = (unsigned int) obj;
    card_data = sgen_card_table_get_card_address (obj.11);
    <D.20273>:
    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.20173>;
    <D.20172>:
    {
      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.20277 = card_data.12 - card_base.13;
      idx = D.20277 + extra_idx;
      D.20278 = idx * 512;
      D.20279 = (sizetype) D.20278;
      start = obj_start + D.20279;
      card_end = start + 512;
      if (cards == 0B) goto <D.20280>; else goto <D.20281>;
      <D.20280>:
      sgen_card_table_prepare_card_for_scanning (card_data);
      <D.20281>:
      card_end = MIN_EXPR <obj_end, card_end>;
      D.20282 = &arr->vector;
      if (D.20282 >= start) goto <D.20283>; else goto <D.20284>;
      <D.20283>:
      index = 0;
      goto <D.20285>;
      <D.20284>:
      start.14 = (int) start;
      D.20287 = obj + 16;
      D.20288 = (int) D.20287;
      D.20289 = start.14 - D.20288;
      index = D.20289 / elem_size;
      <D.20285>:
      D.20290 = &MEM[(struct MonoArray *)obj].vector;
      D.20291 = elem_size * index;
      D.20292 = (sizetype) D.20291;
      first_elem = D.20290 + D.20292;
      elem = first_elem;
      D.20269 = klass->element_class;
      D.20293 = BIT_FIELD_REF <*D.20269, 8, 160>;
      D.20294 = D.20293 & 8;
      if (D.20294 != 0) goto <D.20295>; else goto <D.20296>;
      <D.20295>:
      {
        void (*ScanVTypeFunc) (char *, mword, struct SgenGrayQueue *) scan_vtype_func;

        D.20297 = sgen_get_current_object_ops ();
        scan_vtype_func = D.20297->scan_vtype;
        goto <D.20164>;
        <D.20163>:
        scan_vtype_func (elem, desc, queue);
        elem_size.15 = (sizetype) elem_size;
        elem = elem + elem_size.15;
        <D.20164>:
        if (elem < card_end) goto <D.20163>; else goto <D.20165>;
        <D.20165>:
      }
      goto <D.20299>;
      <D.20296>:
      {
        void (*CopyOrMarkObjectFunc) (void * *, struct SgenGrayQueue *) copy_func;

        D.20300 = sgen_get_current_object_ops ();
        copy_func = D.20300->copy_or_mark_object;
        goto <D.20170>;
        <D.20169>:
        {
          void * new;
          void * old;

          old = MEM[(void * *)elem];
          D.20303 = mod_union != 0;
          D.20304 = old != 0B;
          D.20305 = D.20303 & D.20304;
          if (D.20305 != 0) goto <D.20301>; else goto <D.20306>;
          <D.20306>:
          D.20307 = sgen_ptr_in_nursery (old);
          D.20308 = D.20307 != 0;
          D.20309 = (long int) D.20308;
          D.20310 = __builtin_expect (D.20309, 0);
          if (D.20310 != 0) goto <D.20301>; else goto <D.20302>;
          <D.20301>:
          copy_func (elem, queue);
          new = MEM[(void * *)elem];
          D.20311 = sgen_ptr_in_nursery (new);
          D.20312 = D.20311 != 0;
          D.20313 = (long int) D.20312;
          D.20314 = __builtin_expect (D.20313, 0);
          if (D.20314 != 0) goto <D.20315>; else goto <D.20316>;
          <D.20315>:
          sgen_add_to_global_remset (elem, new);
          <D.20316>:
          <D.20302>:
        }
        elem = elem + 4;
        <D.20170>:
        if (elem < card_end) goto <D.20169>; else goto <D.20171>;
        <D.20171>:
      }
      <D.20299>:
    }
    D.20317 = card_data + 1;
    card_data = find_next_card (D.20317, card_data_end);
    <D.20173>:
    if (card_data < card_data_end) goto <D.20172>; else goto <D.20174>;
    <D.20174>:
  }
  goto <D.20318>;
  <D.20268>:
  if (cards != 0B) goto <D.20319>; else goto <D.20320>;
  <D.20319>:
  obj.11 = (unsigned int) obj;
  D.20321 = sgen_card_table_is_range_marked (cards, obj.11, block_obj_size);
  if (D.20321 != 0) goto <D.20322>; else goto <D.20323>;
  <D.20322>:
  D.20324 = sgen_get_current_object_ops ();
  D.20325 = D.20324->scan_object;
  D.20325 (obj, queue);
  <D.20323>:
  goto <D.20326>;
  <D.20320>:
  obj.11 = (unsigned int) obj;
  D.20327 = sgen_card_table_region_begin_scanning (obj.11, block_obj_size);
  if (D.20327 != 0) goto <D.20328>; else goto <D.20329>;
  <D.20328>:
  D.20330 = sgen_get_current_object_ops ();
  D.20331 = D.20330->scan_object;
  D.20331 (obj, queue);
  <D.20329>:
  <D.20326>:
  <D.20318>:
}


sgen_gc_descr_has_references (mword desc)
{
  unsigned int D.20333;
  gboolean D.20336;
  unsigned int D.20337;
  unsigned int D.20340;

  D.20333 = desc & 4294901767;
  if (D.20333 == 1) goto <D.20334>; else goto <D.20335>;
  <D.20334>:
  D.20336 = 0;
  return D.20336;
  <D.20335>:
  D.20337 = desc & 49159;
  if (D.20337 == 4) goto <D.20338>; else goto <D.20339>;
  <D.20338>:
  D.20336 = 0;
  return D.20336;
  <D.20339>:
  D.20340 = desc & 7;
  if (D.20340 == 7) goto <D.20341>; else goto <D.20342>;
  <D.20341>:
  D.20336 = 0;
  return D.20336;
  <D.20342>:
  D.20336 = 1;
  return D.20336;
}


sgen_par_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  void * D.20344;
  unsigned int D.20345;
  guint D.20350;
  int D.20351;
  int D.20352;
  unsigned int D.20353;
  unsigned int D.20356;
  int D.20357;
  unsigned int D.20358;
  unsigned int element_size.16;
  unsigned int D.20360;
  unsigned int D.20361;
  struct MonoClass * D.20364;
  unsigned char D.20365;
  unsigned int D.20366;
  unsigned int D.20367;
  mword descr;
  mword type;

  D.20344 = vtable->gc_descr;
  descr = (mword) D.20344;
  type = descr & 7;
  D.20345 = type + 4294967295;
  if (D.20345 <= 1) goto <D.20346>; else goto <D.20347>;
  <D.20346>:
  {
    mword size;

    size = descr & 65528;
    if (size == 0) goto <D.20348>; else goto <D.20349>;
    <D.20348>:
    D.20351 = MEM[(struct MonoString *)o].length;
    D.20352 = D.20351 * 2;
    D.20353 = (unsigned int) D.20352;
    D.20350 = D.20353 + 14;
    return D.20350;
    <D.20349>:
    D.20350 = size;
    return D.20350;
  }
  <D.20347>:
  if (type == 4) goto <D.20354>; else goto <D.20355>;
  <D.20354>:
  {
    int element_size;
    struct MonoArray * array;
    size_t size;

    D.20356 = descr >> 3;
    D.20357 = (int) D.20356;
    element_size = D.20357 & 1023;
    array = o;
    D.20358 = array->max_length;
    element_size.16 = (unsigned int) element_size;
    D.20360 = D.20358 * element_size.16;
    size = D.20360 + 16;
    D.20361 = descr & 8192;
    if (D.20361 != 0) goto <D.20362>; else goto <D.20363>;
    <D.20362>:
    size = size + 3;
    size = size & 4294967292;
    D.20364 = vtable->klass;
    D.20365 = D.20364->rank;
    D.20366 = (unsigned int) D.20365;
    D.20367 = D.20366 * 8;
    size = D.20367 + size;
    <D.20363>:
    D.20350 = size;
    return D.20350;
  }
  <D.20355>:
  D.20350 = slow_object_get_size (vtable, o);
  return D.20350;
}


slow_object_get_size (struct MonoVTable * vtable, struct MonoObject * o)
{
  struct MonoClass * D.20369;
  guint D.20372;
  int D.20373;
  int D.20374;
  unsigned int D.20375;
  unsigned char D.20376;
  int D.20379;
  unsigned int D.20380;
  unsigned int D.20381;
  unsigned int D.20382;
  struct MonoArrayBounds * D.20383;
  _Bool D.20384;
  long int D.20385;
  long int D.20386;
  unsigned int D.20389;
  unsigned int D.20390;
  int D.20391;
  struct MonoClass * klass;

  klass = vtable->klass;
  D.20369 = mono_defaults.string_class;
  if (D.20369 == klass) goto <D.20370>; else goto <D.20371>;
  <D.20370>:
  D.20373 = MEM[(struct MonoString *)o].length;
  D.20374 = D.20373 * 2;
  D.20375 = (unsigned int) D.20374;
  D.20372 = D.20375 + 14;
  return D.20372;
  <D.20371>:
  D.20376 = klass->rank;
  if (D.20376 != 0) goto <D.20377>; else goto <D.20378>;
  <D.20377>:
  {
    struct MonoArray * array;
    size_t size;

    array = o;
    D.20379 = klass->sizes.element_size;
    D.20380 = (unsigned int) D.20379;
    D.20381 = array->max_length;
    D.20382 = D.20380 * D.20381;
    size = D.20382 + 16;
    D.20383 = array->bounds;
    D.20384 = D.20383 != 0B;
    D.20385 = (long int) D.20384;
    D.20386 = __builtin_expect (D.20385, 0);
    if (D.20386 != 0) goto <D.20387>; else goto <D.20388>;
    <D.20387>:
    size = size + 3;
    size = size & 4294967292;
    D.20376 = klass->rank;
    D.20389 = (unsigned int) D.20376;
    D.20390 = D.20389 * 8;
    size = D.20390 + size;
    <D.20388>:
    D.20372 = size;
    return D.20372;
  }
  <D.20378>:
  D.20391 = klass->instance_size;
  D.20372 = (guint) D.20391;
  return D.20372;
}


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


sgen_ptr_in_nursery (void * p)
{
  gboolean D.20393;
  int sgen_nursery_bits.17;
  int D.20395;
  int D.20396;
  unsigned int D.20397;
  unsigned int p.18;
  unsigned int D.20399;
  char * sgen_nursery_start.19;
  unsigned int sgen_nursery_start.20;
  _Bool D.20402;

  sgen_nursery_bits.17 = sgen_nursery_bits;
  D.20395 = 1 << sgen_nursery_bits.17;
  D.20396 = -D.20395;
  D.20397 = (unsigned int) D.20396;
  p.18 = (unsigned int) p;
  D.20399 = D.20397 & p.18;
  sgen_nursery_start.19 = sgen_nursery_start;
  sgen_nursery_start.20 = (unsigned int) sgen_nursery_start.19;
  D.20402 = D.20399 == sgen_nursery_start.20;
  D.20393 = (gboolean) D.20402;
  return D.20393;
}


find_next_card (guint8 * card_data, guint8 * end)
{
  unsigned char D.20404;
  guint8 * D.20407;
  unsigned int card_data.21;
  unsigned int D.20409;
  unsigned int end.22;
  unsigned int D.20414;
  int D.20417;
  sizetype D.20418;
  mword * cards;
  mword * cards_end;
  mword card;

  goto <D.20128>;
  <D.20127>:
  D.20404 = *card_data;
  if (D.20404 != 0) goto <D.20405>; else goto <D.20406>;
  <D.20405>:
  D.20407 = card_data;
  return D.20407;
  <D.20406>:
  card_data = card_data + 1;
  <D.20128>:
  card_data.21 = (unsigned int) card_data;
  D.20409 = card_data.21 & 3;
  if (D.20409 != 0) goto <D.20410>; else goto <D.20129>;
  <D.20410>:
  if (card_data < end) goto <D.20127>; else goto <D.20129>;
  <D.20129>:
  if (card_data == end) goto <D.20411>; else goto <D.20412>;
  <D.20411>:
  D.20407 = end;
  return D.20407;
  <D.20412>:
  cards = card_data;
  end.22 = (unsigned int) end;
  D.20414 = end.22 & 4294967292;
  cards_end = (mword *) D.20414;
  goto <D.20131>;
  <D.20130>:
  card = *cards;
  if (card != 0) goto <D.20415>; else goto <D.20416>;
  <D.20415>:
  D.20417 = find_card_offset (card);
  D.20418 = (sizetype) D.20417;
  D.20407 = cards + D.20418;
  return D.20407;
  <D.20416>:
  cards = cards + 4;
  <D.20131>:
  if (cards < cards_end) goto <D.20130>; else goto <D.20132>;
  <D.20132>:
  card_data = cards_end;
  goto <D.20134>;
  <D.20133>:
  D.20404 = *card_data;
  if (D.20404 != 0) goto <D.20419>; else goto <D.20420>;
  <D.20419>:
  D.20407 = card_data;
  return D.20407;
  <D.20420>:
  card_data = card_data + 1;
  <D.20134>:
  if (card_data < end) goto <D.20133>; else goto <D.20135>;
  <D.20135>:
  D.20407 = end;
  return D.20407;
}


find_card_offset (mword card)
{
  sizetype i.23;
  guint8 * D.20423;
  unsigned char D.20424;
  int D.20427;
  unsigned int i.24;
  int i;
  guint8 * ptr;

  ptr = &card;
  i = 0;
  goto <D.20118>;
  <D.20117>:
  i.23 = (sizetype) i;
  D.20423 = ptr + i.23;
  D.20424 = *D.20423;
  if (D.20424 != 0) goto <D.20425>; else goto <D.20426>;
  <D.20425>:
  D.20427 = i;
  return D.20427;
  <D.20426>:
  i = i + 1;
  <D.20118>:
  i.24 = (unsigned int) i;
  if (i.24 <= 3) goto <D.20117>; else goto <D.20119>;
  <D.20119>:
  D.20427 = 0;
  return D.20427;
}


sgen_card_table_is_range_marked (guint8 * cards, mword address, mword size)
{
  unsigned int D.20430;
  guint8 * cards.25;
  unsigned char D.20432;
  gboolean D.20435;
  guint8 * end;

  D.20430 = cards_in_range (address, size);
  end = cards + D.20430;
  goto <D.20050>;
  <D.20049>:
  cards.25 = cards;
  cards = cards.25 + 1;
  D.20432 = *cards.25;
  if (D.20432 != 0) goto <D.20433>; else goto <D.20434>;
  <D.20433>:
  D.20435 = 1;
  return D.20435;
  <D.20434>:
  <D.20050>:
  if (cards != end) goto <D.20049>; else goto <D.20051>;
  <D.20051>:
  D.20435 = 0;
  return D.20435;
}


sgen_card_table_region_begin_scanning (mword start, mword size)
{
  unsigned int D.20437;
  guint8 * card.26;
  unsigned char D.20439;
  guint8 * D.20442;
  unsigned int D.20443;
  gboolean D.20444;
  gboolean res;
  guint8 * card;
  guint8 * end;

  res = 0;
  card = sgen_card_table_get_card_address (start);
  D.20437 = cards_in_range (start, size);
  end = card + D.20437;
  goto <D.20022>;
  <D.20021>:
  card.26 = card;
  card = card.26 + 1;
  D.20439 = *card.26;
  if (D.20439 != 0) goto <D.20440>; else goto <D.20441>;
  <D.20440>:
  res = 1;
  goto <D.20020>;
  <D.20441>:
  <D.20022>:
  if (card != end) goto <D.20021>; else goto <D.20020>;
  <D.20020>:
  D.20442 = sgen_card_table_get_card_address (start);
  D.20443 = size >> 9;
  memset (D.20442, 0, D.20443);
  D.20444 = res;
  return D.20444;
}


sgen_card_table_init (struct SgenRemeberedSet * remset)
{
  void * sgen_cardtable.27;
  struct SgenMajorCollector * D.20447;
  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.20447 = sgen_get_major_collector ();
  need_mod_union.28 = D.20447->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.20449;
  int addr.29;
  int cards_start.30;
  int D.20452;
  int D.20453;
  sizetype D.20454;
  guint8 * D.20455;
  unsigned char D.20456;

  cards_start = sgen_card_table_align_pointer (cards_start);
  addr.29 = (int) addr;
  cards_start.30 = (int) cards_start;
  D.20452 = addr.29 - cards_start.30;
  D.20453 = D.20452 >> 9;
  D.20454 = (sizetype) D.20453;
  D.20455 = cards + D.20454;
  D.20456 = *D.20455;
  D.20449 = (gboolean) D.20456;
  return D.20449;
}


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

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


sgen_card_table_address_is_marked (mword address)
{
  gboolean D.20461;
  guint8 * D.20462;
  unsigned char D.20463;
  _Bool D.20464;

  D.20462 = sgen_card_table_get_card_address (address);
  D.20463 = *D.20462;
  D.20464 = D.20463 != 0;
  D.20461 = (gboolean) D.20464;
  return D.20461;
}


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.20466;
  unsigned int D.20467;

  D.20466 = sgen_card_table_get_card_address (start);
  D.20467 = cards_in_range (start, size);
  memset (D.20466, 0, D.20467);
}


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.20468;
  long long int D.20469;
  int D.20470;
  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.20475;
  long long int D.20476;
  int D.20477;
  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.20468 = btv - atv;
  D.20469 = D.20468 / 10;
  D.20470 = (int) D.20469;
  last_major_scan_time.32 = (long long int) D.20470;
  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.20475 = atv - btv;
  D.20476 = D.20475 / 10;
  D.20477 = (int) D.20476;
  last_los_scan_time.36 = (long long int) D.20477;
  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.20483;

  address.40 = (unsigned int) address;
  D.20483 = sgen_card_table_get_card_address (address.40);
  *D.20483 = 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.20485;

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


sgen_card_table_wbarrier_object_copy (struct MonoObject * obj, struct MonoObject * src)
{
  struct MonoVTable * D.20486;
  struct MonoClass * D.20487;
  struct SgenThreadInfo * sgen_thread_info.42;
  void * D.20489;
  const void * D.20490;
  unsigned int size.43;
  unsigned int D.20492;
  unsigned int obj.44;
  unsigned int size.45;
  int size;

  D.20486 = obj->vtable;
  D.20487 = D.20486->klass;
  size = D.20487->instance_size;
  sgen_thread_info.42 = sgen_thread_info;
  sgen_thread_info.42->in_critical_region = 1;
  mono_memory_barrier ();
  D.20489 = obj + 8;
  D.20490 = src + 8;
  size.43 = (unsigned int) size;
  D.20492 = size.43 + 4294967288;
  mono_gc_memmove_aligned (D.20489, D.20490, D.20492);
  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.20495;
  unsigned int count.46;
  struct SgenThreadInfo * sgen_thread_info.47;
  unsigned int dest.48;
  size_t element_size;
  size_t size;

  D.20495 = mono_class_value_size (klass, 0B);
  element_size = (size_t) D.20495;
  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.20503;
  void * * D.20504;
  sizetype count.50;
  sizetype D.20507;
  sizetype D.20508;
  int need_mod_union.51;
  int D.20513;
  unsigned int dest.52;
  int D.20518;
  void * * dest;
  void * * src;

  dest = dest_ptr;
  src = src_ptr;
  if (src < dest) goto <D.20501>; else goto <D.20499>;
  <D.20501>:
  count.49 = (unsigned int) count;
  D.20503 = count.49 * 4;
  D.20504 = src + D.20503;
  if (D.20504 > dest) goto <D.20505>; else goto <D.20499>;
  <D.20505>:
  {
    void * * start;

    start = dest;
    count.50 = (sizetype) count;
    D.20507 = count.50 + 1073741823;
    D.20508 = D.20507 * 4;
    dest = dest + D.20508;
    count.50 = (sizetype) count;
    D.20507 = count.50 + 1073741823;
    D.20508 = D.20507 * 4;
    src = src + D.20508;
    goto <D.19990>;
    <D.19989>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.51 = need_mod_union;
      if (need_mod_union.51 != 0) goto <D.20509>; else goto <D.20512>;
      <D.20512>:
      D.20513 = sgen_ptr_in_nursery (value);
      if (D.20513 != 0) goto <D.20509>; else goto <D.20510>;
      <D.20509>:
      dest.52 = (unsigned int) dest;
      sgen_card_table_mark_address (dest.52);
      <D.20510>:
      sgen_dummy_use (value);
    }
    src = src + 4294967292;
    dest = dest + 4294967292;
    <D.19990>:
    if (dest >= start) goto <D.19989>; else goto <D.19991>;
    <D.19991>:
  }
  goto <D.20500>;
  <D.20499>:
  {
    void * * end;

    count.49 = (unsigned int) count;
    D.20503 = count.49 * 4;
    end = dest + D.20503;
    goto <D.19995>;
    <D.19994>:
    {
      void * value;

      value = *src;
      *dest = value;
      need_mod_union.51 = need_mod_union;
      if (need_mod_union.51 != 0) goto <D.20515>; else goto <D.20517>;
      <D.20517>:
      D.20518 = sgen_ptr_in_nursery (value);
      if (D.20518 != 0) goto <D.20515>; else goto <D.20516>;
      <D.20515>:
      dest.52 = (unsigned int) dest;
      sgen_card_table_mark_address (dest.52);
      <D.20516>:
      sgen_dummy_use (value);
    }
    src = src + 4;
    dest = dest + 4;
    <D.19995>:
    if (dest < end) goto <D.19994>; else goto <D.19996>;
    <D.19996>:
  }
  <D.20500>:
}


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.20523;
  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.20519>; else goto <D.20522>;
  <D.20522>:
  D.20523 = sgen_ptr_in_nursery (value);
  if (D.20523 != 0) goto <D.20519>; else goto <D.20520>;
  <D.20519>:
  slot_ptr.54 = (unsigned int) slot_ptr;
  sgen_card_table_mark_address (slot_ptr.54);
  <D.20520>:
  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.20529;
  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.20525>; else goto <D.20528>;
  <D.20528>:
  D.20529 = sgen_ptr_in_nursery (value);
  if (D.20529 != 0) goto <D.20525>; else goto <D.20526>;
  <D.20525>:
  field_ptr.56 = (unsigned int) field_ptr;
  sgen_card_table_mark_address (field_ptr.56);
  <D.20526>:
  sgen_dummy_use (value);
}


