Search
lxdream.org :: lxdream/src/aica/armcore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 66:2ec5b6eb75e5
prev63:be4fec751961
next73:0bb57e51ac9e
author nkeynes
date Tue Jan 10 13:59:19 2006 +0000 (18 years ago)
permissions -rw-r--r--
last change Include sh4core.h (needed to compile)
view annotate diff log raw
     1 /**
     2  * $Id: armcore.c,v 1.16 2006-01-10 13:56:54 nkeynes Exp $
     3  * 
     4  * ARM7TDMI CPU emulation core.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #define MODULE aica_module
    20 #include "dream.h"
    21 #include "aica/armcore.h"
    22 #include "mem.h"
    24 #define STM_R15_OFFSET 12
    26 struct arm_registers armr;
    28 void arm_set_mode( int mode );
    30 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
    31 				{ MODE_UND, 0x00000004 },
    32 				{ MODE_SVC, 0x00000008 },
    33 				{ MODE_ABT, 0x0000000C },
    34 				{ MODE_ABT, 0x00000010 },
    35 				{ MODE_IRQ, 0x00000018 },
    36 				{ MODE_FIQ, 0x0000001C } };
    38 #define EXC_RESET 0
    39 #define EXC_UNDEFINED 1
    40 #define EXC_SOFTWARE 2
    41 #define EXC_PREFETCH_ABORT 3
    42 #define EXC_DATA_ABORT 4
    43 #define EXC_IRQ 5
    44 #define EXC_FAST_IRQ 6
    46 uint32_t arm_cpu_freq = ARM_BASE_RATE;
    47 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
    50 static struct breakpoint_struct arm_breakpoints[MAX_BREAKPOINTS];
    51 static int arm_breakpoint_count = 0;
    53 void arm_set_breakpoint( uint32_t pc, int type )
    54 {
    55     arm_breakpoints[arm_breakpoint_count].address = pc;
    56     arm_breakpoints[arm_breakpoint_count].type = type;
    57     arm_breakpoint_count++;
    58 }
    60 gboolean arm_clear_breakpoint( uint32_t pc, int type )
    61 {
    62     int i;
    64     for( i=0; i<arm_breakpoint_count; i++ ) {
    65 	if( arm_breakpoints[i].address == pc && 
    66 	    arm_breakpoints[i].type == type ) {
    67 	    while( ++i < arm_breakpoint_count ) {
    68 		arm_breakpoints[i-1].address = arm_breakpoints[i].address;
    69 		arm_breakpoints[i-1].type = arm_breakpoints[i].type;
    70 	    }
    71 	    arm_breakpoint_count--;
    72 	    return TRUE;
    73 	}
    74     }
    75     return FALSE;
    76 }
    78 int arm_get_breakpoint( uint32_t pc )
    79 {
    80     int i;
    81     for( i=0; i<arm_breakpoint_count; i++ ) {
    82 	if( arm_breakpoints[i].address == pc )
    83 	    return arm_breakpoints[i].type;
    84     }
    85     return 0;
    86 }
    88 uint32_t arm_run_slice( uint32_t nanosecs )
    89 {
    90     int i;
    91     uint32_t target = armr.icount + nanosecs / arm_cpu_period;
    92     uint32_t start = armr.icount;
    93     while( armr.icount < target ) {
    94 	armr.icount++;
    95 	if( !arm_execute_instruction() )
    96 	    break;
    97 #ifdef ENABLE_DEBUG_MODE
    98 	for( i=0; i<arm_breakpoint_count; i++ ) {
    99 	    if( arm_breakpoints[i].address == armr.r[15] ) {
   100 		break;
   101 	    }
   102 	}
   103 	if( i != arm_breakpoint_count ) {
   104 	    dreamcast_stop();
   105 	    if( arm_breakpoints[i].type == BREAK_ONESHOT )
   106 		arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );
   107 	    break;
   108 	}
   109 #endif	
   110     }
   112     if( target != armr.icount ) {
   113 	/* Halted - compute time actually executed */
   114 	nanosecs = (armr.icount - start) * arm_cpu_period;
   115     }
   116     return nanosecs;
   117 }
   119 void arm_save_state( FILE *f )
   120 {
   121     fwrite( &armr, sizeof(armr), 1, f );
   122 }
   124 int arm_load_state( FILE *f )
   125 {
   126     fread( &armr, sizeof(armr), 1, f );
   127     return 0;
   128 }
   130 /* Exceptions */
   131 void arm_reset( void )
   132 {
   133     /* Wipe all processor state */
   134     memset( &armr, 0, sizeof(armr) );
   136     armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
   137     armr.r[15] = 0x00000000;
   138 }
   140 #define SET_CPSR_CONTROL   0x00010000
   141 #define SET_CPSR_EXTENSION 0x00020000
   142 #define SET_CPSR_STATUS    0x00040000
   143 #define SET_CPSR_FLAGS     0x00080000
   145 uint32_t arm_get_cpsr( void )
   146 {
   147     /* write back all flags to the cpsr */
   148     armr.cpsr = armr.cpsr & CPSR_COMPACT_MASK;
   149     if( armr.n ) armr.cpsr |= CPSR_N;
   150     if( armr.z ) armr.cpsr |= CPSR_Z;
   151     if( armr.c ) armr.cpsr |= CPSR_C;
   152     if( armr.v ) armr.cpsr |= CPSR_V;
   153     if( armr.t ) armr.cpsr |= CPSR_T;  
   154     return armr.cpsr;
   155 }
   157 /**
   158  * Return a pointer to the specified register in the user bank,
   159  * regardless of the active bank
   160  */
   161 static uint32_t *arm_user_reg( int reg )
   162 {
   163     if( IS_EXCEPTION_MODE() ) {
   164 	if( reg == 13 || reg == 14 )
   165 	    return &armr.user_r[reg-8];
   166 	if( IS_FIQ_MODE() ) {
   167 	    if( reg >= 8 || reg <= 12 )
   168 		return &armr.user_r[reg-8];
   169 	}
   170     }
   171     return &armr.r[reg];
   172 }
   174 #define USER_R(n) *arm_user_reg(n)
   176 /**
   177  * Set the CPSR to the specified value.
   178  *
   179  * @param value values to set in CPSR
   180  * @param fields set of mask values to define which sections of the 
   181  *   CPSR to set (one of the SET_CPSR_* values above)
   182  */
   183 void arm_set_cpsr( uint32_t value, uint32_t fields )
   184 {
   185     if( IS_PRIVILEGED_MODE() ) {
   186 	if( fields & SET_CPSR_CONTROL ) {
   187 	    int mode = value & CPSR_MODE;
   188 	    arm_set_mode( mode );
   189 	    armr.t = ( value & CPSR_T ); /* Technically illegal to change */
   190 	    armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
   191 	}
   193 	/* Middle 16 bits not currently defined */
   194     }
   195     if( fields & SET_CPSR_FLAGS ) {
   196 	/* Break flags directly out of given value - don't bother writing
   197 	 * back to CPSR 
   198 	 */
   199 	armr.n = ( value & CPSR_N );
   200 	armr.z = ( value & CPSR_Z );
   201 	armr.c = ( value & CPSR_C );
   202 	armr.v = ( value & CPSR_V );
   203     }
   204 }
   206 void arm_set_spsr( uint32_t value, uint32_t fields )
   207 {
   208     /* Only defined if we actually have an SPSR register */
   209     if( IS_EXCEPTION_MODE() ) {
   210 	if( fields & SET_CPSR_CONTROL ) {
   211 	    armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
   212 	}
   214 	/* Middle 16 bits not currently defined */
   216 	if( fields & SET_CPSR_FLAGS ) {
   217 	    armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
   218 	}
   219     }
   220 }
   222 /**
   223  * Raise an ARM exception (other than reset, which uses arm_reset().
   224  * @param exception one of the EXC_* exception codes defined above.
   225  */
   226 void arm_raise_exception( int exception )
   227 {
   228     int mode = arm_exceptions[exception][0];
   229     uint32_t spsr = arm_get_cpsr();
   230     arm_set_mode( mode );
   231     armr.spsr = spsr;
   232     armr.r[14] = armr.r[15] + 4;
   233     armr.cpsr = (spsr & 0xFFFFFF00) | mode | CPSR_I; 
   234     if( mode == MODE_FIQ )
   235 	armr.cpsr |= CPSR_F;
   236     armr.r[15] = arm_exceptions[exception][1];
   237 }
   239 void arm_restore_cpsr( void )
   240 {
   241     int spsr = armr.spsr;
   242     int mode = spsr & CPSR_MODE;
   243     arm_set_mode( mode );
   244     armr.cpsr = spsr;
   245     armr.n = ( spsr & CPSR_N );
   246     armr.z = ( spsr & CPSR_Z );
   247     armr.c = ( spsr & CPSR_C );
   248     armr.v = ( spsr & CPSR_V );
   249     armr.t = ( spsr & CPSR_T );
   250 }
   254 /**
   255  * Change the current executing ARM mode to the requested mode.
   256  * Saves any required registers to banks and restores those for the
   257  * correct mode. (Note does not actually update CPSR at the moment).
   258  */
   259 void arm_set_mode( int targetMode )
   260 {
   261     int currentMode = armr.cpsr & CPSR_MODE;
   262     if( currentMode == targetMode )
   263 	return;
   265     switch( currentMode ) {
   266     case MODE_USER:
   267     case MODE_SYS:
   268 	armr.user_r[5] = armr.r[13];
   269 	armr.user_r[6] = armr.r[14];
   270 	break;
   271     case MODE_SVC:
   272 	armr.svc_r[0] = armr.r[13];
   273 	armr.svc_r[1] = armr.r[14];
   274 	armr.svc_r[2] = armr.spsr;
   275 	break;
   276     case MODE_ABT:
   277 	armr.abt_r[0] = armr.r[13];
   278 	armr.abt_r[1] = armr.r[14];
   279 	armr.abt_r[2] = armr.spsr;
   280 	break;
   281     case MODE_UND:
   282 	armr.und_r[0] = armr.r[13];
   283 	armr.und_r[1] = armr.r[14];
   284 	armr.und_r[2] = armr.spsr;
   285 	break;
   286     case MODE_IRQ:
   287 	armr.irq_r[0] = armr.r[13];
   288 	armr.irq_r[1] = armr.r[14];
   289 	armr.irq_r[2] = armr.spsr;
   290 	break;
   291     case MODE_FIQ:
   292 	armr.fiq_r[0] = armr.r[8];
   293 	armr.fiq_r[1] = armr.r[9];
   294 	armr.fiq_r[2] = armr.r[10];
   295 	armr.fiq_r[3] = armr.r[11];
   296 	armr.fiq_r[4] = armr.r[12];
   297 	armr.fiq_r[5] = armr.r[13];
   298 	armr.fiq_r[6] = armr.r[14];
   299 	armr.fiq_r[7] = armr.spsr;
   300 	armr.r[8] = armr.user_r[0];
   301 	armr.r[9] = armr.user_r[1];
   302 	armr.r[10] = armr.user_r[2];
   303 	armr.r[11] = armr.user_r[3];
   304 	armr.r[12] = armr.user_r[4];
   305 	break;
   306     }
   308     switch( targetMode ) {
   309     case MODE_USER:
   310     case MODE_SYS:
   311 	armr.r[13] = armr.user_r[5];
   312 	armr.r[14] = armr.user_r[6];
   313 	break;
   314     case MODE_SVC:
   315 	armr.r[13] = armr.svc_r[0];
   316 	armr.r[14] = armr.svc_r[1];
   317 	armr.spsr = armr.svc_r[2];
   318 	break;
   319     case MODE_ABT:
   320 	armr.r[13] = armr.abt_r[0];
   321 	armr.r[14] = armr.abt_r[1];
   322 	armr.spsr = armr.abt_r[2];
   323 	break;
   324     case MODE_UND:
   325 	armr.r[13] = armr.und_r[0];
   326 	armr.r[14] = armr.und_r[1];
   327 	armr.spsr = armr.und_r[2];
   328 	break;
   329     case MODE_IRQ:
   330 	armr.r[13] = armr.irq_r[0];
   331 	armr.r[14] = armr.irq_r[1];
   332 	armr.spsr = armr.irq_r[2];
   333 	break;
   334     case MODE_FIQ:
   335 	armr.user_r[0] = armr.r[8];
   336 	armr.user_r[1] = armr.r[9];
   337 	armr.user_r[2] = armr.r[10];
   338 	armr.user_r[3] = armr.r[11];
   339 	armr.user_r[4] = armr.r[12];
   340 	armr.r[8] = armr.fiq_r[0];
   341 	armr.r[9] = armr.fiq_r[1];
   342 	armr.r[10] = armr.fiq_r[2];
   343 	armr.r[11] = armr.fiq_r[3];
   344 	armr.r[12] = armr.fiq_r[4];
   345 	armr.r[13] = armr.fiq_r[5];
   346 	armr.r[14] = armr.fiq_r[6];
   347 	armr.spsr = armr.fiq_r[7];
   348 	break;
   349     }
   350 }
   352 /* Page references are as per ARM DDI 0100E (June 2000) */
   354 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
   355 #define MEM_READ_WORD( addr ) arm_read_word(addr)
   356 #define MEM_READ_LONG( addr ) arm_read_long(addr)
   357 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
   358 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
   359 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
   362 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
   363 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
   364 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
   365 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
   367 #define PC armr.r[15]
   369 /* Instruction fields */
   370 #define COND(ir) (ir>>28)
   371 #define GRP(ir) ((ir>>26)&0x03)
   372 #define OPCODE(ir) ((ir>>20)&0x1F)
   373 #define IFLAG(ir) (ir&0x02000000)
   374 #define SFLAG(ir) (ir&0x00100000)
   375 #define PFLAG(ir) (ir&0x01000000)
   376 #define UFLAG(ir) (ir&0x00800000)
   377 #define BFLAG(ir) (ir&0x00400000)
   378 #define WFLAG(ir) (ir&0x00200000)
   379 #define LFLAG(ir) SFLAG(ir)
   380 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   381 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))
   382 #define RDn(ir) ((ir>>12)&0x0F)
   383 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))
   384 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )
   385 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
   386 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
   387 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
   388 #define LRM(ir) armr.r[(ir&0x0F)]
   390 #define IMM8(ir) (ir&0xFF)
   391 #define IMM12(ir) (ir&0xFFF)
   392 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
   393 #define IMMROT(ir) ((ir>>7)&0x1E)
   394 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
   395 #define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
   396 #define SHIFT(ir) ((ir>>4)&0x07)
   397 #define DISP24(ir) ((ir&0x00FFFFFF))
   398 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
   399 #define UNIMP(ir) do{ PC-=4; ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); dreamcast_stop(); return FALSE; }while(0)
   401 /**
   402  * Determine the value of the shift-operand for a data processing instruction,
   403  * without determing a value for shift_C (optimized form for instructions that
   404  * don't require shift_C ).
   405  * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
   406  */
   407 static uint32_t arm_get_shift_operand( uint32_t ir )
   408 {
   409 	uint32_t operand, tmp;
   410 	if( IFLAG(ir) == 0 ) {
   411 		operand = RM(ir);
   412 		switch(SHIFT(ir)) {
   413 		case 0: /* (Rm << imm) */
   414 			operand = operand << SHIFTIMM(ir);
   415 			break;
   416 		case 1: /* (Rm << Rs) */
   417 			tmp = RS(ir)&0xFF;
   418 			if( tmp > 31 ) operand = 0;
   419 			else operand = operand << tmp;
   420 			break;
   421 		case 2: /* (Rm >> imm) */
   422 			operand = operand >> SHIFTIMM(ir);
   423 			break;
   424 		case 3: /* (Rm >> Rs) */
   425 			tmp = RS(ir) & 0xFF;
   426 			if( tmp > 31 ) operand = 0;
   427 			else operand = operand >> ir;
   428 			break;
   429 		case 4: /* (Rm >>> imm) */
   430 			tmp = SHIFTIMM(ir);
   431 			if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   432 			else operand = ((int32_t)operand) >> tmp;
   433 			break;
   434 		case 5: /* (Rm >>> Rs) */
   435 			tmp = RS(ir) & 0xFF;
   436 			if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
   437 			else operand = ((int32_t)operand) >> tmp;
   438 			break;
   439 		case 6:
   440 			tmp = SHIFTIMM(ir);
   441 			if( tmp == 0 ) /* RRX aka rotate with carry */
   442 				operand = (operand >> 1) | (armr.c<<31);
   443 			else
   444 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   445 			break;
   446 		case 7:
   447 			tmp = RS(ir)&0x1F;
   448 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   449 			break;
   450 		}
   451 	} else {
   452 		operand = IMM8(ir);
   453 		tmp = IMMROT(ir);
   454 		operand = ROTATE_RIGHT_LONG(operand, tmp);
   455 	}
   456 	return operand;
   457 }
   459 /**
   460  * Determine the value of the shift-operand for a data processing instruction,
   461  * and set armr.shift_c accordingly.
   462  * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
   463  */
   464 static uint32_t arm_get_shift_operand_s( uint32_t ir )
   465 {
   466 	uint32_t operand, tmp;
   467 	if( IFLAG(ir) == 0 ) {
   468 		operand = RM(ir);
   469 		switch(SHIFT(ir)) {
   470 		case 0: /* (Rm << imm) */
   471 			tmp = SHIFTIMM(ir);
   472 			if( tmp == 0 ) { /* Rm */
   473 				armr.shift_c = armr.c;
   474 			} else { /* Rm << imm */
   475 				armr.shift_c = (operand >> (32-tmp)) & 0x01;
   476 				operand = operand << tmp;
   477 			}
   478 			break;
   479 		case 1: /* (Rm << Rs) */
   480 			tmp = RS(ir)&0xFF;
   481 			if( tmp == 0 ) {
   482 				armr.shift_c = armr.c;
   483 			} else {
   484 				if( tmp <= 32 )
   485 					armr.shift_c = (operand >> (32-tmp)) & 0x01;
   486 				else armr.shift_c = 0;
   487 				if( tmp < 32 )
   488 					operand = operand << tmp;
   489 				else operand = 0;
   490 			}
   491 			break;
   492 		case 2: /* (Rm >> imm) */
   493 			tmp = SHIFTIMM(ir);
   494 			if( tmp == 0 ) {
   495 				armr.shift_c = operand >> 31;
   496 				operand = 0;
   497 			} else {
   498 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   499 				operand = RM(ir) >> tmp;
   500 			}
   501 			break;
   502 		case 3: /* (Rm >> Rs) */
   503 			tmp = RS(ir) & 0xFF;
   504 			if( tmp == 0 ) {
   505 				armr.shift_c = armr.c;
   506 			} else {
   507 				if( tmp <= 32 )
   508 					armr.shift_c = (operand >> (tmp-1))&0x01;
   509 				else armr.shift_c = 0;
   510 				if( tmp < 32 )
   511 					operand = operand >> tmp;
   512 				else operand = 0;
   513 			}
   514 			break;
   515 		case 4: /* (Rm >>> imm) */
   516 			tmp = SHIFTIMM(ir);
   517 			if( tmp == 0 ) {
   518 				armr.shift_c = operand >> 31;
   519 				operand = -armr.shift_c;
   520 			} else {
   521 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   522 				operand = ((int32_t)operand) >> tmp;
   523 			}
   524 			break;
   525 		case 5: /* (Rm >>> Rs) */
   526 			tmp = RS(ir) & 0xFF;
   527 			if( tmp == 0 ) {
   528 				armr.shift_c = armr.c;
   529 			} else {
   530 				if( tmp < 32 ) {
   531 					armr.shift_c = (operand >> (tmp-1))&0x01;
   532 					operand = ((int32_t)operand) >> tmp;
   533 				} else {
   534 					armr.shift_c = operand >> 31;
   535 					operand = ((int32_t)operand) >> 31;
   536 				}
   537 			}
   538 			break;
   539 		case 6:
   540 			tmp = SHIFTIMM(ir);
   541 			if( tmp == 0 ) { /* RRX aka rotate with carry */
   542 				armr.shift_c = operand&0x01;
   543 				operand = (operand >> 1) | (armr.c<<31);
   544 			} else {
   545 				armr.shift_c = operand>>(tmp-1);
   546 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   547 			}
   548 			break;
   549 		case 7:
   550 			tmp = RS(ir)&0xFF;
   551 			if( tmp == 0 ) {
   552 				armr.shift_c = armr.c;
   553 			} else {
   554 				tmp &= 0x1F;
   555 				if( tmp == 0 ) {
   556 					armr.shift_c = operand>>31;
   557 				} else {
   558 					armr.shift_c = (operand>>(tmp-1))&0x1;
   559 					operand = ROTATE_RIGHT_LONG(operand,tmp);
   560 				}
   561 			}
   562 			break;
   563 		}
   564 	} else {
   565 		operand = IMM8(ir);
   566 		tmp = IMMROT(ir);
   567 		if( tmp == 0 ) {
   568 			armr.shift_c = armr.c;
   569 		} else {
   570 			operand = ROTATE_RIGHT_LONG(operand, tmp);
   571 			armr.shift_c = operand>>31;
   572 		}
   573 	}
   574 	return operand;
   575 }
   577 /**
   578  * Another variant of the shifter code for index-based memory addressing.
   579  * Distinguished by the fact that it doesn't support register shifts, and
   580  * ignores the I flag (WTF do the load/store instructions use the I flag to
   581  * mean the _exact opposite_ of what it means for the data processing 
   582  * instructions ???)
   583  */
   584 static uint32_t arm_get_address_index( uint32_t ir )
   585 {
   586 	uint32_t operand = RM(ir);
   587 	uint32_t tmp;
   589 	switch(SHIFT(ir)) {
   590 	case 0: /* (Rm << imm) */
   591 		operand = operand << SHIFTIMM(ir);
   592 		break;
   593 	case 2: /* (Rm >> imm) */
   594 		operand = operand >> SHIFTIMM(ir);
   595 		break;
   596 	case 4: /* (Rm >>> imm) */
   597 		tmp = SHIFTIMM(ir);
   598 		if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   599 		else operand = ((int32_t)operand) >> tmp;
   600 		break;
   601 	case 6:
   602 		tmp = SHIFTIMM(ir);
   603 		if( tmp == 0 ) /* RRX aka rotate with carry */
   604 			operand = (operand >> 1) | (armr.c<<31);
   605 		else
   606 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   607 		break;
   608 	default: UNIMP(ir);
   609 	}
   610 	return operand;	
   611 }
   613 /**
   614  * Determine the address operand of a load/store instruction, including
   615  * applying any pre/post adjustments to the address registers.
   616  * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
   617  * @param The instruction word.
   618  * @return The calculated address
   619  */
   620 static uint32_t arm_get_address_operand( uint32_t ir )
   621 {
   622 	uint32_t addr;
   624 	/* I P U . W */
   625 	switch( (ir>>21)&0x1D ) {
   626 	case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   627 	case 1:
   628 		addr = RN(ir);
   629 		LRN(ir) = addr - IMM12(ir);
   630 		break;
   631 	case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
   632 	case 5:
   633 		addr = RN(ir);
   634 		LRN(ir) = addr + IMM12(ir);
   635 		break;
   636 	case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   637 		addr = RN(ir) - IMM12(ir);
   638 		break;
   639 	case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   640 		addr = RN(ir) - IMM12(ir);
   641 		LRN(ir) = addr;
   642 		break;
   643 	case 12: /* Rn + imm offset  [5.2.2 A5-20] */
   644 		addr = RN(ir) + IMM12(ir);
   645 		break;
   646 	case 13: /* Rn += imm offset  [5.2.5 A5-24 ] */
   647 		addr = RN(ir) + IMM12(ir);
   648 		LRN(ir) = addr;
   649 		break;
   650 	case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   651 	case 17:
   652 		addr = RN(ir);
   653 		LRN(ir) = addr - arm_get_address_index(ir);
   654 		break;
   655 	case 20: /* Rn += Rm (post-indexed)  [5.2.10 A5-32 ] */
   656 	case 21:
   657 		addr = RN(ir);
   658 		LRN(ir) = addr - arm_get_address_index(ir);
   659 		break;
   660 	case 24: /* Rn - Rm  [5.2.4 A5-23] */
   661 		addr = RN(ir) - arm_get_address_index(ir);
   662 		break;
   663 	case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   664 		addr = RN(ir) - arm_get_address_index(ir);
   665 		LRN(ir) = addr;
   666 		break;
   667 	case 28: /* Rn + Rm  [5.2.4 A5-23] */
   668 		addr = RN(ir) + arm_get_address_index(ir);
   669 		break;
   670 	case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
   671 		addr = RN(ir) + arm_get_address_index(ir);
   672 		LRN(ir) = addr;
   673 		break;
   674 	}
   675 	return addr;
   676 }
   678 gboolean arm_execute_instruction( void ) 
   679 {
   680     uint32_t pc;
   681     uint32_t ir;
   682     uint32_t operand, operand2, tmp, tmp2, cond;
   683     int i;
   685     tmp = armr.int_pending & (~armr.cpsr);
   686     if( tmp ) {
   687 	if( tmp & CPSR_F ) {
   688 	    arm_raise_exception( EXC_FAST_IRQ );
   689 	} else {
   690 	    arm_raise_exception( EXC_IRQ );
   691 	}
   692     }
   694     ir = MEM_READ_LONG(PC);
   695     pc = PC + 4;
   696     PC = pc;
   698     /** 
   699      * Check the condition bits first - if the condition fails return 
   700      * immediately without actually looking at the rest of the instruction.
   701      */
   702     switch( COND(ir) ) {
   703     case 0: /* EQ */ 
   704 	cond = armr.z;
   705 	break;
   706     case 1: /* NE */
   707 	cond = !armr.z;
   708 	break;
   709     case 2: /* CS/HS */
   710 	cond = armr.c;
   711 	break;
   712     case 3: /* CC/LO */
   713 	cond = !armr.c;
   714 	break;
   715     case 4: /* MI */
   716 	cond = armr.n;
   717 	break;
   718     case 5: /* PL */
   719 	cond = !armr.n;
   720 	break;
   721     case 6: /* VS */
   722 	cond = armr.v;
   723 	break;
   724     case 7: /* VC */
   725 	cond = !armr.v;
   726 	break;
   727     case 8: /* HI */
   728 	cond = armr.c && !armr.z;
   729 	break;
   730     case 9: /* LS */
   731 	cond = (!armr.c) || armr.z;
   732 	break;
   733     case 10: /* GE */
   734 	cond = (armr.n == armr.v);
   735 	break;
   736     case 11: /* LT */
   737 	cond = (armr.n != armr.v);
   738 	break;
   739     case 12: /* GT */
   740 	cond = (!armr.z) && (armr.n == armr.v);
   741 	break;
   742     case 13: /* LE */
   743 	cond = armr.z || (armr.n != armr.v);
   744 	break;
   745     case 14: /* AL */
   746 	cond = 1;
   747 	break;
   748     case 15: /* (NV) */
   749 	cond = 0;
   750 	UNDEF(ir);
   751     }
   752     if( !cond )
   753 	return TRUE;
   755     /**
   756      * Condition passed, now for the actual instructions...
   757      */
   758     switch( GRP(ir) ) {
   759     case 0:
   760 	if( (ir & 0x0D900000) == 0x01000000 ) {
   761 	    /* Instructions that aren't actual data processing even though
   762 	     * they sit in the DP instruction block.
   763 	     */
   764 	    switch( ir & 0x0FF000F0 ) {
   765 	    case 0x01200010: /* BX Rd */
   766 		armr.t = ir & 0x01;
   767 		armr.r[15] = RM(ir) & 0xFFFFFFFE;
   768 		break;
   769 	    case 0x01000000: /* MRS Rd, CPSR */
   770 		LRD(ir) = arm_get_cpsr();
   771 		break;
   772 	    case 0x01400000: /* MRS Rd, SPSR */
   773 		LRD(ir) = armr.spsr;
   774 		break;
   775 	    case 0x01200000: /* MSR CPSR, Rd */
   776 		arm_set_cpsr( RM(ir), ir );
   777 		break;
   778 	    case 0x01600000: /* MSR SPSR, Rd */
   779 		arm_set_spsr( RM(ir), ir );
   780 		break;
   781 	    case 0x03200000: /* MSR CPSR, imm */
   782 		arm_set_cpsr( ROTIMM12(ir), ir );
   783 		break;
   784 	    case 0x03600000: /* MSR SPSR, imm */
   785 		arm_set_spsr( ROTIMM12(ir), ir );
   786 		break;
   787 	    default:
   788 		UNIMP(ir);
   789 	    }
   790 	} else if( (ir & 0x0E000090) == 0x00000090 ) {
   791 	    /* Neither are these */
   792 	    switch( (ir>>5)&0x03 ) {
   793 	    case 0:
   794 		/* Arithmetic extension area */
   795 		switch(OPCODE(ir)) {
   796 		case 0: /* MUL */
   797 		    LRN(ir) = RM(ir) * RS(ir);
   798 		    break;
   799 		case 1: /* MULS */
   800 		    tmp = RM(ir) * RS(ir);
   801 		    LRN(ir) = tmp;
   802 		    armr.n = tmp>>31;
   803 		    armr.z = (tmp == 0);
   804 		    break;
   805 		case 2: /* MLA */
   806 		    LRN(ir) = RM(ir) * RS(ir) + RD(ir);
   807 		    break;
   808 		case 3: /* MLAS */
   809 		    tmp = RM(ir) * RS(ir) + RD(ir);
   810 		    LRN(ir) = tmp;
   811 		    armr.n = tmp>>31;
   812 		    armr.z = (tmp == 0);
   813 		    break;
   814 		case 8: /* UMULL */
   815 		case 9: /* UMULLS */
   816 		case 10: /* UMLAL */
   817 		case 11: /* UMLALS */
   818 		case 12: /* SMULL */
   819 		case 13: /* SMULLS */
   820 		case 14: /* SMLAL */
   821 		case 15: /* SMLALS */
   822 		    UNIMP(ir);
   823 		    break;
   824 		case 16: /* SWP */
   825 		    tmp = arm_read_long( RN(ir) );
   826 		    switch( RN(ir) & 0x03 ) {
   827 		    case 1:
   828 			tmp = ROTATE_RIGHT_LONG(tmp, 8);
   829 			break;
   830 		    case 2:
   831 			tmp = ROTATE_RIGHT_LONG(tmp, 16);
   832 			break;
   833 		    case 3:
   834 			tmp = ROTATE_RIGHT_LONG(tmp, 24);
   835 			break;
   836 		    }
   837 		    arm_write_long( RN(ir), RM(ir) );
   838 		    LRD(ir) = tmp;
   839 		    break;
   840 		case 20: /* SWPB */
   841 		    tmp = arm_read_byte( RN(ir) );
   842 		    arm_write_byte( RN(ir), RM(ir) );
   843 		    LRD(ir) = tmp;
   844 		    break;
   845 		default:
   846 		    UNIMP(ir);
   847 		}
   848 		break;
   849 	    case 1:
   850 		if( LFLAG(ir) ) {
   851 		    /* LDRH */
   852 		} else {
   853 		    /* STRH */
   854 		}
   855 		UNIMP(ir);
   856 		break;
   857 	    case 2:
   858 		if( LFLAG(ir) ) {
   859 		    /* LDRSB */
   860 		} else {
   861 		}
   862 		UNIMP(ir);
   863 		break;
   864 	    case 3:
   865 		if( LFLAG(ir) ) {
   866 		    /* LDRSH */
   867 		} else {
   868 		}
   869 		UNIMP(ir);
   870 		break;
   871 	    }
   872 	} else {
   873 	    /* Data processing */
   875 	    switch(OPCODE(ir)) {
   876 	    case 0: /* AND Rd, Rn, operand */
   877 		LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
   878 		break;
   879 	    case 1: /* ANDS Rd, Rn, operand */
   880 		operand = arm_get_shift_operand_s(ir) & RN(ir);
   881 		LRD(ir) = operand;
   882 		if( RDn(ir) == 15 ) {
   883 		    arm_restore_cpsr();
   884 		} else {
   885 		    armr.n = operand>>31;
   886 		    armr.z = (operand == 0);
   887 		    armr.c = armr.shift_c;
   888 		}
   889 		break;
   890 	    case 2: /* EOR Rd, Rn, operand */
   891 		LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
   892 		break;
   893 	    case 3: /* EORS Rd, Rn, operand */
   894 		operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   895 		LRD(ir) = operand;
   896 		if( RDn(ir) == 15 ) {
   897 		    arm_restore_cpsr();
   898 		} else {
   899 		    armr.n = operand>>31;
   900 		    armr.z = (operand == 0);
   901 		    armr.c = armr.shift_c;
   902 		}
   903 		break;
   904 	    case 4: /* SUB Rd, Rn, operand */
   905 		LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
   906 		break;
   907 	    case 5: /* SUBS Rd, Rn, operand */
   908 		operand = RN(ir);
   909 		operand2 = arm_get_shift_operand(ir);
   910 		tmp = operand - operand2;
   911 		LRD(ir) = tmp;
   912 		if( RDn(ir) == 15 ) {
   913 		    arm_restore_cpsr();
   914 		} else {
   915 		    armr.n = tmp>>31;
   916 		    armr.z = (tmp == 0);
   917 		    armr.c = IS_NOTBORROW(tmp,operand,operand2);
   918 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   919 		}
   920 		break;
   921 	    case 6: /* RSB Rd, operand, Rn */
   922 		LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
   923 		break;
   924 	    case 7: /* RSBS Rd, operand, Rn */
   925 		operand = arm_get_shift_operand(ir);
   926 		operand2 = RN(ir);
   927 		tmp = operand - operand2;
   928 		LRD(ir) = tmp;
   929 		if( RDn(ir) == 15 ) {
   930 		    arm_restore_cpsr();
   931 		} else {
   932 		    armr.n = tmp>>31;
   933 		    armr.z = (tmp == 0);
   934 		    armr.c = IS_NOTBORROW(tmp,operand,operand2);
   935 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   936 		}
   937 		break;
   938 	    case 8: /* ADD Rd, Rn, operand */
   939 		LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
   940 		break;
   941 	    case 9: /* ADDS Rd, Rn, operand */
   942 		operand = arm_get_shift_operand(ir);
   943 		operand2 = RN(ir);
   944 		tmp = operand + operand2;
   945 		LRD(ir) = tmp;
   946 		if( RDn(ir) == 15 ) {
   947 		    arm_restore_cpsr();
   948 		} else {
   949 		    armr.n = tmp>>31;
   950 		    armr.z = (tmp == 0);
   951 		    armr.c = IS_CARRY(tmp,operand,operand2);
   952 		    armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   953 		}
   954 		break;			
   955 	    case 10: /* ADC */
   956 		LRD(ir) = RN(ir) + arm_get_shift_operand(ir) + 
   957 		    (armr.c ? 1 : 0);
   958 		break;
   959 	    case 11: /* ADCS */
   960 		operand = arm_get_shift_operand(ir);
   961 		operand2 = RN(ir);
   962 		tmp = operand + operand2;
   963 		tmp2 = tmp + armr.c ? 1 : 0;
   964 		LRD(ir) = tmp2;
   965 		if( RDn(ir) == 15 ) {
   966 		    arm_restore_cpsr();
   967 		} else {
   968 		    armr.n = tmp >> 31;
   969 		    armr.z = (tmp == 0 );
   970 		    armr.c = IS_CARRY(tmp,operand,operand2) ||
   971 			(tmp2 < tmp);
   972 		    armr.v = IS_ADDOVERFLOW(tmp,operand, operand2) ||
   973 			((tmp&0x80000000) != (tmp2&0x80000000));
   974 		}
   975 		break;
   976 	    case 12: /* SBC */
   977 		LRD(ir) = RN(ir) - arm_get_shift_operand(ir) - 
   978 		    (armr.c ? 0 : 1);
   979 		break;
   980 	    case 13: /* SBCS */
   981 		operand = RN(ir);
   982 		operand2 = arm_get_shift_operand(ir);
   983 		tmp = operand - operand2;
   984 		tmp2 = tmp - (armr.c ? 0 : 1);
   985 		if( RDn(ir) == 15 ) {
   986 		    arm_restore_cpsr();
   987 		} else {
   988 		    armr.n = tmp >> 31;
   989 		    armr.z = (tmp == 0 );
   990 		    armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
   991 			(tmp2<tmp);
   992 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
   993 			((tmp&0x80000000) != (tmp2&0x80000000));
   994 		}
   995 		break;
   996 	    case 14: /* RSC */
   997 		LRD(ir) = arm_get_shift_operand(ir) - RN(ir) -
   998 		    (armr.c ? 0 : 1);
   999 		break;
  1000 	    case 15: /* RSCS */
  1001 		operand = arm_get_shift_operand(ir);
  1002 		operand2 = RN(ir);
  1003 		tmp = operand - operand2;
  1004 		tmp2 = tmp - (armr.c ? 0 : 1);
  1005 		if( RDn(ir) == 15 ) {
  1006 		    arm_restore_cpsr();
  1007 		} else {
  1008 		    armr.n = tmp >> 31;
  1009 		    armr.z = (tmp == 0 );
  1010 		    armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
  1011 			(tmp2<tmp);
  1012 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
  1013 			((tmp&0x80000000) != (tmp2&0x80000000));
  1015 		break;
  1016 	    case 17: /* TST Rn, operand */
  1017 		operand = arm_get_shift_operand_s(ir) & RN(ir);
  1018 		armr.n = operand>>31;
  1019 		armr.z = (operand == 0);
  1020 		armr.c = armr.shift_c;
  1021 		break;
  1022 	    case 19: /* TEQ Rn, operand */
  1023 		operand = arm_get_shift_operand_s(ir) ^ RN(ir);
  1024 		armr.n = operand>>31;
  1025 		armr.z = (operand == 0);
  1026 		armr.c = armr.shift_c;
  1027 		break;				
  1028 	    case 21: /* CMP Rn, operand */
  1029 		operand = RN(ir);
  1030 		operand2 = arm_get_shift_operand(ir);
  1031 		tmp = operand - operand2;
  1032 		armr.n = tmp>>31;
  1033 		armr.z = (tmp == 0);
  1034 		armr.c = IS_NOTBORROW(tmp,operand,operand2);
  1035 		armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
  1036 		break;
  1037 	    case 23: /* CMN Rn, operand */
  1038 		operand = RN(ir);
  1039 		operand2 = arm_get_shift_operand(ir);
  1040 		tmp = operand + operand2;
  1041 		armr.n = tmp>>31;
  1042 		armr.z = (tmp == 0);
  1043 		armr.c = IS_CARRY(tmp,operand,operand2);
  1044 		armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
  1045 		break;
  1046 	    case 24: /* ORR Rd, Rn, operand */
  1047 		LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
  1048 		break;
  1049 	    case 25: /* ORRS Rd, Rn, operand */
  1050 		operand = arm_get_shift_operand_s(ir) | RN(ir);
  1051 		LRD(ir) = operand;
  1052 		if( RDn(ir) == 15 ) {
  1053 		    arm_restore_cpsr();
  1054 		} else {
  1055 		    armr.n = operand>>31;
  1056 		    armr.z = (operand == 0);
  1057 		    armr.c = armr.shift_c;
  1059 		break;
  1060 	    case 26: /* MOV Rd, operand */
  1061 		LRD(ir) = arm_get_shift_operand(ir);
  1062 		break;
  1063 	    case 27: /* MOVS Rd, operand */
  1064 		operand = arm_get_shift_operand_s(ir);
  1065 		LRD(ir) = operand;
  1066 		if( RDn(ir) == 15 ) {
  1067 		    arm_restore_cpsr();
  1068 		} else {
  1069 		    armr.n = operand>>31;
  1070 		    armr.z = (operand == 0);
  1071 		    armr.c = armr.shift_c;
  1073 		break;
  1074 	    case 28: /* BIC Rd, Rn, operand */
  1075 		LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
  1076 		break;
  1077 	    case 29: /* BICS Rd, Rn, operand */
  1078 		operand = RN(ir) & (~arm_get_shift_operand_s(ir));
  1079 		LRD(ir) = operand;
  1080 		if( RDn(ir) == 15 ) {
  1081 		    arm_restore_cpsr();
  1082 		} else {
  1083 		    armr.n = operand>>31;
  1084 		    armr.z = (operand == 0);
  1085 		    armr.c = armr.shift_c;
  1087 		break;
  1088 	    case 30: /* MVN Rd, operand */
  1089 		LRD(ir) = ~arm_get_shift_operand(ir);
  1090 		break;
  1091 	    case 31: /* MVNS Rd, operand */
  1092 		operand = ~arm_get_shift_operand_s(ir);
  1093 		LRD(ir) = operand;
  1094 		if( RDn(ir) == 15 ) {
  1095 		    arm_restore_cpsr();
  1096 		} else {
  1097 		    armr.n = operand>>31;
  1098 		    armr.z = (operand == 0);
  1099 		    armr.c = armr.shift_c;
  1101 		break;
  1102 	    default:
  1103 		UNIMP(ir);
  1106 	break;
  1107     case 1: /* Load/store */
  1108 	operand = arm_get_address_operand(ir);
  1109 	switch( (ir>>20)&0x17 ) {
  1110 	case 0: case 16: case 18: /* STR Rd, address */
  1111 	    arm_write_long( operand, RD(ir) );
  1112 	    break;
  1113 	case 1: case 17: case 19: /* LDR Rd, address */
  1114 	    LRD(ir) = arm_read_long(operand);
  1115 	    break;
  1116 	case 2: /* STRT Rd, address */
  1117 	    arm_write_long_user( operand, RD(ir) );
  1118 	    break;
  1119 	case 3: /* LDRT Rd, address */
  1120 	    LRD(ir) = arm_read_long_user( operand );
  1121 	    break;
  1122 	case 4: case 20: case 22: /* STRB Rd, address */
  1123 	    arm_write_byte( operand, RD(ir) );
  1124 	    break;
  1125 	case 5: case 21: case 23: /* LDRB Rd, address */
  1126 	    LRD(ir) = arm_read_byte( operand );
  1127 	    break;
  1128 	case 6: /* STRBT Rd, address */
  1129 	    arm_write_byte_user( operand, RD(ir) );
  1130 	    break;
  1131 	case 7: /* LDRBT Rd, address */
  1132 	    LRD(ir) = arm_read_byte_user( operand );
  1133 	    break;
  1135 	break;
  1136     case 2: /* Load/store multiple, branch*/
  1137 	if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
  1138 	    operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
  1139 	    if( (ir & 0x01000000) == 0x01000000 ) { 
  1140 		armr.r[14] = pc; /* BL */
  1142 	    armr.r[15] = pc + 4 + operand;
  1143 	} else { /* Load/store multiple */
  1144 	    operand = RN(ir);
  1146 	    switch( (ir & 0x01D00000) >> 20 ) {
  1147 	    case 0: /* STMDA */
  1148 		for( i=15; i>= 0; i-- ) {
  1149 		    if( (ir & (1<<i)) ) {
  1150 			arm_write_long( operand, armr.r[i] );
  1151 			operand -= 4;
  1154 		break;
  1155 	    case 1: /* LDMDA */
  1156 		for( i=15; i>= 0; i-- ) {
  1157 		    if( (ir & (1<<i)) ) {
  1158 			armr.r[i] = arm_read_long( operand );
  1159 			operand -= 4;
  1162 		break;
  1163 	    case 4: /* STMDA (S) */
  1164 		for( i=15; i>= 0; i-- ) {
  1165 		    if( (ir & (1<<i)) ) {
  1166 			arm_write_long( operand, USER_R(i) );
  1167 			operand -= 4;
  1170 		break;
  1171 	    case 5: /* LDMDA (S) */
  1172 		if( (ir&0x00008000) ) { /* Load PC */
  1173 		    for( i=15; i>= 0; i-- ) {
  1174 			if( (ir & (1<<i)) ) {
  1175 			    armr.r[i] = arm_read_long( operand );
  1176 			    operand -= 4;
  1179 		    arm_restore_cpsr();
  1180 		} else {
  1181 		    for( i=15; i>= 0; i-- ) {
  1182 			if( (ir & (1<<i)) ) {
  1183 			    USER_R(i) = arm_read_long( operand );
  1184 			    operand -= 4;
  1188 		break;
  1189 	    case 8: /* STMIA */
  1190 		for( i=0; i< 16; i++ ) {
  1191 		    if( (ir & (1<<i)) ) {
  1192 			arm_write_long( operand, armr.r[i] );
  1193 			operand += 4;
  1196 		break;
  1197 	    case 9: /* LDMIA */
  1198 		for( i=0; i< 16; i++ ) {
  1199 		    if( (ir & (1<<i)) ) {
  1200 			armr.r[i] = arm_read_long( operand );
  1201 			operand += 4;
  1204 		break;
  1205 	    case 12: /* STMIA (S) */
  1206 		for( i=0; i< 16; i++ ) {
  1207 		    if( (ir & (1<<i)) ) {
  1208 			arm_write_long( operand, USER_R(i) );
  1209 			operand += 4;
  1212 		break;
  1213 	    case 13: /* LDMIA (S) */
  1214 		if( (ir&0x00008000) ) { /* Load PC */
  1215 		    for( i=0; i < 16; i++ ) {
  1216 			if( (ir & (1<<i)) ) {
  1217 			    armr.r[i] = arm_read_long( operand );
  1218 			    operand += 4;
  1221 		    arm_restore_cpsr();
  1222 		} else {
  1223 		    for( i=0; i < 16; i++ ) {
  1224 			if( (ir & (1<<i)) ) {
  1225 			    USER_R(i) = arm_read_long( operand );
  1226 			    operand += 4;
  1230 		break;
  1231 	    case 16: /* STMDB */
  1232 		for( i=15; i>= 0; i-- ) {
  1233 		    if( (ir & (1<<i)) ) {
  1234 			operand -= 4;
  1235 			arm_write_long( operand, armr.r[i] );
  1238 		break;
  1239 	    case 17: /* LDMDB */
  1240 		for( i=15; i>= 0; i-- ) {
  1241 		    if( (ir & (1<<i)) ) {
  1242 			operand -= 4;
  1243 			armr.r[i] = arm_read_long( operand );
  1246 		break;
  1247 	    case 20: /* STMDB (S) */
  1248 		for( i=15; i>= 0; i-- ) {
  1249 		    if( (ir & (1<<i)) ) {
  1250 			operand -= 4;
  1251 			arm_write_long( operand, USER_R(i) );
  1254 		break;
  1255 	    case 21: /* LDMDB (S) */
  1256 		if( (ir&0x00008000) ) { /* Load PC */
  1257 		    for( i=15; i>= 0; i-- ) {
  1258 			if( (ir & (1<<i)) ) {
  1259 			    operand -= 4;
  1260 			    armr.r[i] = arm_read_long( operand );
  1263 		    arm_restore_cpsr();
  1264 		} else {
  1265 		    for( i=15; i>= 0; i-- ) {
  1266 			if( (ir & (1<<i)) ) {
  1267 			    operand -= 4;
  1268 			    USER_R(i) = arm_read_long( operand );
  1272 		break;
  1273 	    case 24: /* STMIB */
  1274 		for( i=0; i< 16; i++ ) {
  1275 		    if( (ir & (1<<i)) ) {
  1276 			operand += 4;
  1277 			arm_write_long( operand, armr.r[i] );
  1280 		break;
  1281 	    case 25: /* LDMIB */
  1282 		for( i=0; i< 16; i++ ) {
  1283 		    if( (ir & (1<<i)) ) {
  1284 			operand += 4;
  1285 			armr.r[i] = arm_read_long( operand );
  1288 		break;
  1289 	    case 28: /* STMIB (S) */
  1290 		for( i=0; i< 16; i++ ) {
  1291 		    if( (ir & (1<<i)) ) {
  1292 			operand += 4;
  1293 			arm_write_long( operand, USER_R(i) );
  1296 		break;
  1297 	    case 29: /* LDMIB (S) */
  1298 		if( (ir&0x00008000) ) { /* Load PC */
  1299 		    for( i=0; i < 16; i++ ) {
  1300 			if( (ir & (1<<i)) ) {
  1301 			    operand += 4;
  1302 			    armr.r[i] = arm_read_long( operand );
  1305 		    arm_restore_cpsr();
  1306 		} else {
  1307 		    for( i=0; i < 16; i++ ) {
  1308 			if( (ir & (1<<i)) ) {
  1309 			    operand += 4;
  1310 			    USER_R(i) = arm_read_long( operand );
  1314 		break;
  1317 	    if( WFLAG(ir) ) 
  1318 		LRN(ir) = operand;
  1320 	break;
  1321     case 3: /* Copro */
  1322 	if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */
  1323 	    arm_raise_exception( EXC_SOFTWARE );
  1324 	} else {
  1325 	    UNIMP(ir);
  1327 	break;
  1329     return TRUE;
.