filename | src/aica/armcore.c |
changeset | 35:21a4be098304 |
prev | 30:89b30313d757 |
next | 37:1d84f4c18816 |
author | nkeynes |
date | Mon Dec 26 03:54:55 2005 +0000 (18 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 +00001.2 +++ b/src/aica/armcore.c Mon Dec 26 03:54:55 2005 +00001.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.12 struct arm_registers armr;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 01.26 +#define EXC_UNDEFINED 11.27 +#define EXC_SOFTWARE 21.28 +#define EXC_PREFETCH_ABORT 31.29 +#define EXC_DATA_ABORT 41.30 +#define EXC_IRQ 51.31 +#define EXC_FAST_IRQ 61.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) executing1.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 the1.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.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.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;
.