diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index 4f1bf1071..05f4186f7 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -594,11 +594,6 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr) 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); @@ -608,7 +603,13 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr) 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; @@ -639,31 +640,19 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr) 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; + /* 1st arg: CC addr */ + t_CC_addr = newTemp(cb); + uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr); + uLiteral(cb, BBCC_ptr); + + uInstr2(cb, CCALL_2_0, 0, TempReg, t_CC_addr, + TempReg, t_data_addr); + uLiteral(cb, VGOFF_(cachesim_log_mem_instr)); } -#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); - 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); VG_(copyUInstr)(cb, u_in); diff --git a/cachegrind/cg_sim_gen.c b/cachegrind/cg_sim_gen.c index f938bc4b0..182a03138 100644 --- a/cachegrind/cg_sim_gen.c +++ b/cachegrind/cg_sim_gen.c @@ -199,6 +199,7 @@ miss_treatment: \ 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; \ diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c index 573ee9327..d11dd9b4f 100644 --- a/coregrind/vg_from_ucode.c +++ b/coregrind/vg_from_ucode.c @@ -1067,6 +1067,43 @@ static void synth_call_baseBlock_method ( Bool ensure_shortform, 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 ) { @@ -2524,6 +2561,26 @@ static void emitUInstr ( Int i, UInstr* u ) 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); diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 0d38c9233..74e101697 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -1066,6 +1066,10 @@ typedef 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, diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index 27a02754c..a34c9093b 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -521,6 +521,10 @@ Bool VG_(saneUInstr) ( Bool beforeRA, UInstr* u ) 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: @@ -802,6 +806,8 @@ Char* VG_(nameUOpcode) ( Bool upper, Opcode opc ) 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"; @@ -928,6 +934,20 @@ void VG_(ppUInstr) ( Int instrNo, UInstr* u ) 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); @@ -1050,13 +1070,13 @@ Int getTempUsage ( UInstr* u, TempUse* arr ) 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: diff --git a/vg_cachesim.c b/vg_cachesim.c index 4f1bf1071..05f4186f7 100644 --- a/vg_cachesim.c +++ b/vg_cachesim.c @@ -594,11 +594,6 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr) 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); @@ -608,7 +603,13 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr) 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; @@ -639,31 +640,19 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr) 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; + /* 1st arg: CC addr */ + t_CC_addr = newTemp(cb); + uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_CC_addr); + uLiteral(cb, BBCC_ptr); + + uInstr2(cb, CCALL_2_0, 0, TempReg, t_CC_addr, + TempReg, t_data_addr); + uLiteral(cb, VGOFF_(cachesim_log_mem_instr)); } -#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); - 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); VG_(copyUInstr)(cb, u_in); diff --git a/vg_cachesim_gen.c b/vg_cachesim_gen.c index f938bc4b0..182a03138 100644 --- a/vg_cachesim_gen.c +++ b/vg_cachesim_gen.c @@ -199,6 +199,7 @@ miss_treatment: \ 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; \ diff --git a/vg_from_ucode.c b/vg_from_ucode.c index 573ee9327..d11dd9b4f 100644 --- a/vg_from_ucode.c +++ b/vg_from_ucode.c @@ -1067,6 +1067,43 @@ static void synth_call_baseBlock_method ( Bool ensure_shortform, 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 ) { @@ -2524,6 +2561,26 @@ static void emitUInstr ( Int i, UInstr* u ) 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); diff --git a/vg_include.h b/vg_include.h index 0d38c9233..74e101697 100644 --- a/vg_include.h +++ b/vg_include.h @@ -1066,6 +1066,10 @@ typedef 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, diff --git a/vg_translate.c b/vg_translate.c index 27a02754c..a34c9093b 100644 --- a/vg_translate.c +++ b/vg_translate.c @@ -521,6 +521,10 @@ Bool VG_(saneUInstr) ( Bool beforeRA, UInstr* u ) 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: @@ -802,6 +806,8 @@ Char* VG_(nameUOpcode) ( Bool upper, Opcode opc ) 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"; @@ -928,6 +934,20 @@ void VG_(ppUInstr) ( Int instrNo, UInstr* u ) 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); @@ -1050,13 +1070,13 @@ Int getTempUsage ( UInstr* u, TempUse* arr ) 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: