diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index b7c30016b..a32a3aed8 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1347,12 +1347,24 @@ public: // SVE Stack Allocation // SVE stack frame adjustment + void addvl(XRegister rd, XRegister rn, int32_t imm) { + SVEStackFrameOperation(0b00, rd, rn, imm); + } + void addpl(XRegister rd, XRegister rn, int32_t imm) { + SVEStackFrameOperation(0b01, rd, rn, imm); + } + + // Streaming SVE stack frame adjustment (SME) // XXX: - // Streaming SVE stack frame adjustment - // XXX: + // SVE stack frame size - // XXX: - // Streaming SVE stack frame size + void rdvl(XRegister rd, int32_t imm) { + // Would-be Rn field is just set to all 1's, which is the same + // as writing the encoding for the SP into it. + SVEStackFrameOperation(0b10, rd, XReg::rsp, imm); + } + + // Streaming SVE stack frame size (SME) // XXX: // SVE2 Integer Multiply - Unpredicated @@ -4084,6 +4096,18 @@ private: dc32(Instr); } + void SVEStackFrameOperation(uint32_t opc, XRegister rd, XRegister rn, int32_t imm) { + LOGMAN_THROW_AA_FMT(imm >= -32 && imm <= 31, + "Stack frame operation immediate must be within -32 to 31"); + + uint32_t Instr = 0b0000'0100'0010'0000'0101'0000'0000'0000; + Instr |= opc << 22; + Instr |= rn.Idx() << 16; + Instr |= (static_cast(imm) & 0b111111) << 5; + Instr |= rd.Idx(); + dc32(Instr); + } + // SVE floating-point round to integral value void frintX(uint32_t opc, FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn) { // opc = round mode diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index fc3662736..c398a812c 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -889,13 +889,21 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE Index Generation") { // TODO: Implement in emitter. } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE stack frame adjustment") { - // TODO: Implement in emitter. + TEST_SINGLE(addvl(XReg::rsp, XReg::rsp, -32), "addvl sp, sp, #-32"); + TEST_SINGLE(addvl(XReg::rsp, XReg::rsp, 31), "addvl sp, sp, #31"); + TEST_SINGLE(addvl(XReg::x30, XReg::x29, 15), "addvl x30, x29, #15"); + + TEST_SINGLE(addpl(XReg::rsp, XReg::rsp, -32), "addpl sp, sp, #-32"); + TEST_SINGLE(addpl(XReg::rsp, XReg::rsp, 31), "addpl sp, sp, #31"); + TEST_SINGLE(addpl(XReg::x30, XReg::x29, 15), "addpl x30, x29, #15"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: Streaming SVE stack frame adjustment") { // TODO: Implement in emitter. } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE stack frame size") { - // TODO: Implement in emitter. + TEST_SINGLE(rdvl(XReg::x30, -32), "rdvl x30, #-32"); + TEST_SINGLE(rdvl(XReg::x30, 31), "rdvl x30, #31"); + TEST_SINGLE(rdvl(XReg::x30, 15), "rdvl x30, #15"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: Streaming SVE stack frame size") { // TODO: Implement in emitter.