diff options
| author | xctan <xctan@cirno.icu> | 2023-03-24 15:15:44 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-24 08:15:44 +0100 |
| commit | fdf43e58747f06f69096d4ca40cb633fd0393470 (patch) | |
| tree | 773fb876f12e09c023d54723e2c6c674ec627d35 /src | |
| parent | dcc1a5db5274c2f23a342c5c8d4fe26e51723cb9 (diff) | |
| download | box64-fdf43e58747f06f69096d4ca40cb633fd0393470.tar.gz box64-fdf43e58747f06f69096d4ca40cb633fd0393470.zip | |
[RV64_DYNAREC] Added more opcodes and optimize printer output (#630)
* [RV64_DYNAREC] Added 08 OR opcode * [RV64_DYNAREC] Improve printer output readability * [RV64_DYNAREC] Added 66 0F BE MOVSX opcode * [RV64_DYNAREC] Added 66 2B SUB opcode * [RV64_DYNAREC] Optimize printer output for auipc * [RV64_DYNAREC] Added F6 /6 DIV opcode * [RV64_DYNAREC] Added 66 35 XOR opcode * [RV64_DYNAREC] Fixed 66 0F BE MOVSX opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 16 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 23 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 28 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_logic.c | 31 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_printer.c | 41 |
6 files changed, 135 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 89b4305c..ff009df7 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -79,6 +79,15 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; + case 0x08: + INST_NAME("OR Eb, Gb"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x1, 0); + GETGB(x3); + emit_or8(dyn, ninst, x1, x3, x4, x5); + EBBACK(x5); + break; case 0x09: INST_NAME("OR Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -1359,6 +1368,13 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRLI(x1, x1, 48); OR(xRAX, xRAX, x1); break; + case 6: + INST_NAME("DIV Eb"); + MESSAGE(LOG_DUMP, "Need Optimization\n"); + SETFLAGS(X_ALL, SF_SET); + GETEB(x1, 0); + CALL(div8, -1); + break; default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 2a6f8ad1..13e4a32c 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -97,6 +97,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(xRAX, xRAX, x3); OR(xRAX, xRAX, x1); break; + case 0x2B: + INST_NAME("SUB Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_sub16(dyn, ninst, x1, x2, x3, x4, x5); + GWBACK; + break; case 0x2D: INST_NAME("SUB AX, Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -109,6 +118,20 @@ 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 0x35: + INST_NAME("XOR AX, Iw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + i32 = F16; + SLLI(x1, x1, 48); + SRLI(x1, x1, 48); + MOV32w(x2, i32); + emit_xor16(dyn, ninst, x1, x2, x3, x4, x5); + LUI(x5, 0xffff0); + AND(xRAX, xRAX, x5); + OR(xRAX, xRAX, x1); + break; + case 0x3D: INST_NAME("CMP AX, Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 83569f0e..aabaa019 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -94,6 +94,34 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GWBACK; break; + case 0xBE: + INST_NAME("MOVSX Gw, Eb"); + nextop = F8; + GETGD; + if(MODREG) { + if(rex.rex) { + ed = xRAX+(nextop&7)+(rex.b<<3); + eb1=ed; + eb2=0; + } else { + ed = (nextop&7); + eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx + eb2 = (ed&4)>>2; // L or H + } + SLLI(x1, eb1, 56-eb2*8); + SRAI(x1, x1, 56); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 0, 0); + LB(x1, ed, fixedaddress); + } + LUI(x5, 0xffff0); + AND(gd, gd, x5); + NOT(x5, x5); + AND(x1, x1, x5); + OR(gd, gd, x1); + break; + default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c index c3f09ea4..981c5141 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c @@ -96,6 +96,37 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } } +// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed) +void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + SET_DF(s4, d_xor16); + } else IFX(X_ALL) { + SET_DFNONE(); + } + + XOR(s1, s1, s2); + + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF | X_SF) { + SLLI(s3, s1, 48); + IFX(X_ZF) { + BNEZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_SF) { + BGE(s3, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed) void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) { CLEAR_FLAGS(); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index d0f0b41d..23d4078b 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -792,7 +792,7 @@ void emit_sub16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, //void emit_sub16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_or16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); -//void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); //void emit_xor16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_and16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_and16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); diff --git a/src/dynarec/rv64/rv64_printer.c b/src/dynarec/rv64/rv64_printer.c index 98db51d7..21cc8554 100644 --- a/src/dynarec/rv64/rv64_printer.c +++ b/src/dynarec/rv64/rv64_printer.c @@ -408,6 +408,7 @@ static inline insn_t insn_ciwtype_read(uint16_t data) #define RN(r) insn.f ? fpnames[insn.r] : gpnames[insn.r] #define PRINT_none() snprintf(buff, sizeof(buff), "%s", insn.name); return buff +#define PRINT_rd_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, RN(rd), RN(rs1)); return buff #define PRINT_rd_rs1_rs2() snprintf(buff, sizeof(buff), "%s\t%s, %s, %s", insn.name, RN(rd), RN(rs1), RN(rs2)); return buff #define PRINT_rd_rs1_rs2_rs3() snprintf(buff, sizeof(buff), "%s\t%s, %s, %s, %s", insn.name, RN(rd), RN(rs1), RN(rs2), RN(rs3)); return buff #define PRINT_rd_rs1_imm() snprintf(buff, sizeof(buff), "%s\t%s, %s, %d", insn.name, RN(rd), RN(rs1), insn.imm); return buff @@ -415,8 +416,11 @@ static inline insn_t insn_ciwtype_read(uint16_t data) #define PRINT_rd_imm_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %d(%s)", insn.name, RN(rd), insn.imm, gpnames[insn.rs1]); return buff #define PRINT_rs2_imm_rs1() snprintf(buff, sizeof(buff), "%s\t%s, %d(%s)", insn.name, RN(rs2), insn.imm, gpnames[insn.rs1]); return buff #define PRINT_rd_imm() snprintf(buff, sizeof(buff), "%s\t%s, %d", insn.name, RN(rd), insn.imm); return buff +#define PRINT_rd_imm_rel() snprintf(buff, sizeof(buff), "%s\t%s, pc%+d # 0x%llx", insn.name, RN(rd), insn.imm, insn.imm+(uint64_t)addr); return buff +#define PRINT_imm_rel() snprintf(buff, sizeof(buff), "%s\tpc%+d # 0x%llx", insn.name, insn.imm, insn.imm+(uint64_t)addr); return buff #define PRINT_rd_immx() snprintf(buff, sizeof(buff), "%s\t%s, 0x%x", insn.name, RN(rd), insn.imm); return buff #define PRINT_rs1_rs2_imm() snprintf(buff, sizeof(buff), "%s\t%s, %s, %d", insn.name, RN(rs1), RN(rs2), insn.imm); return buff +#define PRINT_rs1_rs2_imm_rel() snprintf(buff, sizeof(buff), "%s\t%s, %s, pc%+d # 0x%llx", insn.name, RN(rs1), RN(rs2), insn.imm, insn.imm+(uint64_t)addr); return buff #define PRINT_fd_fs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, fpnames[insn.rd], fpnames[insn.rs1]); return buff #define PRINT_xd_fs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, gpnames[insn.rd], fpnames[insn.rs1]); return buff #define PRINT_fd_xs1() snprintf(buff, sizeof(buff), "%s\t%s, %s", insn.name, fpnames[insn.rd], gpnames[insn.rs1]); return buff @@ -731,12 +735,24 @@ const char* rv64_print(uint32_t data, uintptr_t addr) } case 0x4: { int hex = 0; + int mv_alias = 0; + int nop_alias = 0; + int not_alias = 0; uint32_t funct3 = FUNCT3(data); insn = insn_itype_read(data); switch (funct3) { case 0x0: /* ADDI */ insn.name = "addi"; + if (insn.imm == 0) { + if (insn.rd == 0 && insn.rs1 == 0) { + nop_alias = 1; + insn.name = "nop"; + } else { + mv_alias = 1; + insn.name = "mv"; + } + } break; case 0x1: { uint32_t imm116 = IMM116(data); @@ -754,6 +770,10 @@ const char* rv64_print(uint32_t data, uintptr_t addr) case 0x4: /* XORI */ insn.name = "xori"; hex = 1; + if (insn.imm == -1) { + not_alias = 1; + insn.name = "not"; + } break; case 0x5: { uint32_t imm116 = IMM116(data); @@ -775,7 +795,13 @@ const char* rv64_print(uint32_t data, uintptr_t addr) hex = 1; break; } - if(hex) { + if (not_alias) { + PRINT_rd_rs1(); + } else if (nop_alias) { + PRINT_none(); + } else if (mv_alias) { + PRINT_rd_rs1(); + } else if(hex) { PRINT_rd_rs1_immx(); } else { PRINT_rd_rs1_imm(); @@ -784,7 +810,7 @@ const char* rv64_print(uint32_t data, uintptr_t addr) case 0x5: /* AUIPC */ insn = insn_utype_read(data); insn.name = "auipc"; - PRINT_rd_imm(); + PRINT_rd_imm_rel(); case 0x6: { uint32_t funct3 = FUNCT3(data); uint32_t funct7 = FUNCT7(data); @@ -1352,7 +1378,7 @@ const char* rv64_print(uint32_t data, uintptr_t addr) break; } - PRINT_rs1_rs2_imm(); + PRINT_rs1_rs2_imm_rel(); } case 0x19: /* JALR */ insn = insn_itype_read(data); @@ -1360,8 +1386,13 @@ const char* rv64_print(uint32_t data, uintptr_t addr) PRINT_rd_imm_rs1(); case 0x1b: /* JAL */ insn = insn_jtype_read(data); - insn.name = "jal"; - PRINT_rd_imm(); + if (insn.rd != 0) { + insn.name = "jal"; + PRINT_rd_imm_rel(); + } else { + insn.name = "j"; + PRINT_imm_rel(); + } case 0x1c: { if (data == 0x73) { /* ECALL */ insn.name = "ecall"; |