Search
lxdream.org :: lxdream/src/aica/armcore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 37:1d84f4c18816
prev35:21a4be098304
next43:0cf3e339cc59
author nkeynes
date Mon Dec 26 06:38:51 2005 +0000 (14 years ago)
permissions -rw-r--r--
last change More ARM work-in-progress - idle loop works now :)
file annotate diff log raw
1.1 --- a/src/aica/armcore.c Mon Dec 26 03:54:55 2005 +0000
1.2 +++ b/src/aica/armcore.c Mon Dec 26 06:38:51 2005 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: armcore.c,v 1.6 2005-12-26 03:54:55 nkeynes Exp $
1.6 + * $Id: armcore.c,v 1.7 2005-12-26 06:38:51 nkeynes Exp $
1.7 *
1.8 * ARM7TDMI CPU emulation core.
1.9 *
1.10 @@ -16,6 +16,8 @@
1.11 * GNU General Public License for more details.
1.12 */
1.13
1.14 +#define MODULE aica_module
1.15 +#include "dream.h"
1.16 #include "aica/armcore.h"
1.17
1.18 struct arm_registers armr;
1.19 @@ -79,6 +81,69 @@
1.20 armr.r[15] = 0x00000000;
1.21 }
1.22
1.23 +#define SET_CPSR_CONTROL 0x00010000
1.24 +#define SET_CPSR_EXTENSION 0x00020000
1.25 +#define SET_CPSR_STATUS 0x00040000
1.26 +#define SET_CPSR_FLAGS 0x00080000
1.27 +
1.28 +uint32_t arm_get_cpsr( void )
1.29 +{
1.30 + /* write back all flags to the cpsr */
1.31 + armr.cpsr = armr.cpsr & CPSR_COMPACT_MASK;
1.32 + if( armr.n ) armr.cpsr |= CPSR_N;
1.33 + if( armr.z ) armr.cpsr |= CPSR_Z;
1.34 + if( armr.c ) armr.cpsr |= CPSR_C;
1.35 + if( armr.v ) armr.cpsr |= CPSR_V;
1.36 + if( armr.t ) armr.cpsr |= CPSR_T;
1.37 + return armr.cpsr;
1.38 +}
1.39 +
1.40 +/**
1.41 + * Set the CPSR to the specified value.
1.42 + *
1.43 + * @param value values to set in CPSR
1.44 + * @param fields set of mask values to define which sections of the
1.45 + * CPSR to set (one of the SET_CPSR_* values above)
1.46 + */
1.47 +void arm_set_cpsr( uint32_t value, uint32_t fields )
1.48 +{
1.49 + if( IS_PRIVILEGED_MODE() ) {
1.50 + if( fields & SET_CPSR_CONTROL ) {
1.51 + int mode = value & CPSR_MODE;
1.52 + arm_set_mode( mode );
1.53 + armr.t = ( value & CPSR_T ); /* Technically illegal to change */
1.54 + armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
1.55 + }
1.56 +
1.57 + /* Middle 16 bits not currently defined */
1.58 + }
1.59 + if( fields & SET_CPSR_FLAGS ) {
1.60 + /* Break flags directly out of given value - don't bother writing
1.61 + * back to CPSR
1.62 + */
1.63 + armr.n = ( value & CPSR_N );
1.64 + armr.z = ( value & CPSR_Z );
1.65 + armr.c = ( value & CPSR_C );
1.66 + armr.v = ( value & CPSR_V );
1.67 + }
1.68 +}
1.69 +
1.70 +void arm_set_spsr( uint32_t value, uint32_t fields )
1.71 +{
1.72 + /* Only defined if we actually have an SPSR register */
1.73 + if( IS_EXCEPTION_MODE() ) {
1.74 + if( fields & SET_CPSR_CONTROL ) {
1.75 + armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
1.76 + }
1.77 +
1.78 + /* Middle 16 bits not currently defined */
1.79 +
1.80 + if( fields & SET_CPSR_FLAGS ) {
1.81 + armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
1.82 + }
1.83 + }
1.84 +}
1.85 +
1.86 /**
1.87 * Raise an ARM exception (other than reset, which uses arm_reset().
1.88 * @param exception one of the EXC_* exception codes defined above.
1.89 @@ -86,26 +151,27 @@
1.90 void arm_raise_exception( int exception )
1.91 {
1.92 int mode = arm_exceptions[exception][0];
1.93 + uint32_t spsr = arm_get_cpsr();
1.94 arm_set_mode( mode );
1.95 - armr.spsr = armr.cpsr;
1.96 + armr.spsr = spsr;
1.97 armr.r[14] = armr.r[15];
1.98 - armr.cpsr = (armr.cpsr & (~CPSR_T)) | CPSR_I;
1.99 + armr.cpsr = (spsr & (~CPSR_T)) | CPSR_I;
1.100 if( mode == MODE_FIQ )
1.101 armr.cpsr |= CPSR_F;
1.102 armr.r[15] = arm_exceptions[exception][1];
1.103 }
1.104
1.105 -/**
1.106 - * Restore CPSR from SPSR, effectively (under most circumstances) executing
1.107 - * a return-from-exception.
1.108 - */
1.109 -void arm_restore_cpsr()
1.110 +void arm_restore_cpsr( void )
1.111 {
1.112 int spsr = armr.spsr;
1.113 int mode = spsr & CPSR_MODE;
1.114 -
1.115 arm_set_mode( mode );
1.116 armr.cpsr = spsr;
1.117 + armr.n = ( spsr & CPSR_N );
1.118 + armr.z = ( spsr & CPSR_Z );
1.119 + armr.c = ( spsr & CPSR_C );
1.120 + armr.v = ( spsr & CPSR_V );
1.121 + armr.t = ( spsr & CPSR_T );
1.122 }
1.123
1.124
1.125 @@ -237,10 +303,10 @@
1.126 #define WFLAG(ir) (IR&0x00200000)
1.127 #define LFLAG(ir) SFLAG(ir)
1.128 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
1.129 -#define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
1.130 +#define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))
1.131 #define RDn(ir) ((ir>>12)&0x0F)
1.132 -#define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
1.133 -#define RM(ir) (armr.r[(ir&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
1.134 +#define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))
1.135 +#define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )
1.136 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
1.137 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
1.138 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
1.139 @@ -250,11 +316,19 @@
1.140 #define IMM12(ir) (ir&0xFFF)
1.141 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
1.142 #define IMMROT(ir) ((ir>>7)&0x1E)
1.143 +#define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
1.144 +#define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
1.145 #define SHIFT(ir) ((ir>>4)&0x07)
1.146 #define DISP24(ir) ((ir&0x00FFFFFF))
1.147 -#define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return TRUE; } while(0)
1.148 +#define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
1.149 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)
1.150
1.151 +/**
1.152 + * Determine the value of the shift-operand for a data processing instruction,
1.153 + * without determing a value for shift_C (optimized form for instructions that
1.154 + * don't require shift_C ).
1.155 + * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
1.156 + */
1.157 static uint32_t arm_get_shift_operand( uint32_t ir )
1.158 {
1.159 uint32_t operand, tmp;
1.160 @@ -308,9 +382,9 @@
1.161 }
1.162
1.163 /**
1.164 - * Compute the "shift operand" of the instruction for the data processing
1.165 - * instructions. This variant also sets armr.shift_c (carry result for shifter)
1.166 - * Reason for the variants is that most cases don't actually need the shift_c.
1.167 + * Determine the value of the shift-operand for a data processing instruction,
1.168 + * and set armr.shift_c accordingly.
1.169 + * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
1.170 */
1.171 static uint32_t arm_get_shift_operand_s( uint32_t ir )
1.172 {
1.173 @@ -461,6 +535,13 @@
1.174 return operand;
1.175 }
1.176
1.177 +/**
1.178 + * Determine the address operand of a load/store instruction, including
1.179 + * applying any pre/post adjustments to the address registers.
1.180 + * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
1.181 + * @param The instruction word.
1.182 + * @return The calculated address
1.183 + */
1.184 static uint32_t arm_get_address_operand( uint32_t ir )
1.185 {
1.186 uint32_t addr;
1.187 @@ -515,341 +596,395 @@
1.188 addr = RN(ir) + arm_get_address_index(ir);
1.189 LRN(ir) = addr;
1.190 break;
1.191 - default:
1.192 - UNIMP(ir); /* Unreachable */
1.193 }
1.194 return addr;
1.195 }
1.196
1.197 gboolean arm_execute_instruction( void )
1.198 {
1.199 - uint32_t pc = PC;
1.200 - uint32_t ir = MEM_READ_LONG(pc);
1.201 - uint32_t operand, operand2, tmp, cond;
1.202 + uint32_t pc = PC;
1.203 + uint32_t ir = MEM_READ_LONG(pc);
1.204 + uint32_t operand, operand2, tmp, cond;
1.205
1.206 - pc += 4;
1.207 - PC = pc;
1.208 + pc += 4;
1.209 + PC = pc;
1.210
1.211 - switch( COND(ir) ) {
1.212 - case 0: /* EQ */
1.213 - cond = armr.z;
1.214 - break;
1.215 - case 1: /* NE */
1.216 - cond = !armr.z;
1.217 - break;
1.218 - case 2: /* CS/HS */
1.219 - cond = armr.c;
1.220 - break;
1.221 - case 3: /* CC/LO */
1.222 - cond = !armr.c;
1.223 - break;
1.224 - case 4: /* MI */
1.225 - cond = armr.n;
1.226 - break;
1.227 - case 5: /* PL */
1.228 - cond = !armr.n;
1.229 - break;
1.230 - case 6: /* VS */
1.231 - cond = armr.v;
1.232 - break;
1.233 - case 7: /* VC */
1.234 - cond = !armr.v;
1.235 - break;
1.236 - case 8: /* HI */
1.237 - cond = armr.c && !armr.z;
1.238 - break;
1.239 - case 9: /* LS */
1.240 - cond = (!armr.c) || armr.z;
1.241 - break;
1.242 - case 10: /* GE */
1.243 - cond = (armr.n == armr.v);
1.244 - break;
1.245 - case 11: /* LT */
1.246 - cond = (armr.n != armr.v);
1.247 - break;
1.248 - case 12: /* GT */
1.249 - cond = (!armr.z) && (armr.n == armr.v);
1.250 - break;
1.251 - case 13: /* LE */
1.252 - cond = armr.z || (armr.n != armr.v);
1.253 - break;
1.254 - case 14: /* AL */
1.255 - cond = 1;
1.256 - break;
1.257 - case 15: /* (NV) */
1.258 - cond = 0;
1.259 - UNDEF(ir);
1.260 - }
1.261 + /**
1.262 + * Check the condition bits first - if the condition fails return
1.263 + * immediately without actually looking at the rest of the instruction.
1.264 + */
1.265 + switch( COND(ir) ) {
1.266 + case 0: /* EQ */
1.267 + cond = armr.z;
1.268 + break;
1.269 + case 1: /* NE */
1.270 + cond = !armr.z;
1.271 + break;
1.272 + case 2: /* CS/HS */
1.273 + cond = armr.c;
1.274 + break;
1.275 + case 3: /* CC/LO */
1.276 + cond = !armr.c;
1.277 + break;
1.278 + case 4: /* MI */
1.279 + cond = armr.n;
1.280 + break;
1.281 + case 5: /* PL */
1.282 + cond = !armr.n;
1.283 + break;
1.284 + case 6: /* VS */
1.285 + cond = armr.v;
1.286 + break;
1.287 + case 7: /* VC */
1.288 + cond = !armr.v;
1.289 + break;
1.290 + case 8: /* HI */
1.291 + cond = armr.c && !armr.z;
1.292 + break;
1.293 + case 9: /* LS */
1.294 + cond = (!armr.c) || armr.z;
1.295 + break;
1.296 + case 10: /* GE */
1.297 + cond = (armr.n == armr.v);
1.298 + break;
1.299 + case 11: /* LT */
1.300 + cond = (armr.n != armr.v);
1.301 + break;
1.302 + case 12: /* GT */
1.303 + cond = (!armr.z) && (armr.n == armr.v);
1.304 + break;
1.305 + case 13: /* LE */
1.306 + cond = armr.z || (armr.n != armr.v);
1.307 + break;
1.308 + case 14: /* AL */
1.309 + cond = 1;
1.310 + break;
1.311 + case 15: /* (NV) */
1.312 + cond = 0;
1.313 + UNDEF(ir);
1.314 + }
1.315 + if( !cond )
1.316 + return TRUE;
1.317
1.318 - switch( GRP(ir) ) {
1.319 - case 0:
1.320 - if( (ir & 0x0D900000) == 0x01000000 ) {
1.321 - /* Instructions that aren't actual data processing */
1.322 - switch( ir & 0x0FF000F0 ) {
1.323 - case 0x01200010: /* BX */
1.324 - break;
1.325 - case 0x01000000: /* MRS Rd, CPSR */
1.326 - break;
1.327 - case 0x01400000: /* MRS Rd, SPSR */
1.328 - break;
1.329 - case 0x01200000: /* MSR CPSR, Rd */
1.330 - break;
1.331 - case 0x01600000: /* MSR SPSR, Rd */
1.332 - break;
1.333 - case 0x03200000: /* MSR CPSR, imm */
1.334 - break;
1.335 - case 0x03600000: /* MSR SPSR, imm */
1.336 - break;
1.337 - default:
1.338 - UNIMP(ir);
1.339 - }
1.340 - } else if( (ir & 0x0E000090) == 0x00000090 ) {
1.341 - /* Neither are these */
1.342 - switch( (ir>>5)&0x03 ) {
1.343 - case 0:
1.344 - /* Arithmetic extension area */
1.345 - switch(OPCODE(ir)) {
1.346 - case 0: /* MUL */
1.347 - break;
1.348 - case 1: /* MULS */
1.349 - break;
1.350 - case 2: /* MLA */
1.351 - break;
1.352 - case 3: /* MLAS */
1.353 - break;
1.354 - case 8: /* UMULL */
1.355 - break;
1.356 - case 9: /* UMULLS */
1.357 - break;
1.358 - case 10: /* UMLAL */
1.359 - break;
1.360 - case 11: /* UMLALS */
1.361 - break;
1.362 - case 12: /* SMULL */
1.363 - break;
1.364 - case 13: /* SMULLS */
1.365 - break;
1.366 - case 14: /* SMLAL */
1.367 - break;
1.368 - case 15: /* SMLALS */
1.369 - break;
1.370 - case 16: /* SWP */
1.371 - break;
1.372 - case 20: /* SWPB */
1.373 - break;
1.374 - default:
1.375 - UNIMP(ir);
1.376 - }
1.377 - break;
1.378 - case 1:
1.379 - if( LFLAG(ir) ) {
1.380 - /* LDRH */
1.381 - } else {
1.382 - /* STRH */
1.383 - }
1.384 - break;
1.385 - case 2:
1.386 - if( LFLAG(ir) ) {
1.387 - /* LDRSB */
1.388 - } else {
1.389 - UNIMP(ir);
1.390 - }
1.391 - break;
1.392 - case 3:
1.393 - if( LFLAG(ir) ) {
1.394 - /* LDRSH */
1.395 - } else {
1.396 - UNIMP(ir);
1.397 - }
1.398 - break;
1.399 - }
1.400 - } else {
1.401 - /* Data processing */
1.402 -
1.403 - switch(OPCODE(ir)) {
1.404 - case 0: /* AND Rd, Rn, operand */
1.405 - LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
1.406 - break;
1.407 - case 1: /* ANDS Rd, Rn, operand */
1.408 - operand = arm_get_shift_operand_s(ir) & RN(ir);
1.409 - LRD(ir) = operand;
1.410 - if( RDn(ir) == 15 ) {
1.411 - arm_restore_cpsr();
1.412 - } else {
1.413 - armr.n = operand>>31;
1.414 - armr.z = (operand == 0);
1.415 - armr.c = armr.shift_c;
1.416 - }
1.417 - break;
1.418 - case 2: /* EOR Rd, Rn, operand */
1.419 - LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
1.420 - break;
1.421 - case 3: /* EORS Rd, Rn, operand */
1.422 - operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.423 - LRD(ir) = operand;
1.424 - if( RDn(ir) == 15 ) {
1.425 - arm_restore_cpsr();
1.426 - } else {
1.427 - armr.n = operand>>31;
1.428 - armr.z = (operand == 0);
1.429 - armr.c = armr.shift_c;
1.430 - }
1.431 - break;
1.432 - case 4: /* SUB Rd, Rn, operand */
1.433 - LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
1.434 - break;
1.435 - case 5: /* SUBS Rd, Rn, operand */
1.436 - operand = RN(ir);
1.437 - operand2 = arm_get_shift_operand(ir);
1.438 - tmp = operand - operand2;
1.439 - LRD(ir) = tmp;
1.440 - if( RDn(ir) == 15 ) {
1.441 - arm_restore_cpsr();
1.442 - } else {
1.443 - armr.n = tmp>>31;
1.444 - armr.z = (tmp == 0);
1.445 - armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.446 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.447 - }
1.448 - break;
1.449 - case 6: /* RSB Rd, operand, Rn */
1.450 - LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
1.451 - break;
1.452 - case 7: /* RSBS Rd, operand, Rn */
1.453 - operand = arm_get_shift_operand(ir);
1.454 - operand2 = RN(ir);
1.455 - tmp = operand - operand2;
1.456 - LRD(ir) = tmp;
1.457 - if( RDn(ir) == 15 ) {
1.458 - arm_restore_cpsr();
1.459 - } else {
1.460 - armr.n = tmp>>31;
1.461 - armr.z = (tmp == 0);
1.462 - armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.463 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.464 - }
1.465 - break;
1.466 - case 8: /* ADD Rd, Rn, operand */
1.467 - LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
1.468 - break;
1.469 - case 9: /* ADDS Rd, Rn, operand */
1.470 - operand = arm_get_shift_operand(ir);
1.471 - operand2 = RN(ir);
1.472 - tmp = operand + operand2;
1.473 - LRD(ir) = tmp;
1.474 - if( RDn(ir) == 15 ) {
1.475 - arm_restore_cpsr();
1.476 - } else {
1.477 - armr.n = tmp>>31;
1.478 - armr.z = (tmp == 0);
1.479 - armr.c = IS_CARRY(tmp,operand,operand2);
1.480 - armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.481 - }
1.482 - break;
1.483 - case 10: /* ADC */
1.484 - case 11: /* ADCS */
1.485 - case 12: /* SBC */
1.486 - case 13: /* SBCS */
1.487 - case 14: /* RSC */
1.488 - case 15: /* RSCS */
1.489 - break;
1.490 - case 17: /* TST Rn, operand */
1.491 - operand = arm_get_shift_operand_s(ir) & RN(ir);
1.492 - armr.n = operand>>31;
1.493 - armr.z = (operand == 0);
1.494 - armr.c = armr.shift_c;
1.495 - break;
1.496 - case 19: /* TEQ Rn, operand */
1.497 - operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.498 - armr.n = operand>>31;
1.499 - armr.z = (operand == 0);
1.500 - armr.c = armr.shift_c;
1.501 - break;
1.502 - case 21: /* CMP Rn, operand */
1.503 - operand = RN(ir);
1.504 - operand2 = arm_get_shift_operand(ir);
1.505 - tmp = operand - operand2;
1.506 - armr.n = tmp>>31;
1.507 - armr.z = (tmp == 0);
1.508 - armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.509 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.510 - break;
1.511 - case 23: /* CMN Rn, operand */
1.512 - operand = RN(ir);
1.513 - operand2 = arm_get_shift_operand(ir);
1.514 - tmp = operand + operand2;
1.515 - armr.n = tmp>>31;
1.516 - armr.z = (tmp == 0);
1.517 - armr.c = IS_CARRY(tmp,operand,operand2);
1.518 - armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.519 - break;
1.520 - case 24: /* ORR Rd, Rn, operand */
1.521 - LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
1.522 - break;
1.523 - case 25: /* ORRS Rd, Rn, operand */
1.524 - operand = arm_get_shift_operand_s(ir) | RN(ir);
1.525 - LRD(ir) = operand;
1.526 - if( RDn(ir) == 15 ) {
1.527 - arm_restore_cpsr();
1.528 - } else {
1.529 - armr.n = operand>>31;
1.530 - armr.z = (operand == 0);
1.531 - armr.c = armr.shift_c;
1.532 - }
1.533 - break;
1.534 - case 26: /* MOV Rd, operand */
1.535 - LRD(ir) = arm_get_shift_operand(ir);
1.536 - break;
1.537 - case 27: /* MOVS Rd, operand */
1.538 - operand = arm_get_shift_operand_s(ir);
1.539 - LRD(ir) = operand;
1.540 - if( RDn(ir) == 15 ) {
1.541 - arm_restore_cpsr();
1.542 - } else {
1.543 - armr.n = operand>>31;
1.544 - armr.z = (operand == 0);
1.545 - armr.c = armr.shift_c;
1.546 - }
1.547 - break;
1.548 - case 28: /* BIC Rd, Rn, operand */
1.549 - LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
1.550 - break;
1.551 - case 29: /* BICS Rd, Rn, operand */
1.552 - operand = RN(ir) & (~arm_get_shift_operand_s(ir));
1.553 - LRD(ir) = operand;
1.554 - if( RDn(ir) == 15 ) {
1.555 - arm_restore_cpsr();
1.556 - } else {
1.557 - armr.n = operand>>31;
1.558 - armr.z = (operand == 0);
1.559 - armr.c = armr.shift_c;
1.560 - }
1.561 - break;
1.562 - case 30: /* MVN Rd, operand */
1.563 - LRD(ir) = ~arm_get_shift_operand(ir);
1.564 - break;
1.565 - case 31: /* MVNS Rd, operand */
1.566 - operand = ~arm_get_shift_operand_s(ir);
1.567 - LRD(ir) = operand;
1.568 - if( RDn(ir) == 15 ) {
1.569 - arm_restore_cpsr();
1.570 - } else {
1.571 - armr.n = operand>>31;
1.572 - armr.z = (operand == 0);
1.573 - armr.c = armr.shift_c;
1.574 - }
1.575 - break;
1.576 - default:
1.577 - UNIMP(ir);
1.578 - }
1.579 + /**
1.580 + * Condition passed, now for the actual instructions...
1.581 + */
1.582 + switch( GRP(ir) ) {
1.583 + case 0:
1.584 + if( (ir & 0x0D900000) == 0x01000000 ) {
1.585 + /* Instructions that aren't actual data processing even though
1.586 + * they sit in the DP instruction block.
1.587 + */
1.588 + switch( ir & 0x0FF000F0 ) {
1.589 + case 0x01200010: /* BX Rd */
1.590 + armr.t = ir & 0x01;
1.591 + armr.r[15] = RM(ir) & 0xFFFFFFFE;
1.592 + break;
1.593 + case 0x01000000: /* MRS Rd, CPSR */
1.594 + LRD(ir) = arm_get_cpsr();
1.595 + break;
1.596 + case 0x01400000: /* MRS Rd, SPSR */
1.597 + LRD(ir) = armr.spsr;
1.598 + break;
1.599 + case 0x01200000: /* MSR CPSR, Rd */
1.600 + arm_set_cpsr( RM(ir), ir );
1.601 + break;
1.602 + case 0x01600000: /* MSR SPSR, Rd */
1.603 + arm_set_spsr( RM(ir), ir );
1.604 + break;
1.605 + case 0x03200000: /* MSR CPSR, imm */
1.606 + arm_set_cpsr( ROTIMM12(ir), ir );
1.607 + break;
1.608 + case 0x03600000: /* MSR SPSR, imm */
1.609 + arm_set_spsr( ROTIMM12(ir), ir );
1.610 + break;
1.611 + default:
1.612 + UNIMP(ir);
1.613 + }
1.614 + } else if( (ir & 0x0E000090) == 0x00000090 ) {
1.615 + /* Neither are these */
1.616 + switch( (ir>>5)&0x03 ) {
1.617 + case 0:
1.618 + /* Arithmetic extension area */
1.619 + switch(OPCODE(ir)) {
1.620 + case 0: /* MUL */
1.621 + break;
1.622 + case 1: /* MULS */
1.623 + break;
1.624 + case 2: /* MLA */
1.625 + break;
1.626 + case 3: /* MLAS */
1.627 + break;
1.628 + case 8: /* UMULL */
1.629 + break;
1.630 + case 9: /* UMULLS */
1.631 + break;
1.632 + case 10: /* UMLAL */
1.633 + break;
1.634 + case 11: /* UMLALS */
1.635 + break;
1.636 + case 12: /* SMULL */
1.637 + break;
1.638 + case 13: /* SMULLS */
1.639 + break;
1.640 + case 14: /* SMLAL */
1.641 + break;
1.642 + case 15: /* SMLALS */
1.643 + break;
1.644 + case 16: /* SWP */
1.645 + break;
1.646 + case 20: /* SWPB */
1.647 + break;
1.648 + default:
1.649 + UNIMP(ir);
1.650 }
1.651 break;
1.652 - case 1: /* Load/store */
1.653 + case 1:
1.654 + if( LFLAG(ir) ) {
1.655 + /* LDRH */
1.656 + } else {
1.657 + /* STRH */
1.658 + }
1.659 break;
1.660 - case 2: /* Load/store multiple, branch*/
1.661 + case 2:
1.662 + if( LFLAG(ir) ) {
1.663 + /* LDRSB */
1.664 + } else {
1.665 + UNIMP(ir);
1.666 + }
1.667 break;
1.668 - case 3: /* Copro */
1.669 + case 3:
1.670 + if( LFLAG(ir) ) {
1.671 + /* LDRSH */
1.672 + } else {
1.673 + UNIMP(ir);
1.674 + }
1.675 break;
1.676 + }
1.677 + } else {
1.678 + /* Data processing */
1.679 +
1.680 + switch(OPCODE(ir)) {
1.681 + case 0: /* AND Rd, Rn, operand */
1.682 + LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
1.683 + break;
1.684 + case 1: /* ANDS Rd, Rn, operand */
1.685 + operand = arm_get_shift_operand_s(ir) & RN(ir);
1.686 + LRD(ir) = operand;
1.687 + if( RDn(ir) == 15 ) {
1.688 + arm_restore_cpsr();
1.689 + } else {
1.690 + armr.n = operand>>31;
1.691 + armr.z = (operand == 0);
1.692 + armr.c = armr.shift_c;
1.693 + }
1.694 + break;
1.695 + case 2: /* EOR Rd, Rn, operand */
1.696 + LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
1.697 + break;
1.698 + case 3: /* EORS Rd, Rn, operand */
1.699 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.700 + LRD(ir) = operand;
1.701 + if( RDn(ir) == 15 ) {
1.702 + arm_restore_cpsr();
1.703 + } else {
1.704 + armr.n = operand>>31;
1.705 + armr.z = (operand == 0);
1.706 + armr.c = armr.shift_c;
1.707 + }
1.708 + break;
1.709 + case 4: /* SUB Rd, Rn, operand */
1.710 + LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
1.711 + break;
1.712 + case 5: /* SUBS Rd, Rn, operand */
1.713 + operand = RN(ir);
1.714 + operand2 = arm_get_shift_operand(ir);
1.715 + tmp = operand - operand2;
1.716 + LRD(ir) = tmp;
1.717 + if( RDn(ir) == 15 ) {
1.718 + arm_restore_cpsr();
1.719 + } else {
1.720 + armr.n = tmp>>31;
1.721 + armr.z = (tmp == 0);
1.722 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.723 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.724 + }
1.725 + break;
1.726 + case 6: /* RSB Rd, operand, Rn */
1.727 + LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
1.728 + break;
1.729 + case 7: /* RSBS Rd, operand, Rn */
1.730 + operand = arm_get_shift_operand(ir);
1.731 + operand2 = RN(ir);
1.732 + tmp = operand - operand2;
1.733 + LRD(ir) = tmp;
1.734 + if( RDn(ir) == 15 ) {
1.735 + arm_restore_cpsr();
1.736 + } else {
1.737 + armr.n = tmp>>31;
1.738 + armr.z = (tmp == 0);
1.739 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.740 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.741 + }
1.742 + break;
1.743 + case 8: /* ADD Rd, Rn, operand */
1.744 + LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
1.745 + break;
1.746 + case 9: /* ADDS Rd, Rn, operand */
1.747 + operand = arm_get_shift_operand(ir);
1.748 + operand2 = RN(ir);
1.749 + tmp = operand + operand2;
1.750 + LRD(ir) = tmp;
1.751 + if( RDn(ir) == 15 ) {
1.752 + arm_restore_cpsr();
1.753 + } else {
1.754 + armr.n = tmp>>31;
1.755 + armr.z = (tmp == 0);
1.756 + armr.c = IS_CARRY(tmp,operand,operand2);
1.757 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.758 + }
1.759 + break;
1.760 + case 10: /* ADC */
1.761 + case 11: /* ADCS */
1.762 + case 12: /* SBC */
1.763 + case 13: /* SBCS */
1.764 + case 14: /* RSC */
1.765 + case 15: /* RSCS */
1.766 + break;
1.767 + case 17: /* TST Rn, operand */
1.768 + operand = arm_get_shift_operand_s(ir) & RN(ir);
1.769 + armr.n = operand>>31;
1.770 + armr.z = (operand == 0);
1.771 + armr.c = armr.shift_c;
1.772 + break;
1.773 + case 19: /* TEQ Rn, operand */
1.774 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.775 + armr.n = operand>>31;
1.776 + armr.z = (operand == 0);
1.777 + armr.c = armr.shift_c;
1.778 + break;
1.779 + case 21: /* CMP Rn, operand */
1.780 + operand = RN(ir);
1.781 + operand2 = arm_get_shift_operand(ir);
1.782 + tmp = operand - operand2;
1.783 + armr.n = tmp>>31;
1.784 + armr.z = (tmp == 0);
1.785 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.786 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.787 + break;
1.788 + case 23: /* CMN Rn, operand */
1.789 + operand = RN(ir);
1.790 + operand2 = arm_get_shift_operand(ir);
1.791 + tmp = operand + operand2;
1.792 + armr.n = tmp>>31;
1.793 + armr.z = (tmp == 0);
1.794 + armr.c = IS_CARRY(tmp,operand,operand2);
1.795 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.796 + break;
1.797 + case 24: /* ORR Rd, Rn, operand */
1.798 + LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
1.799 + break;
1.800 + case 25: /* ORRS Rd, Rn, operand */
1.801 + operand = arm_get_shift_operand_s(ir) | RN(ir);
1.802 + LRD(ir) = operand;
1.803 + if( RDn(ir) == 15 ) {
1.804 + arm_restore_cpsr();
1.805 + } else {
1.806 + armr.n = operand>>31;
1.807 + armr.z = (operand == 0);
1.808 + armr.c = armr.shift_c;
1.809 + }
1.810 + break;
1.811 + case 26: /* MOV Rd, operand */
1.812 + LRD(ir) = arm_get_shift_operand(ir);
1.813 + break;
1.814 + case 27: /* MOVS Rd, operand */
1.815 + operand = arm_get_shift_operand_s(ir);
1.816 + LRD(ir) = operand;
1.817 + if( RDn(ir) == 15 ) {
1.818 + arm_restore_cpsr();
1.819 + } else {
1.820 + armr.n = operand>>31;
1.821 + armr.z = (operand == 0);
1.822 + armr.c = armr.shift_c;
1.823 + }
1.824 + break;
1.825 + case 28: /* BIC Rd, Rn, operand */
1.826 + LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
1.827 + break;
1.828 + case 29: /* BICS Rd, Rn, operand */
1.829 + operand = RN(ir) & (~arm_get_shift_operand_s(ir));
1.830 + LRD(ir) = operand;
1.831 + if( RDn(ir) == 15 ) {
1.832 + arm_restore_cpsr();
1.833 + } else {
1.834 + armr.n = operand>>31;
1.835 + armr.z = (operand == 0);
1.836 + armr.c = armr.shift_c;
1.837 + }
1.838 + break;
1.839 + case 30: /* MVN Rd, operand */
1.840 + LRD(ir) = ~arm_get_shift_operand(ir);
1.841 + break;
1.842 + case 31: /* MVNS Rd, operand */
1.843 + operand = ~arm_get_shift_operand_s(ir);
1.844 + LRD(ir) = operand;
1.845 + if( RDn(ir) == 15 ) {
1.846 + arm_restore_cpsr();
1.847 + } else {
1.848 + armr.n = operand>>31;
1.849 + armr.z = (operand == 0);
1.850 + armr.c = armr.shift_c;
1.851 + }
1.852 + break;
1.853 + default:
1.854 + UNIMP(ir);
1.855 + }
1.856 }
1.857 - return TRUE;
1.858 + break;
1.859 + case 1: /* Load/store */
1.860 + operand = arm_get_address_operand(ir);
1.861 + switch( (ir>>20)&0x17 ) {
1.862 + case 0: case 16: case 18: /* STR Rd, address */
1.863 + arm_write_long( operand, RD(ir) );
1.864 + break;
1.865 + case 1: case 17: case 19: /* LDR Rd, address */
1.866 + LRD(ir) = arm_read_long(operand);
1.867 + break;
1.868 + case 2: /* STRT Rd, address */
1.869 + arm_write_long_user( operand, RD(ir) );
1.870 + break;
1.871 + case 3: /* LDRT Rd, address */
1.872 + LRD(ir) = arm_read_long_user( operand );
1.873 + break;
1.874 + case 4: case 20: case 22: /* STRB Rd, address */
1.875 + arm_write_byte( operand, RD(ir) );
1.876 + break;
1.877 + case 5: case 21: case 23: /* LDRB Rd, address */
1.878 + LRD(ir) = arm_read_byte( operand );
1.879 + break;
1.880 + case 6: /* STRBT Rd, address */
1.881 + arm_write_byte_user( operand, RD(ir) );
1.882 + break;
1.883 + case 7: /* LDRBT Rd, address */
1.884 + LRD(ir) = arm_read_byte_user( operand );
1.885 + break;
1.886 + }
1.887 + break;
1.888 + case 2: /* Load/store multiple, branch*/
1.889 + if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
1.890 + operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
1.891 + if( (ir & 0x01000000) == 0x01000000 ) {
1.892 + armr.r[14] = pc; /* BL */
1.893 + }
1.894 + armr.r[15] = pc + 4 + operand;
1.895 + } else { /* Load/store multiple */
1.896 + UNIMP(ir);
1.897 + }
1.898 + break;
1.899 + case 3: /* Copro */
1.900 + UNIMP(ir);
1.901 + break;
1.902 + }
1.903 + return TRUE;
1.904 }
.