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