Beispiel #1
0
/* Converts an IRExpr into 1 or 2 "flat" expressions of type Int */
static void packToI32 ( IRSB* sb, IRExpr* e, IRExpr* res[2]) {
  //IRType eType = Ity_I32;
  IRTemp tmp64;
  res[1]=NULL;
  switch (typeOfIRExpr(sb->tyenv,e)) {
    case Ity_I1:   res[0]= IRExpr_Unop(Iop_1Uto32,e);  break;
    case Ity_I8:   res[0]= IRExpr_Unop(Iop_8Uto32,e);  break;
    case Ity_I16:  res[0]= IRExpr_Unop(Iop_16Uto32,e); break;
    case Ity_I32:  res[0]= e; return;
    case Ity_F32:  res[0]= IRExpr_Unop(Iop_ReinterpF32asI32,e); break;
    case Ity_I64:
      res[0]= IRExpr_Unop(Iop_64to32, e);
      res[1]= IRExpr_Unop(Iop_64HIto32, e);
      break;
    case Ity_F64:
      tmp64 = newIRTemp(sb->tyenv, Ity_I64);
      addStmtToIRSB(sb, IRStmt_WrTmp(tmp64, IRExpr_Unop(Iop_ReinterpF64asI64,e)));
      res[0]= IRExpr_Unop(Iop_64to32,   IRExpr_RdTmp(tmp64) );
      res[1]= IRExpr_Unop(Iop_64HIto32, IRExpr_RdTmp(tmp64) );
      break;
    case Ity_V128:   /* 128-bit SIMD */
    case Ity_I128:   /* 128-bit scalar */
    case Ity_INVALID:
    default: VG_(tool_panic)("COJAC cannot packToI32..."); break;
  }
  IRTemp myArg = newIRTemp(sb->tyenv, Ity_I32);
  addStmtToIRSB(sb, IRStmt_WrTmp(myArg, res[0]));
  res[0]=IRExpr_RdTmp(myArg);    // now that's a "flat" expression
  if (res[1]==NULL) return;
  IRTemp myArg2 = newIRTemp(sb->tyenv, Ity_I32);
  addStmtToIRSB(sb, IRStmt_WrTmp(myArg2, res[1]));
  res[1]=IRExpr_RdTmp(myArg2);   // now that's a "flat" expression
}
Beispiel #2
0
/* Converts an IRExpr into 1 or 2 "flat" expressions of type Long */
static void packToI64 ( IRSB* sb, IRExpr* e, IRExpr* res[2], IROp irop) {
  res[1]=NULL;  // won't be used at all
  IRTemp tmp64;
  switch (typeOfIRExpr(sb->tyenv,e)) {
    case Ity_I1:   res[0]= IRExpr_Unop(Iop_1Uto64,e);  break;
    case Ity_I8:   res[0]= IRExpr_Unop(Iop_8Uto64,e);  break;
    case Ity_I16:  res[0]= IRExpr_Unop(Iop_16Uto64,e); break;
    case Ity_I32:  res[0]= IRExpr_Unop(Iop_32Uto64,e); break;
    case Ity_F32:  e = IRExpr_Unop(Iop_ReinterpF32asI32,e);
                   res[0]= IRExpr_Unop(Iop_32Uto64,e);  break;
    case Ity_I64:  res[0]= e; return;
    case Ity_F64:  res[0]= IRExpr_Unop(Iop_ReinterpF64asI64,e); break;
    case Ity_V128:   /* 128-bit SIMD */
        //tmp64 = newIRTemp(sb->tyenv, Ity_I64);
        //addStmtToIRSB(sb, IRStmt_WrTmp(tmp64, IRExpr_Unop(Iop_V128to64,e)));
        //res[0]= IRExpr_Unop(Iop_64to32,   IRExpr_RdTmp(tmp64) );
        //res[1]= IRExpr_Unop(Iop_64HIto32, IRExpr_RdTmp(tmp64) );
    	res[0]= IRExpr_Unop(Iop_V128to64,   e );
    	if (dropV128HiPart(irop)) break;
    	res[1]= IRExpr_Unop(Iop_V128HIto64, e );
    	break;

    case Ity_I128:   /* 128-bit scalar */
    case Ity_INVALID:
    default: VG_(tool_panic)("COJAC cannot packToI64..."); break;
  }
  IRTemp myArg = newIRTemp(sb->tyenv, Ity_I64);
  addStmtToIRSB(sb, IRStmt_WrTmp(myArg, res[0]));
  res[0]=IRExpr_RdTmp(myArg);  // now that's a "flat" expression
  if (res[1]==NULL) return;  // ... else it was 128-bit SIMD
  IRTemp myArg2 = newIRTemp(sb->tyenv, Ity_I64);
  addStmtToIRSB(sb, IRStmt_WrTmp(myArg2, res[1]));
  res[1]=IRExpr_RdTmp(myArg2);   // now that's a "flat" expression
}
Beispiel #3
0
static IRExpr* assignNew_HWord(IRSB* sb_out, IRExpr* expr)
{
    IRTemp tmp = newIRTemp(sb_out->tyenv, Ity_I32);

    switch (typeOfIRExpr(sb_out->tyenv, expr))
    {
        case Ity_I1:
            addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_1Uto32, expr)));
            break;
        case Ity_I8:
            addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_8Uto32, expr)));
            break;
        case Ity_I16:
            addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_16Uto32, expr)));
            break;
        case Ity_I32:
            addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, expr));
            break;
        case Ity_I64:
            addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_64to32, expr)));
            break;
        default:
            VG_(tool_panic)("assignNew_HWord");
   }

    return IRExpr_RdTmp(tmp);
}
Beispiel #4
0
/*
    Bind the given expression to a new temporary, and return the temporary.
    This effectively converts an arbitrary expression into an IRAtom.
*/
static IRExpr* assignNew(IRSB* sb_out, IRExpr* expr)
{
    IRTemp tmp = newIRTemp(sb_out->tyenv, typeOfIRExpr(sb_out->tyenv, expr));

    addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, expr));

    return IRExpr_RdTmp(tmp);
}
Beispiel #5
0
static IRAtom* assignNew ( IRSB* sb, IRExpr* e )
{
   IRTemp   t;
   IRType   ty = typeOfIRExpr(sb->tyenv, e);

   t = newIRTemp(sb->tyenv, ty);
   assign(sb, t, e);
   return mkexpr(t);
}
Beispiel #6
0
PyObject *pyIRTypeEnv_newTemp(pyIRTypeEnv *self, PyObject *type)
{
	IRType t;
	const char *t_str = PyString_AsString(type);
	if (!t_str) { PyErr_SetString(VexException, "Unrecognized type argument to IRTypeEnv.newTemp"); return NULL; }
	PYVEX_ENUM_FROMSTR(IRType, t, t_str, return NULL);

	return PyInt_FromLong(newIRTemp(self->wrapped, t));
}
/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
   both the table in pce->sb and to our auxiliary mapping.  Note that
   newTemp may cause pce->tmpMap to resize, hence previous results
   from VG_(indexXA)(pce->tmpMap) are invalidated. */
static IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind )
{
   Word       newIx;
   TempMapEnt ent;
   IRTemp     tmp = newIRTemp(pce->sb->tyenv, ty);
   ent.kind   = kind;
   ent.shadow = IRTemp_INVALID;
   newIx = VG_(addToXA)( pce->qmpMap, &ent );
   tl_assert(newIx == (Word)tmp);
   return tmp;
}
Beispiel #8
0
static IRSB *
bcg_instrument(VgCallbackClosure* closure,
	       IRSB* bb,
	       VexGuestLayout* layout,
	       VexGuestExtents* vge,
	       IRType gWordTy,
	       IRType hWordTy)
{
	unsigned long rip = 0;
	int i;

	if (bb->jumpkind != Ijk_Ret &&
	    bb->next->tag != Iex_Const) {
		IRTemp tmp;

		for (i = bb->stmts_used - 1; i >= 0; i--) {
			if (bb->stmts[i]->tag == Ist_IMark) {
				rip = bb->stmts[i]->Ist.IMark.addr;
				break;
			}
		}
		tl_assert(i >= 0);
		if (bb->next->tag == Iex_RdTmp) {
			tmp = bb->next->Iex.RdTmp.tmp;
		} else {
			tmp = newIRTemp(bb->tyenv, Ity_I64);
			addStmtToIRSB(bb,
				      IRStmt_WrTmp(tmp, bb->next));
			bb->next = IRExpr_RdTmp(tmp);
		}
		addStmtToIRSB(bb,
			      IRStmt_Dirty(
				      unsafeIRDirty_0_N(
					      0,
					      "log_call",
					      log_call,
					      mkIRExprVec_3(
						      IRExpr_Const(IRConst_U64(rip)),
						      IRExpr_Const(IRConst_U64(bb->jumpkind == Ijk_Call)),
						      bb->next))));
	}

	return bb;
}
Beispiel #9
0
static IRExpr *
log_reads_expr(unsigned tid, IRSB *sb, IRExpr *exp)
{
	if (!exp)
		return NULL;

	switch (exp->tag) {
	case Iex_Get:
	case Iex_FreeVariable:
	case Iex_EntryPoint:
	case Iex_ControlFlow:
		return exp;
	case Iex_GetI: {
		IRExprGetI *e = (IRExprGetI *)exp;
		return IRExpr_GetI(e->descr,
				   log_reads_expr(tid, sb, e->ix),
				   e->bias,
				   e->tid);
	}
	case Iex_Qop: {
		IRExprQop *e = (IRExprQop *)exp;
		return IRExpr_Qop(e->op,
				  log_reads_expr(tid, sb, e->arg1),
				  log_reads_expr(tid, sb, e->arg2),
				  log_reads_expr(tid, sb, e->arg3),
				  log_reads_expr(tid, sb, e->arg4));
	}
	case Iex_Triop: {
		IRExprTriop *e = (IRExprTriop *)exp;
		return IRExpr_Triop(e->op,
				    log_reads_expr(tid, sb, e->arg1),
				    log_reads_expr(tid, sb, e->arg2),
				    log_reads_expr(tid, sb, e->arg3));
	}
	case Iex_Binop: {
		IRExprBinop *e = (IRExprBinop *)exp;
		return IRExpr_Binop(e->op,
				    log_reads_expr(tid, sb, e->arg1),
				    log_reads_expr(tid, sb, e->arg2));
	}
	case Iex_Associative: {
		IRExprAssociative *e = (IRExprAssociative *)exp;
		IRExpr **newArgs = alloc_irexpr_array(e->nr_arguments);
		for (int x = 0;
		     x < e->nr_arguments;
		     x++)
			newArgs[x] =
				log_reads_expr(tid, sb, e->contents[x]);
		return IRExpr_Associative_Claim(e->op, e->nr_arguments, newArgs);
	}
	case Iex_Unop: {
		IRExprUnop *e = (IRExprUnop *)exp;
		return IRExpr_Unop(e->op,
				   log_reads_expr(tid, sb, e->arg));
	}
	case Iex_Load: {
		IRExprLoad *e = (IRExprLoad *)exp;
		IRExpr **args;
		void *helper;
		const char *helper_name;
		IRTemp dest;
		IRDirty *f;

		assert(e->addr->type() == Ity_I64);

		/* Shut compiler up */
		helper = (void *)0xf001;
		helper_name = (const char *)0xdead;

#define HLP(x) helper_name = "helper_load_" #x ; helper = (void *)helper_load_ ## x ;
		switch (e->ty) {
		case Ity_INVALID:
			abort();
		case Ity_I1:
			abort();
		case Ity_I8:
			HLP(8);
			break;
		case Ity_I16:
			HLP(16);
			break;
		case Ity_I32:
			HLP(32);
			break;
		case Ity_I64:
			HLP(64);
			break;
		case Ity_I128:
			HLP(128);
			break;
		}
#undef HLP

		args = mkIRExprVec_3(log_reads_expr(tid, sb, e->addr),
				     IRExpr_Get(OFFSET_amd64_RSP, Ity_I64, tid, 0),
				     IRExpr_Get(OFFSET_amd64_RIP, Ity_I64, tid, 0));
		dest = newIRTemp(sb->tyenv);
		f = unsafeIRDirty_1_N(threadAndRegister::temp(tid, dest, 0),
				      0,
				      helper_name,
				      helper,
				      args);
		addStmtToIRSB(sb, IRStmt_Dirty(f));
		return IRExpr_RdTmp(dest, e->ty, tid, 0);
	}
	case Iex_Const:
		return exp;
	case Iex_CCall: {
		IRExprCCall *e = (IRExprCCall *)exp;
		IRExpr **args;
		int x;
		int nr_args;
		for (nr_args = 0; e->args[nr_args]; nr_args++)
			;
		args = alloc_irexpr_array(nr_args + 1);
		args[nr_args] = NULL;
		for (x = 0; x < nr_args; x++)
			args[x] = log_reads_expr(tid, sb, e->args[x]);
		return IRExpr_CCall(e->cee,
				    e->retty,
				    args);
	}
	case Iex_Mux0X: {
		IRExprMux0X *e = (IRExprMux0X *)exp;
		return IRExpr_Mux0X(log_reads_expr(tid, sb, e->cond),
				    log_reads_expr(tid, sb, e->expr0),
				    log_reads_expr(tid, sb, e->exprX));
	}
	case Iex_HappensBefore:
		abort();
	}
	abort();
}
Beispiel #10
0
IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
                 /*IN*/ void*            callback_opaque,
                 /*IN*/ DisOneInstrFn    dis_instr_fn,
                 /*IN*/ UChar*           guest_code,
                 /*IN*/ Addr64           guest_IP_bbstart,
                 /*IN*/ Bool             (*chase_into_ok)(void*,Addr64),
                 /*IN*/ Bool             host_bigendian,
                 /*IN*/ VexArch          arch_guest,
                 /*IN*/ VexArchInfo*     archinfo_guest,
                 /*IN*/ IRType           guest_word_type,
                 /*IN*/ Bool             do_self_check,
                 /*IN*/ Bool             (*preamble_function)(void*,IRBB*),
                 /*IN*/ Int              offB_TISTART,
                 /*IN*/ Int              offB_TILEN )
{
   Long       delta;
   Int        i, n_instrs, first_stmt_idx;
   Bool       resteerOK, need_to_put_IP, debug_print;
   DisResult  dres;
   IRStmt*    imark;
   static Int n_resteers = 0;
   Int        d_resteers = 0;
   Int        selfcheck_idx = 0;
   IRBB*      irbb;
   Addr64     guest_IP_curr_instr;
   IRConst*   guest_IP_bbstart_IRConst = NULL;

   Bool (*resteerOKfn)(void*,Addr64) = NULL;

   debug_print = toBool(vex_traceflags & VEX_TRACE_FE);

   /* Note: for adler32 to work without % operation for the self
      check, need to limit length of stuff it scans to 5552 bytes.
      Therefore limiting the max bb len to 100 insns seems generously
      conservative. */

   /* check sanity .. */
   vassert(sizeof(HWord) == sizeof(void*));
   vassert(vex_control.guest_max_insns >= 1);
   vassert(vex_control.guest_max_insns < 100);
   vassert(vex_control.guest_chase_thresh >= 0);
   vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
   vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64);

   /* Start a new, empty extent. */
   vge->n_used  = 1;
   vge->base[0] = guest_IP_bbstart;
   vge->len[0]  = 0;

   /* And a new IR BB to dump the result into. */
   irbb = emptyIRBB();

   /* Delta keeps track of how far along the guest_code array we have
      so far gone. */
   delta    = 0;
   n_instrs = 0;

   /* Guest addresses as IRConsts.  Used in the two self-checks
      generated. */
   if (do_self_check) {
      guest_IP_bbstart_IRConst
         = guest_word_type==Ity_I32 
              ? IRConst_U32(toUInt(guest_IP_bbstart))
              : IRConst_U64(guest_IP_bbstart);
   }

   /* If asked to make a self-checking translation, leave 5 spaces
      in which to put the check statements.  We'll fill them in later
      when we know the length and adler32 of the area to check. */
   if (do_self_check) {
      selfcheck_idx = irbb->stmts_used;
      addStmtToIRBB( irbb, IRStmt_NoOp() );
      addStmtToIRBB( irbb, IRStmt_NoOp() );
      addStmtToIRBB( irbb, IRStmt_NoOp() );
      addStmtToIRBB( irbb, IRStmt_NoOp() );
      addStmtToIRBB( irbb, IRStmt_NoOp() );
   }

   /* If the caller supplied a function to add its own preamble, use
      it now. */
   if (preamble_function) {
      Bool stopNow = preamble_function( callback_opaque, irbb );
      if (stopNow) {
         /* The callback has completed the IR block without any guest
            insns being disassembled into it, so just return it at
            this point, even if a self-check was requested - as there
            is nothing to self-check.  The five self-check no-ops will
            still be in place, but they are harmless. */
         return irbb;
      }
   }

   /* Process instructions. */
   while (True) {
      vassert(n_instrs < vex_control.guest_max_insns);

      /* Regardless of what chase_into_ok says, is chasing permissible
         at all right now?  Set resteerOKfn accordingly. */
      resteerOK 
         = toBool(
              n_instrs < vex_control.guest_chase_thresh
              /* If making self-checking translations, don't chase
                 .. it makes the checks too complicated.  We only want
                 to scan just one sequence of bytes in the check, not
                 a whole bunch. */
              && !do_self_check
              /* we can't afford to have a resteer once we're on the
                 last extent slot. */
              && vge->n_used < 3
           );

      resteerOKfn
         = resteerOK ? chase_into_ok : const_False;

      /* This is the IP of the instruction we're just about to deal
         with. */
      guest_IP_curr_instr = guest_IP_bbstart + delta;

      /* This is the irbb statement array index of the first stmt in
         this insn.  That will always be the instruction-mark
         descriptor. */
      first_stmt_idx = irbb->stmts_used;

      /* Add an instruction-mark statement.  We won't know until after
         disassembling the instruction how long it instruction is, so
         just put in a zero length and we'll fix it up later. */
      addStmtToIRBB( irbb, IRStmt_IMark( guest_IP_curr_instr, 0 ));

      /* for the first insn, the dispatch loop will have set
         %IP, but for all the others we have to do it ourselves. */
      need_to_put_IP = toBool(n_instrs > 0);

      /* Finally, actually disassemble an instruction. */
      dres = dis_instr_fn ( irbb,
                            need_to_put_IP,
                            resteerOKfn,
                            callback_opaque,
                            guest_code,
                            delta,
                            guest_IP_curr_instr,
                            arch_guest,
                            archinfo_guest,
                            host_bigendian );

      /* stay sane ... */
      vassert(dres.whatNext == Dis_StopHere
              || dres.whatNext == Dis_Continue
              || dres.whatNext == Dis_Resteer);
      vassert(dres.len >= 0 && dres.len <= 20);
      if (dres.whatNext != Dis_Resteer)
         vassert(dres.continueAt == 0);

      /* Fill in the insn-mark length field. */
      vassert(first_stmt_idx >= 0 && first_stmt_idx < irbb->stmts_used);
      imark = irbb->stmts[first_stmt_idx];
      vassert(imark);
      vassert(imark->tag == Ist_IMark);
      vassert(imark->Ist.IMark.len == 0);
      imark->Ist.IMark.len = toUInt(dres.len);

      /* Print the resulting IR, if needed. */
      if (vex_traceflags & VEX_TRACE_FE) {
         for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
            vex_printf("              ");
            ppIRStmt(irbb->stmts[i]);
            vex_printf("\n");
         }
      }

      /* If dis_instr_fn terminated the BB at this point, check it
	 also filled in the irbb->next field. */
      if (dres.whatNext == Dis_StopHere) {
         vassert(irbb->next != NULL);
         if (debug_print) {
            vex_printf("              ");
            vex_printf( "goto {");
            ppIRJumpKind(irbb->jumpkind);
            vex_printf( "} ");
            ppIRExpr( irbb->next );
            vex_printf( "\n");
         }
      }

      /* Update the VexGuestExtents we are constructing. */
      /* If vex_control.guest_max_insns is required to be < 100 and
	 each insn is at max 20 bytes long, this limit of 5000 then
	 seems reasonable since the max possible extent length will be
	 100 * 20 == 2000. */
      vassert(vge->len[vge->n_used-1] < 5000);
      vge->len[vge->n_used-1] 
         = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
      n_instrs++;
      if (debug_print) 
         vex_printf("\n");

      /* Advance delta (inconspicuous but very important :-) */
      delta += (Long)dres.len;

      switch (dres.whatNext) {
         case Dis_Continue:
            vassert(irbb->next == NULL);
            if (n_instrs < vex_control.guest_max_insns) {
               /* keep going */
            } else {
               /* We have to stop. */
               irbb->next 
                  = IRExpr_Const(
                       guest_word_type == Ity_I32
                          ? IRConst_U32(toUInt(guest_IP_bbstart+delta))
                          : IRConst_U64(guest_IP_bbstart+delta)
                    );
               goto done;
            }
            break;
         case Dis_StopHere:
            vassert(irbb->next != NULL);
            goto done;
         case Dis_Resteer:
            /* Check that we actually allowed a resteer .. */
            vassert(resteerOK);
            vassert(irbb->next == NULL);
            /* figure out a new delta to continue at. */
            vassert(resteerOKfn(callback_opaque,dres.continueAt));
            delta = dres.continueAt - guest_IP_bbstart;
            /* we now have to start a new extent slot. */
            vge->n_used++;
            vassert(vge->n_used <= 3);
            vge->base[vge->n_used-1] = dres.continueAt;
            vge->len[vge->n_used-1] = 0;
            n_resteers++;
            d_resteers++;
            if (0 && (n_resteers & 0xFF) == 0)
            vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
                       n_resteers, d_resteers,
                       dres.continueAt, delta);
            break;
         default:
            vpanic("bb_to_IR");
      }
   }
   /*NOTREACHED*/
   vassert(0);

  done:
   /* We're done.  The only thing that might need attending to is that
      a self-checking preamble may need to be created. */
   if (do_self_check) {

      UInt     len2check, adler32;
      IRTemp   tistart_tmp, tilen_tmp;

      vassert(vge->n_used == 1);
      len2check = vge->len[0];
      if (len2check == 0) 
         len2check = 1;

     adler32 = genericg_compute_adler32( (HWord)guest_code, len2check );

     /* Set TISTART and TILEN.  These will describe to the despatcher
        the area of guest code to invalidate should we exit with a
        self-check failure. */

     tistart_tmp = newIRTemp(irbb->tyenv, guest_word_type);
     tilen_tmp   = newIRTemp(irbb->tyenv, guest_word_type);

     irbb->stmts[selfcheck_idx+0]
        = IRStmt_Tmp(tistart_tmp, IRExpr_Const(guest_IP_bbstart_IRConst) );

     irbb->stmts[selfcheck_idx+1]
        = IRStmt_Tmp(tilen_tmp,
                     guest_word_type==Ity_I32 
                        ? IRExpr_Const(IRConst_U32(len2check)) 
                        : IRExpr_Const(IRConst_U64(len2check))
          );

     irbb->stmts[selfcheck_idx+2]
        = IRStmt_Put( offB_TISTART, IRExpr_Tmp(tistart_tmp) );

     irbb->stmts[selfcheck_idx+3]
        = IRStmt_Put( offB_TILEN, IRExpr_Tmp(tilen_tmp) );

     irbb->stmts[selfcheck_idx+4]
        = IRStmt_Exit( 
             IRExpr_Binop( 
                Iop_CmpNE32, 
                mkIRExprCCall( 
                   Ity_I32, 
                   2/*regparms*/, 
                   "genericg_compute_adler32",
#if defined(__powerpc__) && defined(__powerpc64__)
                   (void*)((ULong*)(&genericg_compute_adler32))[0],
#else
                   &genericg_compute_adler32,
#endif
                   mkIRExprVec_2( 
                      mkIRExpr_HWord( (HWord)guest_code ), 
                      mkIRExpr_HWord( (HWord)len2check )
                   )
                ),
                IRExpr_Const(IRConst_U32(adler32))
             ),
             Ijk_TInval,
             guest_IP_bbstart_IRConst
          );
   }

   return irbb;
}