vg_assert(instr_size >= 1 && instr_size <= MAX_x86_INSTR_SIZE);
vg_assert(0 != instr_addr);
- /* Save the caller-save registers before we push our args */
- uInstr1(cb, PUSH, 4, RealReg, R_EAX);
- uInstr1(cb, PUSH, 4, RealReg, R_ECX);
- uInstr1(cb, PUSH, 4, RealReg, R_EDX);
-
if (!IS_(read) && !IS_(write)) {
iCC* CC_ptr = (iCC*)(BBCC_ptr);
vg_assert(INVALID_DATA_SIZE == data_size);
if (!BB_seen_before)
init_iCC(CC_ptr, instr_addr, instr_size);
- helper = VGOFF_(cachesim_log_non_mem_instr);
+ /* 1st arg: CC addr */
+ t_CC_addr = newTemp(cb);
+ uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr);
+ uLiteral(cb, BBCC_ptr);
+
+ uInstr1(cb, CCALL_1_0, 0, TempReg, t_CC_addr);
+ uLiteral(cb, VGOFF_(cachesim_log_non_mem_instr));
} else {
CC_type X_CC;
INVALID_TEMPREG != t_write_addr);
t_data_addr = t_read_addr;
}
-
+#undef IS_
if (!BB_seen_before)
init_idCC(X_CC, CC_ptr, instr_addr, instr_size, data_size);
- /* 2nd arg: data addr */
- uInstr1(cb, PUSH, 4, TempReg, t_data_addr);
- stack_used += 4;
- }
-#undef IS_
+ /* 1st arg: CC addr */
+ t_CC_addr = newTemp(cb);
+ uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr);
+ uLiteral(cb, BBCC_ptr);
- /* 1st arg: CC addr */
- t_CC_addr = newTemp(cb);
- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr);
- uLiteral(cb, BBCC_ptr);
- uInstr1(cb, PUSH, 4, TempReg, t_CC_addr);
- stack_used += 4;
-
- /* Call function and return. */
- uInstr1(cb, CALLM, 0, Lit16, helper);
- uInstr1(cb, CLEAR, 0, Lit16, stack_used);
-
- /* Restore the caller-save registers now the call is done */
- uInstr1(cb, POP, 4, RealReg, R_EDX);
- uInstr1(cb, POP, 4, RealReg, R_ECX);
- uInstr1(cb, POP, 4, RealReg, R_EAX);
+ uInstr2(cb, CCALL_2_0, 0, TempReg, t_CC_addr,
+ TempReg, t_data_addr);
+ uLiteral(cb, VGOFF_(cachesim_log_mem_instr));
+ }
VG_(copyUInstr)(cb, u_in);
if (is_miss) { MISS_TREATMENT; } \
\
} else { \
+ VG_(printf)("addr: %x size: %u sets: %d %d", a, size, set1, set2); \
VG_(panic)("item straddles more than two cache sets"); \
} \
return; \
emit_call_star_EBP_off ( 4 * word_offset );
}
+static void synth_ccall_saveRegs ( void )
+{
+ emit_pushv_reg ( 4, R_EAX );
+ emit_pushv_reg ( 4, R_ECX );
+ emit_pushv_reg ( 4, R_EDX );
+}
+
+static void synth_ccall_pushOneArg ( Int r1 )
+{
+ emit_pushv_reg ( 4, r1 );
+}
+
+static void synth_ccall_pushTwoArgs ( Int r1, Int r2 )
+{
+ /* must push in reverse order */
+ emit_pushv_reg ( 4, r2 );
+ emit_pushv_reg ( 4, r1 );
+}
+
+/* Synthesise a call to *baseBlock[offset], ie,
+ call * (4 x offset)(%ebp) with arguments
+*/
+static void synth_ccall_call_clearStack_restoreRegs ( Int word_offset,
+ UInt n_args_bytes )
+{
+ vg_assert(word_offset >= 0);
+ vg_assert(word_offset < VG_BASEBLOCK_WORDS);
+ vg_assert(n_args_bytes <= 12); /* Max 3 word-sized args */
+ vg_assert(0 == (n_args_bytes & 0x3)); /* Divisible by four */
+
+ emit_call_star_EBP_off ( 4 * word_offset );
+ if ( 0 != n_args_bytes )
+ emit_add_lit_to_esp ( n_args_bytes );
+ emit_popv_reg ( 4, R_EDX );
+ emit_popv_reg ( 4, R_ECX );
+ emit_popv_reg ( 4, R_EAX );
+}
static void load_ebp_from_JmpKind ( JmpKind jmpkind )
{
emit_put_eflags();
break;
+ case CCALL_1_0:
+ vg_assert(u->tag1 == RealReg);
+ vg_assert(u->tag2 == NoValue);
+ vg_assert(u->size == 0);
+
+ synth_ccall_saveRegs();
+ synth_ccall_pushOneArg ( u->val1 );
+ synth_ccall_call_clearStack_restoreRegs ( u->lit32, 4 );
+ break;
+
+ case CCALL_2_0:
+ vg_assert(u->tag1 == RealReg);
+ vg_assert(u->tag2 == RealReg);
+ vg_assert(u->size == 0);
+
+ synth_ccall_saveRegs();
+ synth_ccall_pushTwoArgs ( u->val1, u->val2 );
+ synth_ccall_call_clearStack_restoreRegs ( u->lit32, 8 );
+ break;
+
case CLEAR:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);
PUSH, POP, CLEAR, /* Add/remove/zap args for helpers. */
CALLM, /* call to a machine-code helper */
+ /* for calling C functions -- CCALL_M_N passes M arguments and returns N
+ * (0 or 1) return values */
+ CCALL_1_0, CCALL_2_0,
+
/* Hack for translating string (REP-) insns. Jump to literal if
TempReg/RealReg is zero. */
JIFZ,
return CC0 && Ls1 && N2 && SZ0 && N3;
case CALLM:
return SZ0 && Ls1 && N2 && N3;
+ case CCALL_1_0:
+ return SZ0 && CC0 && TR1 && N2 && N3;
+ case CCALL_2_0:
+ return SZ0 && CC0 && TR1 && TR2 && N3;
case PUSH: case POP:
return CC0 && TR1 && N2 && N3;
case AND: case OR:
case JMP: return "J" ;
case JIFZ: return "JIFZ" ;
case CALLM: return "CALLM";
+ case CCALL_1_0: return "CCALL_1_0";
+ case CCALL_2_0: return "CCALL_2_0";
case PUSH: return "PUSH" ;
case POP: return "POP" ;
case CLEAR: return "CLEAR";
ppUOperand(u, 1, u->size, False);
break;
+ case CCALL_1_0:
+ VG_(printf)(" ");
+ ppUOperand(u, 1, 0, False);
+ VG_(printf)(" (%u)", u->lit32);
+ break;
+
+ case CCALL_2_0:
+ VG_(printf)(" ");
+ ppUOperand(u, 1, 0, False);
+ VG_(printf)(", ");
+ ppUOperand(u, 2, 0, False);
+ VG_(printf)(" (%u)", u->lit32);
+ break;
+
case JIFZ:
VG_(printf)("\t");
ppUOperand(u, 1, u->size, False);
case GET: WR(2); break;
case PUT: RD(1); break;
case LOAD: RD(1); WR(2); break;
- case STORE: RD(1); RD(2); break;
+ case STORE: case CCALL_2_0: RD(1); RD(2); break;
case MOV: RD(1); WR(2); break;
case JMP: RD(1); break;
case CLEAR: case CALLM: break;
- case PUSH: RD(1); break;
+ case PUSH: case CCALL_1_0: RD(1); break;
case POP: WR(1); break;
case TAG2:
vg_assert(instr_size >= 1 && instr_size <= MAX_x86_INSTR_SIZE);
vg_assert(0 != instr_addr);
- /* Save the caller-save registers before we push our args */
- uInstr1(cb, PUSH, 4, RealReg, R_EAX);
- uInstr1(cb, PUSH, 4, RealReg, R_ECX);
- uInstr1(cb, PUSH, 4, RealReg, R_EDX);
-
if (!IS_(read) && !IS_(write)) {
iCC* CC_ptr = (iCC*)(BBCC_ptr);
vg_assert(INVALID_DATA_SIZE == data_size);
if (!BB_seen_before)
init_iCC(CC_ptr, instr_addr, instr_size);
- helper = VGOFF_(cachesim_log_non_mem_instr);
+ /* 1st arg: CC addr */
+ t_CC_addr = newTemp(cb);
+ uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr);
+ uLiteral(cb, BBCC_ptr);
+
+ uInstr1(cb, CCALL_1_0, 0, TempReg, t_CC_addr);
+ uLiteral(cb, VGOFF_(cachesim_log_non_mem_instr));
} else {
CC_type X_CC;
INVALID_TEMPREG != t_write_addr);
t_data_addr = t_read_addr;
}
-
+#undef IS_
if (!BB_seen_before)
init_idCC(X_CC, CC_ptr, instr_addr, instr_size, data_size);
- /* 2nd arg: data addr */
- uInstr1(cb, PUSH, 4, TempReg, t_data_addr);
- stack_used += 4;
- }
-#undef IS_
+ /* 1st arg: CC addr */
+ t_CC_addr = newTemp(cb);
+ uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr);
+ uLiteral(cb, BBCC_ptr);
- /* 1st arg: CC addr */
- t_CC_addr = newTemp(cb);
- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr);
- uLiteral(cb, BBCC_ptr);
- uInstr1(cb, PUSH, 4, TempReg, t_CC_addr);
- stack_used += 4;
-
- /* Call function and return. */
- uInstr1(cb, CALLM, 0, Lit16, helper);
- uInstr1(cb, CLEAR, 0, Lit16, stack_used);
-
- /* Restore the caller-save registers now the call is done */
- uInstr1(cb, POP, 4, RealReg, R_EDX);
- uInstr1(cb, POP, 4, RealReg, R_ECX);
- uInstr1(cb, POP, 4, RealReg, R_EAX);
+ uInstr2(cb, CCALL_2_0, 0, TempReg, t_CC_addr,
+ TempReg, t_data_addr);
+ uLiteral(cb, VGOFF_(cachesim_log_mem_instr));
+ }
VG_(copyUInstr)(cb, u_in);
if (is_miss) { MISS_TREATMENT; } \
\
} else { \
+ VG_(printf)("addr: %x size: %u sets: %d %d", a, size, set1, set2); \
VG_(panic)("item straddles more than two cache sets"); \
} \
return; \
emit_call_star_EBP_off ( 4 * word_offset );
}
+static void synth_ccall_saveRegs ( void )
+{
+ emit_pushv_reg ( 4, R_EAX );
+ emit_pushv_reg ( 4, R_ECX );
+ emit_pushv_reg ( 4, R_EDX );
+}
+
+static void synth_ccall_pushOneArg ( Int r1 )
+{
+ emit_pushv_reg ( 4, r1 );
+}
+
+static void synth_ccall_pushTwoArgs ( Int r1, Int r2 )
+{
+ /* must push in reverse order */
+ emit_pushv_reg ( 4, r2 );
+ emit_pushv_reg ( 4, r1 );
+}
+
+/* Synthesise a call to *baseBlock[offset], ie,
+ call * (4 x offset)(%ebp) with arguments
+*/
+static void synth_ccall_call_clearStack_restoreRegs ( Int word_offset,
+ UInt n_args_bytes )
+{
+ vg_assert(word_offset >= 0);
+ vg_assert(word_offset < VG_BASEBLOCK_WORDS);
+ vg_assert(n_args_bytes <= 12); /* Max 3 word-sized args */
+ vg_assert(0 == (n_args_bytes & 0x3)); /* Divisible by four */
+
+ emit_call_star_EBP_off ( 4 * word_offset );
+ if ( 0 != n_args_bytes )
+ emit_add_lit_to_esp ( n_args_bytes );
+ emit_popv_reg ( 4, R_EDX );
+ emit_popv_reg ( 4, R_ECX );
+ emit_popv_reg ( 4, R_EAX );
+}
static void load_ebp_from_JmpKind ( JmpKind jmpkind )
{
emit_put_eflags();
break;
+ case CCALL_1_0:
+ vg_assert(u->tag1 == RealReg);
+ vg_assert(u->tag2 == NoValue);
+ vg_assert(u->size == 0);
+
+ synth_ccall_saveRegs();
+ synth_ccall_pushOneArg ( u->val1 );
+ synth_ccall_call_clearStack_restoreRegs ( u->lit32, 4 );
+ break;
+
+ case CCALL_2_0:
+ vg_assert(u->tag1 == RealReg);
+ vg_assert(u->tag2 == RealReg);
+ vg_assert(u->size == 0);
+
+ synth_ccall_saveRegs();
+ synth_ccall_pushTwoArgs ( u->val1, u->val2 );
+ synth_ccall_call_clearStack_restoreRegs ( u->lit32, 8 );
+ break;
+
case CLEAR:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);
PUSH, POP, CLEAR, /* Add/remove/zap args for helpers. */
CALLM, /* call to a machine-code helper */
+ /* for calling C functions -- CCALL_M_N passes M arguments and returns N
+ * (0 or 1) return values */
+ CCALL_1_0, CCALL_2_0,
+
/* Hack for translating string (REP-) insns. Jump to literal if
TempReg/RealReg is zero. */
JIFZ,
return CC0 && Ls1 && N2 && SZ0 && N3;
case CALLM:
return SZ0 && Ls1 && N2 && N3;
+ case CCALL_1_0:
+ return SZ0 && CC0 && TR1 && N2 && N3;
+ case CCALL_2_0:
+ return SZ0 && CC0 && TR1 && TR2 && N3;
case PUSH: case POP:
return CC0 && TR1 && N2 && N3;
case AND: case OR:
case JMP: return "J" ;
case JIFZ: return "JIFZ" ;
case CALLM: return "CALLM";
+ case CCALL_1_0: return "CCALL_1_0";
+ case CCALL_2_0: return "CCALL_2_0";
case PUSH: return "PUSH" ;
case POP: return "POP" ;
case CLEAR: return "CLEAR";
ppUOperand(u, 1, u->size, False);
break;
+ case CCALL_1_0:
+ VG_(printf)(" ");
+ ppUOperand(u, 1, 0, False);
+ VG_(printf)(" (%u)", u->lit32);
+ break;
+
+ case CCALL_2_0:
+ VG_(printf)(" ");
+ ppUOperand(u, 1, 0, False);
+ VG_(printf)(", ");
+ ppUOperand(u, 2, 0, False);
+ VG_(printf)(" (%u)", u->lit32);
+ break;
+
case JIFZ:
VG_(printf)("\t");
ppUOperand(u, 1, u->size, False);
case GET: WR(2); break;
case PUT: RD(1); break;
case LOAD: RD(1); WR(2); break;
- case STORE: RD(1); RD(2); break;
+ case STORE: case CCALL_2_0: RD(1); RD(2); break;
case MOV: RD(1); WR(2); break;
case JMP: RD(1); break;
case CLEAR: case CALLM: break;
- case PUSH: RD(1); break;
+ case PUSH: case CCALL_1_0: RD(1); break;
case POP: WR(1); break;
case TAG2: