Search
lxdream.org :: lxdream/src/aica/armcore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 35:21a4be098304
prev30:89b30313d757
next37:1d84f4c18816
author nkeynes
date Mon Dec 26 03:54:55 2005 +0000 (15 years ago)
permissions -rw-r--r--
last change Remove modules.h - move definitions into dream.h
Add source string to output list (taken from module name)
ARM Work in progress
view annotate diff log raw
     1 /**
     2  * $Id: armcore.c,v 1.6 2005-12-26 03:54:55 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 #include "aica/armcore.h"
    21 struct arm_registers armr;
    23 void arm_set_mode( int mode );
    25 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
    26 				{ MODE_UND, 0x00000004 },
    27 				{ MODE_SVC, 0x00000008 },
    28 				{ MODE_ABT, 0x0000000C },
    29 				{ MODE_ABT, 0x00000010 },
    30 				{ MODE_IRQ, 0x00000018 },
    31 				{ MODE_FIQ, 0x0000001C } };
    33 #define EXC_RESET 0
    34 #define EXC_UNDEFINED 1
    35 #define EXC_SOFTWARE 2
    36 #define EXC_PREFETCH_ABORT 3
    37 #define EXC_DATA_ABORT 4
    38 #define EXC_IRQ 5
    39 #define EXC_FAST_IRQ 6
    41 uint32_t arm_cpu_freq = ARM_BASE_RATE;
    42 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
    44 uint32_t arm_run_slice( uint32_t nanosecs )
    45 {
    46     uint32_t target = armr.icount + nanosecs / arm_cpu_period;
    47     uint32_t start = armr.icount;
    48     while( armr.icount < target ) {
    49 	armr.icount++;
    50 	if( !arm_execute_instruction() )
    51 	    break;
    52     }
    54     if( target != armr.icount ) {
    55 	/* Halted - compute time actually executed */
    56 	nanosecs = (armr.icount - start) * arm_cpu_period;
    57     }
    58     return nanosecs;
    59 }
    61 void arm_save_state( FILE *f )
    62 {
    63     fwrite( &armr, sizeof(armr), 1, f );
    64 }
    66 int arm_load_state( FILE *f )
    67 {
    68     fread( &armr, sizeof(armr), 1, f );
    69     return 0;
    70 }
    72 /* Exceptions */
    73 void arm_reset( void )
    74 {
    75     /* Wipe all processor state */
    76     memset( &armr, 0, sizeof(armr) );
    78     armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
    79     armr.r[15] = 0x00000000;
    80 }
    82 /**
    83  * Raise an ARM exception (other than reset, which uses arm_reset().
    84  * @param exception one of the EXC_* exception codes defined above.
    85  */
    86 void arm_raise_exception( int exception )
    87 {
    88     int mode = arm_exceptions[exception][0];
    89     arm_set_mode( mode );
    90     armr.spsr = armr.cpsr;
    91     armr.r[14] = armr.r[15];
    92     armr.cpsr = (armr.cpsr & (~CPSR_T)) | CPSR_I; 
    93     if( mode == MODE_FIQ )
    94 	armr.cpsr |= CPSR_F;
    95     armr.r[15] = arm_exceptions[exception][1];
    96 }
    98 /**
    99  * Restore CPSR from SPSR, effectively (under most circumstances) executing
   100  * a return-from-exception.
   101  */
   102 void arm_restore_cpsr()
   103 {
   104     int spsr = armr.spsr;
   105     int mode = spsr & CPSR_MODE;
   107     arm_set_mode( mode );
   108     armr.cpsr = spsr;
   109 }
   113 /**
   114  * Change the current executing ARM mode to the requested mode.
   115  * Saves any required registers to banks and restores those for the
   116  * correct mode. (Note does not actually update CPSR at the moment).
   117  */
   118 void arm_set_mode( int targetMode )
   119 {
   120     int currentMode = armr.cpsr & CPSR_MODE;
   121     if( currentMode == targetMode )
   122 	return;
   124     switch( currentMode ) {
   125     case MODE_USER:
   126     case MODE_SYS:
   127 	armr.user_r[5] = armr.r[13];
   128 	armr.user_r[6] = armr.r[14];
   129 	break;
   130     case MODE_SVC:
   131 	armr.svc_r[0] = armr.r[13];
   132 	armr.svc_r[1] = armr.r[14];
   133 	armr.svc_r[2] = armr.spsr;
   134 	break;
   135     case MODE_ABT:
   136 	armr.abt_r[0] = armr.r[13];
   137 	armr.abt_r[1] = armr.r[14];
   138 	armr.abt_r[2] = armr.spsr;
   139 	break;
   140     case MODE_UND:
   141 	armr.und_r[0] = armr.r[13];
   142 	armr.und_r[1] = armr.r[14];
   143 	armr.und_r[2] = armr.spsr;
   144 	break;
   145     case MODE_IRQ:
   146 	armr.irq_r[0] = armr.r[13];
   147 	armr.irq_r[1] = armr.r[14];
   148 	armr.irq_r[2] = armr.spsr;
   149 	break;
   150     case MODE_FIQ:
   151 	armr.fiq_r[0] = armr.r[8];
   152 	armr.fiq_r[1] = armr.r[9];
   153 	armr.fiq_r[2] = armr.r[10];
   154 	armr.fiq_r[3] = armr.r[11];
   155 	armr.fiq_r[4] = armr.r[12];
   156 	armr.fiq_r[5] = armr.r[13];
   157 	armr.fiq_r[6] = armr.r[14];
   158 	armr.fiq_r[7] = armr.spsr;
   159 	armr.r[8] = armr.user_r[0];
   160 	armr.r[9] = armr.user_r[1];
   161 	armr.r[10] = armr.user_r[2];
   162 	armr.r[11] = armr.user_r[3];
   163 	armr.r[12] = armr.user_r[4];
   164 	break;
   165     }
   167     switch( targetMode ) {
   168     case MODE_USER:
   169     case MODE_SYS:
   170 	armr.r[13] = armr.user_r[5];
   171 	armr.r[14] = armr.user_r[6];
   172 	break;
   173     case MODE_SVC:
   174 	armr.r[13] = armr.svc_r[0];
   175 	armr.r[14] = armr.svc_r[1];
   176 	armr.spsr = armr.svc_r[2];
   177 	break;
   178     case MODE_ABT:
   179 	armr.r[13] = armr.abt_r[0];
   180 	armr.r[14] = armr.abt_r[1];
   181 	armr.spsr = armr.abt_r[2];
   182 	break;
   183     case MODE_UND:
   184 	armr.r[13] = armr.und_r[0];
   185 	armr.r[14] = armr.und_r[1];
   186 	armr.spsr = armr.und_r[2];
   187 	break;
   188     case MODE_IRQ:
   189 	armr.r[13] = armr.irq_r[0];
   190 	armr.r[14] = armr.irq_r[1];
   191 	armr.spsr = armr.irq_r[2];
   192 	break;
   193     case MODE_FIQ:
   194 	armr.user_r[0] = armr.r[8];
   195 	armr.user_r[1] = armr.r[9];
   196 	armr.user_r[2] = armr.r[10];
   197 	armr.user_r[3] = armr.r[11];
   198 	armr.user_r[4] = armr.r[12];
   199 	armr.r[8] = armr.fiq_r[0];
   200 	armr.r[9] = armr.fiq_r[1];
   201 	armr.r[10] = armr.fiq_r[2];
   202 	armr.r[11] = armr.fiq_r[3];
   203 	armr.r[12] = armr.fiq_r[4];
   204 	armr.r[13] = armr.fiq_r[5];
   205 	armr.r[14] = armr.fiq_r[6];
   206 	armr.spsr = armr.fiq_r[7];
   207 	break;
   208     }
   209 }
   211 /* Page references are as per ARM DDI 0100E (June 2000) */
   213 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
   214 #define MEM_READ_WORD( addr ) arm_read_word(addr)
   215 #define MEM_READ_LONG( addr ) arm_read_long(addr)
   216 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
   217 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
   218 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
   221 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
   222 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
   223 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
   224 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
   226 #define PC armr.r[15]
   228 /* Instruction fields */
   229 #define COND(ir) (ir>>28)
   230 #define GRP(ir) ((ir>>26)&0x03)
   231 #define OPCODE(ir) ((ir>>20)&0x1F)
   232 #define IFLAG(ir) (ir&0x02000000)
   233 #define SFLAG(ir) (ir&0x00100000)
   234 #define PFLAG(ir) (ir&0x01000000)
   235 #define UFLAG(ir) (ir&0x00800000)
   236 #define BFLAG(ir) (ir&0x00400000)
   237 #define WFLAG(ir) (IR&0x00200000)
   238 #define LFLAG(ir) SFLAG(ir)
   239 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   240 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   241 #define RDn(ir) ((ir>>12)&0x0F)
   242 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   243 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   244 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
   245 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
   246 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
   247 #define LRM(ir) armr.r[(ir&0x0F)]
   249 #define IMM8(ir) (ir&0xFF)
   250 #define IMM12(ir) (ir&0xFFF)
   251 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
   252 #define IMMROT(ir) ((ir>>7)&0x1E)
   253 #define SHIFT(ir) ((ir>>4)&0x07)
   254 #define DISP24(ir) ((ir&0x00FFFFFF))
   255 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return TRUE; } while(0)
   256 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)
   258 static uint32_t arm_get_shift_operand( uint32_t ir )
   259 {
   260 	uint32_t operand, tmp;
   261 	if( IFLAG(ir) == 0 ) {
   262 		operand = RM(ir);
   263 		switch(SHIFT(ir)) {
   264 		case 0: /* (Rm << imm) */
   265 			operand = operand << SHIFTIMM(ir);
   266 			break;
   267 		case 1: /* (Rm << Rs) */
   268 			tmp = RS(ir)&0xFF;
   269 			if( tmp > 31 ) operand = 0;
   270 			else operand = operand << tmp;
   271 			break;
   272 		case 2: /* (Rm >> imm) */
   273 			operand = operand >> SHIFTIMM(ir);
   274 			break;
   275 		case 3: /* (Rm >> Rs) */
   276 			tmp = RS(ir) & 0xFF;
   277 			if( tmp > 31 ) operand = 0;
   278 			else operand = operand >> ir;
   279 			break;
   280 		case 4: /* (Rm >>> imm) */
   281 			tmp = SHIFTIMM(ir);
   282 			if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   283 			else operand = ((int32_t)operand) >> tmp;
   284 			break;
   285 		case 5: /* (Rm >>> Rs) */
   286 			tmp = RS(ir) & 0xFF;
   287 			if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
   288 			else operand = ((int32_t)operand) >> tmp;
   289 			break;
   290 		case 6:
   291 			tmp = SHIFTIMM(ir);
   292 			if( tmp == 0 ) /* RRX aka rotate with carry */
   293 				operand = (operand >> 1) | (armr.c<<31);
   294 			else
   295 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   296 			break;
   297 		case 7:
   298 			tmp = RS(ir)&0x1F;
   299 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   300 			break;
   301 		}
   302 	} else {
   303 		operand = IMM8(ir);
   304 		tmp = IMMROT(ir);
   305 		operand = ROTATE_RIGHT_LONG(operand, tmp);
   306 	}
   307 	return operand;
   308 }
   310 /**
   311  * Compute the "shift operand" of the instruction for the data processing
   312  * instructions. This variant also sets armr.shift_c (carry result for shifter)
   313  * Reason for the variants is that most cases don't actually need the shift_c.
   314  */
   315 static uint32_t arm_get_shift_operand_s( uint32_t ir )
   316 {
   317 	uint32_t operand, tmp;
   318 	if( IFLAG(ir) == 0 ) {
   319 		operand = RM(ir);
   320 		switch(SHIFT(ir)) {
   321 		case 0: /* (Rm << imm) */
   322 			tmp = SHIFTIMM(ir);
   323 			if( tmp == 0 ) { /* Rm */
   324 				armr.shift_c = armr.c;
   325 			} else { /* Rm << imm */
   326 				armr.shift_c = (operand >> (32-tmp)) & 0x01;
   327 				operand = operand << tmp;
   328 			}
   329 			break;
   330 		case 1: /* (Rm << Rs) */
   331 			tmp = RS(ir)&0xFF;
   332 			if( tmp == 0 ) {
   333 				armr.shift_c = armr.c;
   334 			} else {
   335 				if( tmp <= 32 )
   336 					armr.shift_c = (operand >> (32-tmp)) & 0x01;
   337 				else armr.shift_c = 0;
   338 				if( tmp < 32 )
   339 					operand = operand << tmp;
   340 				else operand = 0;
   341 			}
   342 			break;
   343 		case 2: /* (Rm >> imm) */
   344 			tmp = SHIFTIMM(ir);
   345 			if( tmp == 0 ) {
   346 				armr.shift_c = operand >> 31;
   347 				operand = 0;
   348 			} else {
   349 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   350 				operand = RM(ir) >> tmp;
   351 			}
   352 			break;
   353 		case 3: /* (Rm >> Rs) */
   354 			tmp = RS(ir) & 0xFF;
   355 			if( tmp == 0 ) {
   356 				armr.shift_c = armr.c;
   357 			} else {
   358 				if( tmp <= 32 )
   359 					armr.shift_c = (operand >> (tmp-1))&0x01;
   360 				else armr.shift_c = 0;
   361 				if( tmp < 32 )
   362 					operand = operand >> tmp;
   363 				else operand = 0;
   364 			}
   365 			break;
   366 		case 4: /* (Rm >>> imm) */
   367 			tmp = SHIFTIMM(ir);
   368 			if( tmp == 0 ) {
   369 				armr.shift_c = operand >> 31;
   370 				operand = -armr.shift_c;
   371 			} else {
   372 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   373 				operand = ((int32_t)operand) >> tmp;
   374 			}
   375 			break;
   376 		case 5: /* (Rm >>> Rs) */
   377 			tmp = RS(ir) & 0xFF;
   378 			if( tmp == 0 ) {
   379 				armr.shift_c = armr.c;
   380 			} else {
   381 				if( tmp < 32 ) {
   382 					armr.shift_c = (operand >> (tmp-1))&0x01;
   383 					operand = ((int32_t)operand) >> tmp;
   384 				} else {
   385 					armr.shift_c = operand >> 31;
   386 					operand = ((int32_t)operand) >> 31;
   387 				}
   388 			}
   389 			break;
   390 		case 6:
   391 			tmp = SHIFTIMM(ir);
   392 			if( tmp == 0 ) { /* RRX aka rotate with carry */
   393 				armr.shift_c = operand&0x01;
   394 				operand = (operand >> 1) | (armr.c<<31);
   395 			} else {
   396 				armr.shift_c = operand>>(tmp-1);
   397 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   398 			}
   399 			break;
   400 		case 7:
   401 			tmp = RS(ir)&0xFF;
   402 			if( tmp == 0 ) {
   403 				armr.shift_c = armr.c;
   404 			} else {
   405 				tmp &= 0x1F;
   406 				if( tmp == 0 ) {
   407 					armr.shift_c = operand>>31;
   408 				} else {
   409 					armr.shift_c = (operand>>(tmp-1))&0x1;
   410 					operand = ROTATE_RIGHT_LONG(operand,tmp);
   411 				}
   412 			}
   413 			break;
   414 		}
   415 	} else {
   416 		operand = IMM8(ir);
   417 		tmp = IMMROT(ir);
   418 		if( tmp == 0 ) {
   419 			armr.shift_c = armr.c;
   420 		} else {
   421 			operand = ROTATE_RIGHT_LONG(operand, tmp);
   422 			armr.shift_c = operand>>31;
   423 		}
   424 	}
   425 	return operand;
   426 }
   428 /**
   429  * Another variant of the shifter code for index-based memory addressing.
   430  * Distinguished by the fact that it doesn't support register shifts, and
   431  * ignores the I flag (WTF do the load/store instructions use the I flag to
   432  * mean the _exact opposite_ of what it means for the data processing 
   433  * instructions ???)
   434  */
   435 static uint32_t arm_get_address_index( uint32_t ir )
   436 {
   437 	uint32_t operand = RM(ir);
   438 	uint32_t tmp;
   440 	switch(SHIFT(ir)) {
   441 	case 0: /* (Rm << imm) */
   442 		operand = operand << SHIFTIMM(ir);
   443 		break;
   444 	case 2: /* (Rm >> imm) */
   445 		operand = operand >> SHIFTIMM(ir);
   446 		break;
   447 	case 4: /* (Rm >>> imm) */
   448 		tmp = SHIFTIMM(ir);
   449 		if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   450 		else operand = ((int32_t)operand) >> tmp;
   451 		break;
   452 	case 6:
   453 		tmp = SHIFTIMM(ir);
   454 		if( tmp == 0 ) /* RRX aka rotate with carry */
   455 			operand = (operand >> 1) | (armr.c<<31);
   456 		else
   457 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   458 		break;
   459 	default: UNIMP(ir);
   460 	}
   461 	return operand;	
   462 }
   464 static uint32_t arm_get_address_operand( uint32_t ir )
   465 {
   466 	uint32_t addr;
   468 	/* I P U . W */
   469 	switch( (ir>>21)&0x1D ) {
   470 	case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   471 	case 1:
   472 		addr = RN(ir);
   473 		LRN(ir) = addr - IMM12(ir);
   474 		break;
   475 	case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
   476 	case 5:
   477 		addr = RN(ir);
   478 		LRN(ir) = addr + IMM12(ir);
   479 		break;
   480 	case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   481 		addr = RN(ir) - IMM12(ir);
   482 		break;
   483 	case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   484 		addr = RN(ir) - IMM12(ir);
   485 		LRN(ir) = addr;
   486 		break;
   487 	case 12: /* Rn + imm offset  [5.2.2 A5-20] */
   488 		addr = RN(ir) + IMM12(ir);
   489 		break;
   490 	case 13: /* Rn += imm offset  [5.2.5 A5-24 ] */
   491 		addr = RN(ir) + IMM12(ir);
   492 		LRN(ir) = addr;
   493 		break;
   494 	case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   495 	case 17:
   496 		addr = RN(ir);
   497 		LRN(ir) = addr - arm_get_address_index(ir);
   498 		break;
   499 	case 20: /* Rn += Rm (post-indexed)  [5.2.10 A5-32 ] */
   500 	case 21:
   501 		addr = RN(ir);
   502 		LRN(ir) = addr - arm_get_address_index(ir);
   503 		break;
   504 	case 24: /* Rn - Rm  [5.2.4 A5-23] */
   505 		addr = RN(ir) - arm_get_address_index(ir);
   506 		break;
   507 	case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   508 		addr = RN(ir) - arm_get_address_index(ir);
   509 		LRN(ir) = addr;
   510 		break;
   511 	case 28: /* Rn + Rm  [5.2.4 A5-23] */
   512 		addr = RN(ir) + arm_get_address_index(ir);
   513 		break;
   514 	case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
   515 		addr = RN(ir) + arm_get_address_index(ir);
   516 		LRN(ir) = addr;
   517 		break;
   518 	default:
   519 		UNIMP(ir); /* Unreachable */
   520 	}
   521 	return addr;
   522 }
   524 gboolean arm_execute_instruction( void ) 
   525 {
   526 	uint32_t pc = PC;
   527 	uint32_t ir = MEM_READ_LONG(pc);
   528 	uint32_t operand, operand2, tmp, cond;
   530 	pc += 4;
   531 	PC = pc;
   533 	switch( COND(ir) ) {
   534 		case 0: /* EQ */ 
   535 			cond = armr.z;
   536 			break;
   537 		case 1: /* NE */
   538 			cond = !armr.z;
   539 			break;
   540 		case 2: /* CS/HS */
   541 			cond = armr.c;
   542 			break;
   543 		case 3: /* CC/LO */
   544 			cond = !armr.c;
   545 			break;
   546 		case 4: /* MI */
   547 			cond = armr.n;
   548 			break;
   549 		case 5: /* PL */
   550 			cond = !armr.n;
   551 			break;
   552 		case 6: /* VS */
   553 			cond = armr.v;
   554 			break;
   555 		case 7: /* VC */
   556 			cond = !armr.v;
   557 			break;
   558 		case 8: /* HI */
   559 			cond = armr.c && !armr.z;
   560 			break;
   561 		case 9: /* LS */
   562 			cond = (!armr.c) || armr.z;
   563 			break;
   564 		case 10: /* GE */
   565 			cond = (armr.n == armr.v);
   566 			break;
   567 		case 11: /* LT */
   568 			cond = (armr.n != armr.v);
   569 			break;
   570 		case 12: /* GT */
   571 			cond = (!armr.z) && (armr.n == armr.v);
   572 			break;
   573 		case 13: /* LE */
   574 			cond = armr.z || (armr.n != armr.v);
   575 			break;
   576 		case 14: /* AL */
   577 			cond = 1;
   578 			break;
   579 		case 15: /* (NV) */
   580 			cond = 0;
   581 			UNDEF(ir);
   582 	}
   584 	switch( GRP(ir) ) {
   585 	case 0:
   586 		if( (ir & 0x0D900000) == 0x01000000 ) {
   587 			/* Instructions that aren't actual data processing */
   588 			switch( ir & 0x0FF000F0 ) {
   589 			case 0x01200010: /* BX */
   590 				break;
   591 			case 0x01000000: /* MRS Rd, CPSR */
   592 				break;
   593 			case 0x01400000: /* MRS Rd, SPSR */
   594 				break;
   595 			case 0x01200000: /* MSR CPSR, Rd */
   596 				break;
   597 			case 0x01600000: /* MSR SPSR, Rd */
   598 				break;
   599 			case 0x03200000: /* MSR CPSR, imm */
   600 				break;
   601 			case 0x03600000: /* MSR SPSR, imm */
   602 				break;
   603 			default:
   604 				UNIMP(ir);
   605 			}
   606 		} else if( (ir & 0x0E000090) == 0x00000090 ) {
   607 			/* Neither are these */
   608 			switch( (ir>>5)&0x03 ) {
   609 			case 0:
   610 				/* Arithmetic extension area */
   611 				switch(OPCODE(ir)) {
   612 				case 0: /* MUL */
   613 					break;
   614 				case 1: /* MULS */
   615 					break;
   616 				case 2: /* MLA */
   617 					break;
   618 				case 3: /* MLAS */
   619 					break;
   620 				case 8: /* UMULL */
   621 					break;
   622 				case 9: /* UMULLS */
   623 					break;
   624 				case 10: /* UMLAL */
   625 					break;
   626 				case 11: /* UMLALS */
   627 					break;
   628 				case 12: /* SMULL */
   629 					break;
   630 				case 13: /* SMULLS */
   631 					break;
   632 				case 14: /* SMLAL */
   633 					break;
   634 				case 15: /* SMLALS */
   635 					break;
   636 				case 16: /* SWP */
   637 					break;
   638 				case 20: /* SWPB */
   639 					break;
   640 				default:
   641 					UNIMP(ir);
   642 				}
   643 				break;
   644 			case 1:
   645 				if( LFLAG(ir) ) {
   646 					/* LDRH */
   647 				} else {
   648 					/* STRH */
   649 				}
   650 				break;
   651 			case 2:
   652 				if( LFLAG(ir) ) {
   653 					/* LDRSB */
   654 				} else {
   655 					UNIMP(ir);
   656 				}
   657 				break;
   658 			case 3:
   659 				if( LFLAG(ir) ) {
   660 					/* LDRSH */
   661 				} else {
   662 					UNIMP(ir);
   663 				}
   664 				break;
   665 			}
   666 		} else {
   667 			/* Data processing */
   669 			switch(OPCODE(ir)) {
   670 			case 0: /* AND Rd, Rn, operand */
   671 				LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
   672 				break;
   673 			case 1: /* ANDS Rd, Rn, operand */
   674 				operand = arm_get_shift_operand_s(ir) & RN(ir);
   675 				LRD(ir) = operand;
   676 				if( RDn(ir) == 15 ) {
   677 					arm_restore_cpsr();
   678 				} else {
   679 					armr.n = operand>>31;
   680 					armr.z = (operand == 0);
   681 					armr.c = armr.shift_c;
   682 				}
   683 				break;
   684 			case 2: /* EOR Rd, Rn, operand */
   685 				LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
   686 				break;
   687 			case 3: /* EORS Rd, Rn, operand */
   688 				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   689 				LRD(ir) = operand;
   690 				if( RDn(ir) == 15 ) {
   691 					arm_restore_cpsr();
   692 				} else {
   693 					armr.n = operand>>31;
   694 					armr.z = (operand == 0);
   695 					armr.c = armr.shift_c;
   696 				}
   697 				break;
   698 			case 4: /* SUB Rd, Rn, operand */
   699 				LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
   700 				break;
   701 			case 5: /* SUBS Rd, Rn, operand */
   702 			    operand = RN(ir);
   703 				operand2 = arm_get_shift_operand(ir);
   704 				tmp = operand - operand2;
   705 				LRD(ir) = tmp;
   706 				if( RDn(ir) == 15 ) {
   707 					arm_restore_cpsr();
   708 				} else {
   709 					armr.n = tmp>>31;
   710 					armr.z = (tmp == 0);
   711 					armr.c = IS_NOTBORROW(tmp,operand,operand2);
   712 					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   713 				}
   714 				break;
   715 			case 6: /* RSB Rd, operand, Rn */
   716 				LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
   717 				break;
   718 			case 7: /* RSBS Rd, operand, Rn */
   719 				operand = arm_get_shift_operand(ir);
   720 			    operand2 = RN(ir);
   721 				tmp = operand - operand2;
   722 				LRD(ir) = tmp;
   723 				if( RDn(ir) == 15 ) {
   724 					arm_restore_cpsr();
   725 				} else {
   726 					armr.n = tmp>>31;
   727 					armr.z = (tmp == 0);
   728 					armr.c = IS_NOTBORROW(tmp,operand,operand2);
   729 					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   730 				}
   731 				break;
   732 			case 8: /* ADD Rd, Rn, operand */
   733 				LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
   734 				break;
   735 			case 9: /* ADDS Rd, Rn, operand */
   736 				operand = arm_get_shift_operand(ir);
   737 			    operand2 = RN(ir);
   738 				tmp = operand + operand2;
   739 				LRD(ir) = tmp;
   740 				if( RDn(ir) == 15 ) {
   741 					arm_restore_cpsr();
   742 				} else {
   743 					armr.n = tmp>>31;
   744 					armr.z = (tmp == 0);
   745 					armr.c = IS_CARRY(tmp,operand,operand2);
   746 					armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   747 				}
   748 				break;			
   749 			case 10: /* ADC */
   750 			case 11: /* ADCS */
   751 			case 12: /* SBC */
   752 			case 13: /* SBCS */
   753 			case 14: /* RSC */
   754 			case 15: /* RSCS */
   755 				break;
   756 			case 17: /* TST Rn, operand */
   757 				operand = arm_get_shift_operand_s(ir) & RN(ir);
   758 				armr.n = operand>>31;
   759 				armr.z = (operand == 0);
   760 				armr.c = armr.shift_c;
   761 				break;
   762 			case 19: /* TEQ Rn, operand */
   763 				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   764 				armr.n = operand>>31;
   765 				armr.z = (operand == 0);
   766 				armr.c = armr.shift_c;
   767 				break;				
   768 			case 21: /* CMP Rn, operand */
   769 			    operand = RN(ir);
   770 				operand2 = arm_get_shift_operand(ir);
   771 				tmp = operand - operand2;
   772 				armr.n = tmp>>31;
   773 				armr.z = (tmp == 0);
   774 				armr.c = IS_NOTBORROW(tmp,operand,operand2);
   775 				armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   776 				break;
   777 			case 23: /* CMN Rn, operand */
   778 			    operand = RN(ir);
   779 				operand2 = arm_get_shift_operand(ir);
   780 				tmp = operand + operand2;
   781 				armr.n = tmp>>31;
   782 				armr.z = (tmp == 0);
   783 				armr.c = IS_CARRY(tmp,operand,operand2);
   784 				armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   785 				break;
   786 			case 24: /* ORR Rd, Rn, operand */
   787 				LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
   788 				break;
   789 			case 25: /* ORRS Rd, Rn, operand */
   790 				operand = arm_get_shift_operand_s(ir) | RN(ir);
   791 				LRD(ir) = operand;
   792 				if( RDn(ir) == 15 ) {
   793 					arm_restore_cpsr();
   794 				} else {
   795 					armr.n = operand>>31;
   796 					armr.z = (operand == 0);
   797 					armr.c = armr.shift_c;
   798 				}
   799 				break;
   800 			case 26: /* MOV Rd, operand */
   801 				LRD(ir) = arm_get_shift_operand(ir);
   802 				break;
   803 			case 27: /* MOVS Rd, operand */
   804 				operand = arm_get_shift_operand_s(ir);
   805 				LRD(ir) = operand;
   806 				if( RDn(ir) == 15 ) {
   807 					arm_restore_cpsr();
   808 				} else {
   809 					armr.n = operand>>31;
   810 					armr.z = (operand == 0);
   811 					armr.c = armr.shift_c;
   812 				}
   813 				break;
   814 			case 28: /* BIC Rd, Rn, operand */
   815 				LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
   816 				break;
   817 			case 29: /* BICS Rd, Rn, operand */
   818 				operand = RN(ir) & (~arm_get_shift_operand_s(ir));
   819 				LRD(ir) = operand;
   820 				if( RDn(ir) == 15 ) {
   821 					arm_restore_cpsr();
   822 				} else {
   823 					armr.n = operand>>31;
   824 					armr.z = (operand == 0);
   825 					armr.c = armr.shift_c;
   826 				}
   827 				break;
   828 			case 30: /* MVN Rd, operand */
   829 				LRD(ir) = ~arm_get_shift_operand(ir);
   830 				break;
   831 			case 31: /* MVNS Rd, operand */
   832 				operand = ~arm_get_shift_operand_s(ir);
   833 				LRD(ir) = operand;
   834 				if( RDn(ir) == 15 ) {
   835 					arm_restore_cpsr();
   836 				} else {
   837 					armr.n = operand>>31;
   838 					armr.z = (operand == 0);
   839 					armr.c = armr.shift_c;
   840 				}
   841 				break;
   842 			default:
   843 				UNIMP(ir);
   844 			}
   845 		}
   846 		break;
   847 	case 1: /* Load/store */
   848 		break;
   849 	case 2: /* Load/store multiple, branch*/
   850 		break;
   851 	case 3: /* Copro */
   852 		break;
   853 	}
   854 	return TRUE;
   855 }
.