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