#include "arm.h" #include "isa-inlines.h" static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode); void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) { if (mode == cpu->privilegeMode) { // Not switching modes after all return; } enum RegisterBank newBank = _ARMSelectBank(mode); enum RegisterBank oldBank = _ARMSelectBank(cpu->privilegeMode); if (newBank != oldBank) { // Switch banked registers if (mode == MODE_FIQ || cpu->privilegeMode == MODE_FIQ) { int oldFIQBank = oldBank == BANK_FIQ; int newFIQBank = newBank == BANK_FIQ; cpu->bankedRegisters[oldFIQBank][2] = cpu->gprs[8]; cpu->bankedRegisters[oldFIQBank][3] = cpu->gprs[9]; cpu->bankedRegisters[oldFIQBank][4] = cpu->gprs[10]; cpu->bankedRegisters[oldFIQBank][5] = cpu->gprs[11]; cpu->bankedRegisters[oldFIQBank][6] = cpu->gprs[12]; cpu->gprs[8] = cpu->bankedRegisters[newFIQBank][2]; cpu->gprs[9] = cpu->bankedRegisters[newFIQBank][3]; cpu->gprs[10] = cpu->bankedRegisters[newFIQBank][4]; cpu->gprs[11] = cpu->bankedRegisters[newFIQBank][5]; cpu->gprs[12] = cpu->bankedRegisters[newFIQBank][6]; } cpu->bankedRegisters[oldBank][0] = cpu->gprs[ARM_SP]; cpu->bankedRegisters[oldBank][1] = cpu->gprs[ARM_LR]; cpu->gprs[ARM_SP] = cpu->bankedRegisters[newBank][0]; cpu->gprs[ARM_LR] = cpu->bankedRegisters[newBank][1]; cpu->bankedSPSRs[oldBank] = cpu->spsr.packed; cpu->spsr.packed = cpu->bankedSPSRs[newBank]; } cpu->privilegeMode = mode; } static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode mode) { switch (mode) { case MODE_USER: case MODE_SYSTEM: // No banked registers return BANK_NONE; case MODE_FIQ: return BANK_FIQ; case MODE_IRQ: return BANK_IRQ; case MODE_SUPERVISOR: return BANK_SUPERVISOR; case MODE_ABORT: return BANK_ABORT; case MODE_UNDEFINED: return BANK_UNDEFINED; default: // This should be unreached return BANK_NONE; } } void ARMInit(struct ARMCore* cpu) { cpu->memory = 0; cpu->board = 0; } void ARMAssociateMemory(struct ARMCore* cpu, struct ARMMemory* memory) { cpu->memory = memory; } void ARMAssociateBoard(struct ARMCore* cpu, struct ARMBoard* board) { cpu->board = board; board->cpu = cpu; } void ARMReset(struct ARMCore* cpu) { int i; for (i = 0; i < 16; ++i) { cpu->gprs[i] = 0; } for (i = 0; i < 6; ++i) { cpu->bankedRegisters[i][0] = 0; cpu->bankedRegisters[i][1] = 0; cpu->bankedRegisters[i][2] = 0; cpu->bankedRegisters[i][3] = 0; cpu->bankedRegisters[i][4] = 0; cpu->bankedRegisters[i][5] = 0; cpu->bankedRegisters[i][6] = 0; cpu->bankedSPSRs[i] = 0; } cpu->cpsr.packed = MODE_SYSTEM; cpu->spsr.packed = 0; cpu->cyclesToEvent = 0; cpu->shifterOperand = 0; cpu->shifterCarryOut = 0; cpu->executionMode = MODE_THUMB; _ARMSetMode(cpu, MODE_ARM); cpu->board->reset(cpu->board); }