revision 37:1d84f4c18816
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 37:1d84f4c18816 |
parent | 36:f581f9c43c43 |
child | 38:9ccc7ac66a9d |
author | nkeynes |
date | Mon Dec 26 06:38:51 2005 +0000 (17 years ago) |
More ARM work-in-progress - idle loop works now :)
![]() | src/aica/aica.c | view | annotate | diff | log | |
![]() | src/aica/armcore.c | view | annotate | diff | log | |
![]() | src/aica/armcore.h | view | annotate | diff | log | |
![]() | src/aica/armmem.c | view | annotate | diff | log |
1.1 --- a/src/aica/aica.c Mon Dec 26 06:38:13 2005 +00001.2 +++ b/src/aica/aica.c Mon Dec 26 06:38:51 2005 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: aica.c,v 1.6 2005-12-26 03:54:55 nkeynes Exp $1.6 + * $Id: aica.c,v 1.7 2005-12-26 06:38:51 nkeynes Exp $1.7 *1.8 * This is the core sound system (ie the bit which does the actual work)1.9 *1.10 @@ -50,6 +50,7 @@1.11 MMIO_NOTRACE(AICA0);1.12 MMIO_NOTRACE(AICA1);1.13 arm_mem_init();1.14 + arm_reset();1.15 }1.17 void aica_reset( void )1.18 @@ -113,7 +114,7 @@1.19 {1.20 // aica_write_channel( reg >> 7, reg % 128, val );1.21 MMIO_WRITE( AICA0, reg, val );1.22 -1.23 + // DEBUG( "AICA0 Write %08X => %08X", val, reg );1.24 }1.26 /* Write to channels 32-64 */1.27 @@ -121,6 +122,7 @@1.28 {1.29 // aica_write_channel( (reg >> 7) + 32, reg % 128, val );1.30 MMIO_WRITE( AICA1, reg, val );1.31 + // DEBUG( "AICA1 Write %08X => %08X", val, reg );1.32 }1.34 /* General registers */1.35 @@ -130,10 +132,12 @@1.36 switch( reg ) {1.37 case AICA_RESET:1.38 tmp = MMIO_READ( AICA2, AICA_RESET );1.39 - if( tmp & 1 == 1 && val & 1 == 0 ) {1.40 + if( (tmp & 1) == 1 && (val & 1) == 0 ) {1.41 /* ARM enabled - execute a core reset */1.42 - INFO( "ARM enabled" );1.43 + DEBUG( "ARM enabled" );1.44 arm_reset();1.45 + } else if( (tmp&1) == 0 && (val&1) == 1 ) {1.46 + DEBUG( "ARM disabled" );1.47 }1.48 MMIO_WRITE( AICA2, AICA_RESET, val );1.49 break;
2.1 --- a/src/aica/armcore.c Mon Dec 26 06:38:13 2005 +00002.2 +++ b/src/aica/armcore.c Mon Dec 26 06:38:51 2005 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: armcore.c,v 1.6 2005-12-26 03:54:55 nkeynes Exp $2.6 + * $Id: armcore.c,v 1.7 2005-12-26 06:38:51 nkeynes Exp $2.7 *2.8 * ARM7TDMI CPU emulation core.2.9 *2.10 @@ -16,6 +16,8 @@2.11 * GNU General Public License for more details.2.12 */2.14 +#define MODULE aica_module2.15 +#include "dream.h"2.16 #include "aica/armcore.h"2.18 struct arm_registers armr;2.19 @@ -79,6 +81,69 @@2.20 armr.r[15] = 0x00000000;2.21 }2.23 +#define SET_CPSR_CONTROL 0x000100002.24 +#define SET_CPSR_EXTENSION 0x000200002.25 +#define SET_CPSR_STATUS 0x000400002.26 +#define SET_CPSR_FLAGS 0x000800002.27 +2.28 +uint32_t arm_get_cpsr( void )2.29 +{2.30 + /* write back all flags to the cpsr */2.31 + armr.cpsr = armr.cpsr & CPSR_COMPACT_MASK;2.32 + if( armr.n ) armr.cpsr |= CPSR_N;2.33 + if( armr.z ) armr.cpsr |= CPSR_Z;2.34 + if( armr.c ) armr.cpsr |= CPSR_C;2.35 + if( armr.v ) armr.cpsr |= CPSR_V;2.36 + if( armr.t ) armr.cpsr |= CPSR_T;2.37 + return armr.cpsr;2.38 +}2.39 +2.40 +/**2.41 + * Set the CPSR to the specified value.2.42 + *2.43 + * @param value values to set in CPSR2.44 + * @param fields set of mask values to define which sections of the2.45 + * CPSR to set (one of the SET_CPSR_* values above)2.46 + */2.47 +void arm_set_cpsr( uint32_t value, uint32_t fields )2.48 +{2.49 + if( IS_PRIVILEGED_MODE() ) {2.50 + if( fields & SET_CPSR_CONTROL ) {2.51 + int mode = value & CPSR_MODE;2.52 + arm_set_mode( mode );2.53 + armr.t = ( value & CPSR_T ); /* Technically illegal to change */2.54 + armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);2.55 + }2.56 +2.57 + /* Middle 16 bits not currently defined */2.58 + }2.59 + if( fields & SET_CPSR_FLAGS ) {2.60 + /* Break flags directly out of given value - don't bother writing2.61 + * back to CPSR2.62 + */2.63 + armr.n = ( value & CPSR_N );2.64 + armr.z = ( value & CPSR_Z );2.65 + armr.c = ( value & CPSR_C );2.66 + armr.v = ( value & CPSR_V );2.67 + }2.68 +}2.69 +2.70 +void arm_set_spsr( uint32_t value, uint32_t fields )2.71 +{2.72 + /* Only defined if we actually have an SPSR register */2.73 + if( IS_EXCEPTION_MODE() ) {2.74 + if( fields & SET_CPSR_CONTROL ) {2.75 + armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);2.76 + }2.77 +2.78 + /* Middle 16 bits not currently defined */2.79 +2.80 + if( fields & SET_CPSR_FLAGS ) {2.81 + armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);2.82 + }2.83 + }2.84 +}2.85 +2.86 /**2.87 * Raise an ARM exception (other than reset, which uses arm_reset().2.88 * @param exception one of the EXC_* exception codes defined above.2.89 @@ -86,26 +151,27 @@2.90 void arm_raise_exception( int exception )2.91 {2.92 int mode = arm_exceptions[exception][0];2.93 + uint32_t spsr = arm_get_cpsr();2.94 arm_set_mode( mode );2.95 - armr.spsr = armr.cpsr;2.96 + armr.spsr = spsr;2.97 armr.r[14] = armr.r[15];2.98 - armr.cpsr = (armr.cpsr & (~CPSR_T)) | CPSR_I;2.99 + armr.cpsr = (spsr & (~CPSR_T)) | CPSR_I;2.100 if( mode == MODE_FIQ )2.101 armr.cpsr |= CPSR_F;2.102 armr.r[15] = arm_exceptions[exception][1];2.103 }2.105 -/**2.106 - * Restore CPSR from SPSR, effectively (under most circumstances) executing2.107 - * a return-from-exception.2.108 - */2.109 -void arm_restore_cpsr()2.110 +void arm_restore_cpsr( void )2.111 {2.112 int spsr = armr.spsr;2.113 int mode = spsr & CPSR_MODE;2.114 -2.115 arm_set_mode( mode );2.116 armr.cpsr = spsr;2.117 + armr.n = ( spsr & CPSR_N );2.118 + armr.z = ( spsr & CPSR_Z );2.119 + armr.c = ( spsr & CPSR_C );2.120 + armr.v = ( spsr & CPSR_V );2.121 + armr.t = ( spsr & CPSR_T );2.122 }2.125 @@ -237,10 +303,10 @@2.126 #define WFLAG(ir) (IR&0x00200000)2.127 #define LFLAG(ir) SFLAG(ir)2.128 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))2.129 -#define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))2.130 +#define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))2.131 #define RDn(ir) ((ir>>12)&0x0F)2.132 -#define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))2.133 -#define RM(ir) (armr.r[(ir&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))2.134 +#define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))2.135 +#define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )2.136 #define LRN(ir) armr.r[((ir>>16)&0x0F)]2.137 #define LRD(ir) armr.r[((ir>>12)&0x0F)]2.138 #define LRS(ir) armr.r[((ir>>8)&0x0F)]2.139 @@ -250,11 +316,19 @@2.140 #define IMM12(ir) (ir&0xFFF)2.141 #define SHIFTIMM(ir) ((ir>>7)&0x1F)2.142 #define IMMROT(ir) ((ir>>7)&0x1E)2.143 +#define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))2.144 +#define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))2.145 #define SHIFT(ir) ((ir>>4)&0x07)2.146 #define DISP24(ir) ((ir&0x00FFFFFF))2.147 -#define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return TRUE; } while(0)2.148 +#define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)2.149 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)2.151 +/**2.152 + * Determine the value of the shift-operand for a data processing instruction,2.153 + * without determing a value for shift_C (optimized form for instructions that2.154 + * don't require shift_C ).2.155 + * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)2.156 + */2.157 static uint32_t arm_get_shift_operand( uint32_t ir )2.158 {2.159 uint32_t operand, tmp;2.160 @@ -308,9 +382,9 @@2.161 }2.163 /**2.164 - * Compute the "shift operand" of the instruction for the data processing2.165 - * instructions. This variant also sets armr.shift_c (carry result for shifter)2.166 - * Reason for the variants is that most cases don't actually need the shift_c.2.167 + * Determine the value of the shift-operand for a data processing instruction,2.168 + * and set armr.shift_c accordingly.2.169 + * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)2.170 */2.171 static uint32_t arm_get_shift_operand_s( uint32_t ir )2.172 {2.173 @@ -461,6 +535,13 @@2.174 return operand;2.175 }2.177 +/**2.178 + * Determine the address operand of a load/store instruction, including2.179 + * applying any pre/post adjustments to the address registers.2.180 + * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte2.181 + * @param The instruction word.2.182 + * @return The calculated address2.183 + */2.184 static uint32_t arm_get_address_operand( uint32_t ir )2.185 {2.186 uint32_t addr;2.187 @@ -515,341 +596,395 @@2.188 addr = RN(ir) + arm_get_address_index(ir);2.189 LRN(ir) = addr;2.190 break;2.191 - default:2.192 - UNIMP(ir); /* Unreachable */2.193 }2.194 return addr;2.195 }2.197 gboolean arm_execute_instruction( void )2.198 {2.199 - uint32_t pc = PC;2.200 - uint32_t ir = MEM_READ_LONG(pc);2.201 - uint32_t operand, operand2, tmp, cond;2.202 + uint32_t pc = PC;2.203 + uint32_t ir = MEM_READ_LONG(pc);2.204 + uint32_t operand, operand2, tmp, cond;2.206 - pc += 4;2.207 - PC = pc;2.208 + pc += 4;2.209 + PC = pc;2.211 - switch( COND(ir) ) {2.212 - case 0: /* EQ */2.213 - cond = armr.z;2.214 - break;2.215 - case 1: /* NE */2.216 - cond = !armr.z;2.217 - break;2.218 - case 2: /* CS/HS */2.219 - cond = armr.c;2.220 - break;2.221 - case 3: /* CC/LO */2.222 - cond = !armr.c;2.223 - break;2.224 - case 4: /* MI */2.225 - cond = armr.n;2.226 - break;2.227 - case 5: /* PL */2.228 - cond = !armr.n;2.229 - break;2.230 - case 6: /* VS */2.231 - cond = armr.v;2.232 - break;2.233 - case 7: /* VC */2.234 - cond = !armr.v;2.235 - break;2.236 - case 8: /* HI */2.237 - cond = armr.c && !armr.z;2.238 - break;2.239 - case 9: /* LS */2.240 - cond = (!armr.c) || armr.z;2.241 - break;2.242 - case 10: /* GE */2.243 - cond = (armr.n == armr.v);2.244 - break;2.245 - case 11: /* LT */2.246 - cond = (armr.n != armr.v);2.247 - break;2.248 - case 12: /* GT */2.249 - cond = (!armr.z) && (armr.n == armr.v);2.250 - break;2.251 - case 13: /* LE */2.252 - cond = armr.z || (armr.n != armr.v);2.253 - break;2.254 - case 14: /* AL */2.255 - cond = 1;2.256 - break;2.257 - case 15: /* (NV) */2.258 - cond = 0;2.259 - UNDEF(ir);2.260 - }2.261 + /**2.262 + * Check the condition bits first - if the condition fails return2.263 + * immediately without actually looking at the rest of the instruction.2.264 + */2.265 + switch( COND(ir) ) {2.266 + case 0: /* EQ */2.267 + cond = armr.z;2.268 + break;2.269 + case 1: /* NE */2.270 + cond = !armr.z;2.271 + break;2.272 + case 2: /* CS/HS */2.273 + cond = armr.c;2.274 + break;2.275 + case 3: /* CC/LO */2.276 + cond = !armr.c;2.277 + break;2.278 + case 4: /* MI */2.279 + cond = armr.n;2.280 + break;2.281 + case 5: /* PL */2.282 + cond = !armr.n;2.283 + break;2.284 + case 6: /* VS */2.285 + cond = armr.v;2.286 + break;2.287 + case 7: /* VC */2.288 + cond = !armr.v;2.289 + break;2.290 + case 8: /* HI */2.291 + cond = armr.c && !armr.z;2.292 + break;2.293 + case 9: /* LS */2.294 + cond = (!armr.c) || armr.z;2.295 + break;2.296 + case 10: /* GE */2.297 + cond = (armr.n == armr.v);2.298 + break;2.299 + case 11: /* LT */2.300 + cond = (armr.n != armr.v);2.301 + break;2.302 + case 12: /* GT */2.303 + cond = (!armr.z) && (armr.n == armr.v);2.304 + break;2.305 + case 13: /* LE */2.306 + cond = armr.z || (armr.n != armr.v);2.307 + break;2.308 + case 14: /* AL */2.309 + cond = 1;2.310 + break;2.311 + case 15: /* (NV) */2.312 + cond = 0;2.313 + UNDEF(ir);2.314 + }2.315 + if( !cond )2.316 + return TRUE;2.318 - switch( GRP(ir) ) {2.319 - case 0:2.320 - if( (ir & 0x0D900000) == 0x01000000 ) {2.321 - /* Instructions that aren't actual data processing */2.322 - switch( ir & 0x0FF000F0 ) {2.323 - case 0x01200010: /* BX */2.324 - break;2.325 - case 0x01000000: /* MRS Rd, CPSR */2.326 - break;2.327 - case 0x01400000: /* MRS Rd, SPSR */2.328 - break;2.329 - case 0x01200000: /* MSR CPSR, Rd */2.330 - break;2.331 - case 0x01600000: /* MSR SPSR, Rd */2.332 - break;2.333 - case 0x03200000: /* MSR CPSR, imm */2.334 - break;2.335 - case 0x03600000: /* MSR SPSR, imm */2.336 - break;2.337 - default:2.338 - UNIMP(ir);2.339 - }2.340 - } else if( (ir & 0x0E000090) == 0x00000090 ) {2.341 - /* Neither are these */2.342 - switch( (ir>>5)&0x03 ) {2.343 - case 0:2.344 - /* Arithmetic extension area */2.345 - switch(OPCODE(ir)) {2.346 - case 0: /* MUL */2.347 - break;2.348 - case 1: /* MULS */2.349 - break;2.350 - case 2: /* MLA */2.351 - break;2.352 - case 3: /* MLAS */2.353 - break;2.354 - case 8: /* UMULL */2.355 - break;2.356 - case 9: /* UMULLS */2.357 - break;2.358 - case 10: /* UMLAL */2.359 - break;2.360 - case 11: /* UMLALS */2.361 - break;2.362 - case 12: /* SMULL */2.363 - break;2.364 - case 13: /* SMULLS */2.365 - break;2.366 - case 14: /* SMLAL */2.367 - break;2.368 - case 15: /* SMLALS */2.369 - break;2.370 - case 16: /* SWP */2.371 - break;2.372 - case 20: /* SWPB */2.373 - break;2.374 - default:2.375 - UNIMP(ir);2.376 - }2.377 - break;2.378 - case 1:2.379 - if( LFLAG(ir) ) {2.380 - /* LDRH */2.381 - } else {2.382 - /* STRH */2.383 - }2.384 - break;2.385 - case 2:2.386 - if( LFLAG(ir) ) {2.387 - /* LDRSB */2.388 - } else {2.389 - UNIMP(ir);2.390 - }2.391 - break;2.392 - case 3:2.393 - if( LFLAG(ir) ) {2.394 - /* LDRSH */2.395 - } else {2.396 - UNIMP(ir);2.397 - }2.398 - break;2.399 - }2.400 - } else {2.401 - /* Data processing */2.402 -2.403 - switch(OPCODE(ir)) {2.404 - case 0: /* AND Rd, Rn, operand */2.405 - LRD(ir) = RN(ir) & arm_get_shift_operand(ir);2.406 - break;2.407 - case 1: /* ANDS Rd, Rn, operand */2.408 - operand = arm_get_shift_operand_s(ir) & RN(ir);2.409 - LRD(ir) = operand;2.410 - if( RDn(ir) == 15 ) {2.411 - arm_restore_cpsr();2.412 - } else {2.413 - armr.n = operand>>31;2.414 - armr.z = (operand == 0);2.415 - armr.c = armr.shift_c;2.416 - }2.417 - break;2.418 - case 2: /* EOR Rd, Rn, operand */2.419 - LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);2.420 - break;2.421 - case 3: /* EORS Rd, Rn, operand */2.422 - operand = arm_get_shift_operand_s(ir) ^ RN(ir);2.423 - LRD(ir) = operand;2.424 - if( RDn(ir) == 15 ) {2.425 - arm_restore_cpsr();2.426 - } else {2.427 - armr.n = operand>>31;2.428 - armr.z = (operand == 0);2.429 - armr.c = armr.shift_c;2.430 - }2.431 - break;2.432 - case 4: /* SUB Rd, Rn, operand */2.433 - LRD(ir) = RN(ir) - arm_get_shift_operand(ir);2.434 - break;2.435 - case 5: /* SUBS Rd, Rn, operand */2.436 - operand = RN(ir);2.437 - operand2 = arm_get_shift_operand(ir);2.438 - tmp = operand - operand2;2.439 - LRD(ir) = tmp;2.440 - if( RDn(ir) == 15 ) {2.441 - arm_restore_cpsr();2.442 - } else {2.443 - armr.n = tmp>>31;2.444 - armr.z = (tmp == 0);2.445 - armr.c = IS_NOTBORROW(tmp,operand,operand2);2.446 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);2.447 - }2.448 - break;2.449 - case 6: /* RSB Rd, operand, Rn */2.450 - LRD(ir) = arm_get_shift_operand(ir) - RN(ir);2.451 - break;2.452 - case 7: /* RSBS Rd, operand, Rn */2.453 - operand = arm_get_shift_operand(ir);2.454 - operand2 = RN(ir);2.455 - tmp = operand - operand2;2.456 - LRD(ir) = tmp;2.457 - if( RDn(ir) == 15 ) {2.458 - arm_restore_cpsr();2.459 - } else {2.460 - armr.n = tmp>>31;2.461 - armr.z = (tmp == 0);2.462 - armr.c = IS_NOTBORROW(tmp,operand,operand2);2.463 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);2.464 - }2.465 - break;2.466 - case 8: /* ADD Rd, Rn, operand */2.467 - LRD(ir) = RN(ir) + arm_get_shift_operand(ir);2.468 - break;2.469 - case 9: /* ADDS Rd, Rn, operand */2.470 - operand = arm_get_shift_operand(ir);2.471 - operand2 = RN(ir);2.472 - tmp = operand + operand2;2.473 - LRD(ir) = tmp;2.474 - if( RDn(ir) == 15 ) {2.475 - arm_restore_cpsr();2.476 - } else {2.477 - armr.n = tmp>>31;2.478 - armr.z = (tmp == 0);2.479 - armr.c = IS_CARRY(tmp,operand,operand2);2.480 - armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);2.481 - }2.482 - break;2.483 - case 10: /* ADC */2.484 - case 11: /* ADCS */2.485 - case 12: /* SBC */2.486 - case 13: /* SBCS */2.487 - case 14: /* RSC */2.488 - case 15: /* RSCS */2.489 - break;2.490 - case 17: /* TST Rn, operand */2.491 - operand = arm_get_shift_operand_s(ir) & RN(ir);2.492 - armr.n = operand>>31;2.493 - armr.z = (operand == 0);2.494 - armr.c = armr.shift_c;2.495 - break;2.496 - case 19: /* TEQ Rn, operand */2.497 - operand = arm_get_shift_operand_s(ir) ^ RN(ir);2.498 - armr.n = operand>>31;2.499 - armr.z = (operand == 0);2.500 - armr.c = armr.shift_c;2.501 - break;2.502 - case 21: /* CMP Rn, operand */2.503 - operand = RN(ir);2.504 - operand2 = arm_get_shift_operand(ir);2.505 - tmp = operand - operand2;2.506 - armr.n = tmp>>31;2.507 - armr.z = (tmp == 0);2.508 - armr.c = IS_NOTBORROW(tmp,operand,operand2);2.509 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);2.510 - break;2.511 - case 23: /* CMN Rn, operand */2.512 - operand = RN(ir);2.513 - operand2 = arm_get_shift_operand(ir);2.514 - tmp = operand + operand2;2.515 - armr.n = tmp>>31;2.516 - armr.z = (tmp == 0);2.517 - armr.c = IS_CARRY(tmp,operand,operand2);2.518 - armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);2.519 - break;2.520 - case 24: /* ORR Rd, Rn, operand */2.521 - LRD(ir) = RN(ir) | arm_get_shift_operand(ir);2.522 - break;2.523 - case 25: /* ORRS Rd, Rn, operand */2.524 - operand = arm_get_shift_operand_s(ir) | RN(ir);2.525 - LRD(ir) = operand;2.526 - if( RDn(ir) == 15 ) {2.527 - arm_restore_cpsr();2.528 - } else {2.529 - armr.n = operand>>31;2.530 - armr.z = (operand == 0);2.531 - armr.c = armr.shift_c;2.532 - }2.533 - break;2.534 - case 26: /* MOV Rd, operand */2.535 - LRD(ir) = arm_get_shift_operand(ir);2.536 - break;2.537 - case 27: /* MOVS Rd, operand */2.538 - operand = arm_get_shift_operand_s(ir);2.539 - LRD(ir) = operand;2.540 - if( RDn(ir) == 15 ) {2.541 - arm_restore_cpsr();2.542 - } else {2.543 - armr.n = operand>>31;2.544 - armr.z = (operand == 0);2.545 - armr.c = armr.shift_c;2.546 - }2.547 - break;2.548 - case 28: /* BIC Rd, Rn, operand */2.549 - LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));2.550 - break;2.551 - case 29: /* BICS Rd, Rn, operand */2.552 - operand = RN(ir) & (~arm_get_shift_operand_s(ir));2.553 - LRD(ir) = operand;2.554 - if( RDn(ir) == 15 ) {2.555 - arm_restore_cpsr();2.556 - } else {2.557 - armr.n = operand>>31;2.558 - armr.z = (operand == 0);2.559 - armr.c = armr.shift_c;2.560 - }2.561 - break;2.562 - case 30: /* MVN Rd, operand */2.563 - LRD(ir) = ~arm_get_shift_operand(ir);2.564 - break;2.565 - case 31: /* MVNS Rd, operand */2.566 - operand = ~arm_get_shift_operand_s(ir);2.567 - LRD(ir) = operand;2.568 - if( RDn(ir) == 15 ) {2.569 - arm_restore_cpsr();2.570 - } else {2.571 - armr.n = operand>>31;2.572 - armr.z = (operand == 0);2.573 - armr.c = armr.shift_c;2.574 - }2.575 - break;2.576 - default:2.577 - UNIMP(ir);2.578 - }2.579 + /**2.580 + * Condition passed, now for the actual instructions...2.581 + */2.582 + switch( GRP(ir) ) {2.583 + case 0:2.584 + if( (ir & 0x0D900000) == 0x01000000 ) {2.585 + /* Instructions that aren't actual data processing even though2.586 + * they sit in the DP instruction block.2.587 + */2.588 + switch( ir & 0x0FF000F0 ) {2.589 + case 0x01200010: /* BX Rd */2.590 + armr.t = ir & 0x01;2.591 + armr.r[15] = RM(ir) & 0xFFFFFFFE;2.592 + break;2.593 + case 0x01000000: /* MRS Rd, CPSR */2.594 + LRD(ir) = arm_get_cpsr();2.595 + break;2.596 + case 0x01400000: /* MRS Rd, SPSR */2.597 + LRD(ir) = armr.spsr;2.598 + break;2.599 + case 0x01200000: /* MSR CPSR, Rd */2.600 + arm_set_cpsr( RM(ir), ir );2.601 + break;2.602 + case 0x01600000: /* MSR SPSR, Rd */2.603 + arm_set_spsr( RM(ir), ir );2.604 + break;2.605 + case 0x03200000: /* MSR CPSR, imm */2.606 + arm_set_cpsr( ROTIMM12(ir), ir );2.607 + break;2.608 + case 0x03600000: /* MSR SPSR, imm */2.609 + arm_set_spsr( ROTIMM12(ir), ir );2.610 + break;2.611 + default:2.612 + UNIMP(ir);2.613 + }2.614 + } else if( (ir & 0x0E000090) == 0x00000090 ) {2.615 + /* Neither are these */2.616 + switch( (ir>>5)&0x03 ) {2.617 + case 0:2.618 + /* Arithmetic extension area */2.619 + switch(OPCODE(ir)) {2.620 + case 0: /* MUL */2.621 + break;2.622 + case 1: /* MULS */2.623 + break;2.624 + case 2: /* MLA */2.625 + break;2.626 + case 3: /* MLAS */2.627 + break;2.628 + case 8: /* UMULL */2.629 + break;2.630 + case 9: /* UMULLS */2.631 + break;2.632 + case 10: /* UMLAL */2.633 + break;2.634 + case 11: /* UMLALS */2.635 + break;2.636 + case 12: /* SMULL */2.637 + break;2.638 + case 13: /* SMULLS */2.639 + break;2.640 + case 14: /* SMLAL */2.641 + break;2.642 + case 15: /* SMLALS */2.643 + break;2.644 + case 16: /* SWP */2.645 + break;2.646 + case 20: /* SWPB */2.647 + break;2.648 + default:2.649 + UNIMP(ir);2.650 }2.651 break;2.652 - case 1: /* Load/store */2.653 + case 1:2.654 + if( LFLAG(ir) ) {2.655 + /* LDRH */2.656 + } else {2.657 + /* STRH */2.658 + }2.659 break;2.660 - case 2: /* Load/store multiple, branch*/2.661 + case 2:2.662 + if( LFLAG(ir) ) {2.663 + /* LDRSB */2.664 + } else {2.665 + UNIMP(ir);2.666 + }2.667 break;2.668 - case 3: /* Copro */2.669 + case 3:2.670 + if( LFLAG(ir) ) {2.671 + /* LDRSH */2.672 + } else {2.673 + UNIMP(ir);2.674 + }2.675 break;2.676 + }2.677 + } else {2.678 + /* Data processing */2.679 +2.680 + switch(OPCODE(ir)) {2.681 + case 0: /* AND Rd, Rn, operand */2.682 + LRD(ir) = RN(ir) & arm_get_shift_operand(ir);2.683 + break;2.684 + case 1: /* ANDS Rd, Rn, operand */2.685 + operand = arm_get_shift_operand_s(ir) & RN(ir);2.686 + LRD(ir) = operand;2.687 + if( RDn(ir) == 15 ) {2.688 + arm_restore_cpsr();2.689 + } else {2.690 + armr.n = operand>>31;2.691 + armr.z = (operand == 0);2.692 + armr.c = armr.shift_c;2.693 + }2.694 + break;2.695 + case 2: /* EOR Rd, Rn, operand */2.696 + LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);2.697 + break;2.698 + case 3: /* EORS Rd, Rn, operand */2.699 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);2.700 + LRD(ir) = operand;2.701 + if( RDn(ir) == 15 ) {2.702 + arm_restore_cpsr();2.703 + } else {2.704 + armr.n = operand>>31;2.705 + armr.z = (operand == 0);2.706 + armr.c = armr.shift_c;2.707 + }2.708 + break;2.709 + case 4: /* SUB Rd, Rn, operand */2.710 + LRD(ir) = RN(ir) - arm_get_shift_operand(ir);2.711 + break;2.712 + case 5: /* SUBS Rd, Rn, operand */2.713 + operand = RN(ir);2.714 + operand2 = arm_get_shift_operand(ir);2.715 + tmp = operand - operand2;2.716 + LRD(ir) = tmp;2.717 + if( RDn(ir) == 15 ) {2.718 + arm_restore_cpsr();2.719 + } else {2.720 + armr.n = tmp>>31;2.721 + armr.z = (tmp == 0);2.722 + armr.c = IS_NOTBORROW(tmp,operand,operand2);2.723 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);2.724 + }2.725 + break;2.726 + case 6: /* RSB Rd, operand, Rn */2.727 + LRD(ir) = arm_get_shift_operand(ir) - RN(ir);2.728 + break;2.729 + case 7: /* RSBS Rd, operand, Rn */2.730 + operand = arm_get_shift_operand(ir);2.731 + operand2 = RN(ir);2.732 + tmp = operand - operand2;2.733 + LRD(ir) = tmp;2.734 + if( RDn(ir) == 15 ) {2.735 + arm_restore_cpsr();2.736 + } else {2.737 + armr.n = tmp>>31;2.738 + armr.z = (tmp == 0);2.739 + armr.c = IS_NOTBORROW(tmp,operand,operand2);2.740 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);2.741 + }2.742 + break;2.743 + case 8: /* ADD Rd, Rn, operand */2.744 + LRD(ir) = RN(ir) + arm_get_shift_operand(ir);2.745 + break;2.746 + case 9: /* ADDS Rd, Rn, operand */2.747 + operand = arm_get_shift_operand(ir);2.748 + operand2 = RN(ir);2.749 + tmp = operand + operand2;2.750 + LRD(ir) = tmp;2.751 + if( RDn(ir) == 15 ) {2.752 + arm_restore_cpsr();2.753 + } else {2.754 + armr.n = tmp>>31;2.755 + armr.z = (tmp == 0);2.756 + armr.c = IS_CARRY(tmp,operand,operand2);2.757 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);2.758 + }2.759 + break;2.760 + case 10: /* ADC */2.761 + case 11: /* ADCS */2.762 + case 12: /* SBC */2.763 + case 13: /* SBCS */2.764 + case 14: /* RSC */2.765 + case 15: /* RSCS */2.766 + break;2.767 + case 17: /* TST Rn, operand */2.768 + operand = arm_get_shift_operand_s(ir) & RN(ir);2.769 + armr.n = operand>>31;2.770 + armr.z = (operand == 0);2.771 + armr.c = armr.shift_c;2.772 + break;2.773 + case 19: /* TEQ Rn, operand */2.774 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);2.775 + armr.n = operand>>31;2.776 + armr.z = (operand == 0);2.777 + armr.c = armr.shift_c;2.778 + break;2.779 + case 21: /* CMP Rn, operand */2.780 + operand = RN(ir);2.781 + operand2 = arm_get_shift_operand(ir);2.782 + tmp = operand - operand2;2.783 + armr.n = tmp>>31;2.784 + armr.z = (tmp == 0);2.785 + armr.c = IS_NOTBORROW(tmp,operand,operand2);2.786 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);2.787 + break;2.788 + case 23: /* CMN Rn, operand */2.789 + operand = RN(ir);2.790 + operand2 = arm_get_shift_operand(ir);2.791 + tmp = operand + operand2;2.792 + armr.n = tmp>>31;2.793 + armr.z = (tmp == 0);2.794 + armr.c = IS_CARRY(tmp,operand,operand2);2.795 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);2.796 + break;2.797 + case 24: /* ORR Rd, Rn, operand */2.798 + LRD(ir) = RN(ir) | arm_get_shift_operand(ir);2.799 + break;2.800 + case 25: /* ORRS Rd, Rn, operand */2.801 + operand = arm_get_shift_operand_s(ir) | RN(ir);2.802 + LRD(ir) = operand;2.803 + if( RDn(ir) == 15 ) {2.804 + arm_restore_cpsr();2.805 + } else {2.806 + armr.n = operand>>31;2.807 + armr.z = (operand == 0);2.808 + armr.c = armr.shift_c;2.809 + }2.810 + break;2.811 + case 26: /* MOV Rd, operand */2.812 + LRD(ir) = arm_get_shift_operand(ir);2.813 + break;2.814 + case 27: /* MOVS Rd, operand */2.815 + operand = arm_get_shift_operand_s(ir);2.816 + LRD(ir) = operand;2.817 + if( RDn(ir) == 15 ) {2.818 + arm_restore_cpsr();2.819 + } else {2.820 + armr.n = operand>>31;2.821 + armr.z = (operand == 0);2.822 + armr.c = armr.shift_c;2.823 + }2.824 + break;2.825 + case 28: /* BIC Rd, Rn, operand */2.826 + LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));2.827 + break;2.828 + case 29: /* BICS Rd, Rn, operand */2.829 + operand = RN(ir) & (~arm_get_shift_operand_s(ir));2.830 + LRD(ir) = operand;2.831 + if( RDn(ir) == 15 ) {2.832 + arm_restore_cpsr();2.833 + } else {2.834 + armr.n = operand>>31;2.835 + armr.z = (operand == 0);2.836 + armr.c = armr.shift_c;2.837 + }2.838 + break;2.839 + case 30: /* MVN Rd, operand */2.840 + LRD(ir) = ~arm_get_shift_operand(ir);2.841 + break;2.842 + case 31: /* MVNS Rd, operand */2.843 + operand = ~arm_get_shift_operand_s(ir);2.844 + LRD(ir) = operand;2.845 + if( RDn(ir) == 15 ) {2.846 + arm_restore_cpsr();2.847 + } else {2.848 + armr.n = operand>>31;2.849 + armr.z = (operand == 0);2.850 + armr.c = armr.shift_c;2.851 + }2.852 + break;2.853 + default:2.854 + UNIMP(ir);2.855 + }2.856 }2.857 - return TRUE;2.858 + break;2.859 + case 1: /* Load/store */2.860 + operand = arm_get_address_operand(ir);2.861 + switch( (ir>>20)&0x17 ) {2.862 + case 0: case 16: case 18: /* STR Rd, address */2.863 + arm_write_long( operand, RD(ir) );2.864 + break;2.865 + case 1: case 17: case 19: /* LDR Rd, address */2.866 + LRD(ir) = arm_read_long(operand);2.867 + break;2.868 + case 2: /* STRT Rd, address */2.869 + arm_write_long_user( operand, RD(ir) );2.870 + break;2.871 + case 3: /* LDRT Rd, address */2.872 + LRD(ir) = arm_read_long_user( operand );2.873 + break;2.874 + case 4: case 20: case 22: /* STRB Rd, address */2.875 + arm_write_byte( operand, RD(ir) );2.876 + break;2.877 + case 5: case 21: case 23: /* LDRB Rd, address */2.878 + LRD(ir) = arm_read_byte( operand );2.879 + break;2.880 + case 6: /* STRBT Rd, address */2.881 + arm_write_byte_user( operand, RD(ir) );2.882 + break;2.883 + case 7: /* LDRBT Rd, address */2.884 + LRD(ir) = arm_read_byte_user( operand );2.885 + break;2.886 + }2.887 + break;2.888 + case 2: /* Load/store multiple, branch*/2.889 + if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */2.890 + operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);2.891 + if( (ir & 0x01000000) == 0x01000000 ) {2.892 + armr.r[14] = pc; /* BL */2.893 + }2.894 + armr.r[15] = pc + 4 + operand;2.895 + } else { /* Load/store multiple */2.896 + UNIMP(ir);2.897 + }2.898 + break;2.899 + case 3: /* Copro */2.900 + UNIMP(ir);2.901 + break;2.902 + }2.903 + return TRUE;2.904 }
3.1 --- a/src/aica/armcore.h Mon Dec 26 06:38:13 2005 +00003.2 +++ b/src/aica/armcore.h Mon Dec 26 06:38:51 2005 +00003.3 @@ -1,5 +1,5 @@3.4 /**3.5 - * $Id: armcore.h,v 1.7 2005-12-26 03:54:55 nkeynes Exp $3.6 + * $Id: armcore.h,v 1.8 2005-12-26 06:38:51 nkeynes Exp $3.7 *3.8 * Interface definitions for the ARM CPU emulation core proper.3.9 *3.10 @@ -61,6 +61,7 @@3.11 #define CPSR_F 0x00000040 /* Fast interrupt disable bit */3.12 #define CPSR_T 0x00000020 /* Thumb mode */3.13 #define CPSR_MODE 0x0000001F /* Current execution mode */3.14 +#define CPSR_COMPACT_MASK 0x0FFFFFDF /* Mask excluding all separated flags */3.16 #define MODE_USER 0x10 /* User mode */3.17 #define MODE_FIQ 0x11 /* Fast IRQ mode */3.18 @@ -70,6 +71,9 @@3.19 #define MODE_UND 0x1B /* Undefined mode */3.20 #define MODE_SYS 0x1F /* System mode */3.22 +#define IS_PRIVILEGED_MODE() ((armr.cpsr & CPSR_MODE) != MODE_USER)3.23 +#define IS_EXCEPTION_MODE() (IS_PRIVILEGED_MODE() && (armr.cpsr & CPSR_MODE) != MODE_SYS)3.24 +3.25 extern struct arm_registers armr;3.27 #define CARRY_FLAG (armr.cpsr&CPSR_C)3.28 @@ -82,12 +86,16 @@3.29 gboolean arm_execute_instruction( void );3.31 /* ARM Memory */3.32 -int32_t arm_read_long( uint32_t addr );3.33 -int32_t arm_read_word( uint32_t addr );3.34 -int32_t arm_read_byte( uint32_t addr );3.35 +uint32_t arm_read_long( uint32_t addr );3.36 +uint32_t arm_read_word( uint32_t addr );3.37 +uint32_t arm_read_byte( uint32_t addr );3.38 +uint32_t arm_read_long_user( uint32_t addr );3.39 +uint32_t arm_read_byte_user( uint32_t addr );3.40 void arm_write_long( uint32_t addr, uint32_t val );3.41 void arm_write_word( uint32_t addr, uint32_t val );3.42 void arm_write_byte( uint32_t addr, uint32_t val );3.43 +void arm_write_long_user( uint32_t addr, uint32_t val );3.44 +void arm_write_byte_user( uint32_t addr, uint32_t val );3.45 int32_t arm_read_phys_word( uint32_t addr );3.46 int arm_has_page( uint32_t addr );
4.1 --- a/src/aica/armmem.c Mon Dec 26 06:38:13 2005 +00004.2 +++ b/src/aica/armmem.c Mon Dec 26 06:38:51 2005 +00004.3 @@ -1,5 +1,5 @@4.4 /**4.5 - * $Id: armmem.c,v 1.4 2005-12-25 08:24:11 nkeynes Exp $4.6 + * $Id: armmem.c,v 1.5 2005-12-26 06:38:51 nkeynes Exp $4.7 *4.8 * Implements the ARM's memory map.4.9 *4.10 @@ -32,21 +32,34 @@4.11 (addr >= 0x00800000 && addr <= 0x00805000 ) );4.12 }4.14 -int32_t arm_read_long( uint32_t addr ) {4.15 +uint32_t arm_read_long( uint32_t addr ) {4.16 if( addr < 0x00200000 ) {4.17 return *(int32_t *)(arm_mem + addr);4.18 /* Main sound ram */4.19 - } else if( addr >= 0x00800000 && addr <= 0x00803000 ) {4.20 - /* Sound registers / scratch ram */4.21 } else {4.22 - /* Undefined memory */4.23 - ERROR( "Attempted long read to undefined page: %08X",4.24 - addr );4.25 - return 0;4.26 + switch( addr & 0xFFFFF000 ) {4.27 + case 0x00800000:4.28 + return mmio_region_AICA0_read(addr);4.29 + break;4.30 + case 0x00801000:4.31 + return mmio_region_AICA1_read(addr);4.32 + break;4.33 + case 0x00802000:4.34 + return mmio_region_AICA2_read(addr);4.35 + break;4.36 + case 0x00803000:4.37 + break;4.38 + case 0x00804000:4.39 + break;4.40 + }4.41 }4.42 + ERROR( "Attempted long read to undefined page: %08X",4.43 + addr );4.44 + /* Undefined memory */4.45 + return 0;4.46 }4.48 -int16_t arm_read_word( uint32_t addr ) {4.49 +uint32_t arm_read_word( uint32_t addr ) {4.50 if( addr < 0x00200000 ) {4.51 return *(int16_t *)(arm_mem + addr);4.52 /* Main sound ram */4.53 @@ -59,9 +72,9 @@4.55 }4.57 -int8_t arm_read_byte( uint32_t addr ) {4.58 +uint32_t arm_read_byte( uint32_t addr ) {4.59 if( addr < 0x00200000 ) {4.60 - return *(int8_t *)(arm_mem + addr);4.61 + return (uint32_t)(*(uint8_t *)(arm_mem + addr));4.62 /* Main sound ram */4.63 } else {4.64 /* Undefined memory */4.65 @@ -71,10 +84,37 @@4.66 }4.67 }4.69 +void arm_write_long( uint32_t addr, uint32_t value )4.70 +{4.71 + if( addr < 0x00200000 ) {4.72 + *(uint32_t *)(arm_mem + addr) = value;4.73 + } else {4.74 + }4.75 +}4.76 +4.77 +void arm_write_byte( uint32_t addr, uint32_t value )4.78 +{4.79 + if( addr < 0x00200000 ) {4.80 + *(uint8_t *)(arm_mem+addr) = (uint8_t)value;4.81 + } else {4.82 + }4.83 +}4.84 +4.85 +/* User translations - TODO */4.86 +4.87 uint32_t arm_read_long_user( uint32_t addr ) {4.88 -4.89 + return arm_read_long( addr );4.90 }4.92 uint32_t arm_read_byte_user( uint32_t addr ) {4.93 + return arm_read_byte( addr );4.94 +}4.96 +void arm_write_long_user( uint32_t addr, uint32_t val ) {4.97 + arm_write_long( addr, val );4.98 }4.99 +4.100 +void arm_write_byte_user( uint32_t addr, uint32_t val )4.101 +{4.102 + arm_write_byte( addr, val );4.103 +}
.