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