Search
lxdream.org :: lxdream/src/aica/armcore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 63:be4fec751961
prev59:dceb8ef1da55
next66:2ec5b6eb75e5
author nkeynes
date Mon Jan 02 23:07:17 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change Fix exception return address
Accidentally left UNIMP() on entire arith extension block, removed
view annotate diff log raw
     1 /**
     2  * $Id: armcore.c,v 1.15 2006-01-02 23:07:17 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  * Set the CPSR to the specified value.
   159  *
   160  * @param value values to set in CPSR
   161  * @param fields set of mask values to define which sections of the 
   162  *   CPSR to set (one of the SET_CPSR_* values above)
   163  */
   164 void arm_set_cpsr( uint32_t value, uint32_t fields )
   165 {
   166     if( IS_PRIVILEGED_MODE() ) {
   167 	if( fields & SET_CPSR_CONTROL ) {
   168 	    int mode = value & CPSR_MODE;
   169 	    arm_set_mode( mode );
   170 	    armr.t = ( value & CPSR_T ); /* Technically illegal to change */
   171 	    armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
   172 	}
   174 	/* Middle 16 bits not currently defined */
   175     }
   176     if( fields & SET_CPSR_FLAGS ) {
   177 	/* Break flags directly out of given value - don't bother writing
   178 	 * back to CPSR 
   179 	 */
   180 	armr.n = ( value & CPSR_N );
   181 	armr.z = ( value & CPSR_Z );
   182 	armr.c = ( value & CPSR_C );
   183 	armr.v = ( value & CPSR_V );
   184     }
   185 }
   187 void arm_set_spsr( uint32_t value, uint32_t fields )
   188 {
   189     /* Only defined if we actually have an SPSR register */
   190     if( IS_EXCEPTION_MODE() ) {
   191 	if( fields & SET_CPSR_CONTROL ) {
   192 	    armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
   193 	}
   195 	/* Middle 16 bits not currently defined */
   197 	if( fields & SET_CPSR_FLAGS ) {
   198 	    armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
   199 	}
   200     }
   201 }
   203 /**
   204  * Raise an ARM exception (other than reset, which uses arm_reset().
   205  * @param exception one of the EXC_* exception codes defined above.
   206  */
   207 void arm_raise_exception( int exception )
   208 {
   209     int mode = arm_exceptions[exception][0];
   210     uint32_t spsr = arm_get_cpsr();
   211     arm_set_mode( mode );
   212     armr.spsr = spsr;
   213     armr.r[14] = armr.r[15] + 4;
   214     armr.cpsr = (spsr & 0xFFFFFF00) | mode | CPSR_I; 
   215     if( mode == MODE_FIQ )
   216 	armr.cpsr |= CPSR_F;
   217     armr.r[15] = arm_exceptions[exception][1];
   218 }
   220 void arm_restore_cpsr( void )
   221 {
   222     int spsr = armr.spsr;
   223     int mode = spsr & CPSR_MODE;
   224     arm_set_mode( mode );
   225     armr.cpsr = spsr;
   226     armr.n = ( spsr & CPSR_N );
   227     armr.z = ( spsr & CPSR_Z );
   228     armr.c = ( spsr & CPSR_C );
   229     armr.v = ( spsr & CPSR_V );
   230     armr.t = ( spsr & CPSR_T );
   231 }
   235 /**
   236  * Change the current executing ARM mode to the requested mode.
   237  * Saves any required registers to banks and restores those for the
   238  * correct mode. (Note does not actually update CPSR at the moment).
   239  */
   240 void arm_set_mode( int targetMode )
   241 {
   242     int currentMode = armr.cpsr & CPSR_MODE;
   243     if( currentMode == targetMode )
   244 	return;
   246     switch( currentMode ) {
   247     case MODE_USER:
   248     case MODE_SYS:
   249 	armr.user_r[5] = armr.r[13];
   250 	armr.user_r[6] = armr.r[14];
   251 	break;
   252     case MODE_SVC:
   253 	armr.svc_r[0] = armr.r[13];
   254 	armr.svc_r[1] = armr.r[14];
   255 	armr.svc_r[2] = armr.spsr;
   256 	break;
   257     case MODE_ABT:
   258 	armr.abt_r[0] = armr.r[13];
   259 	armr.abt_r[1] = armr.r[14];
   260 	armr.abt_r[2] = armr.spsr;
   261 	break;
   262     case MODE_UND:
   263 	armr.und_r[0] = armr.r[13];
   264 	armr.und_r[1] = armr.r[14];
   265 	armr.und_r[2] = armr.spsr;
   266 	break;
   267     case MODE_IRQ:
   268 	armr.irq_r[0] = armr.r[13];
   269 	armr.irq_r[1] = armr.r[14];
   270 	armr.irq_r[2] = armr.spsr;
   271 	break;
   272     case MODE_FIQ:
   273 	armr.fiq_r[0] = armr.r[8];
   274 	armr.fiq_r[1] = armr.r[9];
   275 	armr.fiq_r[2] = armr.r[10];
   276 	armr.fiq_r[3] = armr.r[11];
   277 	armr.fiq_r[4] = armr.r[12];
   278 	armr.fiq_r[5] = armr.r[13];
   279 	armr.fiq_r[6] = armr.r[14];
   280 	armr.fiq_r[7] = armr.spsr;
   281 	armr.r[8] = armr.user_r[0];
   282 	armr.r[9] = armr.user_r[1];
   283 	armr.r[10] = armr.user_r[2];
   284 	armr.r[11] = armr.user_r[3];
   285 	armr.r[12] = armr.user_r[4];
   286 	break;
   287     }
   289     switch( targetMode ) {
   290     case MODE_USER:
   291     case MODE_SYS:
   292 	armr.r[13] = armr.user_r[5];
   293 	armr.r[14] = armr.user_r[6];
   294 	break;
   295     case MODE_SVC:
   296 	armr.r[13] = armr.svc_r[0];
   297 	armr.r[14] = armr.svc_r[1];
   298 	armr.spsr = armr.svc_r[2];
   299 	break;
   300     case MODE_ABT:
   301 	armr.r[13] = armr.abt_r[0];
   302 	armr.r[14] = armr.abt_r[1];
   303 	armr.spsr = armr.abt_r[2];
   304 	break;
   305     case MODE_UND:
   306 	armr.r[13] = armr.und_r[0];
   307 	armr.r[14] = armr.und_r[1];
   308 	armr.spsr = armr.und_r[2];
   309 	break;
   310     case MODE_IRQ:
   311 	armr.r[13] = armr.irq_r[0];
   312 	armr.r[14] = armr.irq_r[1];
   313 	armr.spsr = armr.irq_r[2];
   314 	break;
   315     case MODE_FIQ:
   316 	armr.user_r[0] = armr.r[8];
   317 	armr.user_r[1] = armr.r[9];
   318 	armr.user_r[2] = armr.r[10];
   319 	armr.user_r[3] = armr.r[11];
   320 	armr.user_r[4] = armr.r[12];
   321 	armr.r[8] = armr.fiq_r[0];
   322 	armr.r[9] = armr.fiq_r[1];
   323 	armr.r[10] = armr.fiq_r[2];
   324 	armr.r[11] = armr.fiq_r[3];
   325 	armr.r[12] = armr.fiq_r[4];
   326 	armr.r[13] = armr.fiq_r[5];
   327 	armr.r[14] = armr.fiq_r[6];
   328 	armr.spsr = armr.fiq_r[7];
   329 	break;
   330     }
   331 }
   333 /* Page references are as per ARM DDI 0100E (June 2000) */
   335 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
   336 #define MEM_READ_WORD( addr ) arm_read_word(addr)
   337 #define MEM_READ_LONG( addr ) arm_read_long(addr)
   338 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
   339 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
   340 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
   343 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
   344 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
   345 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
   346 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
   348 #define PC armr.r[15]
   350 /* Instruction fields */
   351 #define COND(ir) (ir>>28)
   352 #define GRP(ir) ((ir>>26)&0x03)
   353 #define OPCODE(ir) ((ir>>20)&0x1F)
   354 #define IFLAG(ir) (ir&0x02000000)
   355 #define SFLAG(ir) (ir&0x00100000)
   356 #define PFLAG(ir) (ir&0x01000000)
   357 #define UFLAG(ir) (ir&0x00800000)
   358 #define BFLAG(ir) (ir&0x00400000)
   359 #define WFLAG(ir) (ir&0x00200000)
   360 #define LFLAG(ir) SFLAG(ir)
   361 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   362 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))
   363 #define RDn(ir) ((ir>>12)&0x0F)
   364 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))
   365 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )
   366 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
   367 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
   368 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
   369 #define LRM(ir) armr.r[(ir&0x0F)]
   371 #define IMM8(ir) (ir&0xFF)
   372 #define IMM12(ir) (ir&0xFFF)
   373 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
   374 #define IMMROT(ir) ((ir>>7)&0x1E)
   375 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
   376 #define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
   377 #define SHIFT(ir) ((ir>>4)&0x07)
   378 #define DISP24(ir) ((ir&0x00FFFFFF))
   379 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
   380 #define UNIMP(ir) do{ PC-=4; ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); dreamcast_stop(); return FALSE; }while(0)
   382 /**
   383  * Determine the value of the shift-operand for a data processing instruction,
   384  * without determing a value for shift_C (optimized form for instructions that
   385  * don't require shift_C ).
   386  * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
   387  */
   388 static uint32_t arm_get_shift_operand( uint32_t ir )
   389 {
   390 	uint32_t operand, tmp;
   391 	if( IFLAG(ir) == 0 ) {
   392 		operand = RM(ir);
   393 		switch(SHIFT(ir)) {
   394 		case 0: /* (Rm << imm) */
   395 			operand = operand << SHIFTIMM(ir);
   396 			break;
   397 		case 1: /* (Rm << Rs) */
   398 			tmp = RS(ir)&0xFF;
   399 			if( tmp > 31 ) operand = 0;
   400 			else operand = operand << tmp;
   401 			break;
   402 		case 2: /* (Rm >> imm) */
   403 			operand = operand >> SHIFTIMM(ir);
   404 			break;
   405 		case 3: /* (Rm >> Rs) */
   406 			tmp = RS(ir) & 0xFF;
   407 			if( tmp > 31 ) operand = 0;
   408 			else operand = operand >> ir;
   409 			break;
   410 		case 4: /* (Rm >>> imm) */
   411 			tmp = SHIFTIMM(ir);
   412 			if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   413 			else operand = ((int32_t)operand) >> tmp;
   414 			break;
   415 		case 5: /* (Rm >>> Rs) */
   416 			tmp = RS(ir) & 0xFF;
   417 			if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
   418 			else operand = ((int32_t)operand) >> tmp;
   419 			break;
   420 		case 6:
   421 			tmp = SHIFTIMM(ir);
   422 			if( tmp == 0 ) /* RRX aka rotate with carry */
   423 				operand = (operand >> 1) | (armr.c<<31);
   424 			else
   425 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   426 			break;
   427 		case 7:
   428 			tmp = RS(ir)&0x1F;
   429 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   430 			break;
   431 		}
   432 	} else {
   433 		operand = IMM8(ir);
   434 		tmp = IMMROT(ir);
   435 		operand = ROTATE_RIGHT_LONG(operand, tmp);
   436 	}
   437 	return operand;
   438 }
   440 /**
   441  * Determine the value of the shift-operand for a data processing instruction,
   442  * and set armr.shift_c accordingly.
   443  * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
   444  */
   445 static uint32_t arm_get_shift_operand_s( uint32_t ir )
   446 {
   447 	uint32_t operand, tmp;
   448 	if( IFLAG(ir) == 0 ) {
   449 		operand = RM(ir);
   450 		switch(SHIFT(ir)) {
   451 		case 0: /* (Rm << imm) */
   452 			tmp = SHIFTIMM(ir);
   453 			if( tmp == 0 ) { /* Rm */
   454 				armr.shift_c = armr.c;
   455 			} else { /* Rm << imm */
   456 				armr.shift_c = (operand >> (32-tmp)) & 0x01;
   457 				operand = operand << tmp;
   458 			}
   459 			break;
   460 		case 1: /* (Rm << Rs) */
   461 			tmp = RS(ir)&0xFF;
   462 			if( tmp == 0 ) {
   463 				armr.shift_c = armr.c;
   464 			} else {
   465 				if( tmp <= 32 )
   466 					armr.shift_c = (operand >> (32-tmp)) & 0x01;
   467 				else armr.shift_c = 0;
   468 				if( tmp < 32 )
   469 					operand = operand << tmp;
   470 				else operand = 0;
   471 			}
   472 			break;
   473 		case 2: /* (Rm >> imm) */
   474 			tmp = SHIFTIMM(ir);
   475 			if( tmp == 0 ) {
   476 				armr.shift_c = operand >> 31;
   477 				operand = 0;
   478 			} else {
   479 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   480 				operand = RM(ir) >> tmp;
   481 			}
   482 			break;
   483 		case 3: /* (Rm >> Rs) */
   484 			tmp = RS(ir) & 0xFF;
   485 			if( tmp == 0 ) {
   486 				armr.shift_c = armr.c;
   487 			} else {
   488 				if( tmp <= 32 )
   489 					armr.shift_c = (operand >> (tmp-1))&0x01;
   490 				else armr.shift_c = 0;
   491 				if( tmp < 32 )
   492 					operand = operand >> tmp;
   493 				else operand = 0;
   494 			}
   495 			break;
   496 		case 4: /* (Rm >>> imm) */
   497 			tmp = SHIFTIMM(ir);
   498 			if( tmp == 0 ) {
   499 				armr.shift_c = operand >> 31;
   500 				operand = -armr.shift_c;
   501 			} else {
   502 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   503 				operand = ((int32_t)operand) >> tmp;
   504 			}
   505 			break;
   506 		case 5: /* (Rm >>> Rs) */
   507 			tmp = RS(ir) & 0xFF;
   508 			if( tmp == 0 ) {
   509 				armr.shift_c = armr.c;
   510 			} else {
   511 				if( tmp < 32 ) {
   512 					armr.shift_c = (operand >> (tmp-1))&0x01;
   513 					operand = ((int32_t)operand) >> tmp;
   514 				} else {
   515 					armr.shift_c = operand >> 31;
   516 					operand = ((int32_t)operand) >> 31;
   517 				}
   518 			}
   519 			break;
   520 		case 6:
   521 			tmp = SHIFTIMM(ir);
   522 			if( tmp == 0 ) { /* RRX aka rotate with carry */
   523 				armr.shift_c = operand&0x01;
   524 				operand = (operand >> 1) | (armr.c<<31);
   525 			} else {
   526 				armr.shift_c = operand>>(tmp-1);
   527 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   528 			}
   529 			break;
   530 		case 7:
   531 			tmp = RS(ir)&0xFF;
   532 			if( tmp == 0 ) {
   533 				armr.shift_c = armr.c;
   534 			} else {
   535 				tmp &= 0x1F;
   536 				if( tmp == 0 ) {
   537 					armr.shift_c = operand>>31;
   538 				} else {
   539 					armr.shift_c = (operand>>(tmp-1))&0x1;
   540 					operand = ROTATE_RIGHT_LONG(operand,tmp);
   541 				}
   542 			}
   543 			break;
   544 		}
   545 	} else {
   546 		operand = IMM8(ir);
   547 		tmp = IMMROT(ir);
   548 		if( tmp == 0 ) {
   549 			armr.shift_c = armr.c;
   550 		} else {
   551 			operand = ROTATE_RIGHT_LONG(operand, tmp);
   552 			armr.shift_c = operand>>31;
   553 		}
   554 	}
   555 	return operand;
   556 }
   558 /**
   559  * Another variant of the shifter code for index-based memory addressing.
   560  * Distinguished by the fact that it doesn't support register shifts, and
   561  * ignores the I flag (WTF do the load/store instructions use the I flag to
   562  * mean the _exact opposite_ of what it means for the data processing 
   563  * instructions ???)
   564  */
   565 static uint32_t arm_get_address_index( uint32_t ir )
   566 {
   567 	uint32_t operand = RM(ir);
   568 	uint32_t tmp;
   570 	switch(SHIFT(ir)) {
   571 	case 0: /* (Rm << imm) */
   572 		operand = operand << SHIFTIMM(ir);
   573 		break;
   574 	case 2: /* (Rm >> imm) */
   575 		operand = operand >> SHIFTIMM(ir);
   576 		break;
   577 	case 4: /* (Rm >>> imm) */
   578 		tmp = SHIFTIMM(ir);
   579 		if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   580 		else operand = ((int32_t)operand) >> tmp;
   581 		break;
   582 	case 6:
   583 		tmp = SHIFTIMM(ir);
   584 		if( tmp == 0 ) /* RRX aka rotate with carry */
   585 			operand = (operand >> 1) | (armr.c<<31);
   586 		else
   587 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   588 		break;
   589 	default: UNIMP(ir);
   590 	}
   591 	return operand;	
   592 }
   594 /**
   595  * Determine the address operand of a load/store instruction, including
   596  * applying any pre/post adjustments to the address registers.
   597  * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
   598  * @param The instruction word.
   599  * @return The calculated address
   600  */
   601 static uint32_t arm_get_address_operand( uint32_t ir )
   602 {
   603 	uint32_t addr;
   605 	/* I P U . W */
   606 	switch( (ir>>21)&0x1D ) {
   607 	case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   608 	case 1:
   609 		addr = RN(ir);
   610 		LRN(ir) = addr - IMM12(ir);
   611 		break;
   612 	case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
   613 	case 5:
   614 		addr = RN(ir);
   615 		LRN(ir) = addr + IMM12(ir);
   616 		break;
   617 	case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   618 		addr = RN(ir) - IMM12(ir);
   619 		break;
   620 	case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   621 		addr = RN(ir) - IMM12(ir);
   622 		LRN(ir) = addr;
   623 		break;
   624 	case 12: /* Rn + imm offset  [5.2.2 A5-20] */
   625 		addr = RN(ir) + IMM12(ir);
   626 		break;
   627 	case 13: /* Rn += imm offset  [5.2.5 A5-24 ] */
   628 		addr = RN(ir) + IMM12(ir);
   629 		LRN(ir) = addr;
   630 		break;
   631 	case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   632 	case 17:
   633 		addr = RN(ir);
   634 		LRN(ir) = addr - arm_get_address_index(ir);
   635 		break;
   636 	case 20: /* Rn += Rm (post-indexed)  [5.2.10 A5-32 ] */
   637 	case 21:
   638 		addr = RN(ir);
   639 		LRN(ir) = addr - arm_get_address_index(ir);
   640 		break;
   641 	case 24: /* Rn - Rm  [5.2.4 A5-23] */
   642 		addr = RN(ir) - arm_get_address_index(ir);
   643 		break;
   644 	case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   645 		addr = RN(ir) - arm_get_address_index(ir);
   646 		LRN(ir) = addr;
   647 		break;
   648 	case 28: /* Rn + Rm  [5.2.4 A5-23] */
   649 		addr = RN(ir) + arm_get_address_index(ir);
   650 		break;
   651 	case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
   652 		addr = RN(ir) + arm_get_address_index(ir);
   653 		LRN(ir) = addr;
   654 		break;
   655 	}
   656 	return addr;
   657 }
   659 gboolean arm_execute_instruction( void ) 
   660 {
   661     uint32_t pc;
   662     uint32_t ir;
   663     uint32_t operand, operand2, tmp, tmp2, cond;
   665     tmp = armr.int_pending & (~armr.cpsr);
   666     if( tmp ) {
   667 	if( tmp & CPSR_F ) {
   668 	    arm_raise_exception( EXC_FAST_IRQ );
   669 	} else {
   670 	    arm_raise_exception( EXC_IRQ );
   671 	}
   672     }
   674     ir = MEM_READ_LONG(PC);
   675     pc = PC + 4;
   676     PC = pc;
   678     /** 
   679      * Check the condition bits first - if the condition fails return 
   680      * immediately without actually looking at the rest of the instruction.
   681      */
   682     switch( COND(ir) ) {
   683     case 0: /* EQ */ 
   684 	cond = armr.z;
   685 	break;
   686     case 1: /* NE */
   687 	cond = !armr.z;
   688 	break;
   689     case 2: /* CS/HS */
   690 	cond = armr.c;
   691 	break;
   692     case 3: /* CC/LO */
   693 	cond = !armr.c;
   694 	break;
   695     case 4: /* MI */
   696 	cond = armr.n;
   697 	break;
   698     case 5: /* PL */
   699 	cond = !armr.n;
   700 	break;
   701     case 6: /* VS */
   702 	cond = armr.v;
   703 	break;
   704     case 7: /* VC */
   705 	cond = !armr.v;
   706 	break;
   707     case 8: /* HI */
   708 	cond = armr.c && !armr.z;
   709 	break;
   710     case 9: /* LS */
   711 	cond = (!armr.c) || armr.z;
   712 	break;
   713     case 10: /* GE */
   714 	cond = (armr.n == armr.v);
   715 	break;
   716     case 11: /* LT */
   717 	cond = (armr.n != armr.v);
   718 	break;
   719     case 12: /* GT */
   720 	cond = (!armr.z) && (armr.n == armr.v);
   721 	break;
   722     case 13: /* LE */
   723 	cond = armr.z || (armr.n != armr.v);
   724 	break;
   725     case 14: /* AL */
   726 	cond = 1;
   727 	break;
   728     case 15: /* (NV) */
   729 	cond = 0;
   730 	UNDEF(ir);
   731     }
   732     if( !cond )
   733 	return TRUE;
   735     /**
   736      * Condition passed, now for the actual instructions...
   737      */
   738     switch( GRP(ir) ) {
   739     case 0:
   740 	if( (ir & 0x0D900000) == 0x01000000 ) {
   741 	    /* Instructions that aren't actual data processing even though
   742 	     * they sit in the DP instruction block.
   743 	     */
   744 	    switch( ir & 0x0FF000F0 ) {
   745 	    case 0x01200010: /* BX Rd */
   746 		armr.t = ir & 0x01;
   747 		armr.r[15] = RM(ir) & 0xFFFFFFFE;
   748 		break;
   749 	    case 0x01000000: /* MRS Rd, CPSR */
   750 		LRD(ir) = arm_get_cpsr();
   751 		break;
   752 	    case 0x01400000: /* MRS Rd, SPSR */
   753 		LRD(ir) = armr.spsr;
   754 		break;
   755 	    case 0x01200000: /* MSR CPSR, Rd */
   756 		arm_set_cpsr( RM(ir), ir );
   757 		break;
   758 	    case 0x01600000: /* MSR SPSR, Rd */
   759 		arm_set_spsr( RM(ir), ir );
   760 		break;
   761 	    case 0x03200000: /* MSR CPSR, imm */
   762 		arm_set_cpsr( ROTIMM12(ir), ir );
   763 		break;
   764 	    case 0x03600000: /* MSR SPSR, imm */
   765 		arm_set_spsr( ROTIMM12(ir), ir );
   766 		break;
   767 	    default:
   768 		UNIMP(ir);
   769 	    }
   770 	} else if( (ir & 0x0E000090) == 0x00000090 ) {
   771 	    /* Neither are these */
   772 	    switch( (ir>>5)&0x03 ) {
   773 	    case 0:
   774 		/* Arithmetic extension area */
   775 		switch(OPCODE(ir)) {
   776 		case 0: /* MUL */
   777 		    LRN(ir) = RM(ir) * RS(ir);
   778 		    break;
   779 		case 1: /* MULS */
   780 		    tmp = RM(ir) * RS(ir);
   781 		    LRN(ir) = tmp;
   782 		    armr.n = tmp>>31;
   783 		    armr.z = (tmp == 0);
   784 		    break;
   785 		case 2: /* MLA */
   786 		    LRN(ir) = RM(ir) * RS(ir) + RD(ir);
   787 		    break;
   788 		case 3: /* MLAS */
   789 		    tmp = RM(ir) * RS(ir) + RD(ir);
   790 		    LRN(ir) = tmp;
   791 		    armr.n = tmp>>31;
   792 		    armr.z = (tmp == 0);
   793 		    break;
   794 		case 8: /* UMULL */
   795 		case 9: /* UMULLS */
   796 		case 10: /* UMLAL */
   797 		case 11: /* UMLALS */
   798 		case 12: /* SMULL */
   799 		case 13: /* SMULLS */
   800 		case 14: /* SMLAL */
   801 		case 15: /* SMLALS */
   802 		    UNIMP(ir);
   803 		    break;
   804 		case 16: /* SWP */
   805 		    tmp = arm_read_long( RN(ir) );
   806 		    switch( RN(ir) & 0x03 ) {
   807 		    case 1:
   808 			tmp = ROTATE_RIGHT_LONG(tmp, 8);
   809 			break;
   810 		    case 2:
   811 			tmp = ROTATE_RIGHT_LONG(tmp, 16);
   812 			break;
   813 		    case 3:
   814 			tmp = ROTATE_RIGHT_LONG(tmp, 24);
   815 			break;
   816 		    }
   817 		    arm_write_long( RN(ir), RM(ir) );
   818 		    LRD(ir) = tmp;
   819 		    break;
   820 		case 20: /* SWPB */
   821 		    tmp = arm_read_byte( RN(ir) );
   822 		    arm_write_byte( RN(ir), RM(ir) );
   823 		    LRD(ir) = tmp;
   824 		    break;
   825 		default:
   826 		    UNIMP(ir);
   827 		}
   828 		break;
   829 	    case 1:
   830 		if( LFLAG(ir) ) {
   831 		    /* LDRH */
   832 		} else {
   833 		    /* STRH */
   834 		}
   835 		UNIMP(ir);
   836 		break;
   837 	    case 2:
   838 		if( LFLAG(ir) ) {
   839 		    /* LDRSB */
   840 		} else {
   841 		}
   842 		UNIMP(ir);
   843 		break;
   844 	    case 3:
   845 		if( LFLAG(ir) ) {
   846 		    /* LDRSH */
   847 		} else {
   848 		}
   849 		UNIMP(ir);
   850 		break;
   851 	    }
   852 	} else {
   853 	    /* Data processing */
   855 	    switch(OPCODE(ir)) {
   856 	    case 0: /* AND Rd, Rn, operand */
   857 		LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
   858 		break;
   859 	    case 1: /* ANDS Rd, Rn, operand */
   860 		operand = arm_get_shift_operand_s(ir) & RN(ir);
   861 		LRD(ir) = operand;
   862 		if( RDn(ir) == 15 ) {
   863 		    arm_restore_cpsr();
   864 		} else {
   865 		    armr.n = operand>>31;
   866 		    armr.z = (operand == 0);
   867 		    armr.c = armr.shift_c;
   868 		}
   869 		break;
   870 	    case 2: /* EOR Rd, Rn, operand */
   871 		LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
   872 		break;
   873 	    case 3: /* EORS Rd, Rn, operand */
   874 		operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   875 		LRD(ir) = operand;
   876 		if( RDn(ir) == 15 ) {
   877 		    arm_restore_cpsr();
   878 		} else {
   879 		    armr.n = operand>>31;
   880 		    armr.z = (operand == 0);
   881 		    armr.c = armr.shift_c;
   882 		}
   883 		break;
   884 	    case 4: /* SUB Rd, Rn, operand */
   885 		LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
   886 		break;
   887 	    case 5: /* SUBS Rd, Rn, operand */
   888 		operand = RN(ir);
   889 		operand2 = arm_get_shift_operand(ir);
   890 		tmp = operand - operand2;
   891 		LRD(ir) = tmp;
   892 		if( RDn(ir) == 15 ) {
   893 		    arm_restore_cpsr();
   894 		} else {
   895 		    armr.n = tmp>>31;
   896 		    armr.z = (tmp == 0);
   897 		    armr.c = IS_NOTBORROW(tmp,operand,operand2);
   898 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   899 		}
   900 		break;
   901 	    case 6: /* RSB Rd, operand, Rn */
   902 		LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
   903 		break;
   904 	    case 7: /* RSBS Rd, operand, Rn */
   905 		operand = arm_get_shift_operand(ir);
   906 		operand2 = RN(ir);
   907 		tmp = operand - operand2;
   908 		LRD(ir) = tmp;
   909 		if( RDn(ir) == 15 ) {
   910 		    arm_restore_cpsr();
   911 		} else {
   912 		    armr.n = tmp>>31;
   913 		    armr.z = (tmp == 0);
   914 		    armr.c = IS_NOTBORROW(tmp,operand,operand2);
   915 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   916 		}
   917 		break;
   918 	    case 8: /* ADD Rd, Rn, operand */
   919 		LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
   920 		break;
   921 	    case 9: /* ADDS Rd, Rn, operand */
   922 		operand = arm_get_shift_operand(ir);
   923 		operand2 = RN(ir);
   924 		tmp = operand + operand2;
   925 		LRD(ir) = tmp;
   926 		if( RDn(ir) == 15 ) {
   927 		    arm_restore_cpsr();
   928 		} else {
   929 		    armr.n = tmp>>31;
   930 		    armr.z = (tmp == 0);
   931 		    armr.c = IS_CARRY(tmp,operand,operand2);
   932 		    armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   933 		}
   934 		break;			
   935 	    case 10: /* ADC */
   936 		LRD(ir) = RN(ir) + arm_get_shift_operand(ir) + 
   937 		    (armr.c ? 1 : 0);
   938 		break;
   939 	    case 11: /* ADCS */
   940 		operand = arm_get_shift_operand(ir);
   941 		operand2 = RN(ir);
   942 		tmp = operand + operand2;
   943 		tmp2 = tmp + armr.c ? 1 : 0;
   944 		LRD(ir) = tmp2;
   945 		if( RDn(ir) == 15 ) {
   946 		    arm_restore_cpsr();
   947 		} else {
   948 		    armr.n = tmp >> 31;
   949 		    armr.z = (tmp == 0 );
   950 		    armr.c = IS_CARRY(tmp,operand,operand2) ||
   951 			(tmp2 < tmp);
   952 		    armr.v = IS_ADDOVERFLOW(tmp,operand, operand2) ||
   953 			((tmp&0x80000000) != (tmp2&0x80000000));
   954 		}
   955 		break;
   956 	    case 12: /* SBC */
   957 		LRD(ir) = RN(ir) - arm_get_shift_operand(ir) - 
   958 		    (armr.c ? 0 : 1);
   959 		break;
   960 	    case 13: /* SBCS */
   961 		operand = RN(ir);
   962 		operand2 = arm_get_shift_operand(ir);
   963 		tmp = operand - operand2;
   964 		tmp2 = tmp - (armr.c ? 0 : 1);
   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_NOTBORROW(tmp,operand,operand2) &&
   971 			(tmp2<tmp);
   972 		    armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
   973 			((tmp&0x80000000) != (tmp2&0x80000000));
   974 		}
   975 		break;
   976 	    case 14: /* RSC */
   977 		LRD(ir) = arm_get_shift_operand(ir) - RN(ir) -
   978 		    (armr.c ? 0 : 1);
   979 		break;
   980 	    case 15: /* RSCS */
   981 		operand = arm_get_shift_operand(ir);
   982 		operand2 = RN(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 17: /* TST Rn, operand */
   997 		operand = arm_get_shift_operand_s(ir) & RN(ir);
   998 		armr.n = operand>>31;
   999 		armr.z = (operand == 0);
  1000 		armr.c = armr.shift_c;
  1001 		break;
  1002 	    case 19: /* TEQ Rn, operand */
  1003 		operand = arm_get_shift_operand_s(ir) ^ RN(ir);
  1004 		armr.n = operand>>31;
  1005 		armr.z = (operand == 0);
  1006 		armr.c = armr.shift_c;
  1007 		break;				
  1008 	    case 21: /* CMP Rn, operand */
  1009 		operand = RN(ir);
  1010 		operand2 = arm_get_shift_operand(ir);
  1011 		tmp = operand - operand2;
  1012 		armr.n = tmp>>31;
  1013 		armr.z = (tmp == 0);
  1014 		armr.c = IS_NOTBORROW(tmp,operand,operand2);
  1015 		armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
  1016 		break;
  1017 	    case 23: /* CMN Rn, operand */
  1018 		operand = RN(ir);
  1019 		operand2 = arm_get_shift_operand(ir);
  1020 		tmp = operand + operand2;
  1021 		armr.n = tmp>>31;
  1022 		armr.z = (tmp == 0);
  1023 		armr.c = IS_CARRY(tmp,operand,operand2);
  1024 		armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
  1025 		break;
  1026 	    case 24: /* ORR Rd, Rn, operand */
  1027 		LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
  1028 		break;
  1029 	    case 25: /* ORRS Rd, Rn, operand */
  1030 		operand = arm_get_shift_operand_s(ir) | RN(ir);
  1031 		LRD(ir) = operand;
  1032 		if( RDn(ir) == 15 ) {
  1033 		    arm_restore_cpsr();
  1034 		} else {
  1035 		    armr.n = operand>>31;
  1036 		    armr.z = (operand == 0);
  1037 		    armr.c = armr.shift_c;
  1039 		break;
  1040 	    case 26: /* MOV Rd, operand */
  1041 		LRD(ir) = arm_get_shift_operand(ir);
  1042 		break;
  1043 	    case 27: /* MOVS Rd, operand */
  1044 		operand = arm_get_shift_operand_s(ir);
  1045 		LRD(ir) = operand;
  1046 		if( RDn(ir) == 15 ) {
  1047 		    arm_restore_cpsr();
  1048 		} else {
  1049 		    armr.n = operand>>31;
  1050 		    armr.z = (operand == 0);
  1051 		    armr.c = armr.shift_c;
  1053 		break;
  1054 	    case 28: /* BIC Rd, Rn, operand */
  1055 		LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
  1056 		break;
  1057 	    case 29: /* BICS Rd, Rn, operand */
  1058 		operand = RN(ir) & (~arm_get_shift_operand_s(ir));
  1059 		LRD(ir) = operand;
  1060 		if( RDn(ir) == 15 ) {
  1061 		    arm_restore_cpsr();
  1062 		} else {
  1063 		    armr.n = operand>>31;
  1064 		    armr.z = (operand == 0);
  1065 		    armr.c = armr.shift_c;
  1067 		break;
  1068 	    case 30: /* MVN Rd, operand */
  1069 		LRD(ir) = ~arm_get_shift_operand(ir);
  1070 		break;
  1071 	    case 31: /* MVNS Rd, operand */
  1072 		operand = ~arm_get_shift_operand_s(ir);
  1073 		LRD(ir) = operand;
  1074 		if( RDn(ir) == 15 ) {
  1075 		    arm_restore_cpsr();
  1076 		} else {
  1077 		    armr.n = operand>>31;
  1078 		    armr.z = (operand == 0);
  1079 		    armr.c = armr.shift_c;
  1081 		break;
  1082 	    default:
  1083 		UNIMP(ir);
  1086 	break;
  1087     case 1: /* Load/store */
  1088 	operand = arm_get_address_operand(ir);
  1089 	switch( (ir>>20)&0x17 ) {
  1090 	case 0: case 16: case 18: /* STR Rd, address */
  1091 	    arm_write_long( operand, RD(ir) );
  1092 	    break;
  1093 	case 1: case 17: case 19: /* LDR Rd, address */
  1094 	    LRD(ir) = arm_read_long(operand);
  1095 	    break;
  1096 	case 2: /* STRT Rd, address */
  1097 	    arm_write_long_user( operand, RD(ir) );
  1098 	    break;
  1099 	case 3: /* LDRT Rd, address */
  1100 	    LRD(ir) = arm_read_long_user( operand );
  1101 	    break;
  1102 	case 4: case 20: case 22: /* STRB Rd, address */
  1103 	    arm_write_byte( operand, RD(ir) );
  1104 	    break;
  1105 	case 5: case 21: case 23: /* LDRB Rd, address */
  1106 	    LRD(ir) = arm_read_byte( operand );
  1107 	    break;
  1108 	case 6: /* STRBT Rd, address */
  1109 	    arm_write_byte_user( operand, RD(ir) );
  1110 	    break;
  1111 	case 7: /* LDRBT Rd, address */
  1112 	    LRD(ir) = arm_read_byte_user( operand );
  1113 	    break;
  1115 	break;
  1116     case 2: /* Load/store multiple, branch*/
  1117 	if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
  1118 	    operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
  1119 	    if( (ir & 0x01000000) == 0x01000000 ) { 
  1120 		armr.r[14] = pc; /* BL */
  1122 	    armr.r[15] = pc + 4 + operand;
  1123 	} else { /* Load/store multiple */
  1124 	    int prestep, poststep;
  1125 	    if( PFLAG(ir) ) {
  1126 		prestep = UFLAG(ir) ? 4 : -4;
  1127 		poststep = 0 ;
  1128 	    } else {
  1129 		prestep = 0;
  1130 		poststep = UFLAG(ir) ? 4 : -4;
  1132 	    operand = RN(ir);
  1133 	    if( BFLAG(ir) ) { 
  1134 		/* Actually S - bit 22. Means "make massively complicated" */
  1135 		if( LFLAG(ir) && (ir&0x00008000) ) {
  1136 		    /* LDM (3). Much like normal LDM but also copies SPSR
  1137 		     * back to CPSR */
  1138 		    for( tmp=0; tmp < 16; tmp++ ) {
  1139 			if( (ir & (1<<tmp)) ) {
  1140 			    operand += prestep;
  1141 			    armr.r[tmp] = arm_read_long(operand);
  1142 			    operand += poststep;
  1145 		    if( WFLAG(ir) ) 
  1146 			LRN(ir) = operand;
  1147 		    arm_restore_cpsr();
  1148 		    if( armr.t ) PC &= 0xFFFFFFFE;
  1149 		    else PC &= 0xFFFFFFFC;
  1150 		} else {
  1151 		    /* LDM/STM (2). As normal LDM but accesses the User banks
  1152 		     * instead of the active ones. Aka the truly evil case
  1153 		     */
  1154 		    int bank_start;
  1155 		    if( IS_FIQ_MODE() )
  1156 			bank_start = 8;
  1157 		    else if( IS_EXCEPTION_MODE() )
  1158 			bank_start = 13;
  1159 		    else bank_start = 15;
  1160 		    for( tmp=0; tmp<bank_start; tmp++ ) {
  1161 			if( (ir & (1<<tmp)) ) {
  1162 			    operand += prestep;
  1163 			    if( LFLAG(ir) ) {
  1164 				armr.r[tmp] = arm_read_long(operand);
  1165 			    } else {
  1166 				arm_write_long( operand, armr.r[tmp] );
  1168 			    operand += poststep;
  1171 		    for( ; tmp < 15; tmp ++ ) {
  1172 			if( (ir & (1<<tmp)) ) {
  1173 			    operand += prestep;
  1174 			    if( LFLAG(ir) ) {
  1175 				armr.user_r[tmp-8] = arm_read_long(operand);
  1176 			    } else {
  1177 				arm_write_long( operand, armr.user_r[tmp-8] );
  1179 			    operand += poststep;
  1182 		    if( ir & 0x8000 ) {
  1183 			operand += prestep;
  1184 			if( LFLAG(ir) ) {
  1185 			    /* Actually can't happen, but anyway... */
  1186 			    armr.r[15] = arm_read_long(operand);
  1187 			} else {
  1188 			    arm_write_long( operand, armr.r[15]+ STM_R15_OFFSET - 4 );
  1190 			operand += poststep;
  1193 	    } else {
  1194 		/* Normal LDM/STM */
  1195 		for( tmp=0; tmp < 16; tmp++ ) {
  1196 		    if( (ir & (1<<tmp)) ) {
  1197 			operand += prestep;
  1198 			if( LFLAG(ir) ) {
  1199 			    armr.r[tmp] = arm_read_long(operand);
  1200 			} else {
  1201 			    if( tmp == 15 )
  1202 				arm_write_long( operand, 
  1203 						armr.r[15] + STM_R15_OFFSET - 4 );
  1204 			    else
  1205 				arm_write_long( operand, armr.r[tmp] );
  1207 			operand += poststep;
  1210 		if( WFLAG(ir) ) 
  1211 		    LRN(ir) = operand;
  1214 	break;
  1215     case 3: /* Copro */
  1216 	if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */
  1217 	    arm_raise_exception( EXC_SOFTWARE );
  1218 	} else {
  1219 	    UNIMP(ir);
  1221 	break;
  1223     return TRUE;
.