diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h index 8e3bfe8da7..101a44445a 100644 --- a/Source/Core/DSPCore/Src/DSPEmitter.h +++ b/Source/Core/DSPCore/Src/DSPEmitter.h @@ -52,6 +52,8 @@ public: void Update_SR_Register64(Gen::X64Reg val = Gen::EAX); void Update_SR_Register64_Carry(Gen::X64Reg val = Gen::EAX); void Update_SR_Register64_Carry2(Gen::X64Reg val = Gen::EAX); + void Update_SR_Register16(Gen::X64Reg val = Gen::EAX); + void Update_SR_Register16_OverS32(Gen::X64Reg val = Gen::EAX); // Register helpers void setCompileSR(u16 bit); @@ -147,11 +149,31 @@ public: void ilrri(const UDSPInstruction opc); // Arithmetic + void clr(const UDSPInstruction opc); + void clrl(const UDSPInstruction opc); + void andcf(const UDSPInstruction opc); + void andf(const UDSPInstruction opc); void tst(const UDSPInstruction opc); + void tstaxh(const UDSPInstruction opc); + void cmp(const UDSPInstruction opc); + void cmpar(const UDSPInstruction opc); + void cmpi(const UDSPInstruction opc); + void cmpis(const UDSPInstruction opc); + void xorr(const UDSPInstruction opc); + void andr(const UDSPInstruction opc); + void orr(const UDSPInstruction opc); + void andc(const UDSPInstruction opc); + void orc(const UDSPInstruction opc); + void xorc(const UDSPInstruction opc); + void notc(const UDSPInstruction opc); + void xori(const UDSPInstruction opc); + void andi(const UDSPInstruction opc); + void ori(const UDSPInstruction opc); void addr(const UDSPInstruction opc); void addax(const UDSPInstruction opc); void add(const UDSPInstruction opc); void addp(const UDSPInstruction opc); + void addaxl(const UDSPInstruction opc); void addi(const UDSPInstruction opc); void addis(const UDSPInstruction opc); void incm(const UDSPInstruction opc); @@ -171,7 +193,15 @@ public: void lsr16(const UDSPInstruction opc); void asr16(const UDSPInstruction opc); void lsl(const UDSPInstruction opc); + void lsr(const UDSPInstruction opc); void asl(const UDSPInstruction opc); + void asr(const UDSPInstruction opc); + void lsrn(const UDSPInstruction opc); + void asrn(const UDSPInstruction opc); + void lsrnrx(const UDSPInstruction opc); + void asrnrx(const UDSPInstruction opc); + void lsrnr(const UDSPInstruction opc); + void asrnr(const UDSPInstruction opc); // Multipliers void get_multiply_prod(); @@ -192,6 +222,8 @@ public: void mulcac(const UDSPInstruction opc); void mulcmv(const UDSPInstruction opc); void mulcmvz(const UDSPInstruction opc); + void maddx(const UDSPInstruction opc); + void msubx(const UDSPInstruction opc); void maddc(const UDSPInstruction opc); void msubc(const UDSPInstruction opc); void madd(const UDSPInstruction opc); @@ -223,11 +255,13 @@ private: void get_long_prod(Gen::X64Reg long_prod = Gen::RAX); void get_long_prod_round_prodl(Gen::X64Reg long_prod = Gen::RAX); void set_long_prod(); + void round_long_acc(Gen::X64Reg long_acc = Gen::EAX); void set_long_acc(int _reg, Gen::X64Reg acc = Gen::EAX); - void get_acc_m(int _reg); + void get_acc_m(int _reg, Gen::X64Reg acc = Gen::EAX); + void set_acc_m(int _reg); void get_long_acx(int _reg, Gen::X64Reg acx = Gen::EAX); - void get_ax_l(int _reg); - void get_ax_h(int _reg); + void get_ax_l(int _reg, Gen::X64Reg acx = Gen::EAX); + void get_ax_h(int _reg, Gen::X64Reg acc = Gen::EAX); void get_long_acc(int _reg, Gen::X64Reg acc = Gen::EAX); }; diff --git a/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp b/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp index 9b439dade8..3629c6b4bc 100644 --- a/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp +++ b/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp @@ -111,8 +111,8 @@ void Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32) } } -void Update_SR_LZ(bool value) { - +void Update_SR_LZ(bool value) +{ if (value == true) g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO; else diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index 1f5f1618f0..118226eb0c 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -150,12 +150,12 @@ const DSPOPCTemplate opcodes[] = {"SBSET", 0x1300, 0xff00, DSPInterpreter::sbset, &DSPEmitter::sbset, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false, false, false, false}, {"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, &DSPEmitter::lsl, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, + {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, &DSPEmitter::lsr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, + {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, &DSPEmitter::asl, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, + {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, &DSPEmitter::asr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, NULL, 1, 0, {}, false, false, false, false, true}, // discovered by ector! - {"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, NULL, 1, 0, {}, false, false, false, false, true}, // discovered by ector! + {"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, &DSPEmitter::lsrn, 1, 0, {}, false, false, false, false, true}, // discovered by ector! + {"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, &DSPEmitter::asrn, 1, 0, {}, false, false, false, false, true}, // discovered by ector! {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, &DSPEmitter::lri, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, false}, {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, &DSPEmitter::lr, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, false, false, false, true, false}, @@ -166,17 +166,17 @@ const DSPOPCTemplate opcodes[] = {"SI", 0x1600, 0xff00, DSPInterpreter::si, &DSPEmitter::si, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, false}, {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, &DSPEmitter::addis, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, - {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, + {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, &DSPEmitter::cmpis, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, {"LRIS", 0x0800, 0xf800, DSPInterpreter::lris, &DSPEmitter::lris, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, {"ADDI", 0x0200, 0xfeff, DSPInterpreter::addi, &DSPEmitter::addi, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, NULL, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, NULL, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, NULL, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, NULL, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, + {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, &DSPEmitter::xori, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, + {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, &DSPEmitter::andi, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, + {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, &DSPEmitter::ori, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, + {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, &DSPEmitter::cmpi, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, NULL, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andcf, NULL, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, + {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, &DSPEmitter::andf, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, + {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andcf, &DSPEmitter::andcf, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, {"ILRR", 0x0210, 0xfefc, DSPInterpreter::ilrr, &DSPEmitter::ilrr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, {"ILRRD", 0x0214, 0xfefc, DSPInterpreter::ilrrd, &DSPEmitter::ilrrd, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, @@ -207,17 +207,17 @@ const DSPOPCTemplate opcodes[] = // opcodes that can be extended //3 - main opcode defined by 9 bits, extension defined by last 7 bits!! - {"XORR", 0x3000, 0xfc80, DSPInterpreter::xorr, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ANDR", 0x3400, 0xfc80, DSPInterpreter::andr, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ORR", 0x3800, 0xfc80, DSPInterpreter::orr, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ANDC", 0x3c00, 0xfe80, DSPInterpreter::andc, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"ORC", 0x3e00, 0xfe80, DSPInterpreter::orc, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"XORC", 0x3080, 0xfe80, DSPInterpreter::xorc, NULL, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"NOT", 0x3280, 0xfe80, DSPInterpreter::notc, NULL, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"LSRNRX", 0x3480, 0xfc80, DSPInterpreter::lsrnrx, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ASRNRX", 0x3880, 0xfc80, DSPInterpreter::asrnrx, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"LSRNR", 0x3c80, 0xfe80, DSPInterpreter::lsrnr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"ASRNR", 0x3e80, 0xfe80, DSPInterpreter::asrnr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"XORR", 0x3000, 0xfc80, DSPInterpreter::xorr, &DSPEmitter::xorr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, + {"ANDR", 0x3400, 0xfc80, DSPInterpreter::andr, &DSPEmitter::andr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, + {"ORR", 0x3800, 0xfc80, DSPInterpreter::orr, &DSPEmitter::orr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, + {"ANDC", 0x3c00, 0xfe80, DSPInterpreter::andc, &DSPEmitter::andc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"ORC", 0x3e00, 0xfe80, DSPInterpreter::orc, &DSPEmitter::orc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"XORC", 0x3080, 0xfe80, DSPInterpreter::xorc, &DSPEmitter::xorc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"NOT", 0x3280, 0xfe80, DSPInterpreter::notc, &DSPEmitter::notc, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"LSRNRX", 0x3480, 0xfc80, DSPInterpreter::lsrnrx, &DSPEmitter::lsrnrx, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, + {"ASRNRX", 0x3880, 0xfc80, DSPInterpreter::asrnrx, &DSPEmitter::asrnrx, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, + {"LSRNR", 0x3c80, 0xfe80, DSPInterpreter::lsrnr, &DSPEmitter::lsrnr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"ASRNR", 0x3e80, 0xfe80, DSPInterpreter::asrnr, &DSPEmitter::asrnr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, //4 {"ADDR", 0x4000, 0xf800, DSPInterpreter::addr, &DSPEmitter::addr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true, false, false, false, true}, @@ -238,7 +238,7 @@ const DSPOPCTemplate opcodes[] = {"MOVP", 0x6e00, 0xfe00, DSPInterpreter::movp, &DSPEmitter::movp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, //7 - {"ADDAXL", 0x7000, 0xfc00, DSPInterpreter::addaxl, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true, false, false, false, true}, + {"ADDAXL", 0x7000, 0xfc00, DSPInterpreter::addaxl, &DSPEmitter::addaxl, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true, false, false, false, true}, {"INCM", 0x7400, 0xfe00, DSPInterpreter::incm, &DSPEmitter::incm, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"INC", 0x7600, 0xfe00, DSPInterpreter::inc, &DSPEmitter::inc, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"DECM", 0x7800, 0xfe00, DSPInterpreter::decm, &DSPEmitter::decm, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, @@ -248,12 +248,12 @@ const DSPOPCTemplate opcodes[] = //8 {"NX", 0x8000, 0xf700, DSPInterpreter::nx, &DSPEmitter::nx, 1, 0, {}, true, false, false, false, false}, - {"CLR", 0x8100, 0xf700, DSPInterpreter::clr, NULL, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"CMP", 0x8200, 0xff00, DSPInterpreter::cmp, NULL, 1, 0, {}, true, false, false, false, true}, + {"CLR", 0x8100, 0xf700, DSPInterpreter::clr, &DSPEmitter::clr, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false, false, true}, + {"CMP", 0x8200, 0xff00, DSPInterpreter::cmp, &DSPEmitter::cmp, 1, 0, {}, true, false, false, false, true}, {"MULAXH", 0x8300, 0xff00, DSPInterpreter::mulaxh, &DSPEmitter::mulaxh, 1, 0, {}, true, false, false, false, true}, {"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, &DSPEmitter::clrp, 1, 0, {}, true, false, false, false, true}, {"TSTPROD", 0x8500, 0xff00, DSPInterpreter::tstprod, &DSPEmitter::tstprod,1, 0, {}, true, false, false, false, true}, - {"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, NULL, 1, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true, false, false, false, true}, + {"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, &DSPEmitter::tstaxh, 1, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, {"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, {"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, @@ -278,14 +278,14 @@ const DSPOPCTemplate opcodes[] = //c-d {"MULC", 0xc000, 0xe700, DSPInterpreter::mulc, &DSPEmitter::mulc, 1, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"CMPAR" , 0xc100, 0xe700, DSPInterpreter::cmpar, NULL, 1, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false, false, true}, + {"CMPAR" , 0xc100, 0xe700, DSPInterpreter::cmpar, &DSPEmitter::cmpar, 1, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false, false, true}, {"MULCMVZ", 0xc200, 0xe600, DSPInterpreter::mulcmvz, &DSPEmitter::mulcmvz,1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"MULCAC", 0xc400, 0xe600, DSPInterpreter::mulcac, &DSPEmitter::mulcac, 1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"MULCMV", 0xc600, 0xe600, DSPInterpreter::mulcmv, &DSPEmitter::mulcmv, 1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, //e - {"MADDX", 0xe000, 0xfc00, DSPInterpreter::maddx, NULL, 1, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, - {"MSUBX", 0xe400, 0xfc00, DSPInterpreter::msubx, NULL, 1, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, + {"MADDX", 0xe000, 0xfc00, DSPInterpreter::maddx, &DSPEmitter::maddx, 1, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, + {"MSUBX", 0xe400, 0xfc00, DSPInterpreter::msubx, &DSPEmitter::msubx, 1, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, {"MADDC", 0xe800, 0xfc00, DSPInterpreter::maddc, &DSPEmitter::maddc, 1, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, {"MSUBC", 0xec00, 0xfc00, DSPInterpreter::msubc, &DSPEmitter::msubc, 1, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, @@ -295,7 +295,7 @@ const DSPOPCTemplate opcodes[] = {"LSR16", 0xf400, 0xfe00, DSPInterpreter::lsr16, &DSPEmitter::lsl16, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"MSUB", 0xf600, 0xfe00, DSPInterpreter::msub, &DSPEmitter::msub, 1, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true, false, false, false, true}, {"ADDPAXZ", 0xf800, 0xfc00, DSPInterpreter::addpaxz, NULL, 1, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_AX, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"CLRL", 0xfc00, 0xfe00, DSPInterpreter::clrl, NULL, 1, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true, false, false, false, true}, + {"CLRL", 0xfc00, 0xfe00, DSPInterpreter::clrl, &DSPEmitter::clrl, 1, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true, false, false, false, true}, {"MOVPZ", 0xfe00, 0xfe00, DSPInterpreter::movpz, &DSPEmitter::movpz, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, }; diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp index 627f902aab..57431a16b9 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp @@ -30,30 +30,46 @@ using namespace Gen; // Clears accumulator $acR // // flags out: --10 0100 -//void DSPEmitter::clr(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 11) & 0x1; - +void DSPEmitter::clr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 reg = (opc >> 11) & 0x1; // dsp_set_long_acc(reg, 0); + MOV(64, R(RAX), Imm64(0)); + set_long_acc(reg); // Update_SR_Register64(0); -// zeroWriteBackLog(); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(); + } +#else + Default(opc); +#endif +} // CLRL $acR.l // 1111 110r xxxx xxxx // Clears (and rounds!) $acR.l - low 16 bits of accumulator $acR. // // flags out: --xx xx00 -//void DSPEmitter::clrl(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; +void DSPEmitter::clrl(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 reg = (opc >> 8) & 0x1; // s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg)); - -// zeroWriteBackLog(); - + get_long_acc(reg); + round_long_acc(); // dsp_set_long_acc(reg, acc); + set_long_acc(reg); // Update_SR_Register64(acc); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(); + } +#else + Default(opc); +#endif +} //---- @@ -64,14 +80,34 @@ using namespace Gen; // accumulator mid part $acD.m with immediate value I is equal I. // // flags out: -x-- ---- -//void DSPEmitter::andcf(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; - -// u16 imm = dsp_fetch_code(); -// u16 val = dsp_get_acc_m(reg); -// Update_SR_LZ(((val & imm) == imm) ? true : false); -//} +void DSPEmitter::andcf(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + u8 reg = (opc >> 8) & 0x1; +// u16 imm = dsp_fetch_code(); + u16 imm = dsp_imem_read(compilePC+1); +// u16 val = dsp_get_acc_m(reg); + get_acc_m(reg); +// Update_SR_LZ(((val & imm) == imm) ? true : false); +// if ((val & imm) == imm) +// g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO; +// else +// g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO; + AND(16, R(RAX), Imm16(imm)); + CMP(16, R(RAX), Imm16(imm)); + FixupBranch notLogicZero = J_CC(CC_NE); + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_LOGIC_ZERO)); + FixupBranch exit = J(); + SetJumpTarget(notLogicZero); + AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_LOGIC_ZERO)); + SetJumpTarget(exit); + } +#else + Default(opc); +#endif +} // ANDF $acD.m, #I // 0000 001r 1010 0000 @@ -81,14 +117,34 @@ using namespace Gen; // immediate value 0. // // flags out: -x-- ---- -//void DSPEmitter::andf(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; - -// u16 imm = dsp_fetch_code(); -// u16 val = dsp_get_acc_m(reg); -// Update_SR_LZ(((val & imm) == 0) ? true : false); -//} +void DSPEmitter::andf(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + u8 reg = (opc >> 8) & 0x1; +// u16 imm = dsp_fetch_code(); + u16 imm = dsp_imem_read(compilePC+1); +// u16 val = dsp_get_acc_m(reg); + get_acc_m(reg); +// Update_SR_LZ(((val & imm) == 0) ? true : false); +// if ((val & imm) == 0) +// g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO; +// else +// g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO; + AND(16, R(RAX), Imm16(imm)); + CMP(16, R(RAX), Imm16(0)); + FixupBranch notLogicZero = J_CC(CC_NE); + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_LOGIC_ZERO)); + FixupBranch exit = J(); + SetJumpTarget(notLogicZero); + AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_LOGIC_ZERO)); + SetJumpTarget(exit); + } +#else + Default(opc); +#endif +} //---- @@ -118,14 +174,21 @@ void DSPEmitter::tst(const UDSPInstruction opc) // Test high part of secondary accumulator $axR.h. // // flags out: --x0 xx00 -//void DSPEmitter::tstaxh(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; - -// s16 val = dsp_get_ax_h(reg); -// Update_SR_Register16(val); -// zeroWriteBackLog(); -//} +void DSPEmitter::tstaxh(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + u8 reg = (opc >> 8) & 0x1; +// s16 val = dsp_get_ax_h(reg); + get_ax_h(reg); +// Update_SR_Register16(val); + Update_SR_Register16(); + } +#else + Default(opc); +#endif +} //---- @@ -134,15 +197,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // Compares accumulator $ac0 with accumulator $ac1. // // flags out: x-xx xxxx -//void DSPEmitter::cmp(const UDSPInstruction opc) -//{ -// s64 acc0 = dsp_get_long_acc(0); -// s64 acc1 = dsp_get_long_acc(1); -// s64 res = dsp_convert_long_acc(acc0 - acc1); -// -// Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100 -// zeroWriteBackLog(); -//} +void DSPEmitter::cmp(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { +// s64 acc0 = dsp_get_long_acc(0); + get_long_acc(0, RCX); + MOV(64, R(RAX), R(RCX)); +// s64 acc1 = dsp_get_long_acc(1); + get_long_acc(1, RDX); +// s64 res = dsp_convert_long_acc(acc0 - acc1); + SUB(64, R(RAX), R(RDX)); +// Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100 + NEG(64, R(RDX)); + Update_SR_Register64_Carry2(); + } +#else + Default(opc); +#endif +} // CMPAR $acS axR.h // 1100 0001 xxxx xxxx @@ -150,19 +224,31 @@ void DSPEmitter::tst(const UDSPInstruction opc) // Not described by Duddie's doc - at least not as a separate instruction. // // flags out: x-xx xxxx -//void DSPEmitter::cmpar(const UDSPInstruction opc) -//{ -// u8 rreg = ((opc >> 12) & 0x1) + DSP_REG_AXH0; -// u8 sreg = (opc >> 11) & 0x1; +void DSPEmitter::cmpar(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + u8 rreg = ((opc >> 12) & 0x1); + u8 sreg = (opc >> 11) & 0x1; -// s64 sr = dsp_get_long_acc(sreg); -// s64 rr = (s16)g_dsp.r[rreg]; -// rr <<= 16; -// s64 res = dsp_convert_long_acc(sr - rr); -// -// Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res)); -// zeroWriteBackLog(); -//} +// s64 sr = dsp_get_long_acc(sreg); + get_long_acc(sreg, RCX); + MOV(64, R(RAX), R(RCX)); +// s64 rr = (s16)g_dsp.r[rreg]; + get_ax_h(rreg, RDX); +// rr <<= 16; + SHL(64, R(RDX), Imm8(16)); +// s64 res = dsp_convert_long_acc(sr - rr); + SUB(64, R(RAX), R(RDX)); +// Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res)); + NEG(64, R(RDX)); + Update_SR_Register64_Carry2(); + } +#else + Default(opc); +#endif +} // CMPI $amD, #I // 0000 001r 1000 0000 @@ -171,16 +257,28 @@ void DSPEmitter::tst(const UDSPInstruction opc) // Although flags are being set regarding whole accumulator register. // // flags out: x-xx xxxx -//void DSPEmitter::cmpi(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; - -// s64 val = dsp_get_long_acc(reg); -// s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in the 40-bit accumulator. -// s64 res = dsp_convert_long_acc(val - imm); - -// Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res)); -//} +void DSPEmitter::cmpi(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + u8 reg = (opc >> 8) & 0x1; +// s64 val = dsp_get_long_acc(reg); + get_long_acc(reg, RCX); + MOV(64, R(RAX), R(RCX)); +// s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in the 40-bit accumulator. + u16 imm = dsp_imem_read(compilePC+1); + MOV(64, R(RDX), Imm64((s64)(s16)imm << 16)); +// s64 res = dsp_convert_long_acc(val - imm); + SUB(64, R(RAX), R(RDX)); +// Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res)); + NEG(64, R(RDX)); + Update_SR_Register64_Carry2(); + } +#else + Default(opc); +#endif +} // CMPIS $acD, #I // 0000 011d iiii iiii @@ -189,17 +287,28 @@ void DSPEmitter::tst(const UDSPInstruction opc) // $acD.hm and computing flags based on whole accumulator $acD. // // flags out: x-xx xxxx -//void DSPEmitter::cmpis(const UDSPInstruction opc) -//{ -// u8 areg = (opc >> 8) & 0x1; - -// s64 acc = dsp_get_long_acc(areg); -// s64 val = (s8)opc; -// val <<= 16; -// s64 res = dsp_convert_long_acc(acc - val); - -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res)); -//} +void DSPEmitter::cmpis(const UDSPInstruction opc) +{ +#ifdef _M_X64 + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + u8 areg = (opc >> 8) & 0x1; +// s64 acc = dsp_get_long_acc(areg); + get_long_acc(areg, RCX); + MOV(64, R(RAX), R(RCX)); +// s64 val = (s8)opc; +// val <<= 16; + MOV(64, R(RDX), Imm64((s64)(s8)opc << 16)); +// s64 res = dsp_convert_long_acc(acc - val); + SUB(64, R(RAX), R(RDX)); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res)); + NEG(64, R(RDX)); + Update_SR_Register64_Carry2(); + } +#else + Default(opc); +#endif +} //---- @@ -210,17 +319,27 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::xorr(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; +void DSPEmitter::xorr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_AXH0 + sreg]; -// -// zeroWriteBackLogPreserveAcc(dreg); - + get_acc_m(dreg, RAX); + get_ax_h(sreg, RDX); + XOR(64, R(RAX), R(RDX)); // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // ANDR $acD.m, $axS.h // 0011 01sd 0xxx xxxx @@ -229,17 +348,27 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::andr(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; -// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_AXH0 + sreg]; -// -// zeroWriteBackLogPreserveAcc(dreg); - -// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} +void DSPEmitter::andr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; + // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_AXH0 + sreg]; + get_acc_m(dreg, RAX); + get_ax_h(sreg, RDX); + AND(64, R(RAX), R(RDX)); + // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); + // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // ORR $acD.m, $axS.h // 0011 10sd 0xxx xxxx @@ -248,17 +377,27 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::orr(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; -// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_AXH0 + sreg]; -// -// zeroWriteBackLogPreserveAcc(dreg); - -// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} +void DSPEmitter::orr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; + // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_AXH0 + sreg]; + get_acc_m(dreg, RAX); + get_ax_h(sreg, RDX); + OR(64, R(RAX), R(RDX)); + // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); + // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // ANDC $acD.m, $ac(1-D).m // 0011 110d 0xxx xxxx @@ -267,16 +406,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::andc(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; +void DSPEmitter::andc(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; -// -// zeroWriteBackLogPreserveAcc(dreg); - -// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} + get_acc_m(dreg, RAX); + get_acc_m(1 - dreg, RDX); + AND(64, R(RAX), R(RDX)); + // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); + // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // ORC $acD.m, $ac(1-D).m // 0011 111d 0xxx xxxx @@ -285,16 +434,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::orc(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; -// -// zeroWriteBackLogPreserveAcc(dreg); - -// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} +void DSPEmitter::orc(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; + get_acc_m(dreg, RAX); + get_acc_m(1 - dreg, RDX); + OR(64, R(RAX), R(RDX)); + // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); + // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // XORC $acD.m // 0011 000d 1xxx xxxx @@ -302,16 +461,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::xorc(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; - -// zeroWriteBackLogPreserveAcc(dreg); - -// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} +void DSPEmitter::xorc(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; + get_acc_m(dreg, RAX); + get_acc_m(1 - dreg, RDX); + XOR(64, R(RAX), R(RDX)); + // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); + // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // NOT $acD.m // 0011 001d 1xxx xxxx @@ -319,16 +488,25 @@ void DSPEmitter::tst(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::notc(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; +void DSPEmitter::notc(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; // u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ 0xffff; - -// zeroWriteBackLogPreserveAcc(dreg); - + get_acc_m(dreg, RAX); + XOR(16, R(RAX), Imm16(0xffff)); // g_dsp.r[DSP_REG_ACM0 + dreg] = accm; + set_acc_m(dreg); // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(dreg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // XORI $acD.m, #I // 0000 001r 0010 0000 @@ -337,14 +515,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // immediate value I. // // flags out: --xx xx00 -//void DSPEmitter::xori(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; +void DSPEmitter::xori(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 reg = (opc >> 8) & 0x1; // u16 imm = dsp_fetch_code(); + u16 imm = dsp_imem_read(compilePC+1); // g_dsp.r[DSP_REG_ACM0 + reg] ^= imm; - + get_acc_m(reg, RAX); + XOR(16, R(RAX), Imm16(imm)); + set_acc_m(reg); // Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(reg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // ANDI $acD.m, #I // 0000 001r 0100 0000 @@ -352,14 +542,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // Logic AND of accumulator mid part $acD.m with immediate value I. // // flags out: --xx xx00 -//void DSPEmitter::andi(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; +void DSPEmitter::andi(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 reg = (opc >> 8) & 0x1; // u16 imm = dsp_fetch_code(); + u16 imm = dsp_imem_read(compilePC+1); // g_dsp.r[DSP_REG_ACM0 + reg] &= imm; - + get_acc_m(reg, RAX); + AND(16, R(RAX), Imm16(imm)); + set_acc_m(reg); // Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(reg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} // ORI $acD.m, #I // 0000 001r 0110 0000 @@ -367,14 +569,26 @@ void DSPEmitter::tst(const UDSPInstruction opc) // Logic OR of accumulator mid part $acD.m with immediate value I. // // flags out: --xx xx00 -//void DSPEmitter::ori(const UDSPInstruction opc) -//{ -// u8 reg = (opc >> 8) & 0x1; -// u16 imm = dsp_fetch_code(); -// g_dsp.r[DSP_REG_ACM0 + reg] |= imm; - -// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); -//} +void DSPEmitter::ori(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 reg = (opc >> 8) & 0x1; + // u16 imm = dsp_fetch_code(); + u16 imm = dsp_imem_read(compilePC+1); + // g_dsp.r[DSP_REG_ACM0 + reg] |= imm; + get_acc_m(reg, RAX); + OR(16, R(RAX), Imm16(imm)); + set_acc_m(reg); + // Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + get_long_acc(reg, RSI); + Update_SR_Register16_OverS32(); + } +#else + Default(opc); +#endif +} //---- @@ -529,22 +743,36 @@ void DSPEmitter::addp(const UDSPInstruction opc) // should be unsigned values!! // // flags out: x-xx xxxx -//void DSPEmitter::addaxl(const UDSPInstruction opc) -//{ -// u8 sreg = (opc >> 9) & 0x1; -// u8 dreg = (opc >> 8) & 0x1; +void DSPEmitter::addaxl(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 sreg = (opc >> 9) & 0x1; + u8 dreg = (opc >> 8) & 0x1; // u64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg, RCX); + MOV(64, R(RAX), R(RCX)); // u16 acx = (u16)dsp_get_ax_l(sreg); - + get_ax_l(sreg, RDX); // u64 res = acc + acx; - -// zeroWriteBackLog(); - + ADD(64, R(RAX), R(RDX)); // dsp_set_long_acc(dreg, (s64)res); // res = dsp_get_long_acc(dreg); // Update_SR_Register64((s64)res, isCarry(acc, res), isOverflow((s64)acc, (s64)acx, (s64)res)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + MOV(64, R(RSI), R(RAX)); + set_long_acc(dreg, RSI); + Update_SR_Register64_Carry(); + } + else + { + set_long_acc(dreg, RAX); + } +#else + Default(opc); +#endif +} // ADDI $amR, #I // 0000 001r 0000 0000 @@ -632,18 +860,18 @@ void DSPEmitter::incm(const UDSPInstruction opc) { #ifdef _M_X64 u8 dreg = (opc >> 8) & 0x1; - s64 sub = 0x10000; + s64 subtract = 0x10000; // s64 acc = dsp_get_long_acc(dreg); get_long_acc(dreg, RCX); MOV(64, R(RAX), R(RCX)); // s64 res = acc + sub; - ADD(64, R(RAX), Imm32((u32)sub)); + ADD(64, R(RAX), Imm32((u32)subtract)); // dsp_set_long_acc(dreg, res); // res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, sub, res)); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, subtract, res)); if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) { - MOV(64, R(RDX), Imm32((u32)sub)); + MOV(64, R(RDX), Imm32((u32)subtract)); MOV(64, R(RSI), R(RAX)); set_long_acc(dreg, RSI); Update_SR_Register64_Carry(); @@ -850,18 +1078,18 @@ void DSPEmitter::decm(const UDSPInstruction opc) { #ifdef _M_X64 u8 dreg = (opc >> 8) & 0x01; - s64 sub = 0x10000; + s64 subtract = 0x10000; // s64 acc = dsp_get_long_acc(dreg); get_long_acc(dreg, RCX); MOV(64, R(RAX), R(RCX)); // s64 res = acc - sub; - SUB(64, R(RAX), Imm32((u32)sub)); + SUB(64, R(RAX), Imm32((u32)subtract)); // dsp_set_long_acc(dreg, res); // res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -sub, res)); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -subtract, res)); if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) { - MOV(64, R(RDX), Imm64(-sub)); + MOV(64, R(RDX), Imm64(-subtract)); MOV(64, R(RSI), R(RAX)); set_long_acc(dreg, RSI); Update_SR_Register64_Carry2(); @@ -1162,23 +1390,38 @@ void DSPEmitter::lsl(const UDSPInstruction opc) // calculated by negating sign extended bits 0-6. // // flags out: --xx xx00 -//void DSPEmitter::lsr(const UDSPInstruction opc) -//{ -// u8 rreg = (opc >> 8) & 0x01; -// u16 shift; +void DSPEmitter::lsr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 rreg = (opc >> 8) & 0x01; + u16 shift; // u64 acc = dsp_get_long_acc(rreg); -// acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes + get_long_acc(rreg); -// if ((opc & 0x3f) == 0) -// shift = 0; -// else -// shift = 0x40 - (opc & 0x3f); + if ((opc & 0x3f) == 0) + shift = 0; + else + shift = 0x40 - (opc & 0x3f); -// acc >>= shift; -// + if (shift) + { + // acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes + SHL(64, R(RAX), Imm8(24)); + // acc >>= shift; + SHR(64, R(RAX), Imm8(shift + 24)); + } + // dsp_set_long_acc(rreg, (s64)acc); + set_long_acc(rreg); // Update_SR_Register64(dsp_get_long_acc(rreg)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(); + } +#else + Default(opc); +#endif +} // ASL $acR, #I // 0001 010r 10ii iiii @@ -1212,23 +1455,34 @@ void DSPEmitter::asl(const UDSPInstruction opc) // value calculated by negating sign extended bits 0-6. // // flags out: --xx xx00 -//void DSPEmitter::asr(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x01; -// u16 shift; +void DSPEmitter::asr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x01; + u16 shift; -// if ((opc & 0x3f) == 0) -// shift = 0; -// else -// shift = 0x40 - (opc & 0x3f); + if ((opc & 0x3f) == 0) + shift = 0; + else + shift = 0x40 - (opc & 0x3f); -// // arithmetic shift + // arithmetic shift // s64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg); // acc >>= shift; + SHR(64, R(RAX), Imm8((u8)shift)); // dsp_set_long_acc(dreg, acc); + set_long_acc(dreg); // Update_SR_Register64(dsp_get_long_acc(dreg)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(); + } +#else + Default(opc); +#endif +} // LSRN (fixed parameters) // 0000 0010 1100 1010 @@ -1236,29 +1490,60 @@ void DSPEmitter::asl(const UDSPInstruction opc) // (if value negative, becomes left shift). // // flags out: --xx xx00 -//void DSPEmitter::lsrn(const UDSPInstruction opc) -//{ +void DSPEmitter::lsrn(const UDSPInstruction opc) +{ +#ifdef _M_X64 // s16 shift; // u16 accm = (u16)dsp_get_acc_m(1); + get_acc_m(1); // u64 acc = dsp_get_long_acc(0); + get_long_acc(0, RDX); // acc &= 0x000000FFFFFFFFFFULL; + SHL(64, R(RDX), Imm8(24)); + SAR(64, R(RDX), Imm8(24)); -// if ((accm & 0x3f) == 0) -// shift = 0; -// else if (accm & 0x40) -// shift = -0x40 + (accm & 0x3f); -// else -// shift = accm & 0x3f; + // if ((accm & 0x3f) == 0) + // shift = 0; + // else if (accm & 0x40) + // shift = -0x40 + (accm & 0x3f); + // else + // shift = accm & 0x3f; -// if (shift > 0) { -// acc >>= shift; -// } else if (shift < 0) { -// acc <<= -shift; -// } + // if (shift > 0) { + // acc >>= shift; + // } else if (shift < 0) { + // acc <<= -shift; + // } + + CMP(64, R(RDX), Imm8(0)); + FixupBranch zero = J_CC(CC_E); + TEST(16, R(RAX), Imm16(0x3f)); + FixupBranch noShift = J_CC(CC_Z); + MOVZX(64, 16, RCX, R(RAX)); + AND(16, R(RCX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x40)); + FixupBranch shiftLeft = J_CC(CC_Z); + NEG(16, R(RCX)); + ADD(16, R(RCX), Imm16(0x40)); + SHL(64, R(RDX), R(RCX)); + FixupBranch exit = J(); + SetJumpTarget(shiftLeft); + SAR(64, R(RDX), R(RCX)); + SetJumpTarget(noShift); + SetJumpTarget(exit); // dsp_set_long_acc(0, (s64)acc); + set_long_acc(0, RDX); + SetJumpTarget(zero); // Update_SR_Register64(dsp_get_long_acc(0)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(RDX); + } +#else + Default(opc); +#endif +} // ASRN (fixed parameters) // 0000 0010 1100 1011 @@ -1266,11 +1551,14 @@ void DSPEmitter::asl(const UDSPInstruction opc) // (if value negative, becomes left shift). // // flags out: --xx xx00 -//void DSPEmitter::asrn(const UDSPInstruction opc) -//{ +void DSPEmitter::asrn(const UDSPInstruction opc) +{ +#ifdef _M_X64 // s16 shift; // u16 accm = (u16)dsp_get_acc_m(1); + get_acc_m(1); // s64 acc = dsp_get_long_acc(0); + get_long_acc(0, RDX); // if ((accm & 0x3f) == 0) // shift = 0; @@ -1285,9 +1573,35 @@ void DSPEmitter::asl(const UDSPInstruction opc) // acc <<= -shift; // } + CMP(64, R(RDX), Imm8(0)); + FixupBranch zero = J_CC(CC_E); + TEST(16, R(RAX), Imm16(0x3f)); + FixupBranch noShift = J_CC(CC_Z); + MOVZX(64, 16, RCX, R(RAX)); + AND(16, R(RCX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x40)); + FixupBranch shiftLeft = J_CC(CC_Z); + NEG(16, R(RCX)); + ADD(16, R(RCX), Imm16(0x40)); + SHL(64, R(RDX), R(RCX)); + FixupBranch exit = J(); + SetJumpTarget(shiftLeft); + SAR(64, R(RDX), R(RCX)); + SetJumpTarget(noShift); + SetJumpTarget(exit); + // dsp_set_long_acc(0, acc); // Update_SR_Register64(dsp_get_long_acc(0)); -//} + set_long_acc(0, RDX); + SetJumpTarget(zero); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(RDX); + } +#else + Default(opc); +#endif +} // LSRNRX $acD, $axS.h // 0011 01sd 1xxx xxxx @@ -1295,15 +1609,20 @@ void DSPEmitter::asl(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::lsrnrx(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; +void DSPEmitter::lsrnrx(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; // s16 shift; // u16 axh = g_dsp.r[DSP_REG_AXH0 + sreg]; + get_ax_h(sreg); // u64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg, RDX); // acc &= 0x000000FFFFFFFFFFULL; + SHL(64, R(RDX), Imm8(24)); + SHR(64, R(RDX), Imm8(24)); // if ((axh & 0x3f) == 0) // shift = 0; @@ -1318,11 +1637,35 @@ void DSPEmitter::asl(const UDSPInstruction opc) // acc >>= -shift; // } -// zeroWriteBackLog(); + CMP(64, R(RDX), Imm8(0)); + FixupBranch zero = J_CC(CC_E); + TEST(16, R(RAX), Imm16(0x3f)); + FixupBranch noShift = J_CC(CC_Z); + MOVZX(64, 16, RCX, R(RAX)); + AND(16, R(RCX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x40)); + FixupBranch shiftLeft = J_CC(CC_Z); + NEG(16, R(RCX)); + ADD(16, R(RCX), Imm16(0x40)); + SHL(64, R(RDX), R(RCX)); + FixupBranch exit = J(); + SetJumpTarget(shiftLeft); + SAR(64, R(RDX), R(RCX)); + SetJumpTarget(noShift); + SetJumpTarget(exit); // dsp_set_long_acc(dreg, (s64)acc); // Update_SR_Register64(dsp_get_long_acc(dreg)); -//} + set_long_acc(dreg, RDX); + SetJumpTarget(zero); + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(RDX); + } +#else + Default(opc); +#endif +} // ASRNRX $acD, $axS.h // 0011 10sd 1xxx xxxx @@ -1330,14 +1673,17 @@ void DSPEmitter::asl(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::asrnrx(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; +void DSPEmitter::asrnrx(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; // s16 shift; // u16 axh = g_dsp.r[DSP_REG_AXH0 + sreg]; + get_ax_h(sreg); // s64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg, RDX); // if ((axh & 0x3f) == 0) // shift = 0; @@ -1352,11 +1698,35 @@ void DSPEmitter::asl(const UDSPInstruction opc) // acc >>= -shift; // } -// zeroWriteBackLog(); + CMP(64, R(RDX), Imm8(0)); + FixupBranch zero = J_CC(CC_E); + TEST(16, R(RAX), Imm16(0x3f)); + FixupBranch noShift = J_CC(CC_Z); + MOVZX(64, 16, RCX, R(RAX)); + AND(16, R(RCX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x40)); + FixupBranch shiftLeft = J_CC(CC_Z); + NEG(16, R(RCX)); + ADD(16, R(RCX), Imm16(0x40)); + SHL(64, R(RDX), R(RCX)); + FixupBranch exit = J(); + SetJumpTarget(shiftLeft); + SAR(64, R(RDX), R(RCX)); + SetJumpTarget(noShift); + SetJumpTarget(exit); // dsp_set_long_acc(dreg, acc); + set_long_acc(dreg, RDX); + SetJumpTarget(zero); // Update_SR_Register64(dsp_get_long_acc(dreg)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(RDX); + } +#else + Default(opc); +#endif +} // LSRNR $acD // 0011 110d 1xxx xxxx @@ -1364,14 +1734,19 @@ void DSPEmitter::asl(const UDSPInstruction opc) // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::lsrnr(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; +void DSPEmitter::lsrnr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; // s16 shift; // u16 accm = (u16)dsp_get_acc_m(1 - dreg); + get_acc_m(1 - dreg); // u64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg, RDX); // acc &= 0x000000FFFFFFFFFFULL; + SHL(64, R(RDX), Imm8(24)); + SHR(64, R(RDX), Imm8(24)); // if ((accm & 0x3f) == 0) // shift = 0; @@ -1385,25 +1760,53 @@ void DSPEmitter::asl(const UDSPInstruction opc) // else if (shift < 0) // acc >>= -shift; -// zeroWriteBackLog(); + CMP(64, R(RDX), Imm8(0)); + FixupBranch zero = J_CC(CC_E); + TEST(16, R(RAX), Imm16(0x3f)); + FixupBranch noShift = J_CC(CC_Z); + MOVZX(64, 16, RCX, R(RAX)); + AND(16, R(RCX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x40)); + FixupBranch shiftLeft = J_CC(CC_Z); + NEG(16, R(RCX)); + ADD(16, R(RCX), Imm16(0x40)); + SHL(64, R(RDX), R(RCX)); + FixupBranch exit = J(); + SetJumpTarget(shiftLeft); + SAR(64, R(RDX), R(RCX)); + SetJumpTarget(noShift); + SetJumpTarget(exit); + // dsp_set_long_acc(dreg, (s64)acc); + set_long_acc(dreg, RDX); + SetJumpTarget(zero); // Update_SR_Register64(dsp_get_long_acc(dreg)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(RDX); + } +#else + Default(opc); +#endif +} // ASRNR $acD // 0011 111d 1xxx xxxx -// Arithmeticaly shift left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M +// Arithmetically shift left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M // x = extension (7 bits!!) // // flags out: --xx xx00 -//void DSPEmitter::asrnr(const UDSPInstruction opc) -//{ -// u8 dreg = (opc >> 8) & 0x1; +void DSPEmitter::asrnr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; // s16 shift; // u16 accm = (u16)dsp_get_acc_m(1 - dreg); + get_acc_m(1 - dreg); // s64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg); // if ((accm & 0x3f) == 0) // shift = 0; @@ -1417,11 +1820,35 @@ void DSPEmitter::asl(const UDSPInstruction opc) // else if (shift < 0) // acc >>= -shift; -// zeroWriteBackLog(); + CMP(64, R(RDX), Imm8(0)); + FixupBranch zero = J_CC(CC_E); + TEST(16, R(RAX), Imm16(0x3f)); + FixupBranch noShift = J_CC(CC_Z); + MOVZX(64, 16, RCX, R(RAX)); + AND(16, R(RCX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x40)); + FixupBranch shiftLeft = J_CC(CC_Z); + NEG(16, R(RCX)); + ADD(16, R(RCX), Imm16(0x40)); + SHL(64, R(RDX), R(RCX)); + FixupBranch exit = J(); + SetJumpTarget(shiftLeft); + SAR(64, R(RDX), R(RCX)); + SetJumpTarget(noShift); + SetJumpTarget(exit); // dsp_set_long_acc(dreg, acc); + set_long_acc(dreg, RDX); + SetJumpTarget(zero); // Update_SR_Register64(dsp_get_long_acc(dreg)); -//} + if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) + { + Update_SR_Register64(RDX); + } +#else + Default(opc); +#endif +} //} // namespace diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp index 6826c87820..3387a933b9 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp @@ -150,38 +150,6 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val) //void DSPEmitter::Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32) //{ -// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; - -// // 0x01 -// if (carry) -// { -// g_dsp.r[DSP_REG_SR] |= SR_CARRY; -// } - -// // 0x02 and 0x80 -// if (overflow) -// { -// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW; -// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY; -// } - -// // 0x04 -// if (_Value == 0) -// { -// g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; -// } - -// // 0x08 -// if (_Value < 0) -// { -// g_dsp.r[DSP_REG_SR] |= SR_SIGN; -// } - -// // 0x10 -// if (overS32) -// { -// g_dsp.r[DSP_REG_SR] |= SR_OVER_S32; -// } // // 0x20 - Checks if top bits of m are equal // if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) @@ -190,6 +158,69 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val) // } //} +// In: RAX: s64 _Value +// In: RCX: 1 = carry, 2 = overflow +// Clobbers RDX +void DSPEmitter::Update_SR_Register16(Gen::X64Reg val) +{ +#ifdef _M_X64 + AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_CMP_MASK)); + + // // 0x04 + // if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; + CMP(64, R(val), Imm8(0)); + FixupBranch notZero = J_CC(CC_NZ); + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_ARITH_ZERO)); + SetJumpTarget(notZero); + + // // 0x08 + // if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN; + CMP(64, R(val), Imm8(0)); + FixupBranch greaterThanEqual = J_CC(CC_GE); + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_SIGN)); + SetJumpTarget(greaterThanEqual); + + // // 0x20 - Checks if top bits of m are equal + // if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) + //AND(32, R(val), Imm32(0xc0000000)); + SHR(16, R(val), Imm8(14)); + CMP(16, R(val), Imm16(0)); + FixupBranch nZero = J_CC(CC_NE); + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_TOP2BITS)); + FixupBranch cC = J(); + SetJumpTarget(nZero); + CMP(16, R(val), Imm16(3)); + FixupBranch notThree = J_CC(CC_NE); + // g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS; + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_TOP2BITS)); + SetJumpTarget(notThree); + SetJumpTarget(cC); +#endif +} + +// In: RAX: s64 _Value +// In: RCX: 1 = carry, 2 = overflow +// Clobbers RDX +void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val) +{ +#ifdef _M_X64 + AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_CMP_MASK)); + + // // 0x10 + // if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32; + MOVSX(64, 32, RSI, R(val)); + CMP(64, R(RSI), R(val)); + FixupBranch noOverS32 = J_CC(CC_E); + OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_OVER_S32)); + SetJumpTarget(noOverS32); + + // // 0x20 - Checks if top bits of m are equal + // if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) + //AND(32, R(val), Imm32(0xc0000000)); + Update_SR_Register16(val); +#endif +} + //void DSPEmitter::Update_SR_LZ(bool value) { // if (value == true) diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp index d8f4d59aa5..20c620d5e6 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp @@ -407,16 +407,14 @@ void DSPEmitter::mulmvz(const UDSPInstruction opc) u8 rreg = (opc >> 8) & 0x1; // s64 acc = dsp_get_long_prod_round_prodl(); - get_long_prod_round_prodl(); - PUSH(64, R(RAX)); - mul(opc); + get_long_prod_round_prodl(RDX); // dsp_set_long_acc(rreg, acc); - POP(64, R(RAX)); - set_long_acc(rreg); + set_long_acc(rreg, RDX); + mul(opc); // Update_SR_Register64(dsp_get_long_acc(rreg)); if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) { - Update_SR_Register64(); + Update_SR_Register64(RDX); } #else Default(opc); @@ -673,38 +671,50 @@ void DSPEmitter::mulcmvz(const UDSPInstruction opc) // Multiply one part of secondary accumulator $ax0 (selected by S) by // one part of secondary accumulator $ax1 (selected by T) (treat them both as // signed) and add result to product register. -//void DSPEmitter::maddx(const UDSPInstruction opc) -//{ -// u8 treg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; +void DSPEmitter::maddx(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 treg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; -// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); -// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); -// s64 prod = dsp_multiply_add(val1, val2); -// -// zeroWriteBackLog(); - -// dsp_set_long_prod(prod); -//} + MOV(64, R(R11), ImmPtr(&g_dsp.r)); + // u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + MOVSX(64, 16, RSI, MDisp(R11, (DSP_REG_AXL0 + sreg*2) * 2)); + // u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + MOVSX(64, 16, RDI, MDisp(R11, (DSP_REG_AXL1 + treg*2) * 2)); + // s64 prod = dsp_multiply_add(val1, val2); + multiply_add(); + // dsp_set_long_prod(prod); + set_long_prod(); +#else + Default(opc); +#endif +} // MSUBX $(0x18+S*2), $(0x19+T*2) // 1110 01st xxxx xxxx // Multiply one part of secondary accumulator $ax0 (selected by S) by // one part of secondary accumulator $ax1 (selected by T) (treat them both as // signed) and subtract result from product register. -//void DSPEmitter::msubx(const UDSPInstruction opc) -//{ -// u8 treg = (opc >> 8) & 0x1; -// u8 sreg = (opc >> 9) & 0x1; +void DSPEmitter::msubx(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 treg = (opc >> 8) & 0x1; + u8 sreg = (opc >> 9) & 0x1; -// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); -// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); -// s64 prod = dsp_multiply_sub(val1, val2); - -// zeroWriteBackLog(); - -// dsp_set_long_prod(prod); -//} + MOV(64, R(R11), ImmPtr(&g_dsp.r)); + // u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); + MOVSX(64, 16, RSI, MDisp(R11, (DSP_REG_AXL0 + sreg*2) * 2)); + // u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); + MOVSX(64, 16, RDI, MDisp(R11, (DSP_REG_AXL1 + treg*2) * 2)); + // s64 prod = dsp_multiply_sub(val1, val2); + multiply_sub(); + // dsp_set_long_prod(prod); + set_long_prod(); +#else + Default(opc); +#endif +} // MADDC $acS.m, $axT.h // 1110 10st xxxx xxxx diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp index 814de5786c..fd41794e5d 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp @@ -186,7 +186,7 @@ void DSPEmitter::increase_addr_reg(int reg) // TODO: ToMask flushes flags set by TEST, // needs another CMP here. CMP(16, R(ECX), Imm16(0)); - FixupBranch neg = J_CC(CC_L); + FixupBranch negative = J_CC(CC_L); JumpTarget loop_pos = GetCodePtr(); @@ -211,7 +211,7 @@ void DSPEmitter::increase_addr_reg(int reg) FixupBranch end_pos = J(); // else, IX0 < 0 - SetJumpTarget(neg); + SetJumpTarget(negative); JumpTarget loop_neg = GetCodePtr(); // dsp_decrement @@ -269,7 +269,7 @@ void DSPEmitter::decrease_addr_reg(int reg) // TODO: ToMask flushes flags set by TEST, // needs another CMP here. CMP(16, R(ECX), Imm16(0)); - FixupBranch neg = J_CC(CC_L); + FixupBranch negative = J_CC(CC_L); JumpTarget loop_pos = GetCodePtr(); @@ -282,7 +282,7 @@ void DSPEmitter::decrease_addr_reg(int reg) FixupBranch end_pos = J(); // else, IX0 < 0 - SetJumpTarget(neg); + SetJumpTarget(negative); JumpTarget loop_neg = GetCodePtr(); // dsp_increment @@ -512,7 +512,7 @@ void DSPEmitter::get_long_prod_round_prodl(X64Reg long_prod) { #ifdef _M_X64 //s64 prod = dsp_get_long_prod(); - get_long_prod(); + get_long_prod(long_prod); //if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff; TEST(32, R(long_prod), Imm32(0x10000)); @@ -554,6 +554,28 @@ void DSPEmitter::set_long_prod() #endif } +// Returns s64 in RAX +// Clobbers RSI +void DSPEmitter::round_long_acc(X64Reg long_acc) +{ +#ifdef _M_X64 + //if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff; + TEST(32, R(long_acc), Imm32(0x10000)); + FixupBranch jump = J_CC(CC_Z); + ADD(64, R(long_acc), Imm32(0x8000)); + MOV(64, R(ESI), Imm64(~0xffff)); + AND(64, R(long_acc), R(RSI)); + FixupBranch ret = J(); + //else prod = (prod + 0x7fff) & ~0xffff; + SetJumpTarget(jump); + ADD(64, R(long_acc), Imm32(0x7fff)); + MOV(64, R(RSI), Imm64(~0xffff)); + AND(64, R(long_acc), R(RSI)); + SetJumpTarget(ret); + //return prod; +#endif +} + // Returns s64 in RAX void DSPEmitter::get_long_acc(int _reg, X64Reg acc) { @@ -591,12 +613,22 @@ void DSPEmitter::set_long_acc(int _reg, X64Reg acc) } // Returns s16 in AX -void DSPEmitter::get_acc_m(int _reg) +void DSPEmitter::get_acc_m(int _reg, X64Reg acm) { // return g_dsp.r[DSP_REG_ACM0 + _reg]; #ifdef _M_X64 MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOVSX(64, 16, RAX, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2)); + MOVSX(64, 16, acm, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2)); +#endif +} + +// Returns s16 in AX +void DSPEmitter::set_acc_m(int _reg) +{ + // return g_dsp.r[DSP_REG_ACM0 + _reg]; +#ifdef _M_X64 + MOV(64, R(R11), ImmPtr(&g_dsp.r)); + MOV(16, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2), R(RAX)); #endif } @@ -613,22 +645,22 @@ void DSPEmitter::get_long_acx(int _reg, X64Reg acx) } // Returns s16 in EAX -void DSPEmitter::get_ax_l(int _reg) +void DSPEmitter::get_ax_l(int _reg, X64Reg axl) { // return (s16)g_dsp.r[DSP_REG_AXL0 + _reg]; #ifdef _M_X64 MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOVSX(64, 16, RAX, MDisp(R11, (DSP_REG_AXL0 + _reg) * 2)); + MOVSX(64, 16, axl, MDisp(R11, (DSP_REG_AXL0 + _reg) * 2)); #endif } // Returns s16 in EAX -void DSPEmitter::get_ax_h(int _reg) +void DSPEmitter::get_ax_h(int _reg, X64Reg axh) { // return (s16)g_dsp.r[DSP_REG_AXH0 + _reg]; #ifdef _M_X64 MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOVSX(64, 16, RAX, MDisp(R11, (DSP_REG_AXH0 + _reg) * 2)); + MOVSX(64, 16, axh, MDisp(R11, (DSP_REG_AXH0 + _reg) * 2)); #endif }