diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-15 23:11:28 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-15 16:11:28 +0100 |
| commit | 9b2b603c8ddb2c4b94cbab8e5f02d11989641f5d (patch) | |
| tree | 3bd703fed34b5ab6b118e4db6ebff17ffb1baea3 /src | |
| parent | 6f85a204a9b913047ae322ba8a48dd85a98c9ab8 (diff) | |
| download | box64-9b2b603c8ddb2c4b94cbab8e5f02d11989641f5d.tar.gz box64-9b2b603c8ddb2c4b94cbab8e5f02d11989641f5d.zip | |
[RV64_DYNAREC] Added 80 /7 CMP opcode (#567)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 20 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_tests.c | 65 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 42 |
4 files changed, 120 insertions, 11 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index c7434831..f72e9f1b 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -108,7 +108,25 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ADDI(xRSP, xRSP, 8); } break; - + case 0x80: + nextop = F8; + switch((nextop>>3)&7) { + case 7: // CMP + INST_NAME("CMP Eb, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEB(x1, 1); + u8 = F8; + if(u8) { + ADDI(x2, xZR, u8); + emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); + } else { + emit_cmp8_0(dyn, ninst, x1, x3, x4); + } + break; + default: + DEFAULT; + } + break; case 0x81: case 0x83: nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 417d0ccf..51491555 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -146,7 +146,7 @@ void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s if (!rex.w) { ZEROUP(s1); } - CALC_SUB_FLAGS(s5, s2, s1, s3, s4); + CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w?64:32); IFX(X_ZF) { BEQZ(s1, 4); ORI(xFlags, xFlags, 1 << F_ZF); @@ -210,7 +210,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i if (!rex.w) { ZEROUP(s1); } - CALC_SUB_FLAGS(s5, s2, s1, s3, s4); + CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w?64:32); IFX(X_ZF) { BEQZ(s1, 4); ORI(xFlags, xFlags, 1 << F_ZF); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index f4394800..6218aae6 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -23,6 +23,69 @@ #include "dynarec_rv64_functions.h" #include "dynarec_rv64_helper.h" +// emit CMP8 instruction, from cmp s1, s2, using s3, s4, s5 and s6 as scratch +void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6) { + CLEAR_FLAGS(); + IFX_PENDOR0 { + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SB(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s4, d_cmp8); + } else { + SET_DFNONE(s4); + } + + IFX(X_AF | X_CF | X_OF) { + // for later flag calculation + NOT(s5, s1); + } + + // It's a cmp, we can't store the result back to s1. + SUB(s6, s1, s2); + ANDI(s6, s6, 0xff); + IFX_PENDOR0 { + SB(s6, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_SF) { + SRLI(s3, s6, 7); + BEQZ(s3, 4); + ORI(xFlags, xFlags, 1 << F_SF); + } + CALC_SUB_FLAGS(s5, s2, s6, s3, s4, 8); + IFX(X_ZF) { + BEQZ(s6, 4); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s6, s3, s4); + } +} + +// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch +void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) { + CLEAR_FLAGS(); + IFX_PENDOR0 { + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SB(xZR, xEmu, offsetof(x64emu_t, op2)); + SB(s1, xEmu, offsetof(x64emu_t, res)); + SET_DF(s3, d_cmp8); + } else { + SET_DFNONE(s4); + } + + IFX(X_SF) { + SRLI(s3, s1, 7); + BEQZ(s3, 4); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_ZF) { + BEQZ(s1, 4); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6) { @@ -52,7 +115,7 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s if (!rex.w) { ZEROUP(s1); } - CALC_SUB_FLAGS(s5, s2, s6, s3, s4); + CALC_SUB_FLAGS(s5, s2, s6, s3, s4, rex.w?64:32); IFX(X_ZF) { BEQZ(s6, 4); ORI(xFlags, xFlags, 1 << F_ZF); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index b3017667..c4bebc19 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -76,6 +76,29 @@ // Write back ed in wback (if wback not 0) #define WBACK if(wback) {SDxw(ed, wback, fixedaddress); SMWRITE();} +// GETEB will use i for ed, and can use r3 for wback. +#define GETEB(i, D) if(MODREG) { \ + if(rex.rex) { \ + wback = xRAX+(nextop&7)+(rex.b<<3); \ + wb2 = 0; \ + } else { \ + wback = (nextop&7); \ + wb2 = (wback>>2)*8; \ + wback = xRAX+(wback&3); \ + } \ + MV(i, wback); \ + if (wb2) SRLI(i, i, wb2); \ + ANDI(i, i, 0xff); \ + wb1 = 0; \ + ed = i; \ + } else { \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 0, D); \ + LBU(i, wback, fixedaddress);\ + wb1 = 1; \ + ed = i; \ + } + #define IFX(A) if((dyn->insts[ninst].x64.gen_flags&(A))) #define IFX_PENDOR0 if((dyn->insts[ninst].x64.gen_flags&(X_PEND) || !dyn->insts[ninst].x64.gen_flags)) #define IFXX(A) if((dyn->insts[ninst].x64.gen_flags==(A))) @@ -89,7 +112,7 @@ #define CLEAR_FLAGS() IFX(X_ALL) {ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_CF) | (1UL<<F_OF) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF)));} -#define CALC_SUB_FLAGS(op1_, op2, res, scratch1, scratch2) \ +#define CALC_SUB_FLAGS(op1_, op2, res, scratch1, scratch2, width) \ IFX(X_AF | X_CF | X_OF) { \ /* calc borrow chain */ \ /* bc = (res & (~op1 | op2)) | (~op1 & op2) */ \ @@ -104,14 +127,19 @@ ORI(xFlags, xFlags, 1 << F_AF); \ } \ IFX(X_CF) { \ - /* cf = bc & (rex.w?(1<<63):(1<<31)) */ \ - SRLI(scratch1, scratch2, rex.w?63:31); \ + /* cf = bc & (1<<(width-1)) */ \ + if (width == 8) { \ + ANDI(scratch1, scratch2, 0x80); \ + } else { \ + SRLI(scratch1, scratch2, width-1); \ + if (width == 16) ANDI(scratch1, scratch1, 1); \ + } \ BEQZ(scratch1, 4); \ ORI(xFlags, xFlags, 1 << F_CF); \ } \ IFX(X_OF) { \ - /* of = ((bc >> rex.w?62:30) ^ (bc >> rex.w?63:31)) & 0x1; */ \ - SRLI(scratch1, scratch2, rex.w?62:30); \ + /* of = ((bc >> (width-2)) ^ (bc >> (width-1))) & 0x1; */ \ + SRLI(scratch1, scratch2, width-2); \ SRLI(scratch2, scratch1, 1); \ XOR(scratch1, scratch1, scratch2); \ ANDI(scratch1, scratch1, 1); \ @@ -359,10 +387,10 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst); //void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg); //void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w); //void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment); -//void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); +void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6); //void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6); -//void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); +void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); //void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); //void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); //void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); |