From: Fei Wu <fe...@in...> - 2023-05-26 13:57:49
|
There is no conditional move instruction on riscv so far, support LoadG/StoreG with branches in host isel. Signed-off-by: Fei Wu <fe...@in...> --- VEX/priv/host_riscv64_defs.c | 133 +++++++++++++++++++++++++++++++++++ VEX/priv/host_riscv64_defs.h | 23 ++++++ VEX/priv/host_riscv64_isel.c | 58 +++++++++++++++ VEX/priv/ir_defs.c | 6 ++ VEX/priv/ir_opt.c | 4 +- VEX/pub/libvex_ir.h | 2 + memcheck/mc_translate.c | 4 ++ 7 files changed, 229 insertions(+), 1 deletion(-) diff --git a/VEX/priv/host_riscv64_defs.c b/VEX/priv/host_riscv64_defs.c index f6137b55b..457b2fde4 100644 --- a/VEX/priv/host_riscv64_defs.c +++ b/VEX/priv/host_riscv64_defs.c @@ -440,6 +440,20 @@ RISCV64Instr_Load(RISCV64LoadOp op, HReg dst, HReg base, Int soff12) return i; } +RISCV64Instr* +RISCV64Instr_LoadG(RISCV64LoadOp op, HReg dst, HReg base, Int soff12, HReg guard, HReg alt) +{ + RISCV64Instr* i = LibVEX_Alloc_inline(sizeof(RISCV64Instr)); + i->tag = RISCV64in_LoadG; + i->RISCV64in.LoadG.op = op; + i->RISCV64in.LoadG.dst = dst; + i->RISCV64in.LoadG.base = base; + i->RISCV64in.LoadG.soff12 = soff12; + i->RISCV64in.LoadG.guard = guard; + i->RISCV64in.LoadG.alt = alt; + return i; +} + RISCV64Instr* RISCV64Instr_Store(RISCV64StoreOp op, HReg src, HReg base, Int soff12) { @@ -452,6 +466,19 @@ RISCV64Instr_Store(RISCV64StoreOp op, HReg src, HReg base, Int soff12) return i; } +RISCV64Instr* +RISCV64Instr_StoreG(RISCV64StoreOp op, HReg src, HReg base, Int soff12, HReg guard) +{ + RISCV64Instr* i = LibVEX_Alloc_inline(sizeof(RISCV64Instr)); + i->tag = RISCV64in_StoreG; + i->RISCV64in.StoreG.op = op; + i->RISCV64in.StoreG.src = src; + i->RISCV64in.StoreG.base = base; + i->RISCV64in.StoreG.soff12 = soff12; + i->RISCV64in.StoreG.guard = guard; + return i; +} + RISCV64Instr* RISCV64Instr_LoadR(RISCV64LoadROp op, HReg dst, HReg addr) { RISCV64Instr* i = LibVEX_Alloc_inline(sizeof(RISCV64Instr)); @@ -703,6 +730,16 @@ void ppRISCV64Instr(const RISCV64Instr* i, Bool mode64) ppHRegRISCV64(i->RISCV64in.Load.base); vex_printf(")"); return; + case RISCV64in_LoadG: + vex_printf("%-7s ", showRISCV64LoadOp(i->RISCV64in.LoadG.op)); + ppHRegRISCV64(i->RISCV64in.LoadG.dst); + vex_printf(", %d(", i->RISCV64in.LoadG.soff12); + ppHRegRISCV64(i->RISCV64in.LoadG.base); + vex_printf("), "); + ppHRegRISCV64(i->RISCV64in.LoadG.guard); + vex_printf(", "); + ppHRegRISCV64(i->RISCV64in.LoadG.alt); + return; case RISCV64in_Store: vex_printf("%-7s ", showRISCV64StoreOp(i->RISCV64in.Store.op)); ppHRegRISCV64(i->RISCV64in.Store.src); @@ -710,6 +747,14 @@ void ppRISCV64Instr(const RISCV64Instr* i, Bool mode64) ppHRegRISCV64(i->RISCV64in.Store.base); vex_printf(")"); return; + case RISCV64in_StoreG: + vex_printf("%-7s ", showRISCV64StoreOp(i->RISCV64in.StoreG.op)); + ppHRegRISCV64(i->RISCV64in.StoreG.src); + vex_printf(", %d(", i->RISCV64in.StoreG.soff12); + ppHRegRISCV64(i->RISCV64in.StoreG.base); + vex_printf("), "); + ppHRegRISCV64(i->RISCV64in.StoreG.guard); + return; case RISCV64in_LoadR: vex_printf("%-7s ", showRISCV64LoadROp(i->RISCV64in.LoadR.op)); ppHRegRISCV64(i->RISCV64in.LoadR.dst); @@ -997,10 +1042,21 @@ void getRegUsage_RISCV64Instr(HRegUsage* u, const RISCV64Instr* i, Bool mode64) addHRegUse(u, HRmWrite, i->RISCV64in.Load.dst); addHRegUse(u, HRmRead, i->RISCV64in.Load.base); return; + case RISCV64in_LoadG: + addHRegUse(u, HRmWrite, i->RISCV64in.LoadG.dst); + addHRegUse(u, HRmRead, i->RISCV64in.LoadG.base); + addHRegUse(u, HRmRead, i->RISCV64in.LoadG.guard); + addHRegUse(u, HRmRead, i->RISCV64in.LoadG.alt); + return; case RISCV64in_Store: addHRegUse(u, HRmRead, i->RISCV64in.Store.src); addHRegUse(u, HRmRead, i->RISCV64in.Store.base); return; + case RISCV64in_StoreG: + addHRegUse(u, HRmRead, i->RISCV64in.StoreG.src); + addHRegUse(u, HRmRead, i->RISCV64in.StoreG.base); + addHRegUse(u, HRmRead, i->RISCV64in.StoreG.guard); + return; case RISCV64in_LoadR: addHRegUse(u, HRmWrite, i->RISCV64in.LoadR.dst); addHRegUse(u, HRmRead, i->RISCV64in.LoadR.addr); @@ -1218,10 +1274,21 @@ void mapRegs_RISCV64Instr(HRegRemap* m, RISCV64Instr* i, Bool mode64) mapReg(m, &i->RISCV64in.Load.dst); mapReg(m, &i->RISCV64in.Load.base); return; + case RISCV64in_LoadG: + mapReg(m, &i->RISCV64in.LoadG.dst); + mapReg(m, &i->RISCV64in.LoadG.base); + mapReg(m, &i->RISCV64in.LoadG.guard); + mapReg(m, &i->RISCV64in.LoadG.alt); + return; case RISCV64in_Store: mapReg(m, &i->RISCV64in.Store.src); mapReg(m, &i->RISCV64in.Store.base); return; + case RISCV64in_StoreG: + mapReg(m, &i->RISCV64in.StoreG.src); + mapReg(m, &i->RISCV64in.StoreG.base); + mapReg(m, &i->RISCV64in.StoreG.guard); + return; case RISCV64in_LoadR: mapReg(m, &i->RISCV64in.LoadR.dst); mapReg(m, &i->RISCV64in.LoadR.addr); @@ -1914,6 +1981,43 @@ Int emit_RISCV64Instr(/*MB_MOD*/ Bool* is_profInc, } break; } + case RISCV64in_LoadG: { + /* beq guard, zero, 1f + * l<size> dst, soff12(base) + * c.j 2f + * 1: c.mv dst, alt + * 2: + */ + UInt guard = iregEnc(i->RISCV64in.LoadG.guard); + p = emit_B(p, 0b1100011, (8 >> 1) & 0xfff, 0b000, guard, 0 /*x0/zero*/); + + UInt dst = iregEnc(i->RISCV64in.LoadG.dst); + UInt base = iregEnc(i->RISCV64in.LoadG.base); + Int soff12 = i->RISCV64in.LoadG.soff12; + vassert(soff12 >= -2048 && soff12 < 2048); + UInt imm11_0 = soff12 & 0xfff; + switch (i->RISCV64in.LoadG.op) { + case RISCV64op_LD: + p = emit_I(p, 0b0000011, dst, 0b011, base, imm11_0); + goto done; + case RISCV64op_LW: + p = emit_I(p, 0b0000011, dst, 0b010, base, imm11_0); + goto done; + case RISCV64op_LH: + p = emit_I(p, 0b0000011, dst, 0b001, base, imm11_0); + goto done; + case RISCV64op_LB: + p = emit_I(p, 0b0000011, dst, 0b000, base, imm11_0); + goto done; + } + + p = emit_CJ(p, 0b01, (4 >> 1) & 0x7ff, 0b101); + + UInt alt = iregEnc(i->RISCV64in.LoadG.alt); + p = emit_CR(p, 0b10, alt, dst, 0b1000); + + break; + } case RISCV64in_Store: { /* s<size> src, soff12(base) */ UInt src = iregEnc(i->RISCV64in.Store.src); @@ -1937,6 +2041,35 @@ Int emit_RISCV64Instr(/*MB_MOD*/ Bool* is_profInc, } goto done; } + case RISCV64in_StoreG: { + /* beq guard, zero, 1f + * s<size> src, soff12(base) + * 1: + */ + UInt guard = iregEnc(i->RISCV64in.StoreG.guard); + p = emit_B(p, 0b1100011, (8 >> 1) & 0xfff, 0b000, guard, 0 /*x0/zero*/); + + UInt src = iregEnc(i->RISCV64in.StoreG.src); + UInt base = iregEnc(i->RISCV64in.StoreG.base); + Int soff12 = i->RISCV64in.StoreG.soff12; + vassert(soff12 >= -2048 && soff12 < 2048); + UInt imm11_0 = soff12 & 0xfff; + switch (i->RISCV64in.StoreG.op) { + case RISCV64op_SD: + p = emit_S(p, 0b0100011, imm11_0, 0b011, base, src); + goto done; + case RISCV64op_SW: + p = emit_S(p, 0b0100011, imm11_0, 0b010, base, src); + goto done; + case RISCV64op_SH: + p = emit_S(p, 0b0100011, imm11_0, 0b001, base, src); + goto done; + case RISCV64op_SB: + p = emit_S(p, 0b0100011, imm11_0, 0b000, base, src); + goto done; + } + goto done; + } case RISCV64in_LoadR: { /* lr.<size> dst, (addr) */ UInt dst = iregEnc(i->RISCV64in.LoadR.dst); diff --git a/VEX/priv/host_riscv64_defs.h b/VEX/priv/host_riscv64_defs.h index 1990fe3f5..45fadeb6c 100644 --- a/VEX/priv/host_riscv64_defs.h +++ b/VEX/priv/host_riscv64_defs.h @@ -324,7 +324,9 @@ typedef enum { RISCV64in_ALUImm, /* Computational binary instruction, with an immediate as the second input. */ RISCV64in_Load, /* Load from memory (sign-extended). */ + RISCV64in_LoadG, /* Load from memory (sign-extended) with guard. */ RISCV64in_Store, /* Store to memory. */ + RISCV64in_StoreG, /* Store to memory with guard. */ RISCV64in_LoadR, /* Load-reserved from memory (sign-extended). */ RISCV64in_StoreC, /* Store-conditional to memory. */ RISCV64in_CSRRW, /* Atomic swap of values in a CSR and an integer @@ -382,6 +384,15 @@ typedef struct { HReg base; Int soff12; /* -2048 .. +2047 */ } Load; + /* Load from memory (sign-extended) with guard. */ + struct { + RISCV64LoadOp op; + HReg dst; + HReg base; + Int soff12; /* -2048 .. +2047 */ + HReg guard; + HReg alt; + } LoadG; /* Store to memory. */ struct { RISCV64StoreOp op; @@ -389,6 +400,14 @@ typedef struct { HReg base; Int soff12; /* -2048 .. +2047 */ } Store; + /* Store to memory with guard. */ + struct { + RISCV64StoreOp op; + HReg src; + HReg base; + Int soff12; /* -2048 .. +2047 */ + HReg guard; + } StoreG; /* Load-reserved from memory (sign-extended). */ struct { RISCV64LoadROp op; @@ -536,7 +555,11 @@ RISCV64Instr_ALUImm(RISCV64ALUImmOp op, HReg dst, HReg src, Int imm12); RISCV64Instr* RISCV64Instr_Load(RISCV64LoadOp op, HReg dst, HReg base, Int soff12); RISCV64Instr* +RISCV64Instr_LoadG(RISCV64LoadOp op, HReg dst, HReg base, Int soff12, HReg guard, HReg alt); +RISCV64Instr* RISCV64Instr_Store(RISCV64StoreOp op, HReg src, HReg base, Int soff12); +RISCV64Instr* +RISCV64Instr_StoreG(RISCV64StoreOp op, HReg src, HReg base, Int soff12, HReg guard); RISCV64Instr* RISCV64Instr_LoadR(RISCV64LoadROp op, HReg dst, HReg addr); RISCV64Instr* RISCV64Instr_StoreC(RISCV64StoreCOp op, HReg res, HReg src, HReg addr); diff --git a/VEX/priv/host_riscv64_isel.c b/VEX/priv/host_riscv64_isel.c index 87213fb86..355f559bd 100644 --- a/VEX/priv/host_riscv64_isel.c +++ b/VEX/priv/host_riscv64_isel.c @@ -1587,6 +1587,37 @@ static void iselStmt(ISelEnv* env, IRStmt* stmt) } switch (stmt->tag) { + /* ----------------------- LoadG ------------------------ */ + case Ist_LoadG: { + IRLoadG* lg = stmt->Ist.LoadG.details; + if (lg->end != Iend_LE) + goto stmt_fail; + + IRType tyd = typeOfIRExpr(env->type_env, lg->alt); + if (tyd == Ity_I64 || tyd == Ity_I32 || tyd == Ity_I16 || tyd == Ity_I8) { + HReg dst = lookupIRTemp(env, lg->dst); + HReg addr = iselIntExpr_R(env, lg->addr); + HReg guard = iselIntExpr_R(env, lg->guard); + HReg alt = iselIntExpr_R(env, lg->alt); + + vassert(lg->cvt == ILGop_Ident8 || lg->cvt == ILGop_Ident16 || + lg->cvt == ILGop_Ident32 || lg->cvt == ILGop_Ident64); + + if (tyd == Ity_I64) + addInstr(env, RISCV64Instr_LoadG(RISCV64op_LD, dst, addr, 0, guard, alt)); + else if (tyd == Ity_I32) + addInstr(env, RISCV64Instr_LoadG(RISCV64op_LW, dst, addr, 0, guard, alt)); + else if (tyd == Ity_I16) + addInstr(env, RISCV64Instr_LoadG(RISCV64op_LH, dst, addr, 0, guard, alt)); + else if (tyd == Ity_I8) + addInstr(env, RISCV64Instr_LoadG(RISCV64op_LB, dst, addr, 0, guard, alt)); + else + vassert(0); + return; + } + return; + } + /* ------------------------ STORE ------------------------ */ /* Little-endian write to memory. */ case Ist_Store: { @@ -1623,6 +1654,33 @@ static void iselStmt(ISelEnv* env, IRStmt* stmt) break; } + /* ----------------------- StoreG ------------------------ */ + case Ist_StoreG: { + IRStoreG* sg = stmt->Ist.StoreG.details; + if (sg->end != Iend_LE) + goto stmt_fail; + + IRType tyd = typeOfIRExpr(env->type_env, sg->data); + if (tyd == Ity_I64 || tyd == Ity_I32 || tyd == Ity_I16 || tyd == Ity_I8) { + HReg src = iselIntExpr_R(env, sg->data); + HReg addr = iselIntExpr_R(env, sg->addr); + HReg guard = iselIntExpr_R(env, sg->guard); + + if (tyd == Ity_I64) + addInstr(env, RISCV64Instr_StoreG(RISCV64op_SD, src, addr, 0, guard)); + else if (tyd == Ity_I32) + addInstr(env, RISCV64Instr_StoreG(RISCV64op_SW, src, addr, 0, guard)); + else if (tyd == Ity_I16) + addInstr(env, RISCV64Instr_StoreG(RISCV64op_SH, src, addr, 0, guard)); + else if (tyd == Ity_I8) + addInstr(env, RISCV64Instr_StoreG(RISCV64op_SB, src, addr, 0, guard)); + else + vassert(0); + return; + } + return; + } + /* ------------------------- PUT ------------------------- */ /* Write guest state, fixed offset. */ case Ist_Put: { diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index 875816c78..697e34313 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -2032,6 +2032,8 @@ void ppIRLoadGOp ( IRLoadGOp cvt ) case ILGop_IdentV128: vex_printf("IdentV128"); break; case ILGop_Ident64: vex_printf("Ident64"); break; case ILGop_Ident32: vex_printf("Ident32"); break; + case ILGop_Ident16: vex_printf("Ident16"); break; + case ILGop_Ident8: vex_printf("Ident8"); break; case ILGop_16Uto32: vex_printf("16Uto32"); break; case ILGop_16Sto32: vex_printf("16Sto32"); break; case ILGop_8Uto32: vex_printf("8Uto32"); break; @@ -4261,6 +4263,10 @@ void typeOfIRLoadGOp ( IRLoadGOp cvt, *t_res = Ity_I64; *t_arg = Ity_I64; break; case ILGop_Ident32: *t_res = Ity_I32; *t_arg = Ity_I32; break; + case ILGop_Ident16: + *t_res = Ity_I16; *t_arg = Ity_I16; break; + case ILGop_Ident8: + *t_res = Ity_I8; *t_arg = Ity_I8; break; case ILGop_16Uto32: case ILGop_16Sto32: *t_res = Ity_I32; *t_arg = Ity_I16; break; case ILGop_8Uto32: case ILGop_8Sto32: diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 93dd6188e..e790acb5b 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -2996,7 +2996,9 @@ static IRSB* cprop_BB_WRK ( IRSB* in, Bool mustRetainNoOps, Bool doFolding ) switch (lg->cvt) { case ILGop_IdentV128: case ILGop_Ident64: - case ILGop_Ident32: break; + case ILGop_Ident32: + case ILGop_Ident16: + case ILGop_Ident8: break; case ILGop_8Uto32: cvtOp = Iop_8Uto32; break; case ILGop_8Sto32: cvtOp = Iop_8Sto32; break; case ILGop_16Uto32: cvtOp = Iop_16Uto32; break; diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index b4b1e9d6e..c7b97c11d 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -2829,6 +2829,8 @@ typedef ILGop_IdentV128, /* 128 bit vector, no conversion */ ILGop_Ident64, /* 64 bit, no conversion */ ILGop_Ident32, /* 32 bit, no conversion */ + ILGop_Ident16, /* 16 bit, no conversion */ + ILGop_Ident8, /* 8 bit, no conversion */ ILGop_16Uto32, /* 16 bit load, Z-widen to 32 */ ILGop_16Sto32, /* 16 bit load, S-widen to 32 */ ILGop_8Uto32, /* 8 bit load, Z-widen to 32 */ diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c index 72ccb3c8c..b6c63aa05 100644 --- a/memcheck/mc_translate.c +++ b/memcheck/mc_translate.c @@ -6987,6 +6987,8 @@ static void do_shadow_LoadG ( MCEnv* mce, IRLoadG* lg ) case ILGop_IdentV128: loadedTy = Ity_V128; vwiden = Iop_INVALID; break; case ILGop_Ident64: loadedTy = Ity_I64; vwiden = Iop_INVALID; break; case ILGop_Ident32: loadedTy = Ity_I32; vwiden = Iop_INVALID; break; + case ILGop_Ident16: loadedTy = Ity_I16; vwiden = Iop_INVALID; break; + case ILGop_Ident8: loadedTy = Ity_I8; vwiden = Iop_INVALID; break; case ILGop_16Uto32: loadedTy = Ity_I16; vwiden = Iop_16Uto32; break; case ILGop_16Sto32: loadedTy = Ity_I16; vwiden = Iop_16Sto32; break; case ILGop_8Uto32: loadedTy = Ity_I8; vwiden = Iop_8Uto32; break; @@ -7619,6 +7621,8 @@ static void do_origins_LoadG ( MCEnv* mce, IRLoadG* lg ) case ILGop_IdentV128: loadedTy = Ity_V128; break; case ILGop_Ident64: loadedTy = Ity_I64; break; case ILGop_Ident32: loadedTy = Ity_I32; break; + case ILGop_Ident16: loadedTy = Ity_I16; break; + case ILGop_Ident8: loadedTy = Ity_I8; break; case ILGop_16Uto32: loadedTy = Ity_I16; break; case ILGop_16Sto32: loadedTy = Ity_I16; break; case ILGop_8Uto32: loadedTy = Ity_I8; break; -- 2.25.1 |