diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-24 20:12:42 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-24 13:12:42 +0100 |
| commit | 45015d6106133b940cbb5f24e08aac4d70bd7de8 (patch) | |
| tree | 712b816d0bf866fa6ae61db4048c9a30242ec16b /src | |
| parent | c3223245e561f1f78c4e2b053c43a14929df615e (diff) | |
| download | box64-45015d6106133b940cbb5f24e08aac4d70bd7de8.tar.gz box64-45015d6106133b940cbb5f24e08aac4d70bd7de8.zip | |
[RV64_DYNAREC] Added more opcodes & some fixes & some optimizations (#632)
* [RV64_DYNAREC] Added 66 D1,D3 SAR opcode * [RV64_DYNAREC] Added 66 F7 /7 IDIV opcode * [RV64_DYNAREC] Fixed 32 XOR opcode * [RV64_DYNAREC] Some small optims * [RV64_DYNAREC] Added 66 33 XOR opcode * [RV64_DYNAREC] Added 66 81,83 /6 XOR opcode * [RV64_DYNAREC] Added 66 31 XOR opcode * [RV64_DYNAREC] Fixed a typo in IDIV opcode * [RV64_DYNAREC] Added A4 REP MOVSB opcode * [RV64_DYNAREC] Fixed 66 35 XOR opcode * [RV64_DYNAREC] Added 66 39 CMP opcode * [RV64_DYNAREC] Added F6 /7 IDIV opcode * [RV64_DYNAREC] Added 1C SBB opcode * [RV64_DYNAREC] Added 66 05 ADD opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 50 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 97 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 10 |
3 files changed, 144 insertions, 13 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index e1455292..fb259259 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -153,6 +153,16 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; + case 0x1C: + INST_NAME("SBB AL, Ib"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + u8 = F8; + ANDI(x1, xRAX, 0xff); + emit_sbb8c(dyn, ninst, x1, u8, x3, x4, x5, x6); + ANDI(xRAX, xRAX, ~0xff); + OR(xRAX, xRAX, x1); + break; case 0x20: INST_NAME("AND Eb, Gb"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -244,7 +254,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni nextop = F8; GETEB(x1, 0); GETGB(x3); - emit_xor8(dyn, ninst, x1, x3, x4, x5); + emit_xor8(dyn, ninst, x3, x1, x4, x5); GBBACK(x5); break; case 0x33: @@ -742,6 +752,37 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ZEROUP(xRDX); } break; + case 0xA4: + if(rep) { + INST_NAME("REP MOVSB"); + CBZ_NEXT(xRCX); + ANDI(x1, xFlags, 1<<F_DF); + BNEZ_MARK2(x1); + MARK; // Part with DF==0 + LBU(x1, xRSI, 0); + SB(x1, xRDI, 0); + ADDI(xRSI, xRSI, 1); + ADDI(xRDI, xRDI, 1); + SUBI(xRCX, xRCX, 1); + BNEZ_MARK(xRCX); + B_NEXT_nocond; + MARK2; // Part with DF==1 + LBU(x1, xRSI, 0); + LBU(x1, xRDI, 0); + SUBI(xRSI, xRSI, 1); + SUBI(xRDI, xRDI, 1); + SUBI(xRCX, xRCX, 1); + BNEZ_MARK2(xRCX); + // done + } else { + INST_NAME("MOVSB"); + GETDIR(x3, x1, 1); + LBU(x1, xRSI, 0); + SB(x1, xRDI, 0); + ADD(xRSI, xRSI, x3); + ADD(xRDI, xRDI, x3); + } + break; case 0xA5: if(rep) { INST_NAME("REP MOVSD"); @@ -1407,6 +1448,13 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEB(x1, 0); CALL(div8, -1); break; + case 7: + INST_NAME("IDIV Eb"); + MESSAGE(LOG_DUMP, "Need Optimization\n"); + SETFLAGS(X_ALL, SF_SET); + GETEB(x1, 0); + CALL(idiv8, -1); + break; default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index e296b662..5989f2bf 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -61,6 +61,18 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode switch(opcode) { + case 0x05: + INST_NAME("ADD AX, Iw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + i32 = F16; + SLLI(x1 , xRAX, 48); + SRLI(x1, x1, 48); + MOV32w(x2, i32); + emit_add16(dyn, ninst, x1, x2, x3, x4); + LUI(x3, 0xffff0); + AND(xRAX, xRAX, x3); + OR(xRAX, xRAX, x1); + break; case 0x0B: INST_NAME("OR Gw, Ew"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -136,12 +148,29 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(xRAX, xRAX, x2); OR(xRAX, xRAX, x1); break; - + case 0x31: + INST_NAME("XOR Ew, Gw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x2); + GETEW(x1, 0); + emit_xor16(dyn, ninst, x1, x2, x4, x5, x6); + EWBACK; + break; + case 0x33: + INST_NAME("XOR Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_xor16(dyn, ninst, x1, x2, x4, x5, x6); + GWBACK; + break; case 0x35: INST_NAME("XOR AX, Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); i32 = F16; - SLLI(x1, x1, 48); + SLLI(x1, xRAX, 48); SRLI(x1, x1, 48); MOV32w(x2, i32); emit_xor16(dyn, ninst, x1, x2, x3, x4, x5); @@ -149,7 +178,14 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(xRAX, xRAX, x5); OR(xRAX, xRAX, x1); break; - + case 0x39: + INST_NAME("CMP Ew, Gw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x2); + GETEW(x1, 0); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + break; case 0x3D: INST_NAME("CMP AX, Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -222,6 +258,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sub16(dyn, ninst, x1, x5, x2, x4, x5); EWBACK; break; + case 6: // XOR + if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");} + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEW(x1, (opcode==0x81)?2:1); + if(opcode==0x81) i16 = F16S; else i16 = F8S; + MOV32w(x5, i16); + emit_xor16(dyn, ninst, x1, x5, x2, x4, x6); + EWBACK; + break; case 7: // CMP if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");} SETFLAGS(X_ALL, SF_SET_PENDING); @@ -421,7 +466,31 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITELOCK(lock); } break; - + case 0xD1: + case 0xD3: + nextop = F8; + switch((nextop>>3)&7) { + case 7: + if(opcode==0xD1) { + INST_NAME("SAR Ew, 1"); + MOV32w(x4, 1); + } else { + INST_NAME("SAR Ew, CL"); + ANDI(x4, xRCX, 0x1f); + } + UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");} + SETFLAGS(X_ALL, SF_PENDING); + GETSEW(x1, 0); + UFLAG_OP12(ed, x4) + SRA(ed, ed, x4); + EWBACK; + UFLAG_RES(ed); + UFLAG_DF(x3, d_sar16); + break; + default: + DEFAULT; + } + break; case 0xF7: nextop = F8; switch((nextop>>3)&7) { @@ -454,6 +523,26 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni OR(xRAX, xRAX, x3); OR(xRDX, xRDX, x4); break; + case 7: + INST_NAME("IDIV Ew"); + SETFLAGS(X_ALL, SF_SET); + GETSEW(x1, 0); + SLLI(x2, xRAX, 48); + SLLI(x3, xRDX, 48); + SRLI(x2, x2, 48); + SRLI(x3, x3, 32); + OR(x2, x2, x3); + DIVW(x3, x2, ed); + REMW(x4, x2, ed); + MOV64x(x5, ~0xffff); + AND(xRAX, xRAX, x5); + AND(xRDX, xRDX, x5); + NOT(x5, x5); + AND(x3, x3, x5); + AND(x4, x4, x5); + OR(xRAX, xRAX, x3); + OR(xRDX, xRDX, x4); + break; default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index bcdbc840..55467e89 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -181,9 +181,7 @@ wb2 = (wback>>2)*8; \ wback = xRAX+(wback&3); \ } \ - MV(i, wback); \ - if (wb2) SRLI(i, i, wb2); \ - ANDI(i, i, 0xff); \ + if (wb2) {MV(i, wback); SRLI(i, i, wb2); ANDI(i, i, 0xff);} else ANDI(i, wback, 0xff); \ wb1 = 0; \ ed = i; \ } else { \ @@ -226,21 +224,17 @@ gb1 = xRAX+(gd&3); \ } \ gd = i; \ - MV(gd, gb1); \ - if (gb2) SRLI(gd, gd, gb2*8); \ - ANDI(gd, gd, 0xff); + if (gb2) {MV(gd, gb1); SRLI(gd, gd, 8); ANDI(gd, gd, 0xff);} else ANDI(gd, gb1, 0xff); // Write gb (gd) back to original register / memory, using s1 as scratch #define GBBACK(s1) if(gb2) { \ assert(gb2 == 8); \ MOV64x(s1, 0xffffffffffff00ffLL); \ AND(gb1, gb1, s1); \ - ANDI(gd, gd, 0xff); \ SLLI(s1, gd, 8); \ OR(gb1, gb1, s1); \ } else { \ ANDI(gb1, gb1, ~0xff); \ - ANDI(gd, gd, 0xff); \ OR(gb1, gb1, gd); \ } |