diff options
| author | nakeee <nakeee@gmail.com> | 2010-04-07 15:04:45 +0000 |
|---|---|---|
| committer | nakeee <nakeee@gmail.com> | 2010-04-07 15:04:45 +0000 |
| commit | 499936561a0683d6798c6edfa0b86b1ffcba8ec0 (patch) | |
| tree | 753037fea47837c2ae6bc6eb88e01f81f378a58f /Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp | |
| parent | 1b96bef8e1ee40fdaff7636b9b17b3e71c683dc7 (diff) | |
DSP LLE Jit, joined work with XK and skidu.
VERY EXPERIMENTAL DON'T EXPECT HIGH PERFORMANCE!.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5288 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp')
| -rw-r--r-- | Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp new file mode 100644 index 0000000000..19e0d44063 --- /dev/null +++ b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp @@ -0,0 +1,425 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "../DSPMemoryMap.h" +#include "../DSPEmitter.h" +#include "../DSPIntExtOps.h" // remove when getting rid of writebacklog +// See docs in the interpeter + +inline bool IsSameMemArea(u16 a, u16 b) +{ +//LM: tested on WII + if ((a>>10)==(b>>10)) + return true; + else + return false; +} + +// DR $arR +// xxxx xxxx 0000 01rr +// Decrement addressing register $arR. +void DSPEmitter::dr(const UDSPInstruction opc) { + decrement_addr_reg(opc & 0x3); +} + +// IR $arR +// xxxx xxxx 0000 10rr +// Increment addressing register $arR. +void DSPEmitter::ir(const UDSPInstruction opc) { + increment_addr_reg(opc & 0x3); +} + +// NR $arR +// xxxx xxxx 0000 11rr +// Add corresponding indexing register $ixR to addressing register $arR. +void DSPEmitter::nr(const UDSPInstruction opc) { + u8 reg = opc & 0x3; + + increase_addr_reg(reg); +} + +// MV $axD.D, $acS.S +// xxxx xxxx 0001 ddss +// Move value of $acS.S to the $axD.D. +void DSPEmitter::mv(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x3) + DSP_REG_ACL0; + u8 dreg = ((opc >> 2) & 0x3); + +#if 0 //more tests + if ((sreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)) + writeToBackLog(0, dreg + DSP_REG_AXL0, ((u16)dsp_get_acc_h(sreg-DSP_REG_ACM0) & 0x0080) ? 0x8000 : 0x7fff); + else +#endif + writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r[sreg]); +} + +// S @$arD, $acS.S +// xxxx xxxx 001s s0dd +// Store value of $acS.S in the memory pointed by register $arD. +// Post increment register $arD. +void DSPEmitter::s(const UDSPInstruction opc) +{ + u8 dreg = opc & 0x3; + u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0; + + ext_dmem_write(dreg, sreg); + increment_addr_reg(dreg); +} + +// SN @$arD, $acS.S +// xxxx xxxx 001s s1dd +// Store value of register $acS.S in the memory pointed by register $arD. +// Add indexing register $ixD to register $arD. +void DSPEmitter::sn(const UDSPInstruction opc) +{ + u8 dreg = opc & 0x3; + u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0; + + ext_dmem_write(dreg, sreg); + increase_addr_reg(dreg); +} + +// L $axD.D, @$arS +// xxxx xxxx 01dd d0ss +// Load $axD.D/$acD.D with value from memory pointed by register $arS. +// Post increment register $arS. +void DSPEmitter::l(const UDSPInstruction opc) +{ + u8 sreg = opc & 0x3; + u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; + + if ((dreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)) + { + u16 val = ext_dmem_read(g_dsp.r[sreg]); + writeToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000); + writeToBackLog(1, dreg, val); + writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0); + increment_addr_reg(sreg); + } + else + { + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[sreg])); + increment_addr_reg(sreg); + } +} + +// LN $axD.D, @$arS +// xxxx xxxx 01dd d0ss +// Load $axD.D/$acD.D with value from memory pointed by register $arS. +// Add indexing register register $ixS to register $arS. +void DSPEmitter::ln(const UDSPInstruction opc) +{ + u8 sreg = opc & 0x3; + u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; + + if ((dreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)) + { + u16 val = ext_dmem_read(g_dsp.r[sreg]); + writeToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000); + writeToBackLog(1, dreg, val); + writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0); + increase_addr_reg(sreg); + } + else + { + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[sreg])); + increase_addr_reg(sreg); + } +} + +// LS $axD.D, $acS.m +// xxxx xxxx 10dd 000s +// Load register $axD.D with value from memory pointed by register +// $ar0. Store value from register $acS.m to memory location pointed by +// register $ar3. Increment both $ar0 and $ar3. +void DSPEmitter::ls(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR3, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR0])); + increment_addr_reg(DSP_REG_AR3); + increment_addr_reg(DSP_REG_AR0); +} + + +// LSN $axD.D, $acS.m +// xxxx xxxx 10dd 010s +// Load register $axD.D with value from memory pointed by register +// $ar0. Store value from register $acS.m to memory location pointed by +// register $ar3. Add corresponding indexing register $ix0 to addressing +// register $ar0 and increment $ar3. +void DSPEmitter::lsn(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR3, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR0])); + increment_addr_reg(DSP_REG_AR3); + increase_addr_reg(DSP_REG_AR0); +} + +// LSM $axD.D, $acS.m +// xxxx xxxx 10dd 100s +// Load register $axD.D with value from memory pointed by register +// $ar0. Store value from register $acS.m to memory location pointed by +// register $ar3. Add corresponding indexing register $ix3 to addressing +// register $ar3 and increment $ar0. +void DSPEmitter::lsm(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR3, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR0])); + increase_addr_reg(DSP_REG_AR3); + increment_addr_reg(DSP_REG_AR0); +} + +// LSMN $axD.D, $acS.m +// xxxx xxxx 10dd 110s +// Load register $axD.D with value from memory pointed by register +// $ar0. Store value from register $acS.m to memory location pointed by +// register $ar3. Add corresponding indexing register $ix0 to addressing +// register $ar0 and add corresponding indexing register $ix3 to addressing +// register $ar3. +void DSPEmitter::lsnm(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR3, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR0])); + increase_addr_reg(DSP_REG_AR3); + increase_addr_reg(DSP_REG_AR0); +} + +// SL $acS.m, $axD.D +// xxxx xxxx 10dd 001s +// Store value from register $acS.m to memory location pointed by register +// $ar0. Load register $axD.D with value from memory pointed by register +// $ar3. Increment both $ar0 and $ar3. +void DSPEmitter::sl(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR0, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + increment_addr_reg(DSP_REG_AR3); + increment_addr_reg(DSP_REG_AR0); +} + +// SLN $acS.m, $axD.D +// xxxx xxxx 10dd 011s +// Store value from register $acS.m to memory location pointed by register +// $ar0. Load register $axD.D with value from memory pointed by register +// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0 +// and increment $ar3. +void DSPEmitter::sln(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR0, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + increment_addr_reg(DSP_REG_AR3); + increase_addr_reg(DSP_REG_AR0); +} + +// SLM $acS.m, $axD.D +// xxxx xxxx 10dd 101s +// Store value from register $acS.m to memory location pointed by register +// $ar0. Load register $axD.D with value from memory pointed by register +// $ar3. Add corresponding indexing register $ix3 to addressing register $ar3 +// and increment $ar0. +void DSPEmitter::slm(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR0, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + increase_addr_reg(DSP_REG_AR3); + increment_addr_reg(DSP_REG_AR0); +} + +// SLMN $acS.m, $axD.D +// xxxx xxxx 10dd 111s +// Store value from register $acS.m to memory location pointed by register +// $ar0. Load register $axD.D with value from memory pointed by register +// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0 +// and add corresponding indexing register $ix3 to addressing register $ar3. +void DSPEmitter::slnm(const UDSPInstruction opc) +{ + u8 sreg = (opc & 0x1) + DSP_REG_ACM0; + u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; + + ext_dmem_write(DSP_REG_AR0, sreg); + + writeToBackLog(0, dreg, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + increase_addr_reg(DSP_REG_AR3); + increase_addr_reg(DSP_REG_AR0); +} + +// LD $ax0.d, $ax1.r, @$arS +// xxxx xxxx 11dr 00ss +// example for "nx'ld $AX0.L, $AX1.L, @$AR3" +// Loads the word pointed by AR0 to AX0.H, then loads the word pointed by AR3 +// to AX0.L. Increments AR0 and AR3. If AR0 and AR3 point into the same +// memory page (upper 6 bits of addr are the same -> games are not doing that!) +// then the value pointed by AR0 is loaded to BOTH AX0.H and AX0.L. If AR0 +// points into an invalid memory page (ie 0x2000), then AX0.H keeps its old +// value. (not implemented yet) If AR3 points into an invalid memory page, then +// AX0.L gets the same value as AX0.H. (not implemented yet) +void DSPEmitter::ld(const UDSPInstruction opc) +{ + u8 dreg = (opc >> 5) & 0x1; + u8 rreg = (opc >> 4) & 0x1; + u8 sreg = opc & 0x3; + + if (sreg != DSP_REG_AR3) { + writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[sreg])); + + if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[sreg])); + else + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increment_addr_reg(sreg); + } else { + writeToBackLog(0, rreg + DSP_REG_AXH0, ext_dmem_read(g_dsp.r[dreg])); + + if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[dreg])); + else + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increment_addr_reg(dreg); + } + + increment_addr_reg(DSP_REG_AR3); +} + +// LDN $ax0.d, $ax1.r, @$arS +// xxxx xxxx 11dr 01ss +void DSPEmitter::ldn(const UDSPInstruction opc) +{ + u8 dreg = (opc >> 5) & 0x1; + u8 rreg = (opc >> 4) & 0x1; + u8 sreg = opc & 0x3; + + if (sreg != DSP_REG_AR3) { + writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[sreg])); + + if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[sreg])); + else + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increase_addr_reg(sreg); + } else { + writeToBackLog(0, rreg + DSP_REG_AXH0, ext_dmem_read(g_dsp.r[dreg])); + + if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[dreg])); + else + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increase_addr_reg(dreg); + } + + increment_addr_reg(DSP_REG_AR3); +} + +// LDM $ax0.d, $ax1.r, @$arS +// xxxx xxxx 11dr 10ss +void DSPEmitter::ldm(const UDSPInstruction opc) +{ + u8 dreg = (opc >> 5) & 0x1; + u8 rreg = (opc >> 4) & 0x1; + u8 sreg = opc & 0x3; + + if (sreg != DSP_REG_AR3) { + writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[sreg])); + + if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[sreg])); + else + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increment_addr_reg(sreg); + } else { + writeToBackLog(0, rreg + DSP_REG_AXH0, ext_dmem_read(g_dsp.r[dreg])); + + if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[dreg])); + else + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increment_addr_reg(dreg); + } + + increase_addr_reg(DSP_REG_AR3); +} + +// LDNM $ax0.d, $ax1.r, @$arS +// xxxx xxxx 11dr 11ss +void DSPEmitter::ldnm(const UDSPInstruction opc) +{ + u8 dreg = (opc >> 5) & 0x1; + u8 rreg = (opc >> 4) & 0x1; + u8 sreg = opc & 0x3; + + if (sreg != DSP_REG_AR3) { + writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[sreg])); + + if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[sreg])); + else + writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increase_addr_reg(sreg); + } else { + writeToBackLog(0, rreg + DSP_REG_AXH0, ext_dmem_read(g_dsp.r[dreg])); + + if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[dreg])); + else + writeToBackLog(1, rreg + DSP_REG_AXL0, ext_dmem_read(g_dsp.r[DSP_REG_AR3])); + + increase_addr_reg(dreg); + } + + increase_addr_reg(DSP_REG_AR3); +} + + +void DSPEmitter::writeAxAcc(const UDSPInstruction opc) { + +} + + |
