diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-06-22 22:26:45 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-06-22 22:26:45 +0200 |
commit | 20575a338e9640eca924958484a5fee800e09971 (patch) | |
tree | efaeac41a8a21bea1c90494b3b0968169d4f8732 /plugins/ao/eng_dsf/arm7.c | |
parent | c901a7cbf52ee234220f21b85c2e77667264d16c (diff) |
audio overload plugin - highly experimental; no seeking; crashes
Diffstat (limited to 'plugins/ao/eng_dsf/arm7.c')
-rw-r--r-- | plugins/ao/eng_dsf/arm7.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/plugins/ao/eng_dsf/arm7.c b/plugins/ao/eng_dsf/arm7.c new file mode 100644 index 00000000..980c306f --- /dev/null +++ b/plugins/ao/eng_dsf/arm7.c @@ -0,0 +1,274 @@ +// +// ARM7 processor emulator +// version 1.6 / 2008-02-16 +// (c) Radoslaw Balcewicz +// + +#include "arm7.h" +#include "arm7i.h" + +#ifdef ARM7_THUMB +#include "arm7thumb.h" +#endif + + //-------------------------------------------------------------------------- + // definitions and macros + + /** Macro for accessing banked registers. */ +#define RX_BANK(t,r) (ARM7.Rx_bank [t][r - 8]) + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // private functions + + /** CPU Reset. */ +static void Reset (void); + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + // public variables + + /** ARM7 state. */ +struct sARM7 ARM7; + + // private variables + + /** Table for decoding bit-coded mode to zero based index. */ +static const int s_tabTryb [32] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, ARM7_MODE_usr, ARM7_MODE_fiq, ARM7_MODE_irq, + ARM7_MODE_svc, -1, -1, -1, ARM7_MODE_abt, -1, -1, -1, ARM7_MODE_und, + -1, -1, -1, ARM7_MODE_sys}; + //-------------------------------------------------------------------------- + + + // public functions + + + //-------------------------------------------------------------------------- + /** ARM7 emulator init. */ +void ARM7_Init () + { + // sane startup values + ARM7.fiq = 0; + ARM7.irq = 0; + ARM7.carry = 0; + ARM7.overflow = 0; + ARM7.flagi = FALSE; + ARM7.cykle = 0; + + // reset will do the rest + ARM7_HardReset (); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Power-ON reset. */ +void ARM7_HardReset () + { + // CPSR that makes sense + ARM7.Rx [ARM7_CPSR] = ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc; + Reset (); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Hardware reset via /RESET line. */ +void ARM7_SoftReset () + { + Reset (); + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** CPSR update, possibly changing operating mode. */ +void ARM7_SetCPSR (ARM7_REG sr) + { + int stary, nowy; + + stary = s_tabTryb [ARM7_CPSR_M (ARM7.Rx [ARM7_CPSR])]; + nowy = s_tabTryb [ARM7_CPSR_M (sr)]; + // do we have to change modes? + if (nowy != stary) + { + // save this mode registers + RX_BANK (stary, ARM7_SP) = ARM7.Rx [ARM7_SP], + RX_BANK (stary, ARM7_LR) = ARM7.Rx [ARM7_LR], + RX_BANK (stary, ARM7_SPSR) = ARM7.Rx [ARM7_SPSR]; + if (stary == ARM7_MODE_fiq) + { + // copy R8-R12 + RX_BANK (ARM7_MODE_fiq, 8) = ARM7.Rx [8], + RX_BANK (ARM7_MODE_fiq, 9) = ARM7.Rx [9], + RX_BANK (ARM7_MODE_fiq, 10) = ARM7.Rx [10], + RX_BANK (ARM7_MODE_fiq, 11) = ARM7.Rx [11], + RX_BANK (ARM7_MODE_fiq, 12) = ARM7.Rx [12]; + ARM7.Rx [8] = RX_BANK (ARM7_MODE_usr, 8), + ARM7.Rx [9] = RX_BANK (ARM7_MODE_usr, 9), + ARM7.Rx [10] = RX_BANK (ARM7_MODE_usr, 10), + ARM7.Rx [11] = RX_BANK (ARM7_MODE_usr, 11), + ARM7.Rx [12] = RX_BANK (ARM7_MODE_usr, 12); + } + + // fetch new mode registers + ARM7.Rx [ARM7_SP] = RX_BANK (nowy, ARM7_SP), + ARM7.Rx [ARM7_LR] = RX_BANK (nowy, ARM7_LR), + ARM7.Rx [ARM7_SPSR] = RX_BANK (nowy, ARM7_SPSR); + if (nowy == ARM7_MODE_fiq) + { + // copy R8-R12 + RX_BANK (ARM7_MODE_usr, 8) = ARM7.Rx [8], + RX_BANK (ARM7_MODE_usr, 9) = ARM7.Rx [9], + RX_BANK (ARM7_MODE_usr, 10) = ARM7.Rx [10], + RX_BANK (ARM7_MODE_usr, 11) = ARM7.Rx [11], + RX_BANK (ARM7_MODE_usr, 12) = ARM7.Rx [12]; + ARM7.Rx [8] = RX_BANK (ARM7_MODE_fiq, 8), + ARM7.Rx [9] = RX_BANK (ARM7_MODE_fiq, 9), + ARM7.Rx [10] = RX_BANK (ARM7_MODE_fiq, 10), + ARM7.Rx [11] = RX_BANK (ARM7_MODE_fiq, 11), + ARM7.Rx [12] = RX_BANK (ARM7_MODE_fiq, 12); + } + } + + // new CPSR value + ARM7.Rx [ARM7_CPSR] = sr; + + // mode change could've enabled interrups, so we test for those and set + // appropriate flag for the instruction loop to catch + if (ARM7.fiq) + ARM7.flagi |= ARM7_FL_FIQ; +#ifndef ARM7_DREAMCAST + if (ARM7.irq) + ARM7.flagi |= ARM7_FL_IRQ; +#endif + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Sets FIQ line state. */ +void ARM7_SetFIQ (int stan) + { + stan = stan ? TRUE : FALSE; + // we catch changes only + if (stan ^ ARM7.fiq) + { + ARM7.fiq = stan; + if (ARM7.fiq) + ARM7.flagi |= ARM7_FL_FIQ; + } + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Sets IRQ line state. */ +void ARM7_SetIRQ (int stan) + { + stan = stan ? TRUE : FALSE; + // we catch changes only + if (stan ^ ARM7.irq) + { + ARM7.irq = stan; + if (ARM7.irq) + ARM7.flagi |= ARM7_FL_IRQ; + } + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Tests for pending interrupts, switches to one if possible. */ +void ARM7_CheckIRQ () + { + UINT32 sr = ARM7.Rx [ARM7_CPSR]; + + // clear all interrupt flags + ARM7.flagi &= ~(ARM7_FL_FIQ | ARM7_FL_IRQ); + + // check for pending interrupts we can switch to + // (FIQ can interrupt IRQ, but not the other way around) + if (ARM7.fiq) + { + if (!(sr & ARM7_CPSR_F)) + { + // FIQ + ARM7_SetCPSR (ARM7_CPSR_MX (sr, ARM7_CPSR_M_fiq) | ARM7_CPSR_F | ARM7_CPSR_I); + ARM7.Rx [ARM7_SPSR] = sr; + // set new PC (return from interrupt will subtract 4) + ARM7.Rx [ARM7_LR] = ARM7.Rx [ARM7_PC] + 4; + ARM7.Rx [ARM7_PC] = 0x0000001c; + } + } +#ifndef ARM7_DREAMCAST + if (ARM7.irq) + { + if (!(sr & ARM7_CPSR_I)) + { + // IRQ + ARM7_SetCPSR (ARM7_CPSR_MX (sr, ARM7_CPSR_M_irq) | ARM7_CPSR_I); + ARM7.Rx [ARM7_SPSR] = sr; + // set new PC (return from interrupt will subtract 4) + ARM7.Rx [ARM7_LR] = ARM7.Rx [ARM7_PC] + 4; + ARM7.Rx [ARM7_PC] = 0x00000018; + ARM7.irq = 0; + } + } +#endif + } + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Single step. */ +void ARM7_Step () +{ + // make a step +#ifdef ARM7_THUMB + if (ARM7.Rx[ARM7_CPSR] & ARM7_CPSR_T) + { + ARM7i_Thumb_Step(); + } + else +#endif + { + ARM7i_Step (); + } + // and test interrupts + ARM7_CheckIRQ (); +} + //-------------------------------------------------------------------------- + + //-------------------------------------------------------------------------- + /** Runs emulation for at least n cycles, returns actual amount of cycles + burned - normal interpreter. */ +int ARM7_Execute (int n) + { + ARM7.cykle = 0; + while (ARM7.cykle < n) + { + ARM7_CheckIRQ (); + while (!ARM7.flagi && ARM7.cykle < n) + // make one step, sum up cycles + ARM7.cykle += ARM7i_Step (); + } + return ARM7.cykle; + } + //-------------------------------------------------------------------------- + + + // private functions + + + //-------------------------------------------------------------------------- + /** CPU Reset. */ +void Reset (void) + { + // clear ALU flags + ARM7.carry = 0; + ARM7.overflow = 0; + // test CPSR mode and pick a valid one if necessary + if (s_tabTryb [ARM7_CPSR_M (ARM7.Rx [ARM7_CPSR])] < 0) + ARM7.Rx [ARM7_CPSR] = ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc; + // set up registers according to manual + RX_BANK (ARM7_MODE_svc, ARM7_LR) = ARM7.Rx [ARM7_PC]; + RX_BANK (ARM7_MODE_svc, ARM7_SPSR) = ARM7.Rx [ARM7_CPSR]; + ARM7_SetCPSR (ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc); + ARM7.Rx [ARM7_PC] = 0x00000000; + } + //-------------------------------------------------------------------------- |