Search
lxdream.org :: lxdream/src/aica/armcore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 35:21a4be098304
prev30:89b30313d757
next37:1d84f4c18816
author nkeynes
date Mon Dec 26 03:54:55 2005 +0000 (15 years ago)
permissions -rw-r--r--
last change Remove modules.h - move definitions into dream.h
Add source string to output list (taken from module name)
ARM Work in progress
file annotate diff log raw
1.1 --- a/src/aica/armcore.c Sun Dec 25 05:57:00 2005 +0000
1.2 +++ b/src/aica/armcore.c Mon Dec 26 03:54:55 2005 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: armcore.c,v 1.5 2005-12-25 05:57:00 nkeynes Exp $
1.6 + * $Id: armcore.c,v 1.6 2005-12-26 03:54:55 nkeynes Exp $
1.7 *
1.8 * ARM7TDMI CPU emulation core.
1.9 *
1.10 @@ -20,7 +20,194 @@
1.11
1.12 struct arm_registers armr;
1.13
1.14 -/* NB: The arm has a different memory map, but for the meantime... */
1.15 +void arm_set_mode( int mode );
1.16 +
1.17 +uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
1.18 + { MODE_UND, 0x00000004 },
1.19 + { MODE_SVC, 0x00000008 },
1.20 + { MODE_ABT, 0x0000000C },
1.21 + { MODE_ABT, 0x00000010 },
1.22 + { MODE_IRQ, 0x00000018 },
1.23 + { MODE_FIQ, 0x0000001C } };
1.24 +
1.25 +#define EXC_RESET 0
1.26 +#define EXC_UNDEFINED 1
1.27 +#define EXC_SOFTWARE 2
1.28 +#define EXC_PREFETCH_ABORT 3
1.29 +#define EXC_DATA_ABORT 4
1.30 +#define EXC_IRQ 5
1.31 +#define EXC_FAST_IRQ 6
1.32 +
1.33 +uint32_t arm_cpu_freq = ARM_BASE_RATE;
1.34 +uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
1.35 +
1.36 +uint32_t arm_run_slice( uint32_t nanosecs )
1.37 +{
1.38 + uint32_t target = armr.icount + nanosecs / arm_cpu_period;
1.39 + uint32_t start = armr.icount;
1.40 + while( armr.icount < target ) {
1.41 + armr.icount++;
1.42 + if( !arm_execute_instruction() )
1.43 + break;
1.44 + }
1.45 +
1.46 + if( target != armr.icount ) {
1.47 + /* Halted - compute time actually executed */
1.48 + nanosecs = (armr.icount - start) * arm_cpu_period;
1.49 + }
1.50 + return nanosecs;
1.51 +}
1.52 +
1.53 +void arm_save_state( FILE *f )
1.54 +{
1.55 + fwrite( &armr, sizeof(armr), 1, f );
1.56 +}
1.57 +
1.58 +int arm_load_state( FILE *f )
1.59 +{
1.60 + fread( &armr, sizeof(armr), 1, f );
1.61 + return 0;
1.62 +}
1.63 +
1.64 +/* Exceptions */
1.65 +void arm_reset( void )
1.66 +{
1.67 + /* Wipe all processor state */
1.68 + memset( &armr, 0, sizeof(armr) );
1.69 +
1.70 + armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
1.71 + armr.r[15] = 0x00000000;
1.72 +}
1.73 +
1.74 +/**
1.75 + * Raise an ARM exception (other than reset, which uses arm_reset().
1.76 + * @param exception one of the EXC_* exception codes defined above.
1.77 + */
1.78 +void arm_raise_exception( int exception )
1.79 +{
1.80 + int mode = arm_exceptions[exception][0];
1.81 + arm_set_mode( mode );
1.82 + armr.spsr = armr.cpsr;
1.83 + armr.r[14] = armr.r[15];
1.84 + armr.cpsr = (armr.cpsr & (~CPSR_T)) | CPSR_I;
1.85 + if( mode == MODE_FIQ )
1.86 + armr.cpsr |= CPSR_F;
1.87 + armr.r[15] = arm_exceptions[exception][1];
1.88 +}
1.89 +
1.90 +/**
1.91 + * Restore CPSR from SPSR, effectively (under most circumstances) executing
1.92 + * a return-from-exception.
1.93 + */
1.94 +void arm_restore_cpsr()
1.95 +{
1.96 + int spsr = armr.spsr;
1.97 + int mode = spsr & CPSR_MODE;
1.98 +
1.99 + arm_set_mode( mode );
1.100 + armr.cpsr = spsr;
1.101 +}
1.102 +
1.103 +
1.104 +
1.105 +/**
1.106 + * Change the current executing ARM mode to the requested mode.
1.107 + * Saves any required registers to banks and restores those for the
1.108 + * correct mode. (Note does not actually update CPSR at the moment).
1.109 + */
1.110 +void arm_set_mode( int targetMode )
1.111 +{
1.112 + int currentMode = armr.cpsr & CPSR_MODE;
1.113 + if( currentMode == targetMode )
1.114 + return;
1.115 +
1.116 + switch( currentMode ) {
1.117 + case MODE_USER:
1.118 + case MODE_SYS:
1.119 + armr.user_r[5] = armr.r[13];
1.120 + armr.user_r[6] = armr.r[14];
1.121 + break;
1.122 + case MODE_SVC:
1.123 + armr.svc_r[0] = armr.r[13];
1.124 + armr.svc_r[1] = armr.r[14];
1.125 + armr.svc_r[2] = armr.spsr;
1.126 + break;
1.127 + case MODE_ABT:
1.128 + armr.abt_r[0] = armr.r[13];
1.129 + armr.abt_r[1] = armr.r[14];
1.130 + armr.abt_r[2] = armr.spsr;
1.131 + break;
1.132 + case MODE_UND:
1.133 + armr.und_r[0] = armr.r[13];
1.134 + armr.und_r[1] = armr.r[14];
1.135 + armr.und_r[2] = armr.spsr;
1.136 + break;
1.137 + case MODE_IRQ:
1.138 + armr.irq_r[0] = armr.r[13];
1.139 + armr.irq_r[1] = armr.r[14];
1.140 + armr.irq_r[2] = armr.spsr;
1.141 + break;
1.142 + case MODE_FIQ:
1.143 + armr.fiq_r[0] = armr.r[8];
1.144 + armr.fiq_r[1] = armr.r[9];
1.145 + armr.fiq_r[2] = armr.r[10];
1.146 + armr.fiq_r[3] = armr.r[11];
1.147 + armr.fiq_r[4] = armr.r[12];
1.148 + armr.fiq_r[5] = armr.r[13];
1.149 + armr.fiq_r[6] = armr.r[14];
1.150 + armr.fiq_r[7] = armr.spsr;
1.151 + armr.r[8] = armr.user_r[0];
1.152 + armr.r[9] = armr.user_r[1];
1.153 + armr.r[10] = armr.user_r[2];
1.154 + armr.r[11] = armr.user_r[3];
1.155 + armr.r[12] = armr.user_r[4];
1.156 + break;
1.157 + }
1.158 +
1.159 + switch( targetMode ) {
1.160 + case MODE_USER:
1.161 + case MODE_SYS:
1.162 + armr.r[13] = armr.user_r[5];
1.163 + armr.r[14] = armr.user_r[6];
1.164 + break;
1.165 + case MODE_SVC:
1.166 + armr.r[13] = armr.svc_r[0];
1.167 + armr.r[14] = armr.svc_r[1];
1.168 + armr.spsr = armr.svc_r[2];
1.169 + break;
1.170 + case MODE_ABT:
1.171 + armr.r[13] = armr.abt_r[0];
1.172 + armr.r[14] = armr.abt_r[1];
1.173 + armr.spsr = armr.abt_r[2];
1.174 + break;
1.175 + case MODE_UND:
1.176 + armr.r[13] = armr.und_r[0];
1.177 + armr.r[14] = armr.und_r[1];
1.178 + armr.spsr = armr.und_r[2];
1.179 + break;
1.180 + case MODE_IRQ:
1.181 + armr.r[13] = armr.irq_r[0];
1.182 + armr.r[14] = armr.irq_r[1];
1.183 + armr.spsr = armr.irq_r[2];
1.184 + break;
1.185 + case MODE_FIQ:
1.186 + armr.user_r[0] = armr.r[8];
1.187 + armr.user_r[1] = armr.r[9];
1.188 + armr.user_r[2] = armr.r[10];
1.189 + armr.user_r[3] = armr.r[11];
1.190 + armr.user_r[4] = armr.r[12];
1.191 + armr.r[8] = armr.fiq_r[0];
1.192 + armr.r[9] = armr.fiq_r[1];
1.193 + armr.r[10] = armr.fiq_r[2];
1.194 + armr.r[11] = armr.fiq_r[3];
1.195 + armr.r[12] = armr.fiq_r[4];
1.196 + armr.r[13] = armr.fiq_r[5];
1.197 + armr.r[14] = armr.fiq_r[6];
1.198 + armr.spsr = armr.fiq_r[7];
1.199 + break;
1.200 + }
1.201 +}
1.202 +
1.203 /* Page references are as per ARM DDI 0100E (June 2000) */
1.204
1.205 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
1.206 @@ -68,11 +255,6 @@
1.207 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return TRUE; } while(0)
1.208 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)
1.209
1.210 -void arm_restore_cpsr()
1.211 -{
1.212 -
1.213 -}
1.214 -
1.215 static uint32_t arm_get_shift_operand( uint32_t ir )
1.216 {
1.217 uint32_t operand, tmp;
.