diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-04-21 00:23:25 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-20 18:23:25 +0200 |
| commit | 5f69e58f3743c12e68691373421c893b367076ef (patch) | |
| tree | 3adb4b5670a8ff5b9093c73e1f59e57eb8ba2fb9 /src | |
| parent | 84b0ee2284598a65ef7f727bb27b8c1527e8b5a3 (diff) | |
| download | box64-5f69e58f3743c12e68691373421c893b367076ef.tar.gz box64-5f69e58f3743c12e68691373421c893b367076ef.zip | |
[RV64_DYNAREC] Added more opcodes (#718)
* Added F0 01 LOCK ADD opcode * Added F2 0F 51 SQRTSD opcode * Added FE /0,/1 INC/DEC opcodes
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 21 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 109 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f0.c | 22 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f20f.c | 7 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 4 |
5 files changed, 161 insertions, 2 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index f6c2a4ed..a1e7421e 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -914,6 +914,27 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("CLD"); ANDI(xFlags, xFlags, ~(1<<F_CF)); break; + case 0xFE: + nextop = F8; + switch((nextop>>3)&7) { + case 0: + INST_NAME("INC Eb"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING); + GETEB(x1, 0); + emit_inc8(dyn, ninst, ed, x2, x4, x5); + EBBACK(x5, 0); + break; + case 1: + INST_NAME("DEC Eb"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING); + GETEB(x1, 0); + emit_dec8(dyn, ninst, ed, x2, x4, x5); + EBBACK(x5, 0); + break; + default: + DEFAULT; + } + break; case 0xFF: nextop = F8; switch((nextop>>3)&7) { diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 2f4138d6..df70eac4 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -557,6 +557,115 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } } +// emit INC8 instruction, from s1, store result in s1 using s2, s3 and s4 as scratch +void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + IFX(X_ALL) { + ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_OF2) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF))); + } + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, d_inc8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + IFX(X_AF | X_OF) { + ORI(s3, s1, 1); // s3 = op1 | op2 + ANDI(s4, s1, 1); // s5 = op1 & op2 + } + + ADDIW(s1, s1, 1); + + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF | X_OF) { + NOT(s2, s1); // s2 = ~res + AND(s3, s2, s3); // s3 = ~res & (op1 | op2) + OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2) + IFX(X_AF) { + ANDI(s2, s3, 0x08); // AF: cc & 0x08 + BEQZ(s2, 8); + ORI(xFlags, xFlags, 1 << F_AF); + } + IFX(X_OF) { + SRLI(s3, s3, 6); + SRLI(s2, s3, 1); + XOR(s3, s3, s2); + ANDI(s3, s3, 1); // OF: xor of two MSB's of cc + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_OF2); + } + } + IFX(X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + ANDI(s1, s1, 0xff); + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s2); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } +} + + +// emit DEC8 instruction, from s1, store result in s1 using s2, s3 and s4 as scratch +void emit_dec8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + IFX(X_ALL) { + ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_OF2) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF))); + } + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, d_dec8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + IFX(X_AF | X_OF) { + ORI(s3, s1, 1); // s3 = op1 | op2 + ANDI(s4, s1, 1); // s4 = op1 & op2 + } + + ADDIW(s1, s1, -1); + + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF | X_OF) { + NOT(s2, s1); // s2 = ~res + AND(s3, s2, s3); // s3 = ~res & (op1 | op2) + OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2) + IFX(X_AF) { + ANDI(s2, s3, 0x08); // AF: cc & 0x08 + BEQZ(s2, 8); + ORI(xFlags, xFlags, 1 << F_AF); + } + IFX(X_OF) { + SRLI(s3, s3, 6); + SRLI(s2, s3, 1); + XOR(s3, s3, s2); + ANDI(s3, s3, 1); // OF: xor of two MSB's of cc + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_OF2); + } + } + IFX(X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + ANDI(s1, s1, 0xff); + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s2); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } +} + // emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch void emit_inc32(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_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index ff15db2b..f5ae3950 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -57,6 +57,28 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni // TODO: Take care of unligned memory access for all the LOCK ones. // https://github.com/ptitSeb/box64/pull/604 switch(opcode) { + case 0x01: + INST_NAME("LOCK ADD Ed, Gd"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGD; + SMDMB(); + if((nextop&0xC0)==0xC0) { + ed = xRAX+(nextop&7)+(rex.b<<3); + emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + MARKLOCK; + LRxw(x1, wback, 1, 1); + ADDxw(x4, x1, gd); + SCxw(x3, x4, wback, 1, 1); + BNEZ_MARKLOCK(x3); + IFX(X_ALL|X_PEND) { + emit_add32(dyn, ninst, rex, x1, gd, x3, x4, x5); + } + } + SMDMB(); + break; case 0x09: INST_NAME("LOCK OR Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index c8976aff..11b4f506 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -178,6 +178,13 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DEFAULT; } break; + case 0x51: // TODO: fastnan handling + INST_NAME("SQRTSD Gx, Ex"); + nextop = F8; + GETEXSD(d0, 0); + GETGXSD_empty(d1); + FSQRTD(d1, d0); + break; case 0x58: INST_NAME("ADDSD Gx, Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 2785ce99..90d2598e 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -945,10 +945,10 @@ 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); void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); //void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); -//void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); +void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_dec32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); //void emit_dec16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); -//void emit_dec8(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); +void emit_dec8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); //void emit_adc32c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_adc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); |