mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
ARM64 emitter/disasm: More scalar FPU instructions
This commit is contained in:
parent
ff758f58ad
commit
9a5a093105
4 changed files with 99 additions and 2 deletions
|
@ -2697,6 +2697,50 @@ void ARM64FloatEmitter::FDIV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
|||
{
|
||||
Emit2Source(0, 0, IsDouble(Rd), 1, Rd, Rn, Rm);
|
||||
}
|
||||
void ARM64FloatEmitter::FMAX(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
Emit2Source(0, 0, IsDouble(Rd), 4, Rd, Rn, Rm);
|
||||
}
|
||||
void ARM64FloatEmitter::FMIN(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
Emit2Source(0, 0, IsDouble(Rd), 5, Rd, Rn, Rm);
|
||||
}
|
||||
void ARM64FloatEmitter::FMAXNM(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
Emit2Source(0, 0, IsDouble(Rd), 6, Rd, Rn, Rm);
|
||||
}
|
||||
void ARM64FloatEmitter::FMINNM(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
Emit2Source(0, 0, IsDouble(Rd), 7, Rd, Rn, Rm);
|
||||
}
|
||||
void ARM64FloatEmitter::FNMUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
Emit2Source(0, 0, IsDouble(Rd), 8, Rd, Rn, Rm);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::FMADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
|
||||
Emit3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 0);
|
||||
}
|
||||
void ARM64FloatEmitter::FMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
|
||||
Emit3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 1);
|
||||
}
|
||||
void ARM64FloatEmitter::FNMADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
|
||||
Emit3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 2);
|
||||
}
|
||||
void ARM64FloatEmitter::FNMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
|
||||
Emit3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 3);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::Emit3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra, int opcode) {
|
||||
int type = isDouble ? 1 : 0;
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
Ra = DecodeReg(Ra);
|
||||
int o1 = opcode >> 1;
|
||||
int o0 = opcode & 1;
|
||||
m_emit->Write32((0x1F << 24) | (type << 22) | (o1 << 21) | (Rm << 16) | (o0 << 15) | (Ra << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
// Scalar floating point immediate
|
||||
void ARM64FloatEmitter::FMOV(ARM64Reg Rd, u32 imm)
|
||||
|
@ -3366,6 +3410,25 @@ bool ARM64XEmitter::TryEORI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) {
|
|||
}
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch, bool negate) {
|
||||
_assert_msg_(JIT, !IsDouble(Rd), "MOVI2F does not yet support double precision");
|
||||
if (value == 0.0) {
|
||||
FMOV(Rd, 0);
|
||||
if (negate) {
|
||||
FNEG(Rd, Rd);
|
||||
}
|
||||
// TODO: There are some other values we could generate with the float-imm instruction, like 1.0...
|
||||
} else {
|
||||
_assert_msg_(JIT, scratch != INVALID_REG, "Failed to find a way to generate FP immediate %f without scratch", value);
|
||||
u32 ival;
|
||||
if (negate) {
|
||||
value = -value;
|
||||
}
|
||||
memcpy(&ival, &value, sizeof(ival));
|
||||
m_emit->MOVI2R(scratch, ival);
|
||||
FMOV(Rd, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
|
||||
u32 val;
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
|
||||
#define DYNA_REC JIT
|
||||
|
||||
#ifdef FMAX
|
||||
#undef FMAX
|
||||
#endif
|
||||
#ifdef FMIN
|
||||
#undef FMIN
|
||||
#endif
|
||||
|
||||
namespace Arm64Gen
|
||||
{
|
||||
|
||||
|
@ -765,6 +772,17 @@ public:
|
|||
void FMUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FDIV(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FMAX(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FMIN(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FMAXNM(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FMINNM(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void FNMUL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
|
||||
// Scalar - 3 Source. Note - the accumulator is last on ARM!
|
||||
void FMADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
|
||||
void FMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
|
||||
void FNMADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
|
||||
void FNMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra);
|
||||
|
||||
// Scalar floating point immediate
|
||||
void FMOV(ARM64Reg Rd, u32 imm);
|
||||
|
@ -852,6 +870,8 @@ public:
|
|||
// vector x indexed element
|
||||
void FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index);
|
||||
|
||||
void MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG, bool negate = false);
|
||||
|
||||
// ABI related
|
||||
void ABI_PushRegisters(BitSet32 registers);
|
||||
void ABI_PopRegisters(BitSet32 registers, BitSet32 ignore_mask = BitSet32(0));
|
||||
|
@ -881,6 +901,7 @@ private:
|
|||
void EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm);
|
||||
void EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round, bool sign);
|
||||
void Emit3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra, int opcode);
|
||||
};
|
||||
|
||||
class ARM64CodeBlock : public CodeBlock<ARM64XEmitter>
|
||||
|
|
|
@ -518,8 +518,13 @@ static void FPandASIMD2(uint32_t w, uint64_t addr, Instruction *instr) {
|
|||
} else if (((w >> 10) & 3) == 3) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(float cond select %08x)", w);
|
||||
}
|
||||
} else if (((w >> 21) & 0x2F9) == 0xF8) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(float data 3-source %08x)", w);
|
||||
} else if (((w >> 21) & 0x2F8) == 0xF8) {
|
||||
int opcode = ((w >> 15) & 1) | ((w >> 20) & 2);
|
||||
const char *opnames[9] = { "fmadd", "fmsub", "fnmadd", "fnmsub" };
|
||||
int size = (w >> 22) & 1;
|
||||
char r = size ? 'd' : 's';
|
||||
int Ra = (w >> 10) & 0x1f;
|
||||
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, %c%d, %c%d", opnames[opcode], r, Rd, r, Rn, r, Rm, r, Ra);
|
||||
} else if (((w >> 21) & 0x2F9) == 0x2F1) {
|
||||
if (((w >> 10) & 3) == 0) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(asimd scalar three different %08x)", w);
|
||||
|
|
|
@ -38,6 +38,14 @@ bool TestArm64Emitter() {
|
|||
|
||||
//emitter.EXTR(W1, W3, 0, 7);
|
||||
//RET(CheckLast(emitter, "53033061 extr w1, w3, w7"));
|
||||
fp.FMADD(S1, S2, S3, S4);
|
||||
RET(CheckLast(emitter, "1f031041 fmadd s1, s2, s3, s4"));
|
||||
fp.FNMSUB(D1, D2, D3, D4);
|
||||
RET(CheckLast(emitter, "1f639041 fnmsub d1, d2, d3, d4"));
|
||||
fp.FMAX(S1, S2, S3);
|
||||
RET(CheckLast(emitter, "1e234841 fmax s1, s2, s3"));
|
||||
fp.FNMUL(D1, D2, D3);
|
||||
RET(CheckLast(emitter, "1e638841 fnmul d1, d2, d3"));
|
||||
fp.SCVTF(S13, W7);
|
||||
RET(CheckLast(emitter, "1e2200ed scvtf s13, w7"));
|
||||
emitter.UBFM(W1, W3, 0, 7);
|
||||
|
|
Loading…
Add table
Reference in a new issue