From 4b6ec02517635f7ff0a074c5b4092b589b9b04bf Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 16 Mar 2023 16:52:30 +0800 Subject: [RV64_DYNAREC] Added (81/83) /7 CMP opcode (#571) * [RV64_DYNAREC] Added (81/83) /7 CMP opcode * [RV64_DYNAREC] Added B[8-F] MOV opcode * [RV64_DYNAREC] Added another C7 MOV opcode * [RV64_DYNAREC] Zeroup for MOV32w --- src/dynarec/rv64/dynarec_rv64_00.c | 56 ++++++++++++++++++++++++++---- src/dynarec/rv64/dynarec_rv64_emit_math.c | 14 ++++---- src/dynarec/rv64/dynarec_rv64_emit_tests.c | 29 ++++++++++++++++ src/dynarec/rv64/dynarec_rv64_helper.h | 2 +- src/dynarec/rv64/rv64_emitter.h | 4 ++- 5 files changed, 90 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index c437299e..6f1b7f7c 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -61,7 +61,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; - + case 0x0F: switch(rep) { case 2: @@ -150,7 +150,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x83: nextop = F8; switch((nextop>>3)&7) { - case 0: //ADD + case 0: // ADD if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");} SETFLAGS(X_ALL, SF_SET_PENDING); GETED((opcode==0x81)?4:1); @@ -166,6 +166,17 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6); WBACK; break; + case 7: // CMP + if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");} + SETFLAGS(X_ALL, SF_SET_PENDING); + GETED((opcode==0x81)?4:1); + if(opcode==0x81) i64 = F32S; else i64 = F8S; + if(i64) { + MOV64xw(x2, i64); + emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6); + } else + emit_cmp32_0(dyn, ninst, rex, ed, x3, x4); + break; default: DEFAULT; } @@ -222,7 +233,24 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } break; - + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + INST_NAME("MOV Reg, Id"); + gd = xRAX+(opcode&7)+(rex.b<<3); + if(rex.w) { + u64 = F64; + MOV64x(gd, u64); + } else { + u32 = F32; + MOV32w(gd, u32); + } + break; case 0xC1: nextop = F8; switch((nextop>>3)&7) { @@ -310,7 +338,25 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITELOCK(lock); } break; - + case 0xC7: + INST_NAME("MOV Ed, Id"); + nextop=F8; + if(MODREG) { // reg <= i32 + i64 = F32S; + ed = xRAX+(nextop&7)+(rex.b<<3); + MOV64xw(ed, i64); + } else { // mem <= i32 + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, &lock, 0, 4); + i64 = F32S; + if(i64) { + MOV64xw(x3, i64); + ed = x3; + } else + ed = xZR; + SDxw(ed, wback, fixedaddress); + SMWRITELOCK(lock); + } + break; case 0xCC: SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...) if(PK(0)=='S' && PK(1)=='C') { @@ -369,7 +415,6 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni #endif } break; - case 0xD1: nextop = F8; switch((nextop>>3)&7) { @@ -391,7 +436,6 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; - case 0xE8: INST_NAME("CALL Id"); i32 = F32S; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 307765ac..b2e9be9c 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -108,13 +108,13 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i if(c >= -2048 && c < 2048) { ADDIxw(s1, s1, c); } else { - MOV64x(s2, c); + MOV64xw(s2, c); ADDxw(s1, s1, s2); } return; } IFX(X_PEND | X_AF | X_CF | X_OF) { - MOV64x(s2, c); + MOV64xw(s2, c); } IFX(X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, op1)); @@ -151,7 +151,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i if(c >= -2048 && c < 2048) { ADDIxw(s1, s1, c); } else { - IFX(X_PEND | X_AF | X_CF | X_OF) {} else {MOV64x(s2, c);} + IFX(X_PEND | X_AF | X_CF | X_OF) {} else {MOV64xw(s2, c);} ADDxw(s1, s1, s2); } @@ -242,7 +242,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i if (c > -2048 && c <= 2048) { ADDI(s1, s1, -c); } else { - MOV64x(s2, c); + MOV64xw(s2, c); SUBxw(s1, s1, s2); } return; @@ -250,7 +250,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX(X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, op1)); - MOV64x(s2, c); + MOV64xw(s2, c); SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s3, rex.w?d_sub64:d_sub32); } else IFX(X_ALL) { @@ -265,14 +265,14 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i if (c > -2048 && c <= 2048) { ADDIxw(s1, s1, -c); } else { - IFX(X_PEND) {} else {MOV64x(s2, c);} + IFX(X_PEND) {} else {MOV64xw(s2, c);} SUBxw(s1, s1, s2); } IFX(X_AF | X_CF | X_OF) { IFX(X_PEND) {} else if (c > -2048 && c <= 2048) { - MOV64x(s2, c); + MOV64xw(s2, c); } } IFX(X_PEND) { diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index 6218aae6..0b85d831 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -125,6 +125,35 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } } +// emit CMP32 instruction, from cmp s1, 0, using s3 and s4 as scratch +void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4) +{ + IFX_PENDOR0 { + SD(s1, xEmu, offsetof(x64emu_t, op1)); + SD(xZR, xEmu, offsetof(x64emu_t, op2)); + SD(s1, xEmu, offsetof(x64emu_t, res)); + SET_DF(s4, rex.w?d_cmp64:d_cmp32); + } else { + SET_DFNONE(s4); + } + IFX(X_SF) { + if (rex.w) { + BGE(s1, xZR, 4); + } else { + SRLI(s3, s1, 31); + 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 TEST32 instruction, from test s1, s2, using s3 and s4 as scratch void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index b9c16ca6..55869194 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -510,7 +510,7 @@ void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i 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_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_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); //void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 5359daca..32988c19 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -108,8 +108,10 @@ f28–31 ft8–11 FP temporaries Caller #define SPLIT20(A) (((A)+0x800)>>12) #define SPLIT12(A) ((A)&0xfff) -// MOVE64x is quite complex, so use a function for this +// MOV64x/MOV32w is quite complex, so use a function for this #define MOV64x(A, B) rv64_move64(dyn, ninst, A, B) +#define MOV32w(A, B) do{ rv64_move32(dyn, ninst, A, B); if(A&0x80000000) ZEROUP(A); }while(0); +#define MOV64xw(A, B) if(rex.w) {MOV64x(A, B);} else {MOV32w(A, B);} // ZERO the upper part #define ZEROUP(r) AND(r, r, xMASK) -- cgit 1.4.1