Search
lxdream.org :: lxdream/src/aica/armcore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 736:a02d1475ccfd
prev642:c7383f21f122
next811:7ff871670e58
author nkeynes
date Sat Jul 19 02:41:30 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Remove built sources from SVN
file annotate diff log raw
1.1 --- a/src/aica/armcore.c Tue Feb 26 01:06:59 2008 +0000
1.2 +++ b/src/aica/armcore.c Sat Jul 19 02:41:30 2008 +0000
1.3 @@ -30,12 +30,12 @@
1.4 void arm_set_mode( int mode );
1.5
1.6 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
1.7 - { MODE_UND, 0x00000004 },
1.8 - { MODE_SVC, 0x00000008 },
1.9 - { MODE_ABT, 0x0000000C },
1.10 - { MODE_ABT, 0x00000010 },
1.11 - { MODE_IRQ, 0x00000018 },
1.12 - { MODE_FIQ, 0x0000001C } };
1.13 + { MODE_UND, 0x00000004 },
1.14 + { MODE_SVC, 0x00000008 },
1.15 + { MODE_ABT, 0x0000000C },
1.16 + { MODE_ABT, 0x00000010 },
1.17 + { MODE_IRQ, 0x00000018 },
1.18 + { MODE_FIQ, 0x0000001C } };
1.19
1.20 #define EXC_RESET 0
1.21 #define EXC_UNDEFINED 1
1.22 @@ -65,15 +65,15 @@
1.23 int i;
1.24
1.25 for( i=0; i<arm_breakpoint_count; i++ ) {
1.26 - if( arm_breakpoints[i].address == pc &&
1.27 - arm_breakpoints[i].type == type ) {
1.28 - while( ++i < arm_breakpoint_count ) {
1.29 - arm_breakpoints[i-1].address = arm_breakpoints[i].address;
1.30 - arm_breakpoints[i-1].type = arm_breakpoints[i].type;
1.31 - }
1.32 - arm_breakpoint_count--;
1.33 - return TRUE;
1.34 - }
1.35 + if( arm_breakpoints[i].address == pc &&
1.36 + arm_breakpoints[i].type == type ) {
1.37 + while( ++i < arm_breakpoint_count ) {
1.38 + arm_breakpoints[i-1].address = arm_breakpoints[i].address;
1.39 + arm_breakpoints[i-1].type = arm_breakpoints[i].type;
1.40 + }
1.41 + arm_breakpoint_count--;
1.42 + return TRUE;
1.43 + }
1.44 }
1.45 return FALSE;
1.46 }
1.47 @@ -82,8 +82,8 @@
1.48 {
1.49 int i;
1.50 for( i=0; i<arm_breakpoint_count; i++ ) {
1.51 - if( arm_breakpoints[i].address == pc )
1.52 - return arm_breakpoints[i].type;
1.53 + if( arm_breakpoints[i].address == pc )
1.54 + return arm_breakpoints[i].type;
1.55 }
1.56 return 0;
1.57 }
1.58 @@ -93,35 +93,35 @@
1.59 int i,j,k;
1.60
1.61 if( !armr.running )
1.62 - return num_samples;
1.63 + return num_samples;
1.64
1.65 for( i=0; i<num_samples; i++ ) {
1.66 - for( j=0; j < CYCLES_PER_SAMPLE; j++ ) {
1.67 - armr.icount++;
1.68 - if( !arm_execute_instruction() )
1.69 - return i;
1.70 + for( j=0; j < CYCLES_PER_SAMPLE; j++ ) {
1.71 + armr.icount++;
1.72 + if( !arm_execute_instruction() )
1.73 + return i;
1.74 #ifdef ENABLE_DEBUG_MODE
1.75 - for( k=0; k<arm_breakpoint_count; k++ ) {
1.76 - if( arm_breakpoints[k].address == armr.r[15] ) {
1.77 - dreamcast_stop();
1.78 - if( arm_breakpoints[k].type == BREAK_ONESHOT )
1.79 - arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );
1.80 - return i;
1.81 - }
1.82 - }
1.83 + for( k=0; k<arm_breakpoint_count; k++ ) {
1.84 + if( arm_breakpoints[k].address == armr.r[15] ) {
1.85 + dreamcast_stop();
1.86 + if( arm_breakpoints[k].type == BREAK_ONESHOT )
1.87 + arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );
1.88 + return i;
1.89 + }
1.90 + }
1.91 #endif
1.92 - }
1.93 -
1.94 - k = MMIO_READ( AICA2, AICA_TCR );
1.95 - uint8_t val = MMIO_READ( AICA2, AICA_TIMER );
1.96 - val++;
1.97 - if( val == 0 ) {
1.98 - aica_event( AICA_EVENT_TIMER );
1.99 - // MMIO_WRITE( AICA2, AICA_TCR, k & ~0x40 );
1.100 - }
1.101 - MMIO_WRITE( AICA2, AICA_TIMER, val );
1.102 - if( !dreamcast_is_running() )
1.103 - break;
1.104 + }
1.105 +
1.106 + k = MMIO_READ( AICA2, AICA_TCR );
1.107 + uint8_t val = MMIO_READ( AICA2, AICA_TIMER );
1.108 + val++;
1.109 + if( val == 0 ) {
1.110 + aica_event( AICA_EVENT_TIMER );
1.111 + // MMIO_WRITE( AICA2, AICA_TCR, k & ~0x40 );
1.112 + }
1.113 + MMIO_WRITE( AICA2, AICA_TIMER, val );
1.114 + if( !dreamcast_is_running() )
1.115 + break;
1.116 }
1.117
1.118 return i;
1.119 @@ -173,12 +173,12 @@
1.120 static uint32_t *arm_user_reg( int reg )
1.121 {
1.122 if( IS_EXCEPTION_MODE() ) {
1.123 - if( reg == 13 || reg == 14 )
1.124 - return &armr.user_r[reg-8];
1.125 - if( IS_FIQ_MODE() ) {
1.126 - if( reg >= 8 || reg <= 12 )
1.127 - return &armr.user_r[reg-8];
1.128 - }
1.129 + if( reg == 13 || reg == 14 )
1.130 + return &armr.user_r[reg-8];
1.131 + if( IS_FIQ_MODE() ) {
1.132 + if( reg >= 8 || reg <= 12 )
1.133 + return &armr.user_r[reg-8];
1.134 + }
1.135 }
1.136 return &armr.r[reg];
1.137 }
1.138 @@ -195,23 +195,23 @@
1.139 void arm_set_cpsr( uint32_t value, uint32_t fields )
1.140 {
1.141 if( IS_PRIVILEGED_MODE() ) {
1.142 - if( fields & SET_CPSR_CONTROL ) {
1.143 - int mode = value & CPSR_MODE;
1.144 - arm_set_mode( mode );
1.145 - armr.t = ( value & CPSR_T ); /* Technically illegal to change */
1.146 - armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
1.147 - }
1.148 + if( fields & SET_CPSR_CONTROL ) {
1.149 + int mode = value & CPSR_MODE;
1.150 + arm_set_mode( mode );
1.151 + armr.t = ( value & CPSR_T ); /* Technically illegal to change */
1.152 + armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
1.153 + }
1.154
1.155 - /* Middle 16 bits not currently defined */
1.156 + /* Middle 16 bits not currently defined */
1.157 }
1.158 if( fields & SET_CPSR_FLAGS ) {
1.159 - /* Break flags directly out of given value - don't bother writing
1.160 - * back to CPSR
1.161 - */
1.162 - armr.n = ( value & CPSR_N );
1.163 - armr.z = ( value & CPSR_Z );
1.164 - armr.c = ( value & CPSR_C );
1.165 - armr.v = ( value & CPSR_V );
1.166 + /* Break flags directly out of given value - don't bother writing
1.167 + * back to CPSR
1.168 + */
1.169 + armr.n = ( value & CPSR_N );
1.170 + armr.z = ( value & CPSR_Z );
1.171 + armr.c = ( value & CPSR_C );
1.172 + armr.v = ( value & CPSR_V );
1.173 }
1.174 }
1.175
1.176 @@ -219,15 +219,15 @@
1.177 {
1.178 /* Only defined if we actually have an SPSR register */
1.179 if( IS_EXCEPTION_MODE() ) {
1.180 - if( fields & SET_CPSR_CONTROL ) {
1.181 - armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
1.182 - }
1.183 + if( fields & SET_CPSR_CONTROL ) {
1.184 + armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
1.185 + }
1.186
1.187 - /* Middle 16 bits not currently defined */
1.188 + /* Middle 16 bits not currently defined */
1.189
1.190 - if( fields & SET_CPSR_FLAGS ) {
1.191 - armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
1.192 - }
1.193 + if( fields & SET_CPSR_FLAGS ) {
1.194 + armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
1.195 + }
1.196 }
1.197 }
1.198
1.199 @@ -244,7 +244,7 @@
1.200 armr.r[14] = armr.r[15] + 4;
1.201 armr.cpsr = (spsr & 0xFFFFFF00) | mode | CPSR_I;
1.202 if( mode == MODE_FIQ )
1.203 - armr.cpsr |= CPSR_F;
1.204 + armr.cpsr |= CPSR_F;
1.205 armr.r[15] = arm_exceptions[exception][1];
1.206 }
1.207
1.208 @@ -272,92 +272,92 @@
1.209 {
1.210 int currentMode = armr.cpsr & CPSR_MODE;
1.211 if( currentMode == targetMode )
1.212 - return;
1.213 + return;
1.214
1.215 switch( currentMode ) {
1.216 case MODE_USER:
1.217 case MODE_SYS:
1.218 - armr.user_r[5] = armr.r[13];
1.219 - armr.user_r[6] = armr.r[14];
1.220 - break;
1.221 + armr.user_r[5] = armr.r[13];
1.222 + armr.user_r[6] = armr.r[14];
1.223 + break;
1.224 case MODE_SVC:
1.225 - armr.svc_r[0] = armr.r[13];
1.226 - armr.svc_r[1] = armr.r[14];
1.227 - armr.svc_r[2] = armr.spsr;
1.228 - break;
1.229 + armr.svc_r[0] = armr.r[13];
1.230 + armr.svc_r[1] = armr.r[14];
1.231 + armr.svc_r[2] = armr.spsr;
1.232 + break;
1.233 case MODE_ABT:
1.234 - armr.abt_r[0] = armr.r[13];
1.235 - armr.abt_r[1] = armr.r[14];
1.236 - armr.abt_r[2] = armr.spsr;
1.237 - break;
1.238 + armr.abt_r[0] = armr.r[13];
1.239 + armr.abt_r[1] = armr.r[14];
1.240 + armr.abt_r[2] = armr.spsr;
1.241 + break;
1.242 case MODE_UND:
1.243 - armr.und_r[0] = armr.r[13];
1.244 - armr.und_r[1] = armr.r[14];
1.245 - armr.und_r[2] = armr.spsr;
1.246 - break;
1.247 + armr.und_r[0] = armr.r[13];
1.248 + armr.und_r[1] = armr.r[14];
1.249 + armr.und_r[2] = armr.spsr;
1.250 + break;
1.251 case MODE_IRQ:
1.252 - armr.irq_r[0] = armr.r[13];
1.253 - armr.irq_r[1] = armr.r[14];
1.254 - armr.irq_r[2] = armr.spsr;
1.255 - break;
1.256 + armr.irq_r[0] = armr.r[13];
1.257 + armr.irq_r[1] = armr.r[14];
1.258 + armr.irq_r[2] = armr.spsr;
1.259 + break;
1.260 case MODE_FIQ:
1.261 - armr.fiq_r[0] = armr.r[8];
1.262 - armr.fiq_r[1] = armr.r[9];
1.263 - armr.fiq_r[2] = armr.r[10];
1.264 - armr.fiq_r[3] = armr.r[11];
1.265 - armr.fiq_r[4] = armr.r[12];
1.266 - armr.fiq_r[5] = armr.r[13];
1.267 - armr.fiq_r[6] = armr.r[14];
1.268 - armr.fiq_r[7] = armr.spsr;
1.269 - armr.r[8] = armr.user_r[0];
1.270 - armr.r[9] = armr.user_r[1];
1.271 - armr.r[10] = armr.user_r[2];
1.272 - armr.r[11] = armr.user_r[3];
1.273 - armr.r[12] = armr.user_r[4];
1.274 - break;
1.275 + armr.fiq_r[0] = armr.r[8];
1.276 + armr.fiq_r[1] = armr.r[9];
1.277 + armr.fiq_r[2] = armr.r[10];
1.278 + armr.fiq_r[3] = armr.r[11];
1.279 + armr.fiq_r[4] = armr.r[12];
1.280 + armr.fiq_r[5] = armr.r[13];
1.281 + armr.fiq_r[6] = armr.r[14];
1.282 + armr.fiq_r[7] = armr.spsr;
1.283 + armr.r[8] = armr.user_r[0];
1.284 + armr.r[9] = armr.user_r[1];
1.285 + armr.r[10] = armr.user_r[2];
1.286 + armr.r[11] = armr.user_r[3];
1.287 + armr.r[12] = armr.user_r[4];
1.288 + break;
1.289 }
1.290 -
1.291 +
1.292 switch( targetMode ) {
1.293 case MODE_USER:
1.294 case MODE_SYS:
1.295 - armr.r[13] = armr.user_r[5];
1.296 - armr.r[14] = armr.user_r[6];
1.297 - break;
1.298 + armr.r[13] = armr.user_r[5];
1.299 + armr.r[14] = armr.user_r[6];
1.300 + break;
1.301 case MODE_SVC:
1.302 - armr.r[13] = armr.svc_r[0];
1.303 - armr.r[14] = armr.svc_r[1];
1.304 - armr.spsr = armr.svc_r[2];
1.305 - break;
1.306 + armr.r[13] = armr.svc_r[0];
1.307 + armr.r[14] = armr.svc_r[1];
1.308 + armr.spsr = armr.svc_r[2];
1.309 + break;
1.310 case MODE_ABT:
1.311 - armr.r[13] = armr.abt_r[0];
1.312 - armr.r[14] = armr.abt_r[1];
1.313 - armr.spsr = armr.abt_r[2];
1.314 - break;
1.315 + armr.r[13] = armr.abt_r[0];
1.316 + armr.r[14] = armr.abt_r[1];
1.317 + armr.spsr = armr.abt_r[2];
1.318 + break;
1.319 case MODE_UND:
1.320 - armr.r[13] = armr.und_r[0];
1.321 - armr.r[14] = armr.und_r[1];
1.322 - armr.spsr = armr.und_r[2];
1.323 - break;
1.324 + armr.r[13] = armr.und_r[0];
1.325 + armr.r[14] = armr.und_r[1];
1.326 + armr.spsr = armr.und_r[2];
1.327 + break;
1.328 case MODE_IRQ:
1.329 - armr.r[13] = armr.irq_r[0];
1.330 - armr.r[14] = armr.irq_r[1];
1.331 - armr.spsr = armr.irq_r[2];
1.332 - break;
1.333 + armr.r[13] = armr.irq_r[0];
1.334 + armr.r[14] = armr.irq_r[1];
1.335 + armr.spsr = armr.irq_r[2];
1.336 + break;
1.337 case MODE_FIQ:
1.338 - armr.user_r[0] = armr.r[8];
1.339 - armr.user_r[1] = armr.r[9];
1.340 - armr.user_r[2] = armr.r[10];
1.341 - armr.user_r[3] = armr.r[11];
1.342 - armr.user_r[4] = armr.r[12];
1.343 - armr.r[8] = armr.fiq_r[0];
1.344 - armr.r[9] = armr.fiq_r[1];
1.345 - armr.r[10] = armr.fiq_r[2];
1.346 - armr.r[11] = armr.fiq_r[3];
1.347 - armr.r[12] = armr.fiq_r[4];
1.348 - armr.r[13] = armr.fiq_r[5];
1.349 - armr.r[14] = armr.fiq_r[6];
1.350 - armr.spsr = armr.fiq_r[7];
1.351 - break;
1.352 + armr.user_r[0] = armr.r[8];
1.353 + armr.user_r[1] = armr.r[9];
1.354 + armr.user_r[2] = armr.r[10];
1.355 + armr.user_r[3] = armr.r[11];
1.356 + armr.user_r[4] = armr.r[12];
1.357 + armr.r[8] = armr.fiq_r[0];
1.358 + armr.r[9] = armr.fiq_r[1];
1.359 + armr.r[10] = armr.fiq_r[2];
1.360 + armr.r[11] = armr.fiq_r[3];
1.361 + armr.r[12] = armr.fiq_r[4];
1.362 + armr.r[13] = armr.fiq_r[5];
1.363 + armr.r[14] = armr.fiq_r[6];
1.364 + armr.spsr = armr.fiq_r[7];
1.365 + break;
1.366 }
1.367 }
1.368
1.369 @@ -418,54 +418,54 @@
1.370 */
1.371 static uint32_t arm_get_shift_operand( uint32_t ir )
1.372 {
1.373 - uint32_t operand, tmp;
1.374 - if( IFLAG(ir) == 0 ) {
1.375 - operand = RM(ir);
1.376 - switch(SHIFT(ir)) {
1.377 - case 0: /* (Rm << imm) */
1.378 - operand = operand << SHIFTIMM(ir);
1.379 - break;
1.380 - case 1: /* (Rm << Rs) */
1.381 - tmp = RS(ir)&0xFF;
1.382 - if( tmp > 31 ) operand = 0;
1.383 - else operand = operand << tmp;
1.384 - break;
1.385 - case 2: /* (Rm >> imm) */
1.386 - operand = operand >> SHIFTIMM(ir);
1.387 - break;
1.388 - case 3: /* (Rm >> Rs) */
1.389 - tmp = RS(ir) & 0xFF;
1.390 - if( tmp > 31 ) operand = 0;
1.391 - else operand = operand >> ir;
1.392 - break;
1.393 - case 4: /* (Rm >>> imm) */
1.394 - tmp = SHIFTIMM(ir);
1.395 - if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
1.396 - else operand = ((int32_t)operand) >> tmp;
1.397 - break;
1.398 - case 5: /* (Rm >>> Rs) */
1.399 - tmp = RS(ir) & 0xFF;
1.400 - if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
1.401 - else operand = ((int32_t)operand) >> tmp;
1.402 - break;
1.403 - case 6:
1.404 - tmp = SHIFTIMM(ir);
1.405 - if( tmp == 0 ) /* RRX aka rotate with carry */
1.406 - operand = (operand >> 1) | (armr.c<<31);
1.407 - else
1.408 - operand = ROTATE_RIGHT_LONG(operand,tmp);
1.409 - break;
1.410 - case 7:
1.411 - tmp = RS(ir)&0x1F;
1.412 - operand = ROTATE_RIGHT_LONG(operand,tmp);
1.413 - break;
1.414 - }
1.415 - } else {
1.416 - operand = IMM8(ir);
1.417 - tmp = IMMROT(ir);
1.418 - operand = ROTATE_RIGHT_LONG(operand, tmp);
1.419 - }
1.420 - return operand;
1.421 + uint32_t operand, tmp;
1.422 + if( IFLAG(ir) == 0 ) {
1.423 + operand = RM(ir);
1.424 + switch(SHIFT(ir)) {
1.425 + case 0: /* (Rm << imm) */
1.426 + operand = operand << SHIFTIMM(ir);
1.427 + break;
1.428 + case 1: /* (Rm << Rs) */
1.429 + tmp = RS(ir)&0xFF;
1.430 + if( tmp > 31 ) operand = 0;
1.431 + else operand = operand << tmp;
1.432 + break;
1.433 + case 2: /* (Rm >> imm) */
1.434 + operand = operand >> SHIFTIMM(ir);
1.435 + break;
1.436 + case 3: /* (Rm >> Rs) */
1.437 + tmp = RS(ir) & 0xFF;
1.438 + if( tmp > 31 ) operand = 0;
1.439 + else operand = operand >> ir;
1.440 + break;
1.441 + case 4: /* (Rm >>> imm) */
1.442 + tmp = SHIFTIMM(ir);
1.443 + if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
1.444 + else operand = ((int32_t)operand) >> tmp;
1.445 + break;
1.446 + case 5: /* (Rm >>> Rs) */
1.447 + tmp = RS(ir) & 0xFF;
1.448 + if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
1.449 + else operand = ((int32_t)operand) >> tmp;
1.450 + break;
1.451 + case 6:
1.452 + tmp = SHIFTIMM(ir);
1.453 + if( tmp == 0 ) /* RRX aka rotate with carry */
1.454 + operand = (operand >> 1) | (armr.c<<31);
1.455 + else
1.456 + operand = ROTATE_RIGHT_LONG(operand,tmp);
1.457 + break;
1.458 + case 7:
1.459 + tmp = RS(ir)&0x1F;
1.460 + operand = ROTATE_RIGHT_LONG(operand,tmp);
1.461 + break;
1.462 + }
1.463 + } else {
1.464 + operand = IMM8(ir);
1.465 + tmp = IMMROT(ir);
1.466 + operand = ROTATE_RIGHT_LONG(operand, tmp);
1.467 + }
1.468 + return operand;
1.469 }
1.470
1.471 /**
1.472 @@ -475,115 +475,115 @@
1.473 */
1.474 static uint32_t arm_get_shift_operand_s( uint32_t ir )
1.475 {
1.476 - uint32_t operand, tmp;
1.477 - if( IFLAG(ir) == 0 ) {
1.478 - operand = RM(ir);
1.479 - switch(SHIFT(ir)) {
1.480 - case 0: /* (Rm << imm) */
1.481 - tmp = SHIFTIMM(ir);
1.482 - if( tmp == 0 ) { /* Rm */
1.483 - armr.shift_c = armr.c;
1.484 - } else { /* Rm << imm */
1.485 - armr.shift_c = (operand >> (32-tmp)) & 0x01;
1.486 - operand = operand << tmp;
1.487 - }
1.488 - break;
1.489 - case 1: /* (Rm << Rs) */
1.490 - tmp = RS(ir)&0xFF;
1.491 - if( tmp == 0 ) {
1.492 - armr.shift_c = armr.c;
1.493 - } else {
1.494 - if( tmp <= 32 )
1.495 - armr.shift_c = (operand >> (32-tmp)) & 0x01;
1.496 - else armr.shift_c = 0;
1.497 - if( tmp < 32 )
1.498 - operand = operand << tmp;
1.499 - else operand = 0;
1.500 - }
1.501 - break;
1.502 - case 2: /* (Rm >> imm) */
1.503 - tmp = SHIFTIMM(ir);
1.504 - if( tmp == 0 ) {
1.505 - armr.shift_c = operand >> 31;
1.506 - operand = 0;
1.507 - } else {
1.508 - armr.shift_c = (operand >> (tmp-1)) & 0x01;
1.509 - operand = RM(ir) >> tmp;
1.510 - }
1.511 - break;
1.512 - case 3: /* (Rm >> Rs) */
1.513 - tmp = RS(ir) & 0xFF;
1.514 - if( tmp == 0 ) {
1.515 - armr.shift_c = armr.c;
1.516 - } else {
1.517 - if( tmp <= 32 )
1.518 - armr.shift_c = (operand >> (tmp-1))&0x01;
1.519 - else armr.shift_c = 0;
1.520 - if( tmp < 32 )
1.521 - operand = operand >> tmp;
1.522 - else operand = 0;
1.523 - }
1.524 - break;
1.525 - case 4: /* (Rm >>> imm) */
1.526 - tmp = SHIFTIMM(ir);
1.527 - if( tmp == 0 ) {
1.528 - armr.shift_c = operand >> 31;
1.529 - operand = -armr.shift_c;
1.530 - } else {
1.531 - armr.shift_c = (operand >> (tmp-1)) & 0x01;
1.532 - operand = ((int32_t)operand) >> tmp;
1.533 - }
1.534 - break;
1.535 - case 5: /* (Rm >>> Rs) */
1.536 - tmp = RS(ir) & 0xFF;
1.537 - if( tmp == 0 ) {
1.538 - armr.shift_c = armr.c;
1.539 - } else {
1.540 - if( tmp < 32 ) {
1.541 - armr.shift_c = (operand >> (tmp-1))&0x01;
1.542 - operand = ((int32_t)operand) >> tmp;
1.543 - } else {
1.544 - armr.shift_c = operand >> 31;
1.545 - operand = ((int32_t)operand) >> 31;
1.546 - }
1.547 - }
1.548 - break;
1.549 - case 6:
1.550 - tmp = SHIFTIMM(ir);
1.551 - if( tmp == 0 ) { /* RRX aka rotate with carry */
1.552 - armr.shift_c = operand&0x01;
1.553 - operand = (operand >> 1) | (armr.c<<31);
1.554 - } else {
1.555 - armr.shift_c = operand>>(tmp-1);
1.556 - operand = ROTATE_RIGHT_LONG(operand,tmp);
1.557 - }
1.558 - break;
1.559 - case 7:
1.560 - tmp = RS(ir)&0xFF;
1.561 - if( tmp == 0 ) {
1.562 - armr.shift_c = armr.c;
1.563 - } else {
1.564 - tmp &= 0x1F;
1.565 - if( tmp == 0 ) {
1.566 - armr.shift_c = operand>>31;
1.567 - } else {
1.568 - armr.shift_c = (operand>>(tmp-1))&0x1;
1.569 - operand = ROTATE_RIGHT_LONG(operand,tmp);
1.570 - }
1.571 - }
1.572 - break;
1.573 - }
1.574 - } else {
1.575 - operand = IMM8(ir);
1.576 - tmp = IMMROT(ir);
1.577 - if( tmp == 0 ) {
1.578 - armr.shift_c = armr.c;
1.579 - } else {
1.580 - operand = ROTATE_RIGHT_LONG(operand, tmp);
1.581 - armr.shift_c = operand>>31;
1.582 - }
1.583 - }
1.584 - return operand;
1.585 + uint32_t operand, tmp;
1.586 + if( IFLAG(ir) == 0 ) {
1.587 + operand = RM(ir);
1.588 + switch(SHIFT(ir)) {
1.589 + case 0: /* (Rm << imm) */
1.590 + tmp = SHIFTIMM(ir);
1.591 + if( tmp == 0 ) { /* Rm */
1.592 + armr.shift_c = armr.c;
1.593 + } else { /* Rm << imm */
1.594 + armr.shift_c = (operand >> (32-tmp)) & 0x01;
1.595 + operand = operand << tmp;
1.596 + }
1.597 + break;
1.598 + case 1: /* (Rm << Rs) */
1.599 + tmp = RS(ir)&0xFF;
1.600 + if( tmp == 0 ) {
1.601 + armr.shift_c = armr.c;
1.602 + } else {
1.603 + if( tmp <= 32 )
1.604 + armr.shift_c = (operand >> (32-tmp)) & 0x01;
1.605 + else armr.shift_c = 0;
1.606 + if( tmp < 32 )
1.607 + operand = operand << tmp;
1.608 + else operand = 0;
1.609 + }
1.610 + break;
1.611 + case 2: /* (Rm >> imm) */
1.612 + tmp = SHIFTIMM(ir);
1.613 + if( tmp == 0 ) {
1.614 + armr.shift_c = operand >> 31;
1.615 + operand = 0;
1.616 + } else {
1.617 + armr.shift_c = (operand >> (tmp-1)) & 0x01;
1.618 + operand = RM(ir) >> tmp;
1.619 + }
1.620 + break;
1.621 + case 3: /* (Rm >> Rs) */
1.622 + tmp = RS(ir) & 0xFF;
1.623 + if( tmp == 0 ) {
1.624 + armr.shift_c = armr.c;
1.625 + } else {
1.626 + if( tmp <= 32 )
1.627 + armr.shift_c = (operand >> (tmp-1))&0x01;
1.628 + else armr.shift_c = 0;
1.629 + if( tmp < 32 )
1.630 + operand = operand >> tmp;
1.631 + else operand = 0;
1.632 + }
1.633 + break;
1.634 + case 4: /* (Rm >>> imm) */
1.635 + tmp = SHIFTIMM(ir);
1.636 + if( tmp == 0 ) {
1.637 + armr.shift_c = operand >> 31;
1.638 + operand = -armr.shift_c;
1.639 + } else {
1.640 + armr.shift_c = (operand >> (tmp-1)) & 0x01;
1.641 + operand = ((int32_t)operand) >> tmp;
1.642 + }
1.643 + break;
1.644 + case 5: /* (Rm >>> Rs) */
1.645 + tmp = RS(ir) & 0xFF;
1.646 + if( tmp == 0 ) {
1.647 + armr.shift_c = armr.c;
1.648 + } else {
1.649 + if( tmp < 32 ) {
1.650 + armr.shift_c = (operand >> (tmp-1))&0x01;
1.651 + operand = ((int32_t)operand) >> tmp;
1.652 + } else {
1.653 + armr.shift_c = operand >> 31;
1.654 + operand = ((int32_t)operand) >> 31;
1.655 + }
1.656 + }
1.657 + break;
1.658 + case 6:
1.659 + tmp = SHIFTIMM(ir);
1.660 + if( tmp == 0 ) { /* RRX aka rotate with carry */
1.661 + armr.shift_c = operand&0x01;
1.662 + operand = (operand >> 1) | (armr.c<<31);
1.663 + } else {
1.664 + armr.shift_c = operand>>(tmp-1);
1.665 + operand = ROTATE_RIGHT_LONG(operand,tmp);
1.666 + }
1.667 + break;
1.668 + case 7:
1.669 + tmp = RS(ir)&0xFF;
1.670 + if( tmp == 0 ) {
1.671 + armr.shift_c = armr.c;
1.672 + } else {
1.673 + tmp &= 0x1F;
1.674 + if( tmp == 0 ) {
1.675 + armr.shift_c = operand>>31;
1.676 + } else {
1.677 + armr.shift_c = (operand>>(tmp-1))&0x1;
1.678 + operand = ROTATE_RIGHT_LONG(operand,tmp);
1.679 + }
1.680 + }
1.681 + break;
1.682 + }
1.683 + } else {
1.684 + operand = IMM8(ir);
1.685 + tmp = IMMROT(ir);
1.686 + if( tmp == 0 ) {
1.687 + armr.shift_c = armr.c;
1.688 + } else {
1.689 + operand = ROTATE_RIGHT_LONG(operand, tmp);
1.690 + armr.shift_c = operand>>31;
1.691 + }
1.692 + }
1.693 + return operand;
1.694 }
1.695
1.696 /**
1.697 @@ -595,31 +595,31 @@
1.698 */
1.699 static uint32_t arm_get_address_index( uint32_t ir )
1.700 {
1.701 - uint32_t operand = RM(ir);
1.702 - uint32_t tmp;
1.703 -
1.704 - switch(SHIFT(ir)) {
1.705 - case 0: /* (Rm << imm) */
1.706 - operand = operand << SHIFTIMM(ir);
1.707 - break;
1.708 - case 2: /* (Rm >> imm) */
1.709 - operand = operand >> SHIFTIMM(ir);
1.710 - break;
1.711 - case 4: /* (Rm >>> imm) */
1.712 - tmp = SHIFTIMM(ir);
1.713 - if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
1.714 - else operand = ((int32_t)operand) >> tmp;
1.715 - break;
1.716 - case 6:
1.717 - tmp = SHIFTIMM(ir);
1.718 - if( tmp == 0 ) /* RRX aka rotate with carry */
1.719 - operand = (operand >> 1) | (armr.c<<31);
1.720 - else
1.721 - operand = ROTATE_RIGHT_LONG(operand,tmp);
1.722 - break;
1.723 - default: UNIMP(ir);
1.724 - }
1.725 - return operand;
1.726 + uint32_t operand = RM(ir);
1.727 + uint32_t tmp;
1.728 +
1.729 + switch(SHIFT(ir)) {
1.730 + case 0: /* (Rm << imm) */
1.731 + operand = operand << SHIFTIMM(ir);
1.732 + break;
1.733 + case 2: /* (Rm >> imm) */
1.734 + operand = operand >> SHIFTIMM(ir);
1.735 + break;
1.736 + case 4: /* (Rm >>> imm) */
1.737 + tmp = SHIFTIMM(ir);
1.738 + if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
1.739 + else operand = ((int32_t)operand) >> tmp;
1.740 + break;
1.741 + case 6:
1.742 + tmp = SHIFTIMM(ir);
1.743 + if( tmp == 0 ) /* RRX aka rotate with carry */
1.744 + operand = (operand >> 1) | (armr.c<<31);
1.745 + else
1.746 + operand = ROTATE_RIGHT_LONG(operand,tmp);
1.747 + break;
1.748 + default: UNIMP(ir);
1.749 + }
1.750 + return operand;
1.751 }
1.752
1.753 /**
1.754 @@ -631,60 +631,60 @@
1.755 */
1.756 static uint32_t arm_get_address_operand( uint32_t ir )
1.757 {
1.758 - uint32_t addr=0;
1.759 -
1.760 - /* I P U . W */
1.761 - switch( (ir>>21)&0x1D ) {
1.762 - case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
1.763 - case 1:
1.764 - addr = RN(ir);
1.765 - LRN(ir) = addr - IMM12(ir);
1.766 - break;
1.767 - case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
1.768 - case 5:
1.769 - addr = RN(ir);
1.770 - LRN(ir) = addr + IMM12(ir);
1.771 - break;
1.772 - case 8: /* Rn - imm offset [5.2.2 A5-20] */
1.773 - addr = RN(ir) - IMM12(ir);
1.774 - break;
1.775 - case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
1.776 - addr = RN(ir) - IMM12(ir);
1.777 - LRN(ir) = addr;
1.778 - break;
1.779 - case 12: /* Rn + imm offset [5.2.2 A5-20] */
1.780 - addr = RN(ir) + IMM12(ir);
1.781 - break;
1.782 - case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
1.783 - addr = RN(ir) + IMM12(ir);
1.784 - LRN(ir) = addr;
1.785 - break;
1.786 - case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
1.787 - case 17:
1.788 - addr = RN(ir);
1.789 - LRN(ir) = addr - arm_get_address_index(ir);
1.790 - break;
1.791 - case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
1.792 - case 21:
1.793 - addr = RN(ir);
1.794 - LRN(ir) = addr - arm_get_address_index(ir);
1.795 - break;
1.796 - case 24: /* Rn - Rm [5.2.4 A5-23] */
1.797 - addr = RN(ir) - arm_get_address_index(ir);
1.798 - break;
1.799 - case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
1.800 - addr = RN(ir) - arm_get_address_index(ir);
1.801 - LRN(ir) = addr;
1.802 - break;
1.803 - case 28: /* Rn + Rm [5.2.4 A5-23] */
1.804 - addr = RN(ir) + arm_get_address_index(ir);
1.805 - break;
1.806 - case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
1.807 - addr = RN(ir) + arm_get_address_index(ir);
1.808 - LRN(ir) = addr;
1.809 - break;
1.810 - }
1.811 - return addr;
1.812 + uint32_t addr=0;
1.813 +
1.814 + /* I P U . W */
1.815 + switch( (ir>>21)&0x1D ) {
1.816 + case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
1.817 + case 1:
1.818 + addr = RN(ir);
1.819 + LRN(ir) = addr - IMM12(ir);
1.820 + break;
1.821 + case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
1.822 + case 5:
1.823 + addr = RN(ir);
1.824 + LRN(ir) = addr + IMM12(ir);
1.825 + break;
1.826 + case 8: /* Rn - imm offset [5.2.2 A5-20] */
1.827 + addr = RN(ir) - IMM12(ir);
1.828 + break;
1.829 + case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
1.830 + addr = RN(ir) - IMM12(ir);
1.831 + LRN(ir) = addr;
1.832 + break;
1.833 + case 12: /* Rn + imm offset [5.2.2 A5-20] */
1.834 + addr = RN(ir) + IMM12(ir);
1.835 + break;
1.836 + case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
1.837 + addr = RN(ir) + IMM12(ir);
1.838 + LRN(ir) = addr;
1.839 + break;
1.840 + case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
1.841 + case 17:
1.842 + addr = RN(ir);
1.843 + LRN(ir) = addr - arm_get_address_index(ir);
1.844 + break;
1.845 + case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
1.846 + case 21:
1.847 + addr = RN(ir);
1.848 + LRN(ir) = addr - arm_get_address_index(ir);
1.849 + break;
1.850 + case 24: /* Rn - Rm [5.2.4 A5-23] */
1.851 + addr = RN(ir) - arm_get_address_index(ir);
1.852 + break;
1.853 + case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
1.854 + addr = RN(ir) - arm_get_address_index(ir);
1.855 + LRN(ir) = addr;
1.856 + break;
1.857 + case 28: /* Rn + Rm [5.2.4 A5-23] */
1.858 + addr = RN(ir) + arm_get_address_index(ir);
1.859 + break;
1.860 + case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
1.861 + addr = RN(ir) + arm_get_address_index(ir);
1.862 + LRN(ir) = addr;
1.863 + break;
1.864 + }
1.865 + return addr;
1.866 }
1.867
1.868 gboolean arm_execute_instruction( void )
1.869 @@ -696,11 +696,11 @@
1.870
1.871 tmp = armr.int_pending & (~armr.cpsr);
1.872 if( tmp ) {
1.873 - if( tmp & CPSR_F ) {
1.874 - arm_raise_exception( EXC_FAST_IRQ );
1.875 - } else {
1.876 - arm_raise_exception( EXC_IRQ );
1.877 - }
1.878 + if( tmp & CPSR_F ) {
1.879 + arm_raise_exception( EXC_FAST_IRQ );
1.880 + } else {
1.881 + arm_raise_exception( EXC_IRQ );
1.882 + }
1.883 }
1.884
1.885 ir = MEM_READ_LONG(PC);
1.886 @@ -713,673 +713,673 @@
1.887 */
1.888 switch( COND(ir) ) {
1.889 case 0: /* EQ */
1.890 - cond = armr.z;
1.891 - break;
1.892 + cond = armr.z;
1.893 + break;
1.894 case 1: /* NE */
1.895 - cond = !armr.z;
1.896 - break;
1.897 + cond = !armr.z;
1.898 + break;
1.899 case 2: /* CS/HS */
1.900 - cond = armr.c;
1.901 - break;
1.902 + cond = armr.c;
1.903 + break;
1.904 case 3: /* CC/LO */
1.905 - cond = !armr.c;
1.906 - break;
1.907 + cond = !armr.c;
1.908 + break;
1.909 case 4: /* MI */
1.910 - cond = armr.n;
1.911 - break;
1.912 + cond = armr.n;
1.913 + break;
1.914 case 5: /* PL */
1.915 - cond = !armr.n;
1.916 - break;
1.917 + cond = !armr.n;
1.918 + break;
1.919 case 6: /* VS */
1.920 - cond = armr.v;
1.921 - break;
1.922 + cond = armr.v;
1.923 + break;
1.924 case 7: /* VC */
1.925 - cond = !armr.v;
1.926 - break;
1.927 + cond = !armr.v;
1.928 + break;
1.929 case 8: /* HI */
1.930 - cond = armr.c && !armr.z;
1.931 - break;
1.932 + cond = armr.c && !armr.z;
1.933 + break;
1.934 case 9: /* LS */
1.935 - cond = (!armr.c) || armr.z;
1.936 - break;
1.937 + cond = (!armr.c) || armr.z;
1.938 + break;
1.939 case 10: /* GE */
1.940 - cond = (armr.n == armr.v);
1.941 - break;
1.942 + cond = (armr.n == armr.v);
1.943 + break;
1.944 case 11: /* LT */
1.945 - cond = (armr.n != armr.v);
1.946 - break;
1.947 + cond = (armr.n != armr.v);
1.948 + break;
1.949 case 12: /* GT */
1.950 - cond = (!armr.z) && (armr.n == armr.v);
1.951 - break;
1.952 + cond = (!armr.z) && (armr.n == armr.v);
1.953 + break;
1.954 case 13: /* LE */
1.955 - cond = armr.z || (armr.n != armr.v);
1.956 - break;
1.957 + cond = armr.z || (armr.n != armr.v);
1.958 + break;
1.959 case 14: /* AL */
1.960 - cond = 1;
1.961 - break;
1.962 + cond = 1;
1.963 + break;
1.964 case 15: /* (NV) */
1.965 default:
1.966 - cond = 0;
1.967 - UNDEF(ir);
1.968 + cond = 0;
1.969 + UNDEF(ir);
1.970 }
1.971 if( cond ) {
1.972
1.973 - /**
1.974 - * Condition passed, now for the actual instructions...
1.975 - */
1.976 - switch( GRP(ir) ) {
1.977 - case 0:
1.978 - if( (ir & 0x0D900000) == 0x01000000 ) {
1.979 - /* Instructions that aren't actual data processing even though
1.980 - * they sit in the DP instruction block.
1.981 - */
1.982 - switch( ir & 0x0FF000F0 ) {
1.983 - case 0x01200010: /* BX Rd */
1.984 - armr.t = ir & 0x01;
1.985 - armr.r[15] = RM(ir) & 0xFFFFFFFE;
1.986 - break;
1.987 - case 0x01000000: /* MRS Rd, CPSR */
1.988 - LRD(ir) = arm_get_cpsr();
1.989 - break;
1.990 - case 0x01400000: /* MRS Rd, SPSR */
1.991 - LRD(ir) = armr.spsr;
1.992 - break;
1.993 - case 0x01200000: /* MSR CPSR, Rd */
1.994 - arm_set_cpsr( RM(ir), ir );
1.995 - break;
1.996 - case 0x01600000: /* MSR SPSR, Rd */
1.997 - arm_set_spsr( RM(ir), ir );
1.998 - break;
1.999 - case 0x03200000: /* MSR CPSR, imm */
1.1000 - arm_set_cpsr( ROTIMM12(ir), ir );
1.1001 - break;
1.1002 - case 0x03600000: /* MSR SPSR, imm */
1.1003 - arm_set_spsr( ROTIMM12(ir), ir );
1.1004 - break;
1.1005 - default:
1.1006 - UNIMP(ir);
1.1007 - }
1.1008 - } else if( (ir & 0x0E000090) == 0x00000090 ) {
1.1009 - /* Neither are these */
1.1010 - switch( (ir>>5)&0x03 ) {
1.1011 - case 0:
1.1012 - /* Arithmetic extension area */
1.1013 - switch(OPCODE(ir)) {
1.1014 - case 0: /* MUL */
1.1015 - LRN(ir) = RM(ir) * RS(ir);
1.1016 - break;
1.1017 - case 1: /* MULS */
1.1018 - tmp = RM(ir) * RS(ir);
1.1019 - LRN(ir) = tmp;
1.1020 - armr.n = tmp>>31;
1.1021 - armr.z = (tmp == 0);
1.1022 - break;
1.1023 - case 2: /* MLA */
1.1024 - LRN(ir) = RM(ir) * RS(ir) + RD(ir);
1.1025 - break;
1.1026 - case 3: /* MLAS */
1.1027 - tmp = RM(ir) * RS(ir) + RD(ir);
1.1028 - LRN(ir) = tmp;
1.1029 - armr.n = tmp>>31;
1.1030 - armr.z = (tmp == 0);
1.1031 - break;
1.1032 - case 8: /* UMULL */
1.1033 - case 9: /* UMULLS */
1.1034 - case 10: /* UMLAL */
1.1035 - case 11: /* UMLALS */
1.1036 - case 12: /* SMULL */
1.1037 - case 13: /* SMULLS */
1.1038 - case 14: /* SMLAL */
1.1039 - case 15: /* SMLALS */
1.1040 - UNIMP(ir);
1.1041 - break;
1.1042 - case 16: /* SWP */
1.1043 - tmp = arm_read_long( RN(ir) );
1.1044 - switch( RN(ir) & 0x03 ) {
1.1045 - case 1:
1.1046 - tmp = ROTATE_RIGHT_LONG(tmp, 8);
1.1047 - break;
1.1048 - case 2:
1.1049 - tmp = ROTATE_RIGHT_LONG(tmp, 16);
1.1050 - break;
1.1051 - case 3:
1.1052 - tmp = ROTATE_RIGHT_LONG(tmp, 24);
1.1053 - break;
1.1054 - }
1.1055 - arm_write_long( RN(ir), RM(ir) );
1.1056 - LRD(ir) = tmp;
1.1057 - break;
1.1058 - case 20: /* SWPB */
1.1059 - tmp = arm_read_byte( RN(ir) );
1.1060 - arm_write_byte( RN(ir), RM(ir) );
1.1061 - LRD(ir) = tmp;
1.1062 - break;
1.1063 - default:
1.1064 - UNIMP(ir);
1.1065 - }
1.1066 - break;
1.1067 - case 1:
1.1068 - if( LFLAG(ir) ) {
1.1069 - /* LDRH */
1.1070 - } else {
1.1071 - /* STRH */
1.1072 - }
1.1073 - UNIMP(ir);
1.1074 - break;
1.1075 - case 2:
1.1076 - if( LFLAG(ir) ) {
1.1077 - /* LDRSB */
1.1078 - } else {
1.1079 - }
1.1080 - UNIMP(ir);
1.1081 - break;
1.1082 - case 3:
1.1083 - if( LFLAG(ir) ) {
1.1084 - /* LDRSH */
1.1085 - } else {
1.1086 - }
1.1087 - UNIMP(ir);
1.1088 - break;
1.1089 - }
1.1090 - } else {
1.1091 - /* Data processing */
1.1092 + /**
1.1093 + * Condition passed, now for the actual instructions...
1.1094 + */
1.1095 + switch( GRP(ir) ) {
1.1096 + case 0:
1.1097 + if( (ir & 0x0D900000) == 0x01000000 ) {
1.1098 + /* Instructions that aren't actual data processing even though
1.1099 + * they sit in the DP instruction block.
1.1100 + */
1.1101 + switch( ir & 0x0FF000F0 ) {
1.1102 + case 0x01200010: /* BX Rd */
1.1103 + armr.t = ir & 0x01;
1.1104 + armr.r[15] = RM(ir) & 0xFFFFFFFE;
1.1105 + break;
1.1106 + case 0x01000000: /* MRS Rd, CPSR */
1.1107 + LRD(ir) = arm_get_cpsr();
1.1108 + break;
1.1109 + case 0x01400000: /* MRS Rd, SPSR */
1.1110 + LRD(ir) = armr.spsr;
1.1111 + break;
1.1112 + case 0x01200000: /* MSR CPSR, Rd */
1.1113 + arm_set_cpsr( RM(ir), ir );
1.1114 + break;
1.1115 + case 0x01600000: /* MSR SPSR, Rd */
1.1116 + arm_set_spsr( RM(ir), ir );
1.1117 + break;
1.1118 + case 0x03200000: /* MSR CPSR, imm */
1.1119 + arm_set_cpsr( ROTIMM12(ir), ir );
1.1120 + break;
1.1121 + case 0x03600000: /* MSR SPSR, imm */
1.1122 + arm_set_spsr( ROTIMM12(ir), ir );
1.1123 + break;
1.1124 + default:
1.1125 + UNIMP(ir);
1.1126 + }
1.1127 + } else if( (ir & 0x0E000090) == 0x00000090 ) {
1.1128 + /* Neither are these */
1.1129 + switch( (ir>>5)&0x03 ) {
1.1130 + case 0:
1.1131 + /* Arithmetic extension area */
1.1132 + switch(OPCODE(ir)) {
1.1133 + case 0: /* MUL */
1.1134 + LRN(ir) = RM(ir) * RS(ir);
1.1135 + break;
1.1136 + case 1: /* MULS */
1.1137 + tmp = RM(ir) * RS(ir);
1.1138 + LRN(ir) = tmp;
1.1139 + armr.n = tmp>>31;
1.1140 + armr.z = (tmp == 0);
1.1141 + break;
1.1142 + case 2: /* MLA */
1.1143 + LRN(ir) = RM(ir) * RS(ir) + RD(ir);
1.1144 + break;
1.1145 + case 3: /* MLAS */
1.1146 + tmp = RM(ir) * RS(ir) + RD(ir);
1.1147 + LRN(ir) = tmp;
1.1148 + armr.n = tmp>>31;
1.1149 + armr.z = (tmp == 0);
1.1150 + break;
1.1151 + case 8: /* UMULL */
1.1152 + case 9: /* UMULLS */
1.1153 + case 10: /* UMLAL */
1.1154 + case 11: /* UMLALS */
1.1155 + case 12: /* SMULL */
1.1156 + case 13: /* SMULLS */
1.1157 + case 14: /* SMLAL */
1.1158 + case 15: /* SMLALS */
1.1159 + UNIMP(ir);
1.1160 + break;
1.1161 + case 16: /* SWP */
1.1162 + tmp = arm_read_long( RN(ir) );
1.1163 + switch( RN(ir) & 0x03 ) {
1.1164 + case 1:
1.1165 + tmp = ROTATE_RIGHT_LONG(tmp, 8);
1.1166 + break;
1.1167 + case 2:
1.1168 + tmp = ROTATE_RIGHT_LONG(tmp, 16);
1.1169 + break;
1.1170 + case 3:
1.1171 + tmp = ROTATE_RIGHT_LONG(tmp, 24);
1.1172 + break;
1.1173 + }
1.1174 + arm_write_long( RN(ir), RM(ir) );
1.1175 + LRD(ir) = tmp;
1.1176 + break;
1.1177 + case 20: /* SWPB */
1.1178 + tmp = arm_read_byte( RN(ir) );
1.1179 + arm_write_byte( RN(ir), RM(ir) );
1.1180 + LRD(ir) = tmp;
1.1181 + break;
1.1182 + default:
1.1183 + UNIMP(ir);
1.1184 + }
1.1185 + break;
1.1186 + case 1:
1.1187 + if( LFLAG(ir) ) {
1.1188 + /* LDRH */
1.1189 + } else {
1.1190 + /* STRH */
1.1191 + }
1.1192 + UNIMP(ir);
1.1193 + break;
1.1194 + case 2:
1.1195 + if( LFLAG(ir) ) {
1.1196 + /* LDRSB */
1.1197 + } else {
1.1198 + }
1.1199 + UNIMP(ir);
1.1200 + break;
1.1201 + case 3:
1.1202 + if( LFLAG(ir) ) {
1.1203 + /* LDRSH */
1.1204 + } else {
1.1205 + }
1.1206 + UNIMP(ir);
1.1207 + break;
1.1208 + }
1.1209 + } else {
1.1210 + /* Data processing */
1.1211
1.1212 - switch(OPCODE(ir)) {
1.1213 - case 0: /* AND Rd, Rn, operand */
1.1214 - LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
1.1215 - break;
1.1216 - case 1: /* ANDS Rd, Rn, operand */
1.1217 - operand = arm_get_shift_operand_s(ir) & RN(ir);
1.1218 - LRD(ir) = operand;
1.1219 - if( RDn(ir) == 15 ) {
1.1220 - arm_restore_cpsr();
1.1221 - } else {
1.1222 - armr.n = operand>>31;
1.1223 - armr.z = (operand == 0);
1.1224 - armr.c = armr.shift_c;
1.1225 - }
1.1226 - break;
1.1227 - case 2: /* EOR Rd, Rn, operand */
1.1228 - LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
1.1229 - break;
1.1230 - case 3: /* EORS Rd, Rn, operand */
1.1231 - operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.1232 - LRD(ir) = operand;
1.1233 - if( RDn(ir) == 15 ) {
1.1234 - arm_restore_cpsr();
1.1235 - } else {
1.1236 - armr.n = operand>>31;
1.1237 - armr.z = (operand == 0);
1.1238 - armr.c = armr.shift_c;
1.1239 - }
1.1240 - break;
1.1241 - case 4: /* SUB Rd, Rn, operand */
1.1242 - LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
1.1243 - break;
1.1244 - case 5: /* SUBS Rd, Rn, operand */
1.1245 - operand = RN(ir);
1.1246 - operand2 = arm_get_shift_operand(ir);
1.1247 - tmp = operand - operand2;
1.1248 - LRD(ir) = tmp;
1.1249 - if( RDn(ir) == 15 ) {
1.1250 - arm_restore_cpsr();
1.1251 - } else {
1.1252 - armr.n = tmp>>31;
1.1253 - armr.z = (tmp == 0);
1.1254 - armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.1255 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.1256 - }
1.1257 - break;
1.1258 - case 6: /* RSB Rd, operand, Rn */
1.1259 - LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
1.1260 - break;
1.1261 - case 7: /* RSBS Rd, operand, Rn */
1.1262 - operand = arm_get_shift_operand(ir);
1.1263 - operand2 = RN(ir);
1.1264 - tmp = operand - operand2;
1.1265 - LRD(ir) = tmp;
1.1266 - if( RDn(ir) == 15 ) {
1.1267 - arm_restore_cpsr();
1.1268 - } else {
1.1269 - armr.n = tmp>>31;
1.1270 - armr.z = (tmp == 0);
1.1271 - armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.1272 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.1273 - }
1.1274 - break;
1.1275 - case 8: /* ADD Rd, Rn, operand */
1.1276 - LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
1.1277 - break;
1.1278 - case 9: /* ADDS Rd, Rn, operand */
1.1279 - operand = arm_get_shift_operand(ir);
1.1280 - operand2 = RN(ir);
1.1281 - tmp = operand + operand2;
1.1282 - LRD(ir) = tmp;
1.1283 - if( RDn(ir) == 15 ) {
1.1284 - arm_restore_cpsr();
1.1285 - } else {
1.1286 - armr.n = tmp>>31;
1.1287 - armr.z = (tmp == 0);
1.1288 - armr.c = IS_CARRY(tmp,operand,operand2);
1.1289 - armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.1290 - }
1.1291 - break;
1.1292 - case 10: /* ADC */
1.1293 - LRD(ir) = RN(ir) + arm_get_shift_operand(ir) +
1.1294 - (armr.c ? 1 : 0);
1.1295 - break;
1.1296 - case 11: /* ADCS */
1.1297 - operand = arm_get_shift_operand(ir);
1.1298 - operand2 = RN(ir);
1.1299 - tmp = operand + operand2;
1.1300 - tmp2 = tmp + armr.c ? 1 : 0;
1.1301 - LRD(ir) = tmp2;
1.1302 - if( RDn(ir) == 15 ) {
1.1303 - arm_restore_cpsr();
1.1304 - } else {
1.1305 - armr.n = tmp >> 31;
1.1306 - armr.z = (tmp == 0 );
1.1307 - armr.c = IS_CARRY(tmp,operand,operand2) ||
1.1308 - (tmp2 < tmp);
1.1309 - armr.v = IS_ADDOVERFLOW(tmp,operand, operand2) ||
1.1310 - ((tmp&0x80000000) != (tmp2&0x80000000));
1.1311 - }
1.1312 - break;
1.1313 - case 12: /* SBC */
1.1314 - LRD(ir) = RN(ir) - arm_get_shift_operand(ir) -
1.1315 - (armr.c ? 0 : 1);
1.1316 - break;
1.1317 - case 13: /* SBCS */
1.1318 - operand = RN(ir);
1.1319 - operand2 = arm_get_shift_operand(ir);
1.1320 - tmp = operand - operand2;
1.1321 - tmp2 = tmp - (armr.c ? 0 : 1);
1.1322 - if( RDn(ir) == 15 ) {
1.1323 - arm_restore_cpsr();
1.1324 - } else {
1.1325 - armr.n = tmp >> 31;
1.1326 - armr.z = (tmp == 0 );
1.1327 - armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
1.1328 - (tmp2<tmp);
1.1329 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
1.1330 - ((tmp&0x80000000) != (tmp2&0x80000000));
1.1331 - }
1.1332 - break;
1.1333 - case 14: /* RSC */
1.1334 - LRD(ir) = arm_get_shift_operand(ir) - RN(ir) -
1.1335 - (armr.c ? 0 : 1);
1.1336 - break;
1.1337 - case 15: /* RSCS */
1.1338 - operand = arm_get_shift_operand(ir);
1.1339 - operand2 = RN(ir);
1.1340 - tmp = operand - operand2;
1.1341 - tmp2 = tmp - (armr.c ? 0 : 1);
1.1342 - if( RDn(ir) == 15 ) {
1.1343 - arm_restore_cpsr();
1.1344 - } else {
1.1345 - armr.n = tmp >> 31;
1.1346 - armr.z = (tmp == 0 );
1.1347 - armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
1.1348 - (tmp2<tmp);
1.1349 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
1.1350 - ((tmp&0x80000000) != (tmp2&0x80000000));
1.1351 - }
1.1352 - break;
1.1353 - case 17: /* TST Rn, operand */
1.1354 - operand = arm_get_shift_operand_s(ir) & RN(ir);
1.1355 - armr.n = operand>>31;
1.1356 - armr.z = (operand == 0);
1.1357 - armr.c = armr.shift_c;
1.1358 - break;
1.1359 - case 19: /* TEQ Rn, operand */
1.1360 - operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.1361 - armr.n = operand>>31;
1.1362 - armr.z = (operand == 0);
1.1363 - armr.c = armr.shift_c;
1.1364 - break;
1.1365 - case 21: /* CMP Rn, operand */
1.1366 - operand = RN(ir);
1.1367 - operand2 = arm_get_shift_operand(ir);
1.1368 - tmp = operand - operand2;
1.1369 - armr.n = tmp>>31;
1.1370 - armr.z = (tmp == 0);
1.1371 - armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.1372 - armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.1373 - break;
1.1374 - case 23: /* CMN Rn, operand */
1.1375 - operand = RN(ir);
1.1376 - operand2 = arm_get_shift_operand(ir);
1.1377 - tmp = operand + operand2;
1.1378 - armr.n = tmp>>31;
1.1379 - armr.z = (tmp == 0);
1.1380 - armr.c = IS_CARRY(tmp,operand,operand2);
1.1381 - armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.1382 - break;
1.1383 - case 24: /* ORR Rd, Rn, operand */
1.1384 - LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
1.1385 - break;
1.1386 - case 25: /* ORRS Rd, Rn, operand */
1.1387 - operand = arm_get_shift_operand_s(ir) | RN(ir);
1.1388 - LRD(ir) = operand;
1.1389 - if( RDn(ir) == 15 ) {
1.1390 - arm_restore_cpsr();
1.1391 - } else {
1.1392 - armr.n = operand>>31;
1.1393 - armr.z = (operand == 0);
1.1394 - armr.c = armr.shift_c;
1.1395 - }
1.1396 - break;
1.1397 - case 26: /* MOV Rd, operand */
1.1398 - LRD(ir) = arm_get_shift_operand(ir);
1.1399 - break;
1.1400 - case 27: /* MOVS Rd, operand */
1.1401 - operand = arm_get_shift_operand_s(ir);
1.1402 - LRD(ir) = operand;
1.1403 - if( RDn(ir) == 15 ) {
1.1404 - arm_restore_cpsr();
1.1405 - } else {
1.1406 - armr.n = operand>>31;
1.1407 - armr.z = (operand == 0);
1.1408 - armr.c = armr.shift_c;
1.1409 - }
1.1410 - break;
1.1411 - case 28: /* BIC Rd, Rn, operand */
1.1412 - LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
1.1413 - break;
1.1414 - case 29: /* BICS Rd, Rn, operand */
1.1415 - operand = RN(ir) & (~arm_get_shift_operand_s(ir));
1.1416 - LRD(ir) = operand;
1.1417 - if( RDn(ir) == 15 ) {
1.1418 - arm_restore_cpsr();
1.1419 - } else {
1.1420 - armr.n = operand>>31;
1.1421 - armr.z = (operand == 0);
1.1422 - armr.c = armr.shift_c;
1.1423 - }
1.1424 - break;
1.1425 - case 30: /* MVN Rd, operand */
1.1426 - LRD(ir) = ~arm_get_shift_operand(ir);
1.1427 - break;
1.1428 - case 31: /* MVNS Rd, operand */
1.1429 - operand = ~arm_get_shift_operand_s(ir);
1.1430 - LRD(ir) = operand;
1.1431 - if( RDn(ir) == 15 ) {
1.1432 - arm_restore_cpsr();
1.1433 - } else {
1.1434 - armr.n = operand>>31;
1.1435 - armr.z = (operand == 0);
1.1436 - armr.c = armr.shift_c;
1.1437 - }
1.1438 - break;
1.1439 - default:
1.1440 - UNIMP(ir);
1.1441 - }
1.1442 - }
1.1443 - break;
1.1444 - case 1: /* Load/store */
1.1445 - operand = arm_get_address_operand(ir);
1.1446 - switch( (ir>>20)&0x17 ) {
1.1447 - case 0: case 16: case 18: /* STR Rd, address */
1.1448 - arm_write_long( operand, RD(ir) );
1.1449 - break;
1.1450 - case 1: case 17: case 19: /* LDR Rd, address */
1.1451 - LRD(ir) = arm_read_long(operand);
1.1452 - break;
1.1453 - case 2: /* STRT Rd, address */
1.1454 - arm_write_long_user( operand, RD(ir) );
1.1455 - break;
1.1456 - case 3: /* LDRT Rd, address */
1.1457 - LRD(ir) = arm_read_long_user( operand );
1.1458 - break;
1.1459 - case 4: case 20: case 22: /* STRB Rd, address */
1.1460 - arm_write_byte( operand, RD(ir) );
1.1461 - break;
1.1462 - case 5: case 21: case 23: /* LDRB Rd, address */
1.1463 - LRD(ir) = arm_read_byte( operand );
1.1464 - break;
1.1465 - case 6: /* STRBT Rd, address */
1.1466 - arm_write_byte_user( operand, RD(ir) );
1.1467 - break;
1.1468 - case 7: /* LDRBT Rd, address */
1.1469 - LRD(ir) = arm_read_byte_user( operand );
1.1470 - break;
1.1471 - }
1.1472 - break;
1.1473 - case 2: /* Load/store multiple, branch*/
1.1474 - if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
1.1475 - operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
1.1476 - if( (ir & 0x01000000) == 0x01000000 ) {
1.1477 - armr.r[14] = pc; /* BL */
1.1478 - }
1.1479 - armr.r[15] = pc + 4 + operand;
1.1480 - } else { /* Load/store multiple */
1.1481 - gboolean needRestore = FALSE;
1.1482 - operand = RN(ir);
1.1483 -
1.1484 - switch( (ir & 0x01D00000) >> 20 ) {
1.1485 - case 0: /* STMDA */
1.1486 - if( ir & 0x8000 ) {
1.1487 - arm_write_long( operand, armr.r[15]+4 );
1.1488 - operand -= 4;
1.1489 - }
1.1490 - for( i=14; i>= 0; i-- ) {
1.1491 - if( (ir & (1<<i)) ) {
1.1492 - arm_write_long( operand, armr.r[i] );
1.1493 - operand -= 4;
1.1494 - }
1.1495 - }
1.1496 - break;
1.1497 - case 1: /* LDMDA */
1.1498 - for( i=15; i>= 0; i-- ) {
1.1499 - if( (ir & (1<<i)) ) {
1.1500 - armr.r[i] = arm_read_long( operand );
1.1501 - operand -= 4;
1.1502 - }
1.1503 - }
1.1504 - break;
1.1505 - case 4: /* STMDA (S) */
1.1506 - if( ir & 0x8000 ) {
1.1507 - arm_write_long( operand, armr.r[15]+4 );
1.1508 - operand -= 4;
1.1509 - }
1.1510 - for( i=14; i>= 0; i-- ) {
1.1511 - if( (ir & (1<<i)) ) {
1.1512 - arm_write_long( operand, USER_R(i) );
1.1513 - operand -= 4;
1.1514 - }
1.1515 - }
1.1516 - break;
1.1517 - case 5: /* LDMDA (S) */
1.1518 - if( (ir&0x00008000) ) { /* Load PC */
1.1519 - for( i=15; i>= 0; i-- ) {
1.1520 - if( (ir & (1<<i)) ) {
1.1521 - armr.r[i] = arm_read_long( operand );
1.1522 - operand -= 4;
1.1523 - }
1.1524 - }
1.1525 - needRestore = TRUE;
1.1526 - } else {
1.1527 - for( i=15; i>= 0; i-- ) {
1.1528 - if( (ir & (1<<i)) ) {
1.1529 - USER_R(i) = arm_read_long( operand );
1.1530 - operand -= 4;
1.1531 - }
1.1532 - }
1.1533 - }
1.1534 - break;
1.1535 - case 8: /* STMIA */
1.1536 - for( i=0; i< 15; i++ ) {
1.1537 - if( (ir & (1<<i)) ) {
1.1538 - arm_write_long( operand, armr.r[i] );
1.1539 - operand += 4;
1.1540 - }
1.1541 - }
1.1542 - if( ir & 0x8000 ) {
1.1543 - arm_write_long( operand, armr.r[15]+4 );
1.1544 - operand += 4;
1.1545 - }
1.1546 - break;
1.1547 - case 9: /* LDMIA */
1.1548 - for( i=0; i< 16; i++ ) {
1.1549 - if( (ir & (1<<i)) ) {
1.1550 - armr.r[i] = arm_read_long( operand );
1.1551 - operand += 4;
1.1552 - }
1.1553 - }
1.1554 - break;
1.1555 - case 12: /* STMIA (S) */
1.1556 - for( i=0; i< 15; i++ ) {
1.1557 - if( (ir & (1<<i)) ) {
1.1558 - arm_write_long( operand, USER_R(i) );
1.1559 - operand += 4;
1.1560 - }
1.1561 - }
1.1562 - if( ir & 0x8000 ) {
1.1563 - arm_write_long( operand, armr.r[15]+4 );
1.1564 - operand += 4;
1.1565 - }
1.1566 - break;
1.1567 - case 13: /* LDMIA (S) */
1.1568 - if( (ir&0x00008000) ) { /* Load PC */
1.1569 - for( i=0; i < 16; i++ ) {
1.1570 - if( (ir & (1<<i)) ) {
1.1571 - armr.r[i] = arm_read_long( operand );
1.1572 - operand += 4;
1.1573 - }
1.1574 - }
1.1575 - needRestore = TRUE;
1.1576 - } else {
1.1577 - for( i=0; i < 16; i++ ) {
1.1578 - if( (ir & (1<<i)) ) {
1.1579 - USER_R(i) = arm_read_long( operand );
1.1580 - operand += 4;
1.1581 - }
1.1582 - }
1.1583 - }
1.1584 - break;
1.1585 - case 16: /* STMDB */
1.1586 - if( ir & 0x8000 ) {
1.1587 - operand -= 4;
1.1588 - arm_write_long( operand, armr.r[15]+4 );
1.1589 - }
1.1590 - for( i=14; i>= 0; i-- ) {
1.1591 - if( (ir & (1<<i)) ) {
1.1592 - operand -= 4;
1.1593 - arm_write_long( operand, armr.r[i] );
1.1594 - }
1.1595 - }
1.1596 - break;
1.1597 - case 17: /* LDMDB */
1.1598 - for( i=15; i>= 0; i-- ) {
1.1599 - if( (ir & (1<<i)) ) {
1.1600 - operand -= 4;
1.1601 - armr.r[i] = arm_read_long( operand );
1.1602 - }
1.1603 - }
1.1604 - break;
1.1605 - case 20: /* STMDB (S) */
1.1606 - if( ir & 0x8000 ) {
1.1607 - operand -= 4;
1.1608 - arm_write_long( operand, armr.r[15]+4 );
1.1609 - }
1.1610 - for( i=14; i>= 0; i-- ) {
1.1611 - if( (ir & (1<<i)) ) {
1.1612 - operand -= 4;
1.1613 - arm_write_long( operand, USER_R(i) );
1.1614 - }
1.1615 - }
1.1616 - break;
1.1617 - case 21: /* LDMDB (S) */
1.1618 - if( (ir&0x00008000) ) { /* Load PC */
1.1619 - for( i=15; i>= 0; i-- ) {
1.1620 - if( (ir & (1<<i)) ) {
1.1621 - operand -= 4;
1.1622 - armr.r[i] = arm_read_long( operand );
1.1623 - }
1.1624 - }
1.1625 - needRestore = TRUE;
1.1626 - } else {
1.1627 - for( i=15; i>= 0; i-- ) {
1.1628 - if( (ir & (1<<i)) ) {
1.1629 - operand -= 4;
1.1630 - USER_R(i) = arm_read_long( operand );
1.1631 - }
1.1632 - }
1.1633 - }
1.1634 - break;
1.1635 - case 24: /* STMIB */
1.1636 - for( i=0; i< 15; i++ ) {
1.1637 - if( (ir & (1<<i)) ) {
1.1638 - operand += 4;
1.1639 - arm_write_long( operand, armr.r[i] );
1.1640 - }
1.1641 - }
1.1642 - if( ir & 0x8000 ) {
1.1643 - operand += 4;
1.1644 - arm_write_long( operand, armr.r[15]+4 );
1.1645 - }
1.1646 - break;
1.1647 - case 25: /* LDMIB */
1.1648 - for( i=0; i< 16; i++ ) {
1.1649 - if( (ir & (1<<i)) ) {
1.1650 - operand += 4;
1.1651 - armr.r[i] = arm_read_long( operand );
1.1652 - }
1.1653 - }
1.1654 - break;
1.1655 - case 28: /* STMIB (S) */
1.1656 - for( i=0; i< 15; i++ ) {
1.1657 - if( (ir & (1<<i)) ) {
1.1658 - operand += 4;
1.1659 - arm_write_long( operand, USER_R(i) );
1.1660 - }
1.1661 - }
1.1662 - if( ir & 0x8000 ) {
1.1663 - operand += 4;
1.1664 - arm_write_long( operand, armr.r[15]+4 );
1.1665 - }
1.1666 - break;
1.1667 - case 29: /* LDMIB (S) */
1.1668 - if( (ir&0x00008000) ) { /* Load PC */
1.1669 - for( i=0; i < 16; i++ ) {
1.1670 - if( (ir & (1<<i)) ) {
1.1671 - operand += 4;
1.1672 - armr.r[i] = arm_read_long( operand );
1.1673 - }
1.1674 - }
1.1675 - needRestore = TRUE;
1.1676 - } else {
1.1677 - for( i=0; i < 16; i++ ) {
1.1678 - if( (ir & (1<<i)) ) {
1.1679 - operand += 4;
1.1680 - USER_R(i) = arm_read_long( operand );
1.1681 - }
1.1682 - }
1.1683 - }
1.1684 - break;
1.1685 - }
1.1686 -
1.1687 - if( WFLAG(ir) )
1.1688 - LRN(ir) = operand;
1.1689 - if( needRestore )
1.1690 - arm_restore_cpsr();
1.1691 - }
1.1692 - break;
1.1693 - case 3: /* Copro */
1.1694 - if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */
1.1695 - arm_raise_exception( EXC_SOFTWARE );
1.1696 - } else {
1.1697 - UNIMP(ir);
1.1698 - }
1.1699 - break;
1.1700 - }
1.1701 + switch(OPCODE(ir)) {
1.1702 + case 0: /* AND Rd, Rn, operand */
1.1703 + LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
1.1704 + break;
1.1705 + case 1: /* ANDS Rd, Rn, operand */
1.1706 + operand = arm_get_shift_operand_s(ir) & RN(ir);
1.1707 + LRD(ir) = operand;
1.1708 + if( RDn(ir) == 15 ) {
1.1709 + arm_restore_cpsr();
1.1710 + } else {
1.1711 + armr.n = operand>>31;
1.1712 + armr.z = (operand == 0);
1.1713 + armr.c = armr.shift_c;
1.1714 + }
1.1715 + break;
1.1716 + case 2: /* EOR Rd, Rn, operand */
1.1717 + LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
1.1718 + break;
1.1719 + case 3: /* EORS Rd, Rn, operand */
1.1720 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.1721 + LRD(ir) = operand;
1.1722 + if( RDn(ir) == 15 ) {
1.1723 + arm_restore_cpsr();
1.1724 + } else {
1.1725 + armr.n = operand>>31;
1.1726 + armr.z = (operand == 0);
1.1727 + armr.c = armr.shift_c;
1.1728 + }
1.1729 + break;
1.1730 + case 4: /* SUB Rd, Rn, operand */
1.1731 + LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
1.1732 + break;
1.1733 + case 5: /* SUBS Rd, Rn, operand */
1.1734 + operand = RN(ir);
1.1735 + operand2 = arm_get_shift_operand(ir);
1.1736 + tmp = operand - operand2;
1.1737 + LRD(ir) = tmp;
1.1738 + if( RDn(ir) == 15 ) {
1.1739 + arm_restore_cpsr();
1.1740 + } else {
1.1741 + armr.n = tmp>>31;
1.1742 + armr.z = (tmp == 0);
1.1743 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.1744 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.1745 + }
1.1746 + break;
1.1747 + case 6: /* RSB Rd, operand, Rn */
1.1748 + LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
1.1749 + break;
1.1750 + case 7: /* RSBS Rd, operand, Rn */
1.1751 + operand = arm_get_shift_operand(ir);
1.1752 + operand2 = RN(ir);
1.1753 + tmp = operand - operand2;
1.1754 + LRD(ir) = tmp;
1.1755 + if( RDn(ir) == 15 ) {
1.1756 + arm_restore_cpsr();
1.1757 + } else {
1.1758 + armr.n = tmp>>31;
1.1759 + armr.z = (tmp == 0);
1.1760 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.1761 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.1762 + }
1.1763 + break;
1.1764 + case 8: /* ADD Rd, Rn, operand */
1.1765 + LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
1.1766 + break;
1.1767 + case 9: /* ADDS Rd, Rn, operand */
1.1768 + operand = arm_get_shift_operand(ir);
1.1769 + operand2 = RN(ir);
1.1770 + tmp = operand + operand2;
1.1771 + LRD(ir) = tmp;
1.1772 + if( RDn(ir) == 15 ) {
1.1773 + arm_restore_cpsr();
1.1774 + } else {
1.1775 + armr.n = tmp>>31;
1.1776 + armr.z = (tmp == 0);
1.1777 + armr.c = IS_CARRY(tmp,operand,operand2);
1.1778 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.1779 + }
1.1780 + break;
1.1781 + case 10: /* ADC */
1.1782 + LRD(ir) = RN(ir) + arm_get_shift_operand(ir) +
1.1783 + (armr.c ? 1 : 0);
1.1784 + break;
1.1785 + case 11: /* ADCS */
1.1786 + operand = arm_get_shift_operand(ir);
1.1787 + operand2 = RN(ir);
1.1788 + tmp = operand + operand2;
1.1789 + tmp2 = tmp + armr.c ? 1 : 0;
1.1790 + LRD(ir) = tmp2;
1.1791 + if( RDn(ir) == 15 ) {
1.1792 + arm_restore_cpsr();
1.1793 + } else {
1.1794 + armr.n = tmp >> 31;
1.1795 + armr.z = (tmp == 0 );
1.1796 + armr.c = IS_CARRY(tmp,operand,operand2) ||
1.1797 + (tmp2 < tmp);
1.1798 + armr.v = IS_ADDOVERFLOW(tmp,operand, operand2) ||
1.1799 + ((tmp&0x80000000) != (tmp2&0x80000000));
1.1800 + }
1.1801 + break;
1.1802 + case 12: /* SBC */
1.1803 + LRD(ir) = RN(ir) - arm_get_shift_operand(ir) -
1.1804 + (armr.c ? 0 : 1);
1.1805 + break;
1.1806 + case 13: /* SBCS */
1.1807 + operand = RN(ir);
1.1808 + operand2 = arm_get_shift_operand(ir);
1.1809 + tmp = operand - operand2;
1.1810 + tmp2 = tmp - (armr.c ? 0 : 1);
1.1811 + if( RDn(ir) == 15 ) {
1.1812 + arm_restore_cpsr();
1.1813 + } else {
1.1814 + armr.n = tmp >> 31;
1.1815 + armr.z = (tmp == 0 );
1.1816 + armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
1.1817 + (tmp2<tmp);
1.1818 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
1.1819 + ((tmp&0x80000000) != (tmp2&0x80000000));
1.1820 + }
1.1821 + break;
1.1822 + case 14: /* RSC */
1.1823 + LRD(ir) = arm_get_shift_operand(ir) - RN(ir) -
1.1824 + (armr.c ? 0 : 1);
1.1825 + break;
1.1826 + case 15: /* RSCS */
1.1827 + operand = arm_get_shift_operand(ir);
1.1828 + operand2 = RN(ir);
1.1829 + tmp = operand - operand2;
1.1830 + tmp2 = tmp - (armr.c ? 0 : 1);
1.1831 + if( RDn(ir) == 15 ) {
1.1832 + arm_restore_cpsr();
1.1833 + } else {
1.1834 + armr.n = tmp >> 31;
1.1835 + armr.z = (tmp == 0 );
1.1836 + armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
1.1837 + (tmp2<tmp);
1.1838 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
1.1839 + ((tmp&0x80000000) != (tmp2&0x80000000));
1.1840 + }
1.1841 + break;
1.1842 + case 17: /* TST Rn, operand */
1.1843 + operand = arm_get_shift_operand_s(ir) & RN(ir);
1.1844 + armr.n = operand>>31;
1.1845 + armr.z = (operand == 0);
1.1846 + armr.c = armr.shift_c;
1.1847 + break;
1.1848 + case 19: /* TEQ Rn, operand */
1.1849 + operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1.1850 + armr.n = operand>>31;
1.1851 + armr.z = (operand == 0);
1.1852 + armr.c = armr.shift_c;
1.1853 + break;
1.1854 + case 21: /* CMP Rn, operand */
1.1855 + operand = RN(ir);
1.1856 + operand2 = arm_get_shift_operand(ir);
1.1857 + tmp = operand - operand2;
1.1858 + armr.n = tmp>>31;
1.1859 + armr.z = (tmp == 0);
1.1860 + armr.c = IS_NOTBORROW(tmp,operand,operand2);
1.1861 + armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1.1862 + break;
1.1863 + case 23: /* CMN Rn, operand */
1.1864 + operand = RN(ir);
1.1865 + operand2 = arm_get_shift_operand(ir);
1.1866 + tmp = operand + operand2;
1.1867 + armr.n = tmp>>31;
1.1868 + armr.z = (tmp == 0);
1.1869 + armr.c = IS_CARRY(tmp,operand,operand2);
1.1870 + armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1.1871 + break;
1.1872 + case 24: /* ORR Rd, Rn, operand */
1.1873 + LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
1.1874 + break;
1.1875 + case 25: /* ORRS Rd, Rn, operand */
1.1876 + operand = arm_get_shift_operand_s(ir) | RN(ir);
1.1877 + LRD(ir) = operand;
1.1878 + if( RDn(ir) == 15 ) {
1.1879 + arm_restore_cpsr();
1.1880 + } else {
1.1881 + armr.n = operand>>31;
1.1882 + armr.z = (operand == 0);
1.1883 + armr.c = armr.shift_c;
1.1884 + }
1.1885 + break;
1.1886 + case 26: /* MOV Rd, operand */
1.1887 + LRD(ir) = arm_get_shift_operand(ir);
1.1888 + break;
1.1889 + case 27: /* MOVS Rd, operand */
1.1890 + operand = arm_get_shift_operand_s(ir);
1.1891 + LRD(ir) = operand;
1.1892 + if( RDn(ir) == 15 ) {
1.1893 + arm_restore_cpsr();
1.1894 + } else {
1.1895 + armr.n = operand>>31;
1.1896 + armr.z = (operand == 0);
1.1897 + armr.c = armr.shift_c;
1.1898 + }
1.1899 + break;
1.1900 + case 28: /* BIC Rd, Rn, operand */
1.1901 + LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
1.1902 + break;
1.1903 + case 29: /* BICS Rd, Rn, operand */
1.1904 + operand = RN(ir) & (~arm_get_shift_operand_s(ir));
1.1905 + LRD(ir) = operand;
1.1906 + if( RDn(ir) == 15 ) {
1.1907 + arm_restore_cpsr();
1.1908 + } else {
1.1909 + armr.n = operand>>31;
1.1910 + armr.z = (operand == 0);
1.1911 + armr.c = armr.shift_c;
1.1912 + }
1.1913 + break;
1.1914 + case 30: /* MVN Rd, operand */
1.1915 + LRD(ir) = ~arm_get_shift_operand(ir);
1.1916 + break;
1.1917 + case 31: /* MVNS Rd, operand */
1.1918 + operand = ~arm_get_shift_operand_s(ir);
1.1919 + LRD(ir) = operand;
1.1920 + if( RDn(ir) == 15 ) {
1.1921 + arm_restore_cpsr();
1.1922 + } else {
1.1923 + armr.n = operand>>31;
1.1924 + armr.z = (operand == 0);
1.1925 + armr.c = armr.shift_c;
1.1926 + }
1.1927 + break;
1.1928 + default:
1.1929 + UNIMP(ir);
1.1930 + }
1.1931 + }
1.1932 + break;
1.1933 + case 1: /* Load/store */
1.1934 + operand = arm_get_address_operand(ir);
1.1935 + switch( (ir>>20)&0x17 ) {
1.1936 + case 0: case 16: case 18: /* STR Rd, address */
1.1937 + arm_write_long( operand, RD(ir) );
1.1938 + break;
1.1939 + case 1: case 17: case 19: /* LDR Rd, address */
1.1940 + LRD(ir) = arm_read_long(operand);
1.1941 + break;
1.1942 + case 2: /* STRT Rd, address */
1.1943 + arm_write_long_user( operand, RD(ir) );
1.1944 + break;
1.1945 + case 3: /* LDRT Rd, address */
1.1946 + LRD(ir) = arm_read_long_user( operand );
1.1947 + break;
1.1948 + case 4: case 20: case 22: /* STRB Rd, address */
1.1949 + arm_write_byte( operand, RD(ir) );
1.1950 + break;
1.1951 + case 5: case 21: case 23: /* LDRB Rd, address */
1.1952 + LRD(ir) = arm_read_byte( operand );
1.1953 + break;
1.1954 + case 6: /* STRBT Rd, address */
1.1955 + arm_write_byte_user( operand, RD(ir) );
1.1956 + break;
1.1957 + case 7: /* LDRBT Rd, address */
1.1958 + LRD(ir) = arm_read_byte_user( operand );
1.1959 + break;
1.1960 + }
1.1961 + break;
1.1962 + case 2: /* Load/store multiple, branch*/
1.1963 + if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
1.1964 + operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
1.1965 + if( (ir & 0x01000000) == 0x01000000 ) {
1.1966 + armr.r[14] = pc; /* BL */
1.1967 + }
1.1968 + armr.r[15] = pc + 4 + operand;
1.1969 + } else { /* Load/store multiple */
1.1970 + gboolean needRestore = FALSE;
1.1971 + operand = RN(ir);
1.1972 +
1.1973 + switch( (ir & 0x01D00000) >> 20 ) {
1.1974 + case 0: /* STMDA */
1.1975 + if( ir & 0x8000 ) {
1.1976 + arm_write_long( operand, armr.r[15]+4 );
1.1977 + operand -= 4;
1.1978 + }
1.1979 + for( i=14; i>= 0; i-- ) {
1.1980 + if( (ir & (1<<i)) ) {
1.1981 + arm_write_long( operand, armr.r[i] );
1.1982 + operand -= 4;
1.1983 + }
1.1984 + }
1.1985 + break;
1.1986 + case 1: /* LDMDA */
1.1987 + for( i=15; i>= 0; i-- ) {
1.1988 + if( (ir & (1<<i)) ) {
1.1989 + armr.r[i] = arm_read_long( operand );
1.1990 + operand -= 4;
1.1991 + }
1.1992 + }
1.1993 + break;
1.1994 + case 4: /* STMDA (S) */
1.1995 + if( ir & 0x8000 ) {
1.1996 + arm_write_long( operand, armr.r[15]+4 );
1.1997 + operand -= 4;
1.1998 + }
1.1999 + for( i=14; i>= 0; i-- ) {
1.2000 + if( (ir & (1<<i)) ) {
1.2001 + arm_write_long( operand, USER_R(i) );
1.2002 + operand -= 4;
1.2003 + }
1.2004 + }
1.2005 + break;
1.2006 + case 5: /* LDMDA (S) */
1.2007 + if( (ir&0x00008000) ) { /* Load PC */
1.2008 + for( i=15; i>= 0; i-- ) {
1.2009 + if( (ir & (1<<i)) ) {
1.2010 + armr.r[i] = arm_read_long( operand );
1.2011 + operand -= 4;
1.2012 + }
1.2013 + }
1.2014 + needRestore = TRUE;
1.2015 + } else {
1.2016 + for( i=15; i>= 0; i-- ) {
1.2017 + if( (ir & (1<<i)) ) {
1.2018 + USER_R(i) = arm_read_long( operand );
1.2019 + operand -= 4;
1.2020 + }
1.2021 + }
1.2022 + }
1.2023 + break;
1.2024 + case 8: /* STMIA */
1.2025 + for( i=0; i< 15; i++ ) {
1.2026 + if( (ir & (1<<i)) ) {
1.2027 + arm_write_long( operand, armr.r[i] );
1.2028 + operand += 4;
1.2029 + }
1.2030 + }
1.2031 + if( ir & 0x8000 ) {
1.2032 + arm_write_long( operand, armr.r[15]+4 );
1.2033 + operand += 4;
1.2034 + }
1.2035 + break;
1.2036 + case 9: /* LDMIA */
1.2037 + for( i=0; i< 16; i++ ) {
1.2038 + if( (ir & (1<<i)) ) {
1.2039 + armr.r[i] = arm_read_long( operand );
1.2040 + operand += 4;
1.2041 + }
1.2042 + }
1.2043 + break;
1.2044 + case 12: /* STMIA (S) */
1.2045 + for( i=0; i< 15; i++ ) {
1.2046 + if( (ir & (1<<i)) ) {
1.2047 + arm_write_long( operand, USER_R(i) );
1.2048 + operand += 4;
1.2049 + }
1.2050 + }
1.2051 + if( ir & 0x8000 ) {
1.2052 + arm_write_long( operand, armr.r[15]+4 );
1.2053 + operand += 4;
1.2054 + }
1.2055 + break;
1.2056 + case 13: /* LDMIA (S) */
1.2057 + if( (ir&0x00008000) ) { /* Load PC */
1.2058 + for( i=0; i < 16; i++ ) {
1.2059 + if( (ir & (1<<i)) ) {
1.2060 + armr.r[i] = arm_read_long( operand );
1.2061 + operand += 4;
1.2062 + }
1.2063 + }
1.2064 + needRestore = TRUE;
1.2065 + } else {
1.2066 + for( i=0; i < 16; i++ ) {
1.2067 + if( (ir & (1<<i)) ) {
1.2068 + USER_R(i) = arm_read_long( operand );
1.2069 + operand += 4;
1.2070 + }
1.2071 + }
1.2072 + }
1.2073 + break;
1.2074 + case 16: /* STMDB */
1.2075 + if( ir & 0x8000 ) {
1.2076 + operand -= 4;
1.2077 + arm_write_long( operand, armr.r[15]+4 );
1.2078 + }
1.2079 + for( i=14; i>= 0; i-- ) {
1.2080 + if( (ir & (1<<i)) ) {
1.2081 + operand -= 4;
1.2082 + arm_write_long( operand, armr.r[i] );
1.2083 + }
1.2084 + }
1.2085 + break;
1.2086 + case 17: /* LDMDB */
1.2087 + for( i=15; i>= 0; i-- ) {
1.2088 + if( (ir & (1<<i)) ) {
1.2089 + operand -= 4;
1.2090 + armr.r[i] = arm_read_long( operand );
1.2091 + }
1.2092 + }
1.2093 + break;
1.2094 + case 20: /* STMDB (S) */
1.2095 + if( ir & 0x8000 ) {
1.2096 + operand -= 4;
1.2097 + arm_write_long( operand, armr.r[15]+4 );
1.2098 + }
1.2099 + for( i=14; i>= 0; i-- ) {
1.2100 + if( (ir & (1<<i)) ) {
1.2101 + operand -= 4;
1.2102 + arm_write_long( operand, USER_R(i) );
1.2103 + }
1.2104 + }
1.2105 + break;
1.2106 + case 21: /* LDMDB (S) */
1.2107 + if( (ir&0x00008000) ) { /* Load PC */
1.2108 + for( i=15; i>= 0; i-- ) {
1.2109 + if( (ir & (1<<i)) ) {
1.2110 + operand -= 4;
1.2111 + armr.r[i] = arm_read_long( operand );
1.2112 + }
1.2113 + }
1.2114 + needRestore = TRUE;
1.2115 + } else {
1.2116 + for( i=15; i>= 0; i-- ) {
1.2117 + if( (ir & (1<<i)) ) {
1.2118 + operand -= 4;
1.2119 + USER_R(i) = arm_read_long( operand );
1.2120 + }
1.2121 + }
1.2122 + }
1.2123 + break;
1.2124 + case 24: /* STMIB */
1.2125 + for( i=0; i< 15; i++ ) {
1.2126 + if( (ir & (1<<i)) ) {
1.2127 + operand += 4;
1.2128 + arm_write_long( operand, armr.r[i] );
1.2129 + }
1.2130 + }
1.2131 + if( ir & 0x8000 ) {
1.2132 + operand += 4;
1.2133 + arm_write_long( operand, armr.r[15]+4 );
1.2134 + }
1.2135 + break;
1.2136 + case 25: /* LDMIB */
1.2137 + for( i=0; i< 16; i++ ) {
1.2138 + if( (ir & (1<<i)) ) {
1.2139 + operand += 4;
1.2140 + armr.r[i] = arm_read_long( operand );
1.2141 + }
1.2142 + }
1.2143 + break;
1.2144 + case 28: /* STMIB (S) */
1.2145 + for( i=0; i< 15; i++ ) {
1.2146 + if( (ir & (1<<i)) ) {
1.2147 + operand += 4;
1.2148 + arm_write_long( operand, USER_R(i) );
1.2149 + }
1.2150 + }
1.2151 + if( ir & 0x8000 ) {
1.2152 + operand += 4;
1.2153 + arm_write_long( operand, armr.r[15]+4 );
1.2154 + }
1.2155 + break;
1.2156 + case 29: /* LDMIB (S) */
1.2157 + if( (ir&0x00008000) ) { /* Load PC */
1.2158 + for( i=0; i < 16; i++ ) {
1.2159 + if( (ir & (1<<i)) ) {
1.2160 + operand += 4;
1.2161 + armr.r[i] = arm_read_long( operand );
1.2162 + }
1.2163 + }
1.2164 + needRestore = TRUE;
1.2165 + } else {
1.2166 + for( i=0; i < 16; i++ ) {
1.2167 + if( (ir & (1<<i)) ) {
1.2168 + operand += 4;
1.2169 + USER_R(i) = arm_read_long( operand );
1.2170 + }
1.2171 + }
1.2172 + }
1.2173 + break;
1.2174 + }
1.2175 +
1.2176 + if( WFLAG(ir) )
1.2177 + LRN(ir) = operand;
1.2178 + if( needRestore )
1.2179 + arm_restore_cpsr();
1.2180 + }
1.2181 + break;
1.2182 + case 3: /* Copro */
1.2183 + if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */
1.2184 + arm_raise_exception( EXC_SOFTWARE );
1.2185 + } else {
1.2186 + UNIMP(ir);
1.2187 + }
1.2188 + break;
1.2189 + }
1.2190
1.2191 }
1.2192
1.2193 if( armr.r[15] >= 0x00200000 ) {
1.2194 - armr.running = FALSE;
1.2195 - WARN( "ARM Halted: BRANCH to invalid address %08X at %08X", armr.r[15], pc );
1.2196 - return FALSE;
1.2197 + armr.running = FALSE;
1.2198 + WARN( "ARM Halted: BRANCH to invalid address %08X at %08X", armr.r[15], pc );
1.2199 + return FALSE;
1.2200 }
1.2201 return TRUE;
1.2202 }
.