BizHawk/BizHawk.Emulation/CPUs/ARM/ARM.Execute.cs

147 lines
4.2 KiB
C#

using System;
using System.Text;
using System.Runtime.InteropServices;
namespace BizHawk.Emulation.CPUs.ARM
{
partial class ARM
{
public uint Execute()
{
if (APSR.T == 1) return ExecuteThumb();
else return ExecuteArm();
}
enum CC
{
EQ = 0,
NE = 1,
CS = 2, HS = 2,
CC = 3, LO = 3,
MI = 4,
PL = 5,
VS = 6,
VC = 7,
HI = 8,
LS = 9,
GE = 10,
LT = 11,
GT = 12,
LE = 13,
AL = 14,
}
//return (CPSR.N?0x80000000:0)|(CPSR.Z?0x40000000:0)|(CPSR.C?0x20000000:0)|(CPSR.V?0x10000000:0);
readonly string[] CC_strings = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "AL", "XX" };
readonly string[] Reg_names = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "SP", "LR", "PC" };
uint CONDITION(uint i) { return i >> 28; }
int SIGNEXTEND_24(uint x) { return (((int)x << 8) >> 8); }
//an instruction sets this flag when the results are unpredictable but will be executed anyway
public bool unpredictable;
public uint cycles;
uint _currentCondVal;
uint _CurrentCond()
{
//TODO - calculate CurrentCond from from A8.3.1
return _currentCondVal;
}
bool _ConditionPassed()
{
uint cond = _CurrentCond();
bool result = false;
switch (cond & _.b1110)
{
case _.b0000: result = APSR.Z == 1; break;
case _.b0010: result = APSR.C == 1; break;
case _.b0100: result = APSR.N == 1; break;
case _.b0110: result = APSR.V == 1; break;
case _.b1000: result = APSR.C == 1 && APSR.Z == 0; break;
case _.b1010: result = APSR.N == APSR.V; break;
case _.b1100: result = (APSR.N == APSR.V) && APSR.Z == 0; break;
case _.b1110: result = true; break;
}
if ((cond & 1) == 1 && cond != _.b1111)
result = !result;
return result;
}
bool CHK(uint value, int mask, int test)
{
return (value & mask) == test;
}
uint Reg8(uint pos)
{
return (uint)((instruction >> (int)pos) & 7);
}
uint Reg16(uint pos)
{
return (uint)((instruction >> (int)pos) & 0xF);
}
uint Execute_Undefined()
{
if (disassemble) disassembly = "undefined";
return 0;
}
uint Execute_Unhandled(string descr)
{
if (disassemble) disassembly = descr + " unhandled";
return 1;
}
uint Disassembly_Unhandled(string descr)
{
disassembly = "disasm unhandled: " + descr;
return 1;
}
uint Disassemble_LDR_STR_immediate(string opcode, uint t, uint imm32, uint n, bool index, bool add, bool wback)
{
bool offset = index == true && wback == false;
bool preindexed = index == true && wback == true;
bool postindex = index == false && wback == true;
string rt = "<rt!>";
opcode += "<c>";
//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 + ", [<Rn!><{, #+/-imm}>]", t, n, add, imm32);
else if (preindexed)
return DISNEW(opcode, rt + ", [<Rn!>, <+/-><imm>]!", t, n, add, imm32);
else if (postindex)
return DISNEW(opcode, rt + ", [<Rn!>], <+/-><imm>", t, n, add, imm32);
else throw new InvalidOperationException();
}
uint Disassemble_LDR_STR_register(string opcode, uint t, uint n, uint m, SRType shift_t, int shift_n, bool index, bool add, bool wback)
{
bool offset = index == true && wback == false;
bool preindexed = index == true && wback == true;
bool postindex = index == false && wback == true;
string rt = "<rt!>";
opcode += "<c>";
//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 + ", [<Rn!>, <+/-><rm!><{, shift}>]", t, n, add, m, shift_t, shift_n);
else if (preindexed)
return DISNEW(opcode, rt + ", [<Rn!>, <+/-><rm!><{, shift}>]!", t, n, add, m, shift_t, shift_n);
else if (postindex)
return DISNEW(opcode, rt + ", [<Rn!>], <+/-><rm!><{, shift}>", t, n, add, m, shift_t, shift_n);
else throw new InvalidOperationException();
}
void UnalignedAccess(uint addr)
{
Console.WriteLine("Warning! unaligned access at {0:x8}", addr);
}
}
}