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