diff --git a/BizHawk.Emulation/CPUs/ARM/ARM.Disassembly.cs b/BizHawk.Emulation/CPUs/ARM/ARM.Disassembly.cs index 9b0e0e7fd4..9a3f183e38 100644 --- a/BizHawk.Emulation/CPUs/ARM/ARM.Disassembly.cs +++ b/BizHawk.Emulation/CPUs/ARM/ARM.Disassembly.cs @@ -163,10 +163,10 @@ namespace BizHawk.Emulation.CPUs.ARM } else opcode = opcode.Replace(crepl, ""); - if(opcode.Contains("{.size}")) - { - opcode = opcode.Replace("<{.size}>","." + args[argindex++].ToString()); - } + if(opcode.Contains("{.fpsize}")) + opcode = opcode.Replace("<{.fpsize}>",".F" + args[argindex++].ToString()); + if (opcode.Contains(".fpsize")) + opcode = opcode.Replace("<.fpsize>", ".F" + args[argindex++].ToString()); //--------- string cpcomment = null; @@ -215,6 +215,26 @@ namespace BizHawk.Emulation.CPUs.ARM break; } + case "sdd": + case "sdn": + case "sdm": + if ((bool)args[argindex++]) + item = "s" + args[argindex++].ToString(); + else + item = "d" + args[argindex++].ToString(); + break; + + case "{sdd~sdn, }": + { + bool s = (bool)args[argindex++]; + uint rd = (uint)args[argindex++]; + uint rx = (uint)args[argindex++]; + if (disopt.showExplicitAccumulateRegisters || rd != rx) + item = string.Format("{0}{1}, ", s ? "s" : "d", rd); + else item = ""; + break; + } + case "fpscr": item = nstyle ? "fpscr" : "FPSCR"; break; case "const": item = string.Format("0x{0:x}", args[argindex++]); break; @@ -228,7 +248,7 @@ namespace BizHawk.Emulation.CPUs.ARM else item = string.Format(",#0x{0:x}", temp); break; } - case "{,+/-#imm}": + case "{, #+/-imm}": { uint temp = (uint)args[argindex + 1]; if (temp == 0 && disopt.hideZeroOffset) item = ""; diff --git a/BizHawk.Emulation/CPUs/ARM/ARM.Execute.cs b/BizHawk.Emulation/CPUs/ARM/ARM.Execute.cs index 4eb87c4c3e..994a024cca 100644 --- a/BizHawk.Emulation/CPUs/ARM/ARM.Execute.cs +++ b/BizHawk.Emulation/CPUs/ARM/ARM.Execute.cs @@ -112,7 +112,7 @@ namespace BizHawk.Emulation.CPUs.ARM opcode += ""; //we may want conditional logic here to control whether various registers are displayed (we used to have it, but i changed my mind) if (offset) - return DISNEW(opcode, rt + ", [<{,+/-#imm}>]", t, n, add, imm32); + return DISNEW(opcode, rt + ", [<{, #+/-imm}>]", t, n, add, imm32); else if (preindexed) return DISNEW(opcode, rt + ", [, <+/->]!", t, n, add, imm32); else if (postindex) diff --git a/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteArm.cs b/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteArm.cs index 97c35ad739..47fdff469a 100644 --- a/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteArm.cs +++ b/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteArm.cs @@ -55,7 +55,7 @@ namespace BizHawk.Emulation.CPUs.ARM .r("A==0 && op1 == #0x010", () => Execute_Unhandled("STRT on page A8-416")) .r("A==1 && op1 == #0x010 && B==0", () => Execute_Unhandled("STRT on page A8-416")) .r("A==0 && op1 == #xx0x1 && op1 != #0x011 && Rn != #1111", () => Execute_LDR_immediate_arm_A1()) - .r("A==0 && op1 == #xx0x1 && op1 != #0x011 && Rn == #1111", () => ExecuteArm_LDR_literal_A1()) + .r("A==0 && op1 == #xx0x1 && op1 != #0x011 && Rn == #1111", () => Execute_LDR_literal_A1()) .r("A==1 && op1 == #xx0x1 && A != #0x011 && B==0", () => Execute_Unhandled("LDR (register) on page A8-124")) .r("A==0 && op1 == #0x011", () => Execute_Unhandled("LDRT on page A8-176")) .r("A==1 && op1 == #0x011 && B==0", () => Execute_Unhandled("LDRT on page A8-176")) @@ -141,7 +141,7 @@ namespace BizHawk.Emulation.CPUs.ARM return ExecuteCore_PUSH(Encoding.A2, registers, UnalignedAllowed); } - uint ExecuteArm_LDR_literal_A1() + uint Execute_LDR_literal_A1() { //A8.6.59 //A8-122 @@ -182,7 +182,7 @@ namespace BizHawk.Emulation.CPUs.ARM return ExecuteArm_DataProcessing_Immediate(); if (op1 == _.b10000) return Execute_Unhandled("16-bit immediate load (MOV (immediate on page A8-193) //v6T2"); if (op1 == _.b10100) return Execute_Unhandled("high halfword 16-bit immediate load (MOVT on page A8-200) //v6T2"); - if (CHK(op1, _.b11011, _.b10010)) return Execute_Unhandled("MSR (immediate), and hints on page A5-17"); + if (CHK(op1, _.b11011, _.b10010)) return ExecuteArm_MSR_immediate_and_hints(); throw new InvalidOperationException("unexpected decoder fail"); default: @@ -190,6 +190,48 @@ namespace BizHawk.Emulation.CPUs.ARM } } + uint ExecuteArm_MSR_immediate_and_hints() + { + Bit op = _.BIT22(instruction); + uint op1 = (instruction >> 16) & 0xF; + uint op2 = instruction & 0xFF; + if (op == 0) + { + switch(op1) + { + case _.b0000: + switch (op2) + { + case 0: return Execute_NOP_A1(); + case 1: return Execute_Unhandled("yield"); + case 2: return Execute_Unhandled("wfe"); + case 3: return Execute_Unhandled("wfi"); + case 4: return Execute_Unhandled("sev"); + default: return Execute_Unhandled("DBG"); + } + case _.b0100: + case _.b1000: case _.b1100: + return Execute_Unhandled("MSR immediate"); + case _.b0001: case _.b0101: + case _.b1001: case _.b1101: + return Execute_Unhandled("MSR immediate"); + case _.b0010: case _.b0011: + case _.b0110: case _.b0111: + case _.b1010: case _.b1011: + case _.b1110: case _.b1111: + return Execute_Unhandled("MSR immediate"); + default: throw new InvalidOperationException("decode fail"); + } + } + else return Execute_Unhandled("MSR immediate"); + } + + uint Execute_NOP_A1() + { + //A8.6.110 + return ExecuteCore_NOP(Encoding.A1); + } + uint ExecuteArm_SynchronizationPrimitives() { uint op = (instruction >> 20) & 0xF; @@ -562,7 +604,7 @@ namespace BizHawk.Emulation.CPUs.ARM case _.b001: switch (op) { - case _.b01: return ExecuteArm_BX_A1(); + case _.b01: return Execute_BX_A1(); case _.b11: return Execute_Unhandled("ExecuteArm_CLZ"); default: return Execute_Undefined(); @@ -588,16 +630,11 @@ namespace BizHawk.Emulation.CPUs.ARM } //switch(op2) } - uint ExecuteArm_BX_A1() + uint Execute_BX_A1() { - //A8-62 //A8.6.25 - uint Rm = Reg16(0); - if (disassemble) - return DIS("BX/c/", "/r0/", Rm); - uint m = r[Rm]; - _BXWritePC(m); - return 1; + uint m = Reg16(0); + return ExecuteCore_BX(Encoding.A1, m); } uint ExecuteArm_Media() { return Execute_Unhandled("ExecuteArm_Media"); } @@ -720,7 +757,7 @@ namespace BizHawk.Emulation.CPUs.ARM .r("op1==#00010x && coproc_special==#1", () => Execute_Unhandled("ExecuteArm_SIMD_VFP_64bit_xfer")) .r("op1==#000100 && coproc_special==#0", () => Execute_Unhandled("MCRR,MCRR2")) .r("op1==#000101 && coproc_special==#0", () => Execute_Unhandled("MRRC,MRRC2")) - .r("op1==#10xxxx && op==0 && coproc_special==#1", () => Execute_Unhandled("VFP data-processing on page A7-24")) + .r("op1==#10xxxx && op==0 && coproc_special==#1", () => ExecuteArm_VFP_DataProcessing()) .r("op1==#10xxxx && op==0 && coproc_special==#0", () => Execute_Unhandled("CDP,CDP2 on page A8-68")) .r("op1==#10xxxx && op==1 && coproc_special==#1", () => ExecuteArm_ShortVFPTransfer()) .r("op1==#10xxx0 && op==1 && coproc_special==#0", () => Execute_Unhandled("MCR,MCR2 on pageA8-186")) @@ -739,6 +776,124 @@ namespace BizHawk.Emulation.CPUs.ARM return 1; } + uint ExecuteArm_VFP_DataProcessing() + { + //A7.5 + uint opc1 = (instruction >> 20) & 0xF; + uint opc2 = (instruction >> 16) & 0xF; + uint opc3 = (instruction >> 6) & 3; + + if (opc1 == _.b0000 || opc1 == _.b0100) return Execute_Unhandled("VML, VMLS (floating point)"); + if (opc1 == _.b0001 || opc1 == _.b0101) return Execute_Unhandled("VNMLA, VNMLS, VNMUL"); + if (opc1 == _.b0010 || opc1 == _.b0110) + if (opc3 == _.b01 || opc3 == _.b11) return Execute_Unhandled("VMUL (floating point)"); + else if (opc3 == _.b00 || opc3 == _.b10) return Execute_Unhandled("VMUL (floating point)"); + else throw new InvalidOperationException("decode fail"); + if (opc1 == _.b0011 || opc1 == _.b0111) + if (opc3 == _.b00 || opc3 == _.b10) return Execute_VADD_floating_point_A2(); + else if (opc3 == _.b01 || opc3 == _.b11) return Execute_Unhandled("VSUB (floating point)"); + if (opc1 == _.b1000 || opc1 == _.b1100) + if (opc3 == _.b00 || opc3 == _.b10) return Execute_Unhandled("VDIV"); + else throw new InvalidOperationException("unhandled opcode space.."); + if (opc1 == _.b1011 || opc1 == _.b1111) + { + if (opc3 == _.b00 || opc3 == _.b10) return Execute_Unhandled("VMOV (immediate)"); + if (opc2 == _.b0000 && opc3 == _.b01) return Execute_VMOV_register_A2(); + if (opc2 == _.b0000 && opc3 == _.b11) return Execute_Unhandled("VABS"); + if (opc2 == _.b0001 && opc3 == _.b01) return Execute_Unhandled("VNEG"); + if (opc2 == _.b0001 && opc3 == _.b11) return Execute_Unhandled("VSQRT"); + if (opc2 == _.b0010 || opc2 == _.b0011) return Execute_Unhandled("VCVTB, VCVTT (between half-precision and single precision)"); + if (opc2 == _.b0100 || opc2 == _.b0101) return Execute_Unhandled("VCMP, VCMPE"); + if (opc2 == _.b0111) return Execute_Unhandled("VCVT (between double precision and single precision)"); + if (opc2 == _.b1000) return Execute_Unhandled("VCVT, VCVTR (between floating point and integer)"); + if (opc2 == _.b1010 || opc2 == _.b1011) return Execute_Unhandled("VCVT (between floating point and fixed point)"); + if (opc2 == _.b1100 || opc2 == _.b1101) return Execute_Unhandled("VCVT, VCVTR (between floating point and integer)"); + if (opc2 == _.b1110 || opc2 == _.b1111) return Execute_Unhandled("VCVT (between floating point and fixed point)"); + } + + throw new InvalidOperationException("decoder fail"); + } + + uint Execute_VADD_floating_point_A2() + { + //A8.6.272 + if (_FPSCR_LEN() != _.b000 || _FPSCR_STRIDE() != _.b00) throw new NotImplementedException("see VFP vectors"); + const bool advsimd = false; + Bit sz = _.BIT8(instruction); + bool dp_operation = (sz == 1); + uint D = _.BIT22(instruction); + uint M = _.BIT5(instruction); + uint N = _.BIT7(instruction); + uint Vm = Reg16(0); + uint Vd = Reg16(12); + uint Vn = Reg16(16); + uint d = dp_operation ? ((D << 4) | Vd) : ((Vd << 1) | D); + uint n = dp_operation ? ((N << 4) | Vn) : ((Vn << 1) | N); + uint m = dp_operation ? ((M << 4) | Vm) : ((Vm << 1) | M); + return ExecuteCore_VADD_floating_point(Encoding.A2, dp_operation, advsimd, d, n, m); + } + + uint Execute_VMOV_register_A2() + { + //A8.6.327 + if (_FPSCR_LEN() != _.b000 || _FPSCR_STRIDE() != _.b00) throw new NotImplementedException("see VFP vectors"); + Bit sz = _.BIT8(instruction); + bool single_register = (sz == 0); + const bool advsimd = false; + uint d,m; + uint Vd = Reg16(12); + uint Vm = Reg16(0); + uint D = _.BIT22(instruction); + uint M = _.BIT5(instruction); + uint regs = 0; + if (single_register) + { + d = (Vd << 1) | D; + m = (Vm << 1) | M; + + } + else + { + d = (D << 4) | Vd; + m = (M << 4) | Vm; + regs = 1; + } + + return ExecuteCore_VMOV_register(Encoding.A2, single_register, advsimd, d, m, regs); + } + + uint Execute_VMOV_immediate_A2() + { + ////A8.6.326 + //if (_FPSCR_LEN() != _.b000 || _FPSCR_STRIDE() != _.b00) throw new NotImplementedException("see VFP vectors"); + //Bit sz = _.BIT8(instruction); + //bool single_register = (sz == 0); + //const bool advsimd = false; + //uint d; + //uint Vd = Reg16(12); + //uint D = _.BIT22(instruction); + //uint imm32 = 0; + //ulong imm64 = 0; + //uint imm4H = (instruction>>16)&0xF; + //uint imm4L = (instruction&0xF); + //uint regs = 0; + //if (single_register) + //{ + // d = (Vd << 1) | D; + // imm32 = _VFPExpandImm32((imm4H << 4) | imm4L); + //} + //else + //{ + // d = (D << 4) | Vd; + // imm64 = _VFPExpandImm64((imm4H << 4) | imm4L); + // regs = 1; + //} + + //return ExecuteCore_VMOV(Encoding.A2, single_register, advsimd, d, regs, imm32, imm64); + + return 1; + } + uint Execute_ExtensionRegister_LoadStore() { //A7.6 Extension register load/store instructions @@ -781,7 +936,7 @@ namespace BizHawk.Emulation.CPUs.ARM uint imm8 = instruction & 0xFF; uint imm32 = _ZeroExtend_32(imm8 << 2); uint Vd = Reg16(12); - uint n = Reg16(0); + uint n = Reg16(16); uint d = (Vd << 1) | D; return ExecuteCore_VLDR(Encoding.A1, single_reg, add, d, n, imm32); } @@ -837,7 +992,7 @@ namespace BizHawk.Emulation.CPUs.ARM Decoder_ExecuteArm_ShortVFPTransfer.Ensure(() => Decoder_ExecuteArm_ShortVFPTransfer .d("A", 3).d("L", 1).d("C", 1).d("B", 2) .r("L==0 && C==0 && A==#000", () => Execute_Unhandled("VMOV (between ARM core register and single-precision register) on page A8-648")) - .r("L==0 && C==0 && A==#111", () => ExecuteArm_VMSR_A1()) + .r("L==0 && C==0 && A==#111", () => Execute_VMSR_A1()) .r("L==0 && C==1 && A==#0xx", () => Execute_Unhandled("VMOV (ARM core register to scalar) on page A8-644")) .r("L==0 && C==1 && A==#1xx && B==#0x", () => Execute_Unhandled("VDUP (ARM core register) on page A8-594")) .r("L==1 && C==0 && A==#000", () => Execute_Unhandled("VMOV (between ARM core register and single-precision register) on page A8-648")) @@ -854,7 +1009,7 @@ namespace BizHawk.Emulation.CPUs.ARM return 1; } - uint ExecuteArm_VMSR_A1() + uint Execute_VMSR_A1() { uint t = Reg16(12); if (t == 15 || (t == 13 && _CurrentInstrSet() != EInstrSet.ARM)) return _UNPREDICTABLE(); diff --git a/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteCore.cs b/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteCore.cs index b512101064..dc353e9e96 100644 --- a/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteCore.cs +++ b/BizHawk.Emulation/CPUs/ARM/ARM.ExecuteCore.cs @@ -211,6 +211,17 @@ namespace BizHawk.Emulation.CPUs.ARM return 1; } + //A8.6.25 BX + uint ExecuteCore_BX(Encoding encoding, uint m) + { + if (disassemble) + return DISNEW("BX", "", m); + + _BXWritePC(r[m]); + + return 1; + } + //A8.6.35 CMP (immediate) uint ExecuteCore_CMP_immediate(Encoding encoding, uint n, uint imm32) { @@ -588,6 +599,14 @@ namespace BizHawk.Emulation.CPUs.ARM return 0; } + //A8.6.110 NOP + uint ExecuteCore_NOP(Encoding encoding) + { + if (disassemble) + return DISNEW("NOP", ""); + return 1; + } + //A8.6.113 ORR (immediate) uint ExecuteCore_ORR_immediate(Encoding encoding, uint n, uint d, bool setflags, uint imm32, Bit carry) { @@ -1007,10 +1026,73 @@ namespace BizHawk.Emulation.CPUs.ARM return 1; } + //A8.6.272 VADD (floating point) + uint ExecuteCore_VADD_floating_point(Encoding encoding, bool dp_operation, bool advsimd, uint d, uint n, uint m) + { + if (advsimd) throw new NotImplementedException("VMOV reg adv simd :("); + + if (disassemble) + return DISNEW("VADD<.fpsize>", "<{SDd~SDn, }>, ", dp_operation ? 64 : 32, !dp_operation, d, n, !dp_operation, n, !dp_operation, m); + + if (advsimd) + { + } + else + { + if (dp_operation) + D[d] = _FPAdd(D[n], D[m], true); + else + S[d] = _FPAdd(S[n], S[m], true); + } + + return 1; + } + //A8.6.320 VLDR uint ExecuteCore_VLDR(Encoding encoding, bool single_reg, bool add, uint d, uint n, uint imm32) { - throw new NotImplementedException("TODO"); + if (disassemble) + return DISNEW("VLDR", ", [<{, #+/-imm}>]", single_reg, d, n, add, imm32); + + _CheckVFPEnabled(true); + _NullCheckIfThumbEE(n); + uint @base = (n==15)?_Align(PC,4):r[n]; + uint address = add ? (@base + imm32) : (@base - imm32); + if (single_reg) + S[d] = MemA_ReadSingle(address); + else + D[d] = MemA_ReadDouble(address); + + return 1; + } + + //A8.6.326 VMOV (immediate) + uint ExecuteCore_VMOV_immediate(Encoding encoding, bool single_register, bool advsimd, uint d, uint regs, float imm32, double imm64) + { + if (advsimd) throw new NotImplementedException("VMOV imm adv simd :("); + throw new NotImplementedException("ExecuteCore_VMOV_immediate"); + + //if(disassemble) + // return DISNEW("VMOV<.fpsize>", "", single_register?32:64, single_register, d + return 1; + } + + //A8.6.327 VMOV (register) + uint ExecuteCore_VMOV_register(Encoding encoding, bool single_register, bool advsimd, uint d, uint m, uint regs) + { + if (advsimd) throw new NotImplementedException("VMOV reg adv simd :("); + + if (disassemble) + return DISNEW("VMOV<.fpsize>", ", ", single_register ? 32 : 64, single_register, d, single_register, m); + + _CheckAdvSIMDOrVFPEnabled(true, advsimd); + + if (single_register) + S[d] = S[m]; + else for (uint r = 0; r <= regs - 1; r++) + D[d + r] = D[m + r]; + + return 1; } //A8.6.336 VMSR @@ -1027,7 +1109,7 @@ namespace BizHawk.Emulation.CPUs.ARM uint ExecuteCore_VPUSH(Encoding encoding, bool single_regs, uint d, uint regs, uint imm32) { if (disassemble) - return DISNEW("VPUSH<{.size}>", "", single_regs ? 32 : 64, single_regs, d, regs); + return DISNEW("VPUSH<{.fpsize}>", "", single_regs ? 32 : 64, single_regs, d, regs); _CheckVFPEnabled(true); _NullCheckIfThumbEE(13); diff --git a/BizHawk.Emulation/CPUs/ARM/ARM.Pseudocode.cs b/BizHawk.Emulation/CPUs/ARM/ARM.Pseudocode.cs index c8ff618d15..eb6cda24ba 100644 --- a/BizHawk.Emulation/CPUs/ARM/ARM.Pseudocode.cs +++ b/BizHawk.Emulation/CPUs/ARM/ARM.Pseudocode.cs @@ -89,6 +89,13 @@ namespace BizHawk.Emulation.CPUs.ARM return bus.Read32(AT.READ, addr); } + ulong MemA_Read64(uint addr) + { + ulong ret = MemA_Read32(addr); + ret |= (((ulong)MemA_Read32(addr + 4)) << 32); + return ret; + } + void _SetExclusiveMonitors(uint address, int size) { //TODO!!! boring!! @@ -106,6 +113,16 @@ namespace BizHawk.Emulation.CPUs.ARM MemA_Write32(addr,float_downcast(val)); } + float MemA_ReadSingle(uint addr) + { + return float_upcast(MemA_Read32(addr)); + } + + double MemA_ReadDouble(uint addr) + { + return double_upcast(MemA_Read64(addr)); + } + void MemA_WriteDouble(uint addr, double val) { ulong uval = double_downcast(val); @@ -443,6 +460,78 @@ namespace BizHawk.Emulation.CPUs.ARM return result; } + float _FPAdd(float op1, float op2, bool fpscr_controlled) + { + //TODO + return op1 + op2; + } + + double _FPAdd(double op1, double op2, bool fpscr_controlled) + { + //TODO + return op1 + op2; + } + + bool _CheckAdvSIMDOrVFPEnabled(bool x, bool y) + { + //TODO + return true; + } + + static uint[] __VFPExpandImm32_table; + static uint __VFPExpandImm32_calc(uint imm8) + { + uint a = _.BIT7(imm8); + uint B = _.BIT6(imm8)^1; + uint b = _.BIT6(imm8); + b |= (b << 1); //replicated to 2 bits + b |= (b << 2); //replicated to 4 bits + b |= (b << 1); //replicated to 5 bits + uint cdefgh = imm8 & 0x3F; + + return (a<<31)|(B<<30)|(b<<29)|(cdefgh<<24); + } + + static ulong[] __VFPExpandImm64_table; + static ulong __VFPExpandImm64_calc(uint imm8) + { + uint a = _.BIT7(imm8); + uint B = _.BIT6(imm8) ^ 1; + uint b = _.BIT6(imm8); + b |= (b << 1); //replicated to 2 bits + b |= (b << 2); //replicated to 4 bits + b |= (b << 4); //replicated to 8 bits + uint cdefgh = imm8 & 0x3F; + + uint uintret = (a << 31) | (B << 30) | (b << 29) | (cdefgh << 20); + ulong ulongret = uintret << 32; + return ulongret; + } + + uint _VFPExpandImm32(uint imm8) + { + if(__VFPExpandImm32_table == null) + { + __VFPExpandImm32_table = new uint[256]; + for(uint i=0;i<256;i++) + __VFPExpandImm32_table[i] = __VFPExpandImm32_calc(i); + } + + return __VFPExpandImm32_table[imm8]; + } + + ulong _VFPExpandImm64(uint imm8) + { + if (__VFPExpandImm64_table == null) + { + __VFPExpandImm64_table = new ulong[256]; + for (uint i = 0; i < 256; i++) + __VFPExpandImm64_table[i] = __VFPExpandImm64_calc(i); + } + + return __VFPExpandImm64_table[imm8]; + } + uint _ARMExpandImm(uint imm12) { //A5-10 diff --git a/BizHawk.Emulation/CPUs/ARM/ARM.cs b/BizHawk.Emulation/CPUs/ARM/ARM.cs index c5d1573629..ad087d513e 100644 --- a/BizHawk.Emulation/CPUs/ARM/ARM.cs +++ b/BizHawk.Emulation/CPUs/ARM/ARM.cs @@ -113,18 +113,29 @@ namespace BizHawk.Emulation.CPUs.ARM float[] S = new float[32]; double[] D = new double[16]; - unsafe uint float_downcast(float f) + unsafe static uint float_downcast(float f) { float* fp = &f; return *(uint*)fp; } - unsafe ulong double_downcast(double f) + unsafe static float float_upcast(uint f) + { + uint* fp = &f; + return *(float*)fp; + } + + unsafe static ulong double_downcast(double f) { double* fp = &f; return *(ulong*)fp; } + unsafe static double double_upcast(ulong f) + { + ulong* fp = &f; + return *(double*)fp; + } public uint SP { get { return r[13]; } set { r[13] = value; } } public uint LR { get { return r[14]; } set { r[14] = value; } } @@ -140,6 +151,8 @@ namespace BizHawk.Emulation.CPUs.ARM uint FPSCR; + uint _FPSCR_LEN() { return 0; } + uint _FPSCR_STRIDE() { return 0; } public ARM(ARM_SYS sys, ARM_BUS bus) {