bsnes/higan/processor/arm7tdmi/arm7tdmi.hpp

286 lines
11 KiB
C++

//ARMv4 (ARM7TDMI)
#pragma once
namespace Processor {
struct ARM7TDMI {
enum : uint {
Nonsequential = 1 << 0, //N cycle
Sequential = 1 << 1, //S cycle
Prefetch = 1 << 2, //instruction fetch
Byte = 1 << 3, // 8-bit access
Half = 1 << 4, //16-bit access
Word = 1 << 5, //32-bit access
Load = 1 << 6, //load operation
Store = 1 << 7, //store operation
Signed = 1 << 8, //sign-extend
};
virtual auto step(uint clocks) -> void = 0;
virtual auto sleep() -> void = 0;
virtual auto get(uint mode, uint32 address) -> uint32 = 0;
virtual auto set(uint mode, uint32 address, uint32 word) -> void = 0;
//arm7tdmi.cpp
ARM7TDMI();
auto power() -> void;
//registers.cpp
struct GPR;
struct PSR;
inline auto r(uint4) -> GPR&;
inline auto cpsr() -> PSR&;
inline auto spsr() -> PSR&;
inline auto privileged() const -> bool;
inline auto exception() const -> bool;
//memory.cpp
auto idle() -> void;
auto read(uint mode, uint32 address) -> uint32;
auto load(uint mode, uint32 address) -> uint32;
auto write(uint mode, uint32 address, uint32 word) -> void;
auto store(uint mode, uint32 address, uint32 word) -> void;
//algorithms.cpp
auto ADD(uint32, uint32, bool) -> uint32;
auto ASR(uint32, uint8) -> uint32;
auto BIT(uint32) -> uint32;
auto LSL(uint32, uint8) -> uint32;
auto LSR(uint32, uint8) -> uint32;
auto MUL(uint32, uint32, uint32) -> uint32;
auto ROR(uint32, uint8) -> uint32;
auto RRX(uint32) -> uint32;
auto SUB(uint32, uint32, bool) -> uint32;
auto TST(uint4) -> bool;
//instruction.cpp
auto fetch() -> void;
auto instruction() -> void;
auto exception(uint mode, uint32 address) -> void;
auto armInitialize() -> void;
auto thumbInitialize() -> void;
//instructions-arm.cpp
auto armALU(uint4 mode, uint4 target, uint4 source, uint32 data) -> void;
auto armMoveToStatus(uint4 field, uint1 source, uint32 data) -> void;
auto armInstructionBranch(int24, uint1) -> void;
auto armInstructionBranchExchangeRegister(uint4) -> void;
auto armInstructionDataImmediate(uint8, uint4, uint4, uint4, uint1, uint4) -> void;
auto armInstructionDataImmediateShift(uint4, uint2, uint5, uint4, uint4, uint1, uint4) -> void;
auto armInstructionDataRegisterShift(uint4, uint2, uint4, uint4, uint4, uint1, uint4) -> void;
auto armInstructionLoadImmediate(uint8, uint1, uint4, uint4, uint1, uint1, uint1) -> void;
auto armInstructionLoadRegister(uint4, uint1, uint4, uint4, uint1, uint1, uint1) -> void;
auto armInstructionMemorySwap(uint4, uint4, uint4, uint1) -> void;
auto armInstructionMoveHalfImmediate(uint8, uint4, uint4, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveHalfRegister(uint4, uint4, uint4, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveImmediateOffset(uint12, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveMultiple(uint16, uint4, uint1, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveRegisterOffset(uint4, uint2, uint5, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveToRegisterFromStatus(uint4, uint1) -> void;
auto armInstructionMoveToStatusFromImmediate(uint8, uint4, uint4, uint1) -> void;
auto armInstructionMoveToStatusFromRegister(uint4, uint4, uint1) -> void;
auto armInstructionMultiply(uint4, uint4, uint4, uint4, uint1, uint1) -> void;
auto armInstructionMultiplyLong(uint4, uint4, uint4, uint4, uint1, uint1, uint1) -> void;
auto armInstructionSoftwareInterrupt(uint24 immediate) -> void;
auto armInstructionUndefined() -> void;
//instructions-thumb.cpp
auto thumbInstructionALU(uint3, uint3, uint4) -> void;
auto thumbInstructionALUExtended(uint4, uint4, uint2) -> void;
auto thumbInstructionAddRegister(uint8, uint3, uint1) -> void;
auto thumbInstructionAdjustImmediate(uint3, uint3, uint3, uint1) -> void;
auto thumbInstructionAdjustRegister(uint3, uint3, uint3, uint1) -> void;
auto thumbInstructionAdjustStack(uint7, uint1) -> void;
auto thumbInstructionBranchExchange(uint4) -> void;
auto thumbInstructionBranchFarPrefix(int11) -> void;
auto thumbInstructionBranchFarSuffix(uint11) -> void;
auto thumbInstructionBranchNear(int11) -> void;
auto thumbInstructionBranchTest(int8, uint4) -> void;
auto thumbInstructionImmediate(uint8, uint3, uint2) -> void;
auto thumbInstructionLoadLiteral(uint8, uint3) -> void;
auto thumbInstructionMoveByteImmediate(uint3, uint3, uint5, uint1) -> void;
auto thumbInstructionMoveHalfImmediate(uint3, uint3, uint5, uint1) -> void;
auto thumbInstructionMoveMultiple(uint8, uint3, uint1) -> void;
auto thumbInstructionMoveRegisterOffset(uint3, uint3, uint3, uint3) -> void;
auto thumbInstructionMoveStack(uint8, uint3, uint1) -> void;
auto thumbInstructionMoveWordImmediate(uint3, uint3, uint5, uint1) -> void;
auto thumbInstructionShiftImmediate(uint3, uint3, uint5, uint2) -> void;
auto thumbInstructionSoftwareInterrupt(uint8) -> void;
auto thumbInstructionStackMultiple(uint8, uint1, uint1) -> void;
auto thumbInstructionUndefined() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
//disassembler.cpp
auto disassemble(maybe<uint32> pc = nothing, maybe<boolean> thumb = nothing) -> string;
auto disassembleRegisters() -> string;
struct GPR {
inline operator uint32_t() const { return data; }
inline auto operator=(const GPR& value) -> GPR& { return operator=(value.data); }
inline auto operator=(uint32 value) -> GPR& {
data = value;
if(modify) modify();
return *this;
}
uint32 data;
function<auto () -> void> modify;
};
struct PSR {
enum : uint {
USR = 0x10, //user
FIQ = 0x11, //fast interrupt
IRQ = 0x12, //interrupt
SVC = 0x13, //service
ABT = 0x17, //abort
UND = 0x1b, //undefined
SYS = 0x1f, //system
};
inline operator uint32_t() const {
return m << 0 | t << 5 | f << 6 | i << 7 | v << 28 | c << 29 | z << 30 | n << 31;
}
inline auto operator=(uint32 data) -> PSR& {
m = data.bits(0,4);
t = data.bit(5);
f = data.bit(6);
i = data.bit(7);
v = data.bit(28);
c = data.bit(29);
z = data.bit(30);
n = data.bit(31);
return *this;
}
//serialization.cpp
auto serialize(serializer&) -> void;
uint5 m; //mode
boolean t; //thumb
boolean f; //fiq
boolean i; //irq
boolean v; //overflow
boolean c; //carry
boolean z; //zero
boolean n; //negative
};
struct Processor {
//serialization.cpp
auto serialize(serializer&) -> void;
GPR r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
PSR cpsr;
struct FIQ {
GPR r8, r9, r10, r11, r12, r13, r14;
PSR spsr;
} fiq;
struct IRQ {
GPR r13, r14;
PSR spsr;
} irq;
struct SVC {
GPR r13, r14;
PSR spsr;
} svc;
struct ABT {
GPR r13, r14;
PSR spsr;
} abt;
struct UND {
GPR r13, r14;
PSR spsr;
} und;
} processor;
struct Pipeline {
//serialization.cpp
auto serialize(serializer&) -> void;
struct Instruction {
uint32 address;
uint32 instruction;
boolean thumb; //not used by fetch stage
};
uint1 reload = 1;
uint1 nonsequential = 1;
Instruction fetch;
Instruction decode;
Instruction execute;
} pipeline;
uint32 opcode;
boolean carry;
boolean irq;
function<auto (uint32 opcode) -> void> armInstruction[4096];
function<auto () -> void> thumbInstruction[65536];
//disassembler.cpp
auto armDisassembleBranch(int24, uint1) -> string;
auto armDisassembleBranchExchangeRegister(uint4) -> string;
auto armDisassembleDataImmediate(uint8, uint4, uint4, uint4, uint1, uint4) -> string;
auto armDisassembleDataImmediateShift(uint4, uint2, uint5, uint4, uint4, uint1, uint4) -> string;
auto armDisassembleDataRegisterShift(uint4, uint2, uint4, uint4, uint4, uint1, uint4) -> string;
auto armDisassembleLoadImmediate(uint8, uint1, uint4, uint4, uint1, uint1, uint1) -> string;
auto armDisassembleLoadRegister(uint4, uint1, uint4, uint4, uint1, uint1, uint1) -> string;
auto armDisassembleMemorySwap(uint4, uint4, uint4, uint1) -> string;
auto armDisassembleMoveHalfImmediate(uint8, uint4, uint4, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveHalfRegister(uint4, uint4, uint4, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveImmediateOffset(uint12, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveMultiple(uint16, uint4, uint1, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveRegisterOffset(uint4, uint2, uint5, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveToRegisterFromStatus(uint4, uint1) -> string;
auto armDisassembleMoveToStatusFromImmediate(uint8, uint4, uint4, uint1) -> string;
auto armDisassembleMoveToStatusFromRegister(uint4, uint4, uint1) -> string;
auto armDisassembleMultiply(uint4, uint4, uint4, uint4, uint1, uint1) -> string;
auto armDisassembleMultiplyLong(uint4, uint4, uint4, uint4, uint1, uint1, uint1) -> string;
auto armDisassembleSoftwareInterrupt(uint24) -> string;
auto armDisassembleUndefined() -> string;
auto thumbDisassembleALU(uint3, uint3, uint4) -> string;
auto thumbDisassembleALUExtended(uint4, uint4, uint2) -> string;
auto thumbDisassembleAddRegister(uint8, uint3, uint1) -> string;
auto thumbDisassembleAdjustImmediate(uint3, uint3, uint3, uint1) -> string;
auto thumbDisassembleAdjustRegister(uint3, uint3, uint3, uint1) -> string;
auto thumbDisassembleAdjustStack(uint7, uint1) -> string;
auto thumbDisassembleBranchExchange(uint4) -> string;
auto thumbDisassembleBranchFarPrefix(int11) -> string;
auto thumbDisassembleBranchFarSuffix(uint11) -> string;
auto thumbDisassembleBranchNear(int11) -> string;
auto thumbDisassembleBranchTest(int8, uint4) -> string;
auto thumbDisassembleImmediate(uint8, uint3, uint2) -> string;
auto thumbDisassembleLoadLiteral(uint8, uint3) -> string;
auto thumbDisassembleMoveByteImmediate(uint3, uint3, uint5, uint1) -> string;
auto thumbDisassembleMoveHalfImmediate(uint3, uint3, uint5, uint1) -> string;
auto thumbDisassembleMoveMultiple(uint8, uint3, uint1) -> string;
auto thumbDisassembleMoveRegisterOffset(uint3, uint3, uint3, uint3) -> string;
auto thumbDisassembleMoveStack(uint8, uint3, uint1) -> string;
auto thumbDisassembleMoveWordImmediate(uint3, uint3, uint5, uint1) -> string;
auto thumbDisassembleShiftImmediate(uint3, uint3, uint5, uint2) -> string;
auto thumbDisassembleSoftwareInterrupt(uint8) -> string;
auto thumbDisassembleStackMultiple(uint8, uint1, uint1) -> string;
auto thumbDisassembleUndefined() -> string;
function<auto (uint32 opcode) -> string> armDisassemble[4096];
function<auto () -> string> thumbDisassemble[65536];
uint32 _pc;
string _c;
};
}