diff options
| author | wannacu <wannacu2049@gmail.com> | 2023-08-14 15:44:59 +0800 |
|---|---|---|
| committer | wannacu <wannacu2049@gmail.com> | 2023-08-15 09:28:59 +0800 |
| commit | c4e322a23a19bc94461cb55b584069d422ef9ee3 (patch) | |
| tree | 60c4a2f96ee3437a16263fea5105e31aee78b272 | |
| parent | 6b9d617fa6aaacf1fab2dd154e40f855b99788c6 (diff) | |
| download | box64-c4e322a23a19bc94461cb55b584069d422ef9ee3.tar.gz box64-c4e322a23a19bc94461cb55b584069d422ef9ee3.zip | |
[RV64_DYNAREC] Added E0/E1/E2/E3 opcodes
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 52 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 8 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_67.c | 57 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 1 |
4 files changed, 113 insertions, 5 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 2be53fc8..dece35af 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -621,6 +621,58 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xDF: addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; + #define GO(Z) \ + BARRIER(BARRIER_MAYBE); \ + JUMP(addr+i8, 1); \ + if(dyn->insts[ninst].x64.jmp_insts==-1 || \ + CHECK_CACHE()) { \ + /* out of the block */ \ + i32 = dyn->insts[ninst].epilog-(dyn->native_size); \ + if(Z) {BNE(xRCX, xZR, i32);} else {BEQ(xRCX, xZR, i32);}; \ + if(dyn->insts[ninst].x64.jmp_insts==-1) { \ + if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \ + fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \ + jump_to_next(dyn, addr+i8, 0, ninst); \ + } else { \ + CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ + i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + B(i32); \ + } \ + } else { \ + /* inside the block */ \ + i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + if(Z) {BEQ(xRCX, xZR, i32);} else {BNE(xRCX, xZR, i32);}; \ + } + case 0xE0: + INST_NAME("LOOPNZ"); + READFLAGS(X_ZF); + i8 = F8S; + SUBI(xRCX, xRCX, 1); + ANDI(x1, xFlags, 1 << F_ZF); + CBNZ_NEXT(x1); + GO(0); + break; + case 0xE1: + INST_NAME("LOOPZ"); + READFLAGS(X_ZF); + i8 = F8S; + SUBI(xRCX, xRCX, 1); + ANDI(x1, xFlags, 1 << F_ZF); + CBZ_NEXT(x1); + GO(0); + break; + case 0xE2: + INST_NAME("LOOP"); + i8 = F8S; + SUBI(xRCX, xRCX, 1); + GO(0); + break; + case 0xE3: + INST_NAME("JECXZ"); + i8 = F8S; + GO(1); + break; + #undef GO case 0xE8: INST_NAME("CALL Id"); diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 10c3e63d..199068cf 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -334,7 +334,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } else { if (rex.w) { - LI(x2, 0xff); + MOV_U12(x2, 0xff); SLLI(x1, gd, 56); SRLI(x3, gd, 56); SRLI(x4, gd, 40); @@ -365,7 +365,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(x3, x3, x4); OR(gd, x1, x3); } else { - LI(x2, 0xff); + MOV_U12(x2, 0xff); SLLIW(x2, x2, 8); SLLIW(x1, gd, 24); SRLIW(x3, gd, 24); @@ -393,7 +393,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } else { if (rex.w) { - LI(x2, 0xff); + MOV_U12(x2, 0xff); SLLI(x1, gd, 56); SRLI(x3, gd, 56); SRLI(x4, gd, 40); @@ -424,7 +424,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni AND(x3, x3, x4); OR(x1, x1, x3); } else { - LI(x2, 0xff); + MOV_U12(x2, 0xff); SLLIW(x2, x2, 8); SLLIW(x1, gd, 24); SRLIW(x3, gd, 24); diff --git a/src/dynarec/rv64/dynarec_rv64_67.c b/src/dynarec/rv64/dynarec_rv64_67.c index cb7702a8..5f102742 100644 --- a/src/dynarec/rv64/dynarec_rv64_67.c +++ b/src/dynarec/rv64/dynarec_rv64_67.c @@ -567,6 +567,63 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } break; + #define GO(Z) \ + BARRIER(BARRIER_MAYBE); \ + JUMP(addr+i8, 1); \ + if(dyn->insts[ninst].x64.jmp_insts==-1 || \ + CHECK_CACHE()) { \ + /* out of the block */ \ + i32 = dyn->insts[ninst].epilog-(dyn->native_size); \ + if(Z) {BNE(x1, xZR, i32);} else {BEQ(x1, xZR, i32);}; \ + if(dyn->insts[ninst].x64.jmp_insts==-1) { \ + if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \ + fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \ + jump_to_next(dyn, addr+i8, 0, ninst); \ + } else { \ + CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ + i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + B(i32); \ + } \ + } else { \ + /* inside the block */ \ + i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \ + if(Z) {BEQ(x1, xZR, i32);} else {BNE(x1, xZR, i32);}; \ + } + case 0xE0: + INST_NAME("LOOPNZ (32bits)"); + READFLAGS(X_ZF); + i8 = F8S; + SUBI(xRCX, xRCX, 1); + ANDI(x1, xFlags, 1 << F_ZF); + CBNZ_NEXT(x1); + AND(x1, xRCX, xMASK); + GO(0); + break; + case 0xE1: + INST_NAME("LOOPZ (32bits)"); + READFLAGS(X_ZF); + i8 = F8S; + SUBI(xRCX, xRCX, 1); + ANDI(x1, xFlags, 1 << F_ZF); + CBZ_NEXT(x1); + AND(x1, xRCX, xMASK); + GO(0); + break; + case 0xE2: + INST_NAME("LOOP (32bits)"); + i8 = F8S; + SUBI(xRCX, xRCX, 1); + AND(x1, xRCX, xMASK); + GO(0); + break; + case 0xE3: + INST_NAME("JECXZ (32bits)"); + i8 = F8S; + AND(x1, xRCX, xMASK); + GO(1); + break; + #undef GO + default: DEFAULT; } diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 6a5dd4bd..f23c6716 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -129,7 +129,6 @@ f28–31 ft8–11 FP temporaries Caller // put imm20 in the [31:12] bits of rd, zero [11:0] and sign extend bits31 #define LUI(rd, imm20) EMIT(U_type((imm20)<<12, rd, 0b0110111)) -#define LI(rd, imm12) if (imm12 < 0x800) { ADDI(rd, xZR, imm12);} else {LUI(rd, 1); ADDIW(rd, rd, -(0x1000 - imm12));} // put PC+imm20 in rd #define AUIPC(rd, imm20) EMIT(U_type((imm20)<<12, rd, 0b0010111)) |