[RV64_DYNAREC] Added more opcode (#591)

* [RV64_DYNAREC] Added 84 TEST opcode

* [RV64_DYNAREC] Added 64 8B MOV opcode

* [RV64_DYNAREC] Added {B4,B5,B6,B7} MOV opcode

* [RV64_DYNAREC] Added 3C CMP opcode

* [RV64_DYNAREC] Added {81,83} /1 OR opcode

* [RV64_DYNAREC] Fixed MOV opcode
This commit is contained in:
Yang Liu 2023-03-19 17:28:33 +08:00 committed by GitHub
parent 01d1ea0b90
commit e1ca614f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 230 additions and 7 deletions

View File

@ -610,7 +610,7 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_shift.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_65.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67.c"

View File

@ -149,7 +149,18 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETED(0);
emit_cmp32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
break;
case 0x3C:
INST_NAME("CMP AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
if(u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
case 0x50:
case 0x51:
case 0x52:
@ -201,7 +212,9 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
}
break;
case 0x64:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
@ -361,7 +374,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0x84:
INST_NAME("TEST Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop=F8;
GETEB(x1, 0);
GETGB(x2);
emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x85:
INST_NAME("TEST Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@ -499,6 +519,25 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MOV32w(x2, u8);
emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
INST_NAME("MOV xH, Ib");
u8 = F8;
MOV32w(x1, u8);
if(rex.rex) {
gb1 = xRAX+(opcode&7)+(rex.b<<3);
ANDI(gb1, gb1, ~0xff);
OR(gb1, gb1, x1);
} else {
gb1 = xRAX+(opcode&3);
MOV64x(x2, 0xffffffffffff00ffLL);
AND(gb1, gb1, x2);
SLLI(x1, x1, 8);
OR(gb1, gb1, x1);
}
break;
case 0xB8:
case 0xB9:
case 0xBA:

View File

@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t u8;
uint8_t gd, ed, eb1, eb2, gb1, gb2;
uint8_t wback, wb1, wb2, wb;
int64_t i64, j64;
int v0, v1;
int q0;
int d0;
int64_t fixedaddress;
int unscaled;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(j64);
MAYUSE(d0);
MAYUSE(q0);
MAYUSE(v0);
MAYUSE(v1);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MVxw(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
ADD(x4, ed, x4);
LDxw(gd, x4, 0);
}
break;
default:
DEFAULT;
}
return addr;
}

View File

@ -85,6 +85,23 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
// just use regular conditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 1: // OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV64x(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
default:
DEFAULT;
}
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {

View File

@ -96,6 +96,37 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
}
}
// 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();
IFX(X_PEND) {
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
OR(s1, s1, s2);
SLLI(s1, s1, 48);
SRLI(s1, s1, 48);
IFX(X_PEND) {
SD(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
@ -110,6 +141,7 @@ void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}

View File

@ -481,6 +481,31 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w)
SET_NODF();
}
void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment)
{
(void)addr;
int64_t j64;
MAYUSE(j64);
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
int t1 = x1, t2 = x4;
if(reg==t1) ++t1;
if(reg==t2) ++t2;
LWU(t2, xEmu, offsetof(x64emu_t, segs_serial[segment]));
LD(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
if(segment==_GS) {
CBNZ_MARKSEG(t2); // fast check
} else {
LD(t1, xEmu, offsetof(x64emu_t, context));
LWU(t1, t1, offsetof(box64context_t, sel_serial));
SUBW(t1, t1, t2);
CBZ_MARKSEG(t1);
}
MOV64x(x1, segment);
call_c(dyn, ninst, GetSegmentBaseEmu, t2, reg, 1, 0);
MARKSEG;
MESSAGE(LOG_DUMP, "----%s Offset\n", (segment==_FS)?"FS":"GS");
}
void fpu_reset(dynarec_rv64_t* dyn)
{
//TODO

View File

@ -176,6 +176,20 @@
wb1 = 1; \
ed = i; \
}
//GETGB will use i for gd
#define GETGB(i) if(rex.rex) { \
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
gb2 = 0; \
} else { \
gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
gb1 = xRAX+(gd&3); \
} \
gd = i; \
MV(gd, gb1); \
if (gb2) SRLI(gd, gd, gb2*8); \
ANDI(gd, gd, 0xff);
// CALL will use x6 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL(F, ret) call_c(dyn, ninst, F, x6, ret, 1, 0)
@ -233,6 +247,15 @@
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;\
B(j64)
// Branch to MARKSEG if reg is 0 (use j64)
#define CBZ_MARKSEG(reg) \
j64 = GETMARKSEG-(dyn->native_size); \
BEQZ(reg, j64);
// Branch to MARKSEG if reg is not 0 (use j64)
#define CBNZ_MARKSEG(reg) \
j64 = GETMARKSEG-(dyn->native_size); \
BNEZ(reg, j64);
#define IFX(A) if((dyn->insts[ninst].x64.gen_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.gen_flags&(X_PEND) || !dyn->insts[ninst].x64.gen_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.gen_flags==(A)))
@ -605,7 +628,7 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, int n);
//void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits);
void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w);
//void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6);
//void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6);
@ -640,7 +663,7 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
//void emit_add16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
//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_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_xor16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
@ -745,7 +768,7 @@ void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07);
uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
//uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
//uintptr_t dynarec64_65(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);

View File

@ -174,6 +174,8 @@ f2831 ft811 FP temporaries Caller
// rd = rs1 - rs2
#define SUB(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b000, rd, 0b0110011))
// rd = rs1 - rs2
#define SUBW(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b000, rd, 0b0111011))
// rd = rs1 - rs2
#define SUBxw(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b000, rd, rex.w?0b0110011:0b0111011))
// rd = rs1<<rs2
#define SLL(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b001, rd, 0b0110011))