summaryrefslogtreecommitdiff
path: root/plugins/ao/eng_dsf/arm7.c
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-06-22 22:26:45 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-06-22 22:26:45 +0200
commit20575a338e9640eca924958484a5fee800e09971 (patch)
treeefaeac41a8a21bea1c90494b3b0968169d4f8732 /plugins/ao/eng_dsf/arm7.c
parentc901a7cbf52ee234220f21b85c2e77667264d16c (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.c274
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;
+ }
+ //--------------------------------------------------------------------------