mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
More ARM32 NEON encoding horrors (VMOVL, VSHLL)
This commit is contained in:
parent
cd1665e8f6
commit
0be2b93ceb
@ -2723,7 +2723,22 @@ void ARMXEmitter::VSHL(u32 Size, ARMReg Vd, ARMReg Vm, int shiftAmount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARMXEmitter::VSHLL(u32 Size, ARMReg Vd, ARMReg Vm, int shiftAmount) {
|
void ARMXEmitter::VSHLL(u32 Size, ARMReg Vd, ARMReg Vm, int shiftAmount) {
|
||||||
EncodeShiftByImm((Size & ~I_UNSIGNED), Vd, Vm, shiftAmount, 0xA, false, false, false);
|
if (shiftAmount == (8 * (Size & 0xF))) {
|
||||||
|
// Entirely different encoding (A2) for size == shift! Bleh.
|
||||||
|
int sz = 0;
|
||||||
|
switch (Size & 0xF) {
|
||||||
|
case I_8: sz = 0; break;
|
||||||
|
case I_16: sz = 1; break;
|
||||||
|
case I_32: sz = 2; break;
|
||||||
|
case I_64:
|
||||||
|
_dbg_assert_msg_(JIT, false, "Cannot VSHLL 64-bit elements");
|
||||||
|
}
|
||||||
|
int imm6 = 0x32 | (sz << 2);
|
||||||
|
u32 value = (0xF3 << 24) | (1 << 23) | (imm6 << 16) | EncodeVd(Vd) | (0x3 << 8) | EncodeVm(Vm);
|
||||||
|
Write32(value);
|
||||||
|
} else {
|
||||||
|
EncodeShiftByImm((Size & ~I_UNSIGNED), Vd, Vm, shiftAmount, 0xA, false, false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMXEmitter::VSHR(u32 Size, ARMReg Vd, ARMReg Vm, int shiftAmount) {
|
void ARMXEmitter::VSHR(u32 Size, ARMReg Vd, ARMReg Vm, int shiftAmount) {
|
||||||
|
@ -476,10 +476,10 @@ static bool DisasmNeon2Op(uint32_t op, char *text) {
|
|||||||
if (op & (1 << 16))
|
if (op & (1 << 16))
|
||||||
opname = "NEG";
|
opname = "NEG";
|
||||||
|
|
||||||
int type = (op >> 6) & 0xF;
|
int opcode = (op >> 6) & 0xF;
|
||||||
int sz = (op >> 18) & 3;
|
int sz = (op >> 18) & 3;
|
||||||
const char *size = "f32";
|
const char *size = "f32";
|
||||||
switch (type) {
|
switch (opcode) {
|
||||||
case 0xE:
|
case 0xE:
|
||||||
opname = "NEG";
|
opname = "NEG";
|
||||||
size = GetISizeString(sz);
|
size = GetISizeString(sz);
|
||||||
@ -499,13 +499,24 @@ static bool DisasmNeon2Op(uint32_t op, char *text) {
|
|||||||
quadD = false;
|
quadD = false;
|
||||||
doubleD = true;
|
doubleD = true;
|
||||||
break;
|
break;
|
||||||
|
case 0xC:
|
||||||
|
opname = "SHLL"; // widen and shift
|
||||||
|
size = GetISizeString(sz);
|
||||||
|
quad = false;
|
||||||
|
quadD = true;
|
||||||
|
doubleD = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Vd = GetVd(op, quadD, doubleD);
|
int Vd = GetVd(op, quadD, doubleD);
|
||||||
int Vm = GetVm(op, quad, false);
|
int Vm = GetVm(op, quad, false);
|
||||||
char cD = quadD ? 'q' : 'd';
|
char cD = quadD ? 'q' : 'd';
|
||||||
char c = quad ? 'q' : 'd';
|
char c = quad ? 'q' : 'd';
|
||||||
sprintf(text, "V%s%s%s %c%i, %c%i", opname, strlen(size) ? "." : "", size, cD, Vd, c, Vm);
|
if (opcode == 0xC) {
|
||||||
|
sprintf(text, "V%s%s%s %c%i, %c%i, #%d", opname, strlen(size) ? "." : "", size, cD, Vd, c, Vm, 8 << sz);
|
||||||
|
} else {
|
||||||
|
sprintf(text, "V%s%s%s %c%i, %c%i", opname, strlen(size) ? "." : "", size, cD, Vd, c, Vm);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,6 +616,7 @@ to64:
|
|||||||
return "i32";
|
return "i32";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// What a horror show!
|
||||||
static bool DisasmNeon2RegShiftImm(uint32_t op, char *text) {
|
static bool DisasmNeon2RegShiftImm(uint32_t op, char *text) {
|
||||||
bool U = (op >> 24) & 1;
|
bool U = (op >> 24) & 1;
|
||||||
bool quadDest = false;
|
bool quadDest = false;
|
||||||
@ -617,7 +629,7 @@ static bool DisasmNeon2RegShiftImm(uint32_t op, char *text) {
|
|||||||
bool sign = false;
|
bool sign = false;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0x5: opname = "VSHL"; quadDest = quadSrc = ((op >> 6) & 1); break;
|
case 0x5: opname = "VSHL"; quadDest = quadSrc = ((op >> 6) & 1); break;
|
||||||
case 0xA: opname = "VSHLL"; quadDest = true; quadSrc = false; break;
|
case 0xA: opname = "VSHLL"; quadDest = true; quadSrc = false; sign = true; break;
|
||||||
case 0x0: opname = "VSHR"; sign = true; quadDest = quadSrc = ((op >> 6) & 1); inverse = true; break;
|
case 0x0: opname = "VSHR"; sign = true; quadDest = quadSrc = ((op >> 6) & 1); inverse = true; break;
|
||||||
case 0x8: opname = "VSHRN"; quadDest = false; quadSrc = true; inverse = true; incSize = true; break;
|
case 0x8: opname = "VSHRN"; quadDest = false; quadSrc = true; inverse = true; incSize = true; break;
|
||||||
default:
|
default:
|
||||||
@ -632,8 +644,23 @@ static bool DisasmNeon2RegShiftImm(uint32_t op, char *text) {
|
|||||||
char c2 = quadSrc ? 'q' : 'd';
|
char c2 = quadSrc ? 'q' : 'd';
|
||||||
int imm7 = ((op >> 16) & 0x3f) | ((op & 0x80) >> 1);
|
int imm7 = ((op >> 16) & 0x3f) | ((op & 0x80) >> 1);
|
||||||
int shift;
|
int shift;
|
||||||
const char *size = DecodeSizeAndShiftImm7(U, sign, inverse, imm7, incSize, &shift);
|
|
||||||
sprintf(text, "%s.%s %c%i, %c%i, #%i", opname, size, c1, Vd, c2, Vm, shift);
|
const char *size;
|
||||||
|
if (opcode == 0xA) {
|
||||||
|
if (imm7 & 0x40) {
|
||||||
|
sprintf(text, "neon2regshiftimm undefined %08x", op);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = DecodeSizeAndShiftImm7(U, sign, inverse, imm7, incSize, &shift);
|
||||||
|
|
||||||
|
if (opcode == 0xA && shift == 0) {
|
||||||
|
opname = "VMOVL";
|
||||||
|
sprintf(text, "%s.%s %c%i, %c%i", opname, size, c1, Vd, c2, Vm);
|
||||||
|
} else {
|
||||||
|
sprintf(text, "%s.%s %c%i, %c%i, #%i", opname, size, c1, Vd, c2, Vm, shift);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,16 @@ bool TestArmEmitter() {
|
|||||||
|
|
||||||
u32 code[512];
|
u32 code[512];
|
||||||
ARMXEmitter emitter((u8 *)code);
|
ARMXEmitter emitter((u8 *)code);
|
||||||
|
emitter.VSHLL(I_16, Q0, D0, 16);
|
||||||
|
RET(CheckLast(emitter, "f3b60300 VSHLL.i16 q0, d0, #16"));
|
||||||
|
emitter.VSHLL(I_8, Q0, D0, 4);
|
||||||
|
RET(CheckLast(emitter, "f28c0a10 VSHLL.s8 q0, d0, #4"));
|
||||||
|
emitter.VSHLL(I_8, Q0, D0, 8);
|
||||||
|
RET(CheckLast(emitter, "f3b20300 VSHLL.i8 q0, d0, #8"));
|
||||||
|
emitter.VMOVL(I_16 | I_UNSIGNED, Q0, D0);
|
||||||
|
RET(CheckLast(emitter, "f3900a10 VMOVL.u16 q0, d0"));
|
||||||
|
emitter.VMOVL(I_32 | I_SIGNED, Q0, D0);
|
||||||
|
RET(CheckLast(emitter, "f2a00a10 VMOVL.s32 q0, d0"));
|
||||||
emitter.VSHRN(I_32, D0, Q0, 16);
|
emitter.VSHRN(I_32, D0, Q0, 16);
|
||||||
RET(CheckLast(emitter, "f2900810 VSHRN.i32 d0, q0, #16"));
|
RET(CheckLast(emitter, "f2900810 VSHRN.i32 d0, q0, #16"));
|
||||||
emitter.VSHRN(I_64, D1, Q2, 24);
|
emitter.VSHRN(I_64, D1, Q2, 24);
|
||||||
@ -53,7 +63,7 @@ bool TestArmEmitter() {
|
|||||||
emitter.VSHL(I_8, D1, D2, 7);
|
emitter.VSHL(I_8, D1, D2, 7);
|
||||||
RET(CheckLast(emitter, "f28f1512 VSHL.i8 d1, d2, #7"));
|
RET(CheckLast(emitter, "f28f1512 VSHL.i8 d1, d2, #7"));
|
||||||
emitter.VSHLL(I_32, Q1, D2, 17);
|
emitter.VSHLL(I_32, Q1, D2, 17);
|
||||||
RET(CheckLast(emitter, "f2b12a12 VSHLL.i32 q1, d2, #17"));
|
RET(CheckLast(emitter, "f2b12a12 VSHLL.s32 q1, d2, #17"));
|
||||||
emitter.LDR(R3, R7);
|
emitter.LDR(R3, R7);
|
||||||
RET(CheckLast(emitter, "e5973000 LDR r3, [r7, #0]"));
|
RET(CheckLast(emitter, "e5973000 LDR r3, [r7, #0]"));
|
||||||
emitter.VLDR(S3, R8, 48);
|
emitter.VLDR(S3, R8, 48);
|
||||||
|
Loading…
Reference in New Issue
Block a user