Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LA64_DYNAREC] Added more opcodes #1447

Merged
merged 10 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/dynarec/la64/dynarec_la64_00.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,15 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
i64 = F32S;
emit_sub32c(dyn, ninst, rex, xRAX, i64, x2, x3, x4, x5);
break;
case 0x30:
INST_NAME("XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_xor8(dyn, ninst, x1, x2, x4, x5);
EBBACK();
break;
case 0x31:
INST_NAME("XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
Expand Down Expand Up @@ -1002,6 +1011,21 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
gb1 = TO_LA64(opcode & 3);
BSTRINS_D(gb1, x1, 7, 0);
break;
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
INST_NAME("MOV xH, Ib");
u8 = F8;
MOV32w(x1, u8);
if (rex.rex) {
gb1 = TO_LA64((opcode & 7) + (rex.b << 3));
BSTRINS_D(gb1, x1, 7, 0);
} else {
gb1 = TO_LA64(opcode & 3);
BSTRINS_D(gb1, x1, 15, 8);
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
Expand Down
15 changes: 15 additions & 0 deletions src/dynarec/la64/dynarec_la64_0f.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni

#undef GO

case 0x57:
INST_NAME("XORPS Gx, Ex");
nextop = F8;
GETG;
if (MODREG && ((nextop & 7) + (rex.b << 3) == gd)) {
// special case for XORPS Gx, Gx
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VXOR_V(q0, q0, q0);
} else {
q0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(q1, 0, 0);
VXOR_V(q0, q0, q1);
}
break;

#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
i32_ = F32S; \
Expand Down
40 changes: 40 additions & 0 deletions src/dynarec/la64/dynarec_la64_66.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,50 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x81:
case 0x83:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0: // ADD
if (opcode == 0x81) {
INST_NAME("ADD Ew, Iw");
} else {
INST_NAME("ADD 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_add16(dyn, ninst, ed, x5, x2, x4, x6);
EWBACK;
break;
case 5: // SUB
if (opcode == 0x81) {
INST_NAME("SUB Ew, Iw");
} else {
INST_NAME("SUB Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
MOV32w(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 7: // CMP
if (opcode == 0x81) {
INST_NAME("CMP Ew, Iw");
Expand Down
21 changes: 21 additions & 0 deletions src/dynarec/la64/dynarec_la64_660f.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
FAKEED;
break;
case 0x61:
INST_NAME("PUNPCKLWD Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(q0, 0, 0);
VILVL_H(v0, q0, v0);
break;
case 0x6C:
INST_NAME("PUNPCKLQDQ Gx,Ex");
nextop = F8;
Expand Down Expand Up @@ -133,6 +140,20 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
BSTRINS_D(gd, x1, 15, 0);
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if (MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3));
VXOR_V(v1, v1, v1);
VEXTRINS_D(v1, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
FST_D(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
nextop = F8;
Expand Down
36 changes: 36 additions & 0 deletions src/dynarec/la64/dynarec_la64_emit_logic.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,42 @@
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"

// emit XOR8 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_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s4, d_xor8);
} else IFX (X_ALL) {
SET_DFNONE();
}

IFXA (X_ALL, la64_lbt) {
X64_XOR_B(s1, s2);
}

XOR(s1, s1, s2);
ANDI(s1, s1, 0xff);

IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}

if (la64_lbt) return;

CLEAR_FLAGS(s3);
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}

// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
Expand Down
116 changes: 116 additions & 0 deletions src/dynarec/la64/dynarec_la64_emit_math.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,77 @@ void emit_add8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
}
}

// emit ADD16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add16);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
OR(s3, s1, s2); // s3 = op1 | op2
AND(s4, s1, s2); // s4 = op1 & op2
}

IFXA (X_ALL, la64_lbt) {
X64_ADD_DU(s1, s2);
}

ADD_D(s1, s1, s2);

IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}

if (la64_lbt) {
BSTRPICK_D(s1, s1, 15, 0);
return;
}

CLEAR_FLAGS(s5);
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 14);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}

IFX (X_CF) {
SRLI_D(s3, s1, 16);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_CF);
}

BSTRPICK_D(s1, s1, 15, 0);

IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}

// emit SUB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
Expand Down Expand Up @@ -454,6 +525,51 @@ void emit_sub8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
emit_sub8(dyn, ninst, s1, s2, s3, s4, s5);
}

// emit SUB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub16);
} else IFX (X_ALL) {
SET_DFNONE();
}

IFXA (X_AF | X_CF | X_OF, !la64_lbt) {
// for later flag calculation
NOR(s5, xZR, s1);
}

IFXA (X_ALL, la64_lbt) {
X64_SUB_H(s1, s2);
}

SUB_W(s1, s1, s2);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}

if (la64_lbt) return;

CLEAR_FLAGS(s3);
SLLI_D(s1, s1, 48);
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRLI_D(s1, s1, 48);

CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 16);
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}

// emit SUB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
Expand Down
22 changes: 22 additions & 0 deletions src/dynarec/la64/dynarec_la64_f0.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,28 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETREX();

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 = TO_LA64((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;
LLxw(x1, wback, 0);
ADDxw(x4, x1, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND) {
emit_add32(dyn, ninst, rex, x1, gd, x3, x4, x5);
}
}
SMDMB();
break;
case 0x0F:
nextop = F8;
switch (nextop) {
Expand Down
6 changes: 6 additions & 0 deletions src/dynarec/la64/dynarec_la64_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,8 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
#define emit_add32c STEPNAME(emit_add32c)
#define emit_add8 STEPNAME(emit_add8)
#define emit_add8c STEPNAME(emit_add8c)
#define emit_add16 STEPNAME(emit_add16)
#define emit_sub16 STEPNAME(emit_sub16)
#define emit_sub32 STEPNAME(emit_sub32)
#define emit_sub32c STEPNAME(emit_sub32c)
#define emit_sub8 STEPNAME(emit_sub8)
Expand All @@ -705,6 +707,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
#define emit_or32c STEPNAME(emit_or32c)
#define emit_or8 STEPNAME(emit_or8)
#define emit_or8c STEPNAME(emit_or8c)
#define emit_xor8 STEPNAME(emit_xor8)
#define emit_xor8c STEPNAME(emit_xor8c)
#define emit_xor32 STEPNAME(emit_xor32)
#define emit_xor32c STEPNAME(emit_xor32c)
Expand Down Expand Up @@ -768,6 +771,8 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5);
void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_add8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4);
void emit_add16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_sub16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5);
void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
Expand All @@ -780,6 +785,7 @@ void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
void emit_or8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_or8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4);
void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
Expand Down
Loading