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