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