mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-27 00:30:32 +00:00
[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:
parent
01d1ea0b90
commit
e1ca614f1c
@ -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"
|
||||
|
@ -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:
|
||||
|
85
src/dynarec/rv64/dynarec_rv64_64.c
Normal file
85
src/dynarec/rv64/dynarec_rv64_64.c
Normal 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;
|
||||
}
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -174,6 +174,8 @@ f28–31 ft8–11 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))
|
||||
|
Loading…
Reference in New Issue
Block a user