Search
lxdream.org :: lxdream :: r37:1d84f4c18816
lxdream 0.9.1
released Jun 29
Download Now
changeset37:1d84f4c18816
parent36:f581f9c43c43
child38:9ccc7ac66a9d
authornkeynes
dateMon Dec 26 06:38:51 2005 +0000 (18 years ago)
More ARM work-in-progress - idle loop works now :)
src/aica/aica.c
src/aica/armcore.c
src/aica/armcore.h
src/aica/armmem.c
1.1 --- a/src/aica/aica.c Mon Dec 26 06:38:13 2005 +0000
1.2 +++ b/src/aica/aica.c Mon Dec 26 06:38:51 2005 +0000
1.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.16
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.25
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.33
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 +0000
2.2 +++ b/src/aica/armcore.c Mon Dec 26 06:38:51 2005 +0000
2.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.13
2.14 +#define MODULE aica_module
2.15 +#include "dream.h"
2.16 #include "aica/armcore.h"
2.17
2.18 struct arm_registers armr;
2.19 @@ -79,6 +81,69 @@
2.20 armr.r[15] = 0x00000000;
2.21 }
2.22
2.23 +#define SET_CPSR_CONTROL 0x00010000
2.24 +#define SET_CPSR_EXTENSION 0x00020000
2.25 +#define SET_CPSR_STATUS 0x00040000
2.26 +#define SET_CPSR_FLAGS 0x00080000
2.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 CPSR
2.44 + * @param fields set of mask values to define which sections of the
2.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 writing
2.61 + * back to CPSR
2.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.104
2.105 -/**
2.106 - * Restore CPSR from SPSR, effectively (under most circumstances) executing
2.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.123
2.124
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.150
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 that
2.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.162
2.163 /**
2.164 - * Compute the "shift operand" of the instruction for the data processing
2.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.176
2.177 +/**
2.178 + * Determine the address operand of a load/store instruction, including
2.179 + * applying any pre/post adjustments to the address registers.
2.180 + * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
2.181 + * @param The instruction word.
2.182 + * @return The calculated address
2.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.196
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.205
2.206 - pc += 4;
2.207 - PC = pc;
2.208 + pc += 4;
2.209 + PC = pc;
2.210
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 return
2.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.317
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 though
2.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 +0000
3.2 +++ b/src/aica/armcore.h Mon Dec 26 06:38:51 2005 +0000
3.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.15
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.21
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.26
3.27 #define CARRY_FLAG (armr.cpsr&CPSR_C)
3.28 @@ -82,12 +86,16 @@
3.29 gboolean arm_execute_instruction( void );
3.30
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 );
3.47
4.1 --- a/src/aica/armmem.c Mon Dec 26 06:38:13 2005 +0000
4.2 +++ b/src/aica/armmem.c Mon Dec 26 06:38:51 2005 +0000
4.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.13
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.47
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.54
4.55 }
4.56
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.68
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.91
4.92 uint32_t arm_read_byte_user( uint32_t addr ) {
4.93 + return arm_read_byte( addr );
4.94 +}
4.95
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 +}
.