Search
lxdream.org :: lxdream/src/aica/armcore.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 7:976a16e92aab
prev5:d85c2e81ce2d
next11:0a82ef380c45
author nkeynes
date Sun Dec 12 07:44:09 2004 +0000 (16 years ago)
permissions -rw-r--r--
last change More progress on arm
view annotate diff log raw
     2 #include "aica/armcore.h"
     4 struct arm_registers armr;
     6 /* NB: The arm has a different memory map, but for the meantime... */
     7 /* Page references are as per ARM DDI 0100E (June 2000) */
     9 #define MEM_READ_BYTE( addr ) mem_read_byte(addr)
    10 #define MEM_READ_WORD( addr ) mem_read_word(addr)
    11 #define MEM_READ_LONG( addr ) mem_read_long(addr)
    12 #define MEM_WRITE_BYTE( addr, val ) mem_write_byte(addr, val)
    13 #define MEM_WRITE_WORD( addr, val ) mem_write_word(addr, val)
    14 #define MEM_WRITE_LONG( addr, val ) mem_write_long(addr, val)
    17 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
    18 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
    19 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
    20 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
    22 #define PC armr.r[15]
    24 /* Instruction fields */
    25 #define COND(ir) (ir>>28)
    26 #define GRP(ir) ((ir>>26)&0x03)
    27 #define OPCODE(ir) ((ir>>20)&0x1F)
    28 #define IFLAG(ir) (ir&0x02000000)
    29 #define SFLAG(ir) (ir&0x00100000)
    30 #define PFLAG(ir) (ir&0x01000000)
    31 #define UFLAG(ir) (ir&0x00800000)
    32 #define BFLAG(ir) (ir&0x00400000)
    33 #define WFLAG(ir) (IR&0x00200000)
    34 #define LFLAG(ir) SFLAG(ir)
    35 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
    36 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
    37 #define RDn(ir) ((ir>>12)&0x0F)
    38 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
    39 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
    40 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
    41 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
    42 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
    43 #define LRM(ir) armr.r[(ir&0x0F)]
    45 #define IMM8(ir) (ir&0xFF)
    46 #define IMM12(ir) (ir&0xFFF)
    47 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
    48 #define IMMROT(ir) ((ir>>7)&0x1E)
    49 #define SHIFT(ir) ((ir>>4)&0x07)
    50 #define DISP24(ir) ((ir&0x00FFFFFF))
    51 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return; } while(0)
    52 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return; }while(0)
    55 static uint32_t arm_get_shift_operand( uint32_t ir )
    56 {
    57 	uint32_t operand, tmp;
    58 	if( IFLAG(ir) == 0 ) {
    59 		operand = RM(ir);
    60 		switch(SHIFT(ir)) {
    61 		case 0: /* (Rm << imm) */
    62 			operand = operand << SHIFTIMM(ir);
    63 			break;
    64 		case 1: /* (Rm << Rs) */
    65 			tmp = RS(ir)&0xFF;
    66 			if( tmp > 31 ) operand = 0;
    67 			else operand = operand << tmp;
    68 			break;
    69 		case 2: /* (Rm >> imm) */
    70 			operand = operand >> SHIFTIMM(ir);
    71 			break;
    72 		case 3: /* (Rm >> Rs) */
    73 			tmp = RS(ir) & 0xFF;
    74 			if( tmp > 31 ) operand = 0;
    75 			else operand = operand >> ir;
    76 			break;
    77 		case 4: /* (Rm >>> imm) */
    78 			tmp = SHIFTIMM(ir);
    79 			if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
    80 			else operand = ((int32_t)operand) >> tmp;
    81 			break;
    82 		case 5: /* (Rm >>> Rs) */
    83 			tmp = RS(ir) & 0xFF;
    84 			if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
    85 			else operand = ((int32_t)operand) >> tmp;
    86 			break;
    87 		case 6:
    88 			tmp = SHIFTIMM(ir);
    89 			if( tmp == 0 ) /* RRX aka rotate with carry */
    90 				operand = (operand >> 1) | (armr.c<<31);
    91 			else
    92 				operand = ROTATE_RIGHT_LONG(operand,tmp);
    93 			break;
    94 		case 7:
    95 			tmp = RS(ir)&0x1F;
    96 			operand = ROTATE_RIGHT_LONG(operand,tmp);
    97 			break;
    98 		}
    99 	} else {
   100 		operand = IMM8(ir);
   101 		tmp = IMMROT(ir);
   102 		operand = ROTATE_RIGHT_LONG(operand, tmp);
   103 	}
   104 	return operand;
   105 }
   107 /**
   108  * Compute the "shift operand" of the instruction for the data processing
   109  * instructions. This variant also sets armr.shift_c (carry result for shifter)
   110  * Reason for the variants is that most cases don't actually need the shift_c.
   111  */
   112 static uint32_t arm_get_shift_operand_s( uint32_t ir )
   113 {
   114 	uint32_t operand, tmp;
   115 	if( IFLAG(ir) == 0 ) {
   116 		operand = RM(ir);
   117 		switch(SHIFT(ir)) {
   118 		case 0: /* (Rm << imm) */
   119 			tmp = SHIFTIMM(ir);
   120 			if( tmp == 0 ) { /* Rm */
   121 				armr.shift_c = armr.c;
   122 			} else { /* Rm << imm */
   123 				armr.shift_c = (operand >> (32-tmp)) & 0x01;
   124 				operand = operand << tmp;
   125 			}
   126 			break;
   127 		case 1: /* (Rm << Rs) */
   128 			tmp = RS(ir)&0xFF;
   129 			if( tmp == 0 ) {
   130 				armr.shift_c = armr.c;
   131 			} else {
   132 				if( tmp <= 32 )
   133 					armr.shift_c = (operand >> (32-tmp)) & 0x01;
   134 				else armr.shift_c = 0;
   135 				if( tmp < 32 )
   136 					operand = operand << tmp;
   137 				else operand = 0;
   138 			}
   139 			break;
   140 		case 2: /* (Rm >> imm) */
   141 			tmp = SHIFTIMM(ir);
   142 			if( tmp == 0 ) {
   143 				armr.shift_c = operand >> 31;
   144 				operand = 0;
   145 			} else {
   146 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   147 				operand = RM(ir) >> tmp;
   148 			}
   149 			break;
   150 		case 3: /* (Rm >> Rs) */
   151 			tmp = RS(ir) & 0xFF;
   152 			if( tmp == 0 ) {
   153 				armr.shift_c = armr.c;
   154 			} else {
   155 				if( tmp <= 32 )
   156 					armr.shift_c = (operand >> (tmp-1))&0x01;
   157 				else armr.shift_c = 0;
   158 				if( tmp < 32 )
   159 					operand = operand >> tmp;
   160 				else operand = 0;
   161 			}
   162 			break;
   163 		case 4: /* (Rm >>> imm) */
   164 			tmp = SHIFTIMM(ir);
   165 			if( tmp == 0 ) {
   166 				armr.shift_c = operand >> 31;
   167 				operand = -armr.shift_c;
   168 			} else {
   169 				armr.shift_c = (operand >> (tmp-1)) & 0x01;
   170 				operand = ((int32_t)operand) >> tmp;
   171 			}
   172 			break;
   173 		case 5: /* (Rm >>> Rs) */
   174 			tmp = RS(ir) & 0xFF;
   175 			if( tmp == 0 ) {
   176 				armr.shift_c = armr.c;
   177 			} else {
   178 				if( tmp < 32 ) {
   179 					armr.shift_c = (operand >> (tmp-1))&0x01;
   180 					operand = ((int32_t)operand) >> tmp;
   181 				} else {
   182 					armr.shift_c = operand >> 31;
   183 					operand = ((int32_t)operand) >> 31;
   184 				}
   185 			}
   186 			break;
   187 		case 6:
   188 			tmp = SHIFTIMM(ir);
   189 			if( tmp == 0 ) { /* RRX aka rotate with carry */
   190 				armr.shift_c = operand&0x01;
   191 				operand = (operand >> 1) | (armr.c<<31);
   192 			} else {
   193 				armr.shift_c = operand>>(tmp-1);
   194 				operand = ROTATE_RIGHT_LONG(operand,tmp);
   195 			}
   196 			break;
   197 		case 7:
   198 			tmp = RS(ir)&0xFF;
   199 			if( tmp == 0 ) {
   200 				armr.shift_c = armr.c;
   201 			} else {
   202 				tmp &= 0x1F;
   203 				if( tmp == 0 ) {
   204 					armr.shift_c = operand>>31;
   205 				} else {
   206 					armr.shift_c = (operand>>(tmp-1))&0x1;
   207 					operand = ROTATE_RIGHT_LONG(operand,tmp);
   208 				}
   209 			}
   210 			break;
   211 		}
   212 	} else {
   213 		operand = IMM8(ir);
   214 		tmp = IMMROT(ir);
   215 		if( tmp == 0 ) {
   216 			armr.shift_c = armr.c;
   217 		} else {
   218 			operand = ROTATE_RIGHT_LONG(operand, tmp);
   219 			armr.shift_c = operand>>31;
   220 		}
   221 	}
   222 	return operand;
   223 }
   225 /**
   226  * Another variant of the shifter code for index-based memory addressing.
   227  * Distinguished by the fact that it doesn't support register shifts, and
   228  * ignores the I flag (WTF do the load/store instructions use the I flag to
   229  * mean the _exact opposite_ of what it means for the data processing 
   230  * instructions ???)
   231  */
   232 static uint32_t arm_get_address_index( uint32_t ir )
   233 {
   234 	uint32_t operand = RM(ir);
   235 	uint32_t tmp;
   237 	switch(SHIFT(ir)) {
   238 	case 0: /* (Rm << imm) */
   239 		operand = operand << SHIFTIMM(ir);
   240 		break;
   241 	case 2: /* (Rm >> imm) */
   242 		operand = operand >> SHIFTIMM(ir);
   243 		break;
   244 	case 4: /* (Rm >>> imm) */
   245 		tmp = SHIFTIMM(ir);
   246 		if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   247 		else operand = ((int32_t)operand) >> tmp;
   248 		break;
   249 	case 6:
   250 		tmp = SHIFTIMM(ir);
   251 		if( tmp == 0 ) /* RRX aka rotate with carry */
   252 			operand = (operand >> 1) | (armr.c<<31);
   253 		else
   254 			operand = ROTATE_RIGHT_LONG(operand,tmp);
   255 		break;
   256 	default: UNIMP(ir);
   257 	}
   258 	return operand;	
   259 }
   261 static uint32_t arm_get_address_operand( uint32_t ir )
   262 {
   263 	uint32_t addr;
   265 	/* I P U . W */
   266 	switch( (ir>>21)&0x1D ) {
   267 	case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   268 	case 1:
   269 		addr = RN(ir);
   270 		LRN(ir) = addr - IMM12(ir);
   271 		break;
   272 	case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
   273 	case 5:
   274 		addr = RN(ir);
   275 		LRN(ir) = addr + IMM12(ir);
   276 		break;
   277 	case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   278 		addr = RN(ir) - IMM12(ir);
   279 		break;
   280 	case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   281 		addr = RN(ir) - IMM12(ir);
   282 		LRN(ir) = addr;
   283 		break;
   284 	case 12: /* Rn + imm offset  [5.2.2 A5-20] */
   285 		addr = RN(ir) + IMM12(ir);
   286 		break;
   287 	case 13: /* Rn += imm offset  [5.2.5 A5-24 ] */
   288 		addr = RN(ir) + IMM12(ir);
   289 		LRN(ir) = addr;
   290 		break;
   291 	case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   292 	case 17:
   293 		addr = RN(ir);
   294 		LRN(ir) = addr - arm_get_address_index(ir);
   295 		break;
   296 	case 20: /* Rn += Rm (post-indexed)  [5.2.10 A5-32 ] */
   297 	case 21:
   298 		addr = RN(ir);
   299 		LRN(ir) = addr - arm_get_address_index(ir);
   300 		break;
   301 	case 24: /* Rn - Rm  [5.2.4 A5-23] */
   302 		addr = RN(ir) - arm_get_address_index(ir);
   303 		break;
   304 	case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   305 		addr = RN(ir) - arm_get_address_index(ir);
   306 		LRN(ir) = addr;
   307 		break;
   308 	case 28: /* Rn + Rm  [5.2.4 A5-23] */
   309 		addr = RN(ir) + arm_get_address_index(ir);
   310 		break;
   311 	case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
   312 		addr = RN(ir) + arm_get_address_index(ir);
   313 		LRN(ir) = addr;
   314 		break;
   315 	default:
   316 		UNIMP(ir); /* Unreachable */
   317 	}
   318 	return addr;
   319 }
   321 void arm_execute_instruction( void ) 
   322 {
   323 	uint32_t pc = PC;
   324 	uint32_t ir = MEM_READ_LONG(pc);
   325 	uint32_t operand, operand2, tmp, cond;
   327 	pc += 4;
   328 	PC = pc;
   330 	switch( COND(ir) ) {
   331 		case 0: /* EQ */ 
   332 			cond = armr.z;
   333 			break;
   334 		case 1: /* NE */
   335 			cond = !armr.z;
   336 			break;
   337 		case 2: /* CS/HS */
   338 			cond = armr.c;
   339 			break;
   340 		case 3: /* CC/LO */
   341 			cond = !armr.c;
   342 			break;
   343 		case 4: /* MI */
   344 			cond = armr.n;
   345 			break;
   346 		case 5: /* PL */
   347 			cond = !armr.n;
   348 			break;
   349 		case 6: /* VS */
   350 			cond = armr.v;
   351 			break;
   352 		case 7: /* VC */
   353 			cond = !armr.v;
   354 			break;
   355 		case 8: /* HI */
   356 			cond = armr.c && !armr.z;
   357 			break;
   358 		case 9: /* LS */
   359 			cond = (!armr.c) || armr.z;
   360 			break;
   361 		case 10: /* GE */
   362 			cond = (armr.n == armr.v);
   363 			break;
   364 		case 11: /* LT */
   365 			cond = (armr.n != armr.v);
   366 			break;
   367 		case 12: /* GT */
   368 			cond = (!armr.z) && (armr.n == armr.v);
   369 			break;
   370 		case 13: /* LE */
   371 			cond = armr.z || (armr.n != armr.v);
   372 			break;
   373 		case 14: /* AL */
   374 			cond = 1;
   375 			break;
   376 		case 15: /* (NV) */
   377 			cond = 0;
   378 			UNDEF(ir);
   379 	}
   381 	switch( GRP(ir) ) {
   382 	case 0:
   383 		if( (ir & 0x0D900000) == 0x01000000 ) {
   384 			/* Instructions that aren't actual data processing */
   385 			switch( ir & 0x0FF000F0 ) {
   386 			case 0x01200010: /* BX */
   387 				break;
   388 			case 0x01000000: /* MRS Rd, CPSR */
   389 				break;
   390 			case 0x01400000: /* MRS Rd, SPSR */
   391 				break;
   392 			case 0x01200000: /* MSR CPSR, Rd */
   393 				break;
   394 			case 0x01600000: /* MSR SPSR, Rd */
   395 				break;
   396 			case 0x03200000: /* MSR CPSR, imm */
   397 				break;
   398 			case 0x03600000: /* MSR SPSR, imm */
   399 				break;
   400 			default:
   401 				UNIMP(ir);
   402 			}
   403 		} else if( (ir & 0x0E000090) == 0x00000090 ) {
   404 			/* Neither are these */
   405 			switch( (ir>>5)&0x03 ) {
   406 			case 0:
   407 				/* Arithmetic extension area */
   408 				switch(OPCODE(ir)) {
   409 				case 0: /* MUL */
   410 					break;
   411 				case 1: /* MULS */
   412 					break;
   413 				case 2: /* MLA */
   414 					break;
   415 				case 3: /* MLAS */
   416 					break;
   417 				case 8: /* UMULL */
   418 					break;
   419 				case 9: /* UMULLS */
   420 					break;
   421 				case 10: /* UMLAL */
   422 					break;
   423 				case 11: /* UMLALS */
   424 					break;
   425 				case 12: /* SMULL */
   426 					break;
   427 				case 13: /* SMULLS */
   428 					break;
   429 				case 14: /* SMLAL */
   430 					break;
   431 				case 15: /* SMLALS */
   432 					break;
   433 				case 16: /* SWP */
   434 					break;
   435 				case 20: /* SWPB */
   436 					break;
   437 				default:
   438 					UNIMP(ir);
   439 				}
   440 				break;
   441 			case 1:
   442 				if( LFLAG(ir) ) {
   443 					/* LDRH */
   444 				} else {
   445 					/* STRH */
   446 				}
   447 				break;
   448 			case 2:
   449 				if( LFLAG(ir) ) {
   450 					/* LDRSB */
   451 				} else {
   452 					UNIMP(ir);
   453 				}
   454 				break;
   455 			case 3:
   456 				if( LFLAG(ir) ) {
   457 					/* LDRSH */
   458 				} else {
   459 					UNIMP(ir);
   460 				}
   461 				break;
   462 			}
   463 		} else {
   464 			/* Data processing */
   466 			switch(OPCODE(ir)) {
   467 			case 0: /* AND Rd, Rn, operand */
   468 				LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
   469 				break;
   470 			case 1: /* ANDS Rd, Rn, operand */
   471 				operand = arm_get_shift_operand_s(ir) & RN(ir);
   472 				LRD(ir) = operand;
   473 				if( RDn(ir) == 15 ) {
   474 					arm_restore_cpsr();
   475 				} else {
   476 					armr.n = operand>>31;
   477 					armr.z = (operand == 0);
   478 					armr.c = armr.shift_c;
   479 				}
   480 				break;
   481 			case 2: /* EOR Rd, Rn, operand */
   482 				LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
   483 				break;
   484 			case 3: /* EORS Rd, Rn, operand */
   485 				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   486 				LRD(ir) = operand;
   487 				if( RDn(ir) == 15 ) {
   488 					arm_restore_cpsr();
   489 				} else {
   490 					armr.n = operand>>31;
   491 					armr.z = (operand == 0);
   492 					armr.c = armr.shift_c;
   493 				}
   494 				break;
   495 			case 4: /* SUB Rd, Rn, operand */
   496 				LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
   497 				break;
   498 			case 5: /* SUBS Rd, Rn, operand */
   499 			    operand = RN(ir);
   500 				operand2 = arm_get_shift_operand(ir);
   501 				tmp = operand - operand2;
   502 				LRD(ir) = tmp;
   503 				if( RDn(ir) == 15 ) {
   504 					arm_restore_cpsr();
   505 				} else {
   506 					armr.n = tmp>>31;
   507 					armr.z = (tmp == 0);
   508 					armr.c = IS_NOTBORROW(tmp,operand,operand2);
   509 					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   510 				}
   511 				break;
   512 			case 6: /* RSB Rd, operand, Rn */
   513 				LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
   514 				break;
   515 			case 7: /* RSBS Rd, operand, Rn */
   516 				operand = arm_get_shift_operand(ir);
   517 			    operand2 = RN(ir);
   518 				tmp = operand - operand2;
   519 				LRD(ir) = tmp;
   520 				if( RDn(ir) == 15 ) {
   521 					arm_restore_cpsr();
   522 				} else {
   523 					armr.n = tmp>>31;
   524 					armr.z = (tmp == 0);
   525 					armr.c = IS_NOTBORROW(tmp,operand,operand2);
   526 					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   527 				}
   528 				break;
   529 			case 8: /* ADD Rd, Rn, operand */
   530 				LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
   531 				break;
   532 			case 9: /* ADDS Rd, Rn, operand */
   533 				operand = arm_get_shift_operand(ir);
   534 			    operand2 = RN(ir);
   535 				tmp = operand + operand2;
   536 				LRD(ir) = tmp;
   537 				if( RDn(ir) == 15 ) {
   538 					arm_restore_cpsr();
   539 				} else {
   540 					armr.n = tmp>>31;
   541 					armr.z = (tmp == 0);
   542 					armr.c = IS_CARRY(tmp,operand,operand2);
   543 					armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   544 				}
   545 				break;			
   546 			case 10: /* ADC */
   547 			case 11: /* ADCS */
   548 			case 12: /* SBC */
   549 			case 13: /* SBCS */
   550 			case 14: /* RSC */
   551 			case 15: /* RSCS */
   552 				break;
   553 			case 17: /* TST Rn, operand */
   554 				operand = arm_get_shift_operand_s(ir) & RN(ir);
   555 				armr.n = operand>>31;
   556 				armr.z = (operand == 0);
   557 				armr.c = armr.shift_c;
   558 				break;
   559 			case 19: /* TEQ Rn, operand */
   560 				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   561 				armr.n = operand>>31;
   562 				armr.z = (operand == 0);
   563 				armr.c = armr.shift_c;
   564 				break;				
   565 			case 21: /* CMP Rn, operand */
   566 			    operand = RN(ir);
   567 				operand2 = arm_get_shift_operand(ir);
   568 				tmp = operand - operand2;
   569 				armr.n = tmp>>31;
   570 				armr.z = (tmp == 0);
   571 				armr.c = IS_NOTBORROW(tmp,operand,operand2);
   572 				armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
   573 				break;
   574 			case 23: /* CMN Rn, operand */
   575 			    operand = RN(ir);
   576 				operand2 = arm_get_shift_operand(ir);
   577 				tmp = operand + operand2;
   578 				armr.n = tmp>>31;
   579 				armr.z = (tmp == 0);
   580 				armr.c = IS_CARRY(tmp,operand,operand2);
   581 				armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
   582 				break;
   583 			case 24: /* ORR Rd, Rn, operand */
   584 				LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
   585 				break;
   586 			case 25: /* ORRS Rd, Rn, operand */
   587 				operand = arm_get_shift_operand_s(ir) | RN(ir);
   588 				LRD(ir) = operand;
   589 				if( RDn(ir) == 15 ) {
   590 					arm_restore_cpsr();
   591 				} else {
   592 					armr.n = operand>>31;
   593 					armr.z = (operand == 0);
   594 					armr.c = armr.shift_c;
   595 				}
   596 				break;
   597 			case 26: /* MOV Rd, operand */
   598 				LRD(ir) = arm_get_shift_operand(ir);
   599 				break;
   600 			case 27: /* MOVS Rd, operand */
   601 				operand = arm_get_shift_operand_s(ir);
   602 				LRD(ir) = operand;
   603 				if( RDn(ir) == 15 ) {
   604 					arm_restore_cpsr();
   605 				} else {
   606 					armr.n = operand>>31;
   607 					armr.z = (operand == 0);
   608 					armr.c = armr.shift_c;
   609 				}
   610 				break;
   611 			case 28: /* BIC Rd, Rn, operand */
   612 				LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
   613 				break;
   614 			case 29: /* BICS Rd, Rn, operand */
   615 				operand = RN(ir) & (~arm_get_shift_operand_s(ir));
   616 				LRD(ir) = operand;
   617 				if( RDn(ir) == 15 ) {
   618 					arm_restore_cpsr();
   619 				} else {
   620 					armr.n = operand>>31;
   621 					armr.z = (operand == 0);
   622 					armr.c = armr.shift_c;
   623 				}
   624 				break;
   625 			case 30: /* MVN Rd, operand */
   626 				LRD(ir) = ~arm_get_shift_operand(ir);
   627 				break;
   628 			case 31: /* MVNS Rd, operand */
   629 				operand = ~arm_get_shift_operand_s(ir);
   630 				LRD(ir) = operand;
   631 				if( RDn(ir) == 15 ) {
   632 					arm_restore_cpsr();
   633 				} else {
   634 					armr.n = operand>>31;
   635 					armr.z = (operand == 0);
   636 					armr.c = armr.shift_c;
   637 				}
   638 				break;
   639 			default:
   640 				UNIMP(ir);
   641 			}
   642 		}
   643 		break;
   644 	case 1: /* Load/store */
   645 		break;
   646 	case 2: /* Load/store multiple, branch*/
   647 		break;
   648 	case 3: /* Copro */
   649 		break;
   650 	}
   651 }
.