This commit is contained in:
zeromus 2011-04-03 07:58:12 +00:00
parent 5cd5e799a6
commit 510e52271b
6 changed files with 230 additions and 6 deletions

View File

@ -162,6 +162,11 @@ namespace BizHawk.Emulation.CPUs.ARM
else opcode = opcode.Replace(crepl, CC_strings[_CurrentCond()]);
}
else opcode = opcode.Replace(crepl, "");
if(opcode.Contains("{.size}"))
{
opcode = opcode.Replace("<{.size}>","." + args[argindex++].ToString());
}
//---------
string cpcomment = null;
@ -317,9 +322,26 @@ namespace BizHawk.Emulation.CPUs.ARM
{
item = "";
cpcomment = args[argindex++] as string;
break;
}
break;
case "list":
{
bool single = (bool)args[argindex++];
uint d = (uint)args[argindex++];
uint regs = (uint)args[argindex++];
item = "{";
string name = single ? "s" : "d";
bool first=true;
for (uint r = 0; r <= regs - 1; r++)
{
if (!first) item += ",";
first = false;
item += name + (r + d).ToString();
}
item += "}";
break;
}
default: item = "<" + item + ">"; break;
}

View File

@ -377,7 +377,7 @@ namespace BizHawk.Emulation.CPUs.ARM
case _.b01000:
case _.b01001:
if (Rn != _.b1111) return Execute_ADD_immedate_arm_A1();
else return Execute_Unhandled("arm adr");
else return Execute_ADR_A1();
case _.b01010:
case _.b01011: return Execute_Unhandled("arm adc imm");
case _.b01100:
@ -413,13 +413,35 @@ namespace BizHawk.Emulation.CPUs.ARM
uint imm12 = instruction & 0xFFF;
if (n == _.b1111 && S == 0) throw new NotImplementedException("SEE ADR");
if (n == _.b1101) throw new NotImplementedException("SEE SUB (SP minus immediate");
if (n == _.b1101) return Execute_SUB_SP_minus_immediate_A1();
if (n == _.b1111 && S == 1) throw new NotImplementedException("SEE SUBS PC, LR and related instructions");
bool setflags = (S == 1);
uint imm32 = _ARMExpandImm(imm12);
return ExecuteCore_SUB_immediate_arm(Encoding.A1, setflags, n, d, imm32);
}
uint Execute_SUB_SP_minus_immediate_A1()
{
//A8.6.215
uint d = Reg16(12);
Bit S = _.BIT20(instruction);
if (d == _.b1111 && S == 1) throw new NotImplementedException("SEE SUBS PC, LR and related instructions");
bool setflags = (S == 1);
uint imm12 = instruction & 0xFFF;
uint imm32 = _ARMExpandImm(imm12);
return ExecuteCore_SUB_SP_minus_immediate(Encoding.A1,d,setflags,imm32);
}
uint Execute_ADR_A1()
{
//A8.6.10
uint d = Reg16(12);
uint imm12 = instruction & 0xFFF;
uint imm32 = _ARMExpandImm(imm12);
const bool add = true;
return ExecuteCore_ADR(Encoding.A1, d, imm32, add);
}
uint Execute_ADD_immedate_arm_A1()
{
Bit S = _.BIT20(instruction);
@ -690,7 +712,7 @@ namespace BizHawk.Emulation.CPUs.ARM
Decoder_ExecuteArm_SVCAndCP.Ensure(() => Decoder_ExecuteArm_SVCAndCP
.d("op1", 6).d("op", 1).d("coproc_special", 1).d("rn_is_15", 1)
.r("op1==#0xxxxx && op1!=#000x0x && coproc_special==#1", () => Execute_Unhandled("ExecuteArm_SIMD_VFP_LoadStore"))
.r("op1==#0xxxxx && op1!=#000x0x && coproc_special==#1", () => Execute_ExtensionRegister_LoadStore())
.r("op1==#0xxxx0 && op1!=#000x0x && coproc_special==#0", () => Execute_Unhandled("STC,STC2"))
.r("op1==#0xxxx1 && op1!=#000x0x && coproc_special==#0 && rn_is_15==#0", () => Execute_Unhandled("LDC,LDC2(immediate)"))
.r("op1==#0xxxx1 && op1!=#000x0x && coproc_special==#0 && rn_is_15==#1", () => Execute_Unhandled("LDC,LDC2(literal)"))
@ -717,9 +739,85 @@ namespace BizHawk.Emulation.CPUs.ARM
return 1;
}
uint Execute_ExtensionRegister_LoadStore()
{
//A7.6 Extension register load/store instructions
uint opcode = (instruction >> 20) & 0x1F;
uint n = Reg16(16);
bool bit8 = _.BIT8(instruction)==1;
switch (opcode)
{
case _.b00100: case _.b00101: return Execute_Unhandled("64-bit transfers between ARM core and extension registers");
case _.b01000: case _.b01100: return Execute_Unhandled("VSTM");
case _.b01010: case _.b01110: return Execute_Unhandled("VSTM");
case _.b10000: case _.b10100: case _.b11000: case _.b11100: return Execute_Unhandled("VSTR");
case _.b10010: case _.b10110:
if (n != _.b1101) return Execute_Unhandled("VSTM");
else return bit8?Execute_VPUSH_A1():Execute_VPUSH_A2();
case _.b01001: case _.b01101: return Execute_Unhandled("VLDM");
case _.b01011: case _.b01111:
if (n != _.b1101) return Execute_Unhandled("VLDM");
else return Execute_Unhandled("VPOP");
case _.b10001: case _.b10101: case _.b11001: case _.b11101:
return bit8 ? Execute_VLDR_A1() : Execute_VLDR_A2();
case _.b10011: case _.b10111: return Execute_Unhandled("VLDM");
default: throw new InvalidOperationException("decoder fail");
}
}
uint Execute_VLDR_A1()
{
//A8.6.320
throw new NotSupportedException("Execute_VLDR_A1");
}
uint Execute_VLDR_A2()
{
//A8.6.320
const bool single_reg = true;
Bit U = _.BIT23(instruction);
Bit D = _.BIT22(instruction);
bool add = (U == 1);
uint imm8 = instruction & 0xFF;
uint imm32 = _ZeroExtend_32(imm8 << 2);
uint Vd = Reg16(12);
uint n = Reg16(0);
uint d = (Vd << 1) | D;
return ExecuteCore_VLDR(Encoding.A1, single_reg, add, d, n, imm32);
}
uint Execute_VPUSH_A1()
{
//A8.6.355
const bool single_regs = false;
Bit D = _.BIT22(instruction);
uint d = ((uint)D << 4) | Reg16(12);
uint imm8 = instruction & 0xFF;
uint imm32 = _ZeroExtend_32(imm8 << 2);
uint regs = imm8 / 2;
Debug.Assert(!((imm8&1)==1),"see FSTMX");
if(regs==0 || regs>16 || (d+regs)>32) _FlagUnpredictable();
return ExecuteCore_VPUSH(Encoding.A1, single_regs, d, regs, imm32);
}
uint Execute_VPUSH_A2()
{
//A8.6.355
const bool single_regs = true;
Bit D = _.BIT22(instruction);
uint d = (Reg16(12)<<1)|D;
uint imm8 = instruction & 0xFF;
uint imm32 = _ZeroExtend_32(imm8 << 2);
uint regs = imm8;
if (regs == 0 || regs > 16 || (d + regs) > 32) _FlagUnpredictable();
return ExecuteCore_VPUSH(Encoding.A2, single_regs, d, regs, imm32);
}
uint Execute_MRC_MRC2_A1()
{
//ignoring admonition to see "advanced SIMD and VFP" which has been handled by decode earlier
//TODO - but i should assert anyway
uint t = Reg16(12);
uint cp = Reg16(8);
uint opc1 = Reg8(21);

View File

@ -376,6 +376,34 @@ namespace BizHawk.Emulation.CPUs.ARM
return 1;
}
//A8.6.60 LDR (register)
uint ExecuteCore_LDR_register(Encoding encoding, uint t, uint n, uint m, SRType shift_t, int shift_n, bool index, bool add, bool wback)
{
if(disassemble)
return Disassemble_LDR_STR_register("LDR<c>", t, n, m, shift_t, shift_n, index, add, wback);
_NullCheckIfThumbEE(n);
uint offset = _Shift(r[m], shift_t, shift_n, APSR.C);
uint offset_addr = add ? (r[n] + offset) : (r[n] - offset);
uint address = index ? offset_addr : r[n];
uint data = MemU_Read32(address);
if (wback) r[n] = offset_addr;
if (t == 15)
{
if ((address & 3) == _.b00) _LoadWritePC(data);
else _FlagUnpredictable();
}
else if (_UnalignedSupport() || (address & 3) == _.b00)
r[t] = data;
else //can only apply before ARMv7
if (_CurrentInstrSet() == EInstrSet.ARM)
r[t] = _ROR(data, 8 * ((int)address & 3));
else
r[t] = (uint)_UNKNOWN(32, _ROR(data, 8 * ((int)address & 3)));
return 1;
}
//A8.6.61 LDRB (immediate, thumb)
uint ExecuteCore_LDRB_immediate_thumb(Encoding encoding, uint t, uint n, uint imm32, bool index, bool add, bool wback)
{
@ -979,6 +1007,12 @@ namespace BizHawk.Emulation.CPUs.ARM
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");
}
//A8.6.336 VMSR
uint ExecuteCore_VMSR(uint t)
{
@ -989,6 +1023,33 @@ namespace BizHawk.Emulation.CPUs.ARM
return 1;
}
//A8.6.355 VPUSH
uint ExecuteCore_VPUSH(Encoding encoding, bool single_regs, uint d, uint regs, uint imm32)
{
if (disassemble)
return DISNEW("VPUSH<c><{.size}>", "<list>", single_regs ? 32 : 64, single_regs, d, regs);
_CheckVFPEnabled(true);
_NullCheckIfThumbEE(13);
uint address = SP - imm32;
SP = SP - imm32;
if (single_regs)
for (uint r = 0; r <= regs-1; r++)
{
MemA_WriteSingle(address, S[d+r]);
address += 4;
}
else
for (uint r = 0; r <= regs - 1; r++)
{
MemA_WriteDouble(address, D[d+r]);
address += 8;
}
return 1;
}
}
//unnecessary opcodes: BKPT, BXJ, CBNZ, CHKA, NOP, CPY, DBG, ENTERX, HB, IT, LDRBT, LDRHT, LDRSBT, LDRSHT, LEAVEX, RBIT, SBFX, SDIV, TBB

View File

@ -127,7 +127,7 @@ namespace BizHawk.Emulation.CPUs.ARM
case _.b001: return Execute_Unhandled("STRH (register) on page A8-412");
case _.b010: return Execute_STRB_register_T1();
case _.b011: return Execute_Unhandled("LDRSB (register) on page A8-164");
case _.b100: return Execute_Unhandled("LDR (register) on page A8-124");
case _.b100: return Execute_LDR_register_T1();
case _.b101: return Execute_Unhandled("LDRH (register)");
case _.b110: return Execute_LDRB_register_T1();
case _.b111: return Execute_Unhandled("LDRSH (register) on page A8-172");
@ -201,6 +201,19 @@ namespace BizHawk.Emulation.CPUs.ARM
return ExecuteCore_STRB_register(Encoding.T1, t, n, m, shift_t, shift_n, index, add, wback);
}
uint Execute_LDR_register_T1()
{
//A8.6.60
if (_CurrentInstrSet() == EInstrSet.THUMBEE) throw new NotSupportedException("Modified operatoin in ThumbEE");
uint t = Reg8(0);
uint n = Reg8(3);
uint m = Reg8(6);
const bool index = true; const bool add = true; const bool wback = false;
const SRType shift_t = SRType.LSL;
const int shift_n = 0;
return ExecuteCore_LDR_register(Encoding.T1, t, n, m, shift_t, shift_n, index, add, wback);
}
uint Execute_LDRB_register_T1()
{
//A8.6.64

View File

@ -101,6 +101,19 @@ namespace BizHawk.Emulation.CPUs.ARM
return true;
}
void MemA_WriteSingle(uint addr, float val)
{
MemA_Write32(addr,float_downcast(val));
}
void MemA_WriteDouble(uint addr, double val)
{
ulong uval = double_downcast(val);
//TODO endian
MemA_Write32(addr,(uint)uval);
MemA_Write32(addr+4,(uint)(uval>>32));
}
void MemA_Write32(uint addr, uint val)
{
addr = _Align(addr, 4);
@ -181,6 +194,8 @@ namespace BizHawk.Emulation.CPUs.ARM
_BranchTo((uint)(address & ~1));
}
bool _BigEndian() { return false; }
void _BranchTo(uint address)
{
_R[15] = address;

View File

@ -105,12 +105,27 @@ namespace BizHawk.Emulation.CPUs.ARM
}
}
//todo: make R[] indexer which is defined as in manual with an assert when R[15] is written to
public Registers r;
uint[] _R = new uint[16];
public Status_Reg APSR;
public Status_Reg SPSR;
float[] S = new float[32];
double[] D = new double[16];
unsafe uint float_downcast(float f)
{
float* fp = &f;
return *(uint*)fp;
}
unsafe ulong double_downcast(double f)
{
double* fp = &f;
return *(ulong*)fp;
}
public uint SP { get { return r[13]; } set { r[13] = value; } }
public uint LR { get { return r[14]; } set { r[14] = value; } }
public uint PC { get { return r[15]; } set { r[15] = value; } }