Search
lxdream.org :: lxdream/src/aica/armdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 7:976a16e92aab
prev4:7d6f596ce577
next11:0a82ef380c45
author nkeynes
date Sun Dec 12 07:44:09 2004 +0000 (15 years ago)
permissions -rw-r--r--
last change More progress on arm
file annotate diff log raw
nkeynes@4
     1
/*
nkeynes@4
     2
 * armdasm.c    21 Aug 2004  - ARM7tdmi (ARMv4) disassembler
nkeynes@4
     3
 *
nkeynes@4
     4
 * Copyright (c) 2004 Nathan Keynes. Distribution and modification permitted
nkeynes@4
     5
 * under the terms of the GNU General Public License version 2 or later.
nkeynes@4
     6
 */
nkeynes@4
     7
nkeynes@7
     8
#include "aica/armcore.h"
nkeynes@7
     9
#include <stdlib.h>
nkeynes@4
    10
nkeynes@4
    11
#define COND(ir) (ir>>28)
nkeynes@4
    12
#define OPCODE(ir) ((ir>>20)&0x1F)
nkeynes@4
    13
#define GRP(ir) ((ir>>26)&0x03)
nkeynes@4
    14
#define IFLAG(ir) (ir&0x02000000)
nkeynes@4
    15
#define SFLAG(ir) (ir&0x00100000)
nkeynes@4
    16
#define PFLAG(ir) (ir&0x01000000)
nkeynes@4
    17
#define UFLAG(ir) (ir&0x00800000)
nkeynes@4
    18
#define BFLAG(ir) (ir&0x00400000)
nkeynes@7
    19
#define WFLAG(ir) (ir&0x00200000)
nkeynes@4
    20
#define LFLAG(ir) SFLAG(ir)
nkeynes@4
    21
#define RN(ir) ((ir>>16)&0x0F)
nkeynes@4
    22
#define RD(ir) ((ir>>12)&0x0F)
nkeynes@4
    23
#define RS(ir) ((ir>>8)&0x0F)
nkeynes@4
    24
#define RM(ir) (ir&0x0F)
nkeynes@4
    25
nkeynes@4
    26
#define IMM8(ir) (ir&0xFF)
nkeynes@4
    27
#define IMM12(ir) (ir&0xFFF)
nkeynes@7
    28
#define SHIFTIMM(ir) ((ir>>7)&0x1F)
nkeynes@7
    29
#define IMMROT(ir) ((ir>>7)&0x1E)
nkeynes@4
    30
#define SHIFT(ir) ((ir>>4)&0x07)
nkeynes@4
    31
#define DISP24(ir) ((ir&0x00FFFFFF))
nkeynes@4
    32
#define FSXC(ir) msrFieldMask[RN(ir)]
nkeynes@4
    33
#define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
nkeynes@4
    34
nkeynes@4
    35
char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", 
nkeynes@4
    36
                           "HI", "LS", "GE", "LT", "GT", "LE", "  " /*AL*/, "NV" };
nkeynes@4
    37
                           
nkeynes@4
    38
                         /* fsxc */
nkeynes@4
    39
char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
nkeynes@4
    40
	                     "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
nkeynes@7
    41
char *ldmModes[] = { "DA", "IA", "DB", "IB" };
nkeynes@4
    42
nkeynes@4
    43
#define UNIMP(ir) snprintf( buf, len, "???     " )
nkeynes@4
    44
nkeynes@7
    45
int arm_disasm_shift_operand( uint32_t ir, char *buf, int len )
nkeynes@4
    46
{
nkeynes@7
    47
	uint32_t operand, tmp;
nkeynes@7
    48
	if( IFLAG(ir) == 0 ) {
nkeynes@7
    49
		switch(SHIFT(ir)) {
nkeynes@7
    50
		case 0: /* (Rm << imm) */
nkeynes@7
    51
			return snprintf(buf, len, "R%d << %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    52
		case 1: /* (Rm << Rs) */
nkeynes@7
    53
			return snprintf(buf, len, "R%d << R%d", RM(ir), RS(ir) );
nkeynes@7
    54
		case 2: /* (Rm >> imm) */
nkeynes@7
    55
			return snprintf(buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    56
		case 3: /* (Rm >> Rs) */
nkeynes@7
    57
			return snprintf(buf, len, "R%d >> R%d", RM(ir), RS(ir) );
nkeynes@7
    58
		case 4: /* (Rm >>> imm) */
nkeynes@7
    59
			return snprintf(buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    60
		case 5: /* (Rm >>> Rs) */
nkeynes@7
    61
			return snprintf(buf, len, "R%d >>> R%d", RM(ir), RS(ir) );
nkeynes@7
    62
		case 6:
nkeynes@7
    63
			tmp = SHIFTIMM(ir);
nkeynes@7
    64
			if( tmp == 0 ) /* RRX aka rotate with carry */
nkeynes@7
    65
				return snprintf(buf, len, "R%d roc 1", RM(ir) );
nkeynes@7
    66
			else
nkeynes@7
    67
				return snprintf(buf, len, "R%d rot %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    68
		case 7:
nkeynes@7
    69
			return snprintf(buf, len, "R%d rot R%d", RM(ir), RS(ir) );
nkeynes@7
    70
		}
nkeynes@7
    71
	} else {
nkeynes@7
    72
		operand = IMM8(ir);
nkeynes@7
    73
		tmp = IMMROT(ir);
nkeynes@7
    74
		operand = ROTATE_RIGHT_LONG(operand, tmp);
nkeynes@7
    75
		return snprintf(buf, len, "%08X", operand );
nkeynes@7
    76
	}
nkeynes@7
    77
}
nkeynes@7
    78
nkeynes@7
    79
static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
nkeynes@7
    80
{
nkeynes@7
    81
	uint32_t tmp;
nkeynes@7
    82
	
nkeynes@7
    83
	switch(SHIFT(ir)) {
nkeynes@7
    84
	case 0: /* (Rm << imm) */
nkeynes@7
    85
		return snprintf( buf, len, "R%d << %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    86
	case 2: /* (Rm >> imm) */
nkeynes@7
    87
		return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    88
	case 4: /* (Rm >>> imm) */
nkeynes@7
    89
		return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
nkeynes@7
    90
	case 6:
nkeynes@7
    91
		tmp = SHIFTIMM(ir);
nkeynes@7
    92
		if( tmp == 0 ) /* RRX aka rotate with carry */
nkeynes@7
    93
			return snprintf( buf, len, "R%d roc 1", RM(ir) );
nkeynes@7
    94
		else
nkeynes@7
    95
			return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
nkeynes@7
    96
	default: 
nkeynes@7
    97
		return UNIMP(ir);
nkeynes@7
    98
	}
nkeynes@7
    99
}
nkeynes@7
   100
nkeynes@7
   101
static int arm_disasm_address_operand( uint32_t ir, char *buf, int len )
nkeynes@7
   102
{
nkeynes@7
   103
    char  shift[32];
nkeynes@7
   104
nkeynes@7
   105
	char sign = UFLAG(ir) ? '-' : '+';
nkeynes@7
   106
	/* I P U . W */
nkeynes@7
   107
	switch( (ir>>21)&0x19 ) {
nkeynes@7
   108
	case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
nkeynes@7
   109
	case 1:
nkeynes@7
   110
		return snprintf( buf, len, "[R%d], R%d %c= %04X", RN(ir), RN(ir), sign, IMM12(ir) );
nkeynes@7
   111
	case 8: /* Rn - imm offset  [5.2.2 A5-20] */
nkeynes@7
   112
		return snprintf( buf, len, "[R%d %c %04X]", RN(ir), sign, IMM12(ir) );
nkeynes@7
   113
	case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
nkeynes@7
   114
		return snprintf( buf, len, "[R%d %c= %04X]", RN(ir), sign, IMM12(ir) );
nkeynes@7
   115
	case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
nkeynes@7
   116
	case 17:
nkeynes@7
   117
		arm_disasm_address_index( ir, shift, sizeof(shift) );
nkeynes@7
   118
		return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
nkeynes@7
   119
	case 24: /* Rn - Rm  [5.2.4 A5-23] */
nkeynes@7
   120
		arm_disasm_address_index( ir, shift, sizeof(shift) );
nkeynes@7
   121
		return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
nkeynes@7
   122
	case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
nkeynes@7
   123
		arm_disasm_address_index( ir, shift, sizeof(shift) );
nkeynes@7
   124
		return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
nkeynes@7
   125
	default:
nkeynes@7
   126
		return UNIMP(ir); /* Unreachable */
nkeynes@7
   127
	}
nkeynes@7
   128
}
nkeynes@7
   129
nkeynes@7
   130
int arm_disasm_instruction( uint32_t pc, char *buf, int len )
nkeynes@7
   131
{
nkeynes@7
   132
	char operand[32];
nkeynes@4
   133
    uint32_t ir = arm_mem_read_long(pc);
nkeynes@7
   134
	int i,j;
nkeynes@7
   135
	
nkeynes@4
   136
    if( COND(ir) == 0x0F ) {
nkeynes@4
   137
    	UNIMP(ir);
nkeynes@4
   138
    	return pc+4;
nkeynes@4
   139
    }
nkeynes@4
   140
    char *cond = conditionNames[COND(ir)];
nkeynes@4
   141
nkeynes@4
   142
	switch( GRP(ir) ) {
nkeynes@4
   143
	case 0:
nkeynes@4
   144
		if( (ir & 0x0D900000) == 0x01000000 ) {
nkeynes@4
   145
			/* Instructions that aren't actual data processing */
nkeynes@4
   146
			switch( ir & 0x0FF000F0 ) {
nkeynes@4
   147
			case 0x01200010: /* BXcc */
nkeynes@4
   148
				snprintf(buf, len, "BX%s     R%d", cond, RM(ir));
nkeynes@4
   149
				break;
nkeynes@4
   150
			case 0x01000000: /* MRS Rd, CPSR */
nkeynes@4
   151
				snprintf(buf, len, "MRS%s    R%d, CPSR", cond, RD(ir));
nkeynes@4
   152
				break;
nkeynes@4
   153
			case 0x01400000: /* MRS Rd, SPSR */
nkeynes@4
   154
				snprintf(buf, len, "MRS%s    R%d, SPSR", cond, RD(ir));
nkeynes@4
   155
				break;
nkeynes@4
   156
			case 0x01200000: /* MSR CPSR, Rm */
nkeynes@4
   157
				snprintf(buf, len, "MSR%s    CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
nkeynes@4
   158
				break;
nkeynes@4
   159
			case 0x01600000: /* MSR SPSR, Rm */
nkeynes@4
   160
				snprintf(buf, len, "MSR%s    SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
nkeynes@4
   161
				break;
nkeynes@4
   162
			case 0x03200000: /* MSR CPSR, imm */
nkeynes@4
   163
				snprintf(buf, len, "MSR%s    CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
nkeynes@4
   164
				break;
nkeynes@4
   165
			case 0x03600000: /* MSR SPSR, imm */
nkeynes@4
   166
				snprintf(buf, len, "MSR%s    SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
nkeynes@4
   167
				break;
nkeynes@4
   168
			default:
nkeynes@4
   169
				UNIMP();
nkeynes@4
   170
			}
nkeynes@4
   171
		} else if( (ir & 0x0E000090) == 0x00000090 ) {
nkeynes@4
   172
			/* Neither are these */
nkeynes@4
   173
			switch( (ir>>5)&0x03 ) {
nkeynes@4
   174
			case 0:
nkeynes@4
   175
				/* Arithmetic extension area */
nkeynes@4
   176
				switch(OPCODE(ir)) {
nkeynes@4
   177
				case 0: /* MUL */
nkeynes@4
   178
					snprintf(buf,len, "MUL%s    R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
nkeynes@4
   179
					break;
nkeynes@4
   180
				case 1: /* MULS */
nkeynes@4
   181
					break;
nkeynes@4
   182
				case 2: /* MLA */
nkeynes@4
   183
					snprintf(buf,len, "MLA%s    R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
nkeynes@4
   184
					break;
nkeynes@4
   185
				case 3: /* MLAS */
nkeynes@4
   186
					break;
nkeynes@4
   187
				case 8: /* UMULL */
nkeynes@4
   188
					snprintf(buf,len, "UMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   189
					break;
nkeynes@4
   190
				case 9: /* UMULLS */
nkeynes@4
   191
					break;
nkeynes@4
   192
				case 10: /* UMLAL */
nkeynes@4
   193
					snprintf(buf,len, "UMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   194
					break;
nkeynes@4
   195
				case 11: /* UMLALS */
nkeynes@4
   196
					break;
nkeynes@4
   197
				case 12: /* SMULL */
nkeynes@4
   198
					snprintf(buf,len, "SMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   199
					break;
nkeynes@4
   200
				case 13: /* SMULLS */
nkeynes@4
   201
					break;
nkeynes@4
   202
				case 14: /* SMLAL */
nkeynes@4
   203
					snprintf(buf,len, "SMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   204
					break;
nkeynes@4
   205
				case 15: /* SMLALS */
nkeynes@4
   206
nkeynes@4
   207
					break;
nkeynes@4
   208
				case 16: /* SWP */
nkeynes@4
   209
					snprintf(buf,len, "SWP%s    R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
nkeynes@4
   210
					break;
nkeynes@4
   211
				case 20: /* SWPB */
nkeynes@4
   212
					snprintf(buf,len, "SWPB%s   R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
nkeynes@4
   213
					break;
nkeynes@4
   214
				default:
nkeynes@4
   215
					UNIMP(ir);
nkeynes@4
   216
				}
nkeynes@4
   217
				break;
nkeynes@4
   218
			case 1:
nkeynes@4
   219
				if( LFLAG(ir) ) {
nkeynes@4
   220
					/* LDRH */
nkeynes@4
   221
				} else {
nkeynes@4
   222
					/* STRH */
nkeynes@4
   223
				}
nkeynes@4
   224
				break;
nkeynes@4
   225
			case 2:
nkeynes@4
   226
				if( LFLAG(ir) ) {
nkeynes@4
   227
					/* LDRSB */
nkeynes@4
   228
				} else {
nkeynes@4
   229
					UNIMP(ir);
nkeynes@4
   230
				}
nkeynes@4
   231
				break;
nkeynes@4
   232
			case 3:
nkeynes@4
   233
				if( LFLAG(ir) ) {
nkeynes@4
   234
					/* LDRSH */
nkeynes@4
   235
				} else {
nkeynes@4
   236
					UNIMP(ir);
nkeynes@4
   237
				}
nkeynes@4
   238
				break;
nkeynes@4
   239
			}
nkeynes@4
   240
		} else {
nkeynes@4
   241
			/* Data processing */
nkeynes@4
   242
nkeynes@4
   243
			switch(OPCODE(ir)) {
nkeynes@4
   244
			case 0: /* AND Rd, Rn, operand */
nkeynes@7
   245
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   246
				snprintf(buf, len, "AND%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   247
				break;
nkeynes@4
   248
			case 1: /* ANDS Rd, Rn, operand */
nkeynes@7
   249
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   250
				snprintf(buf, len, "ANDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   251
				break;
nkeynes@4
   252
			case 2: /* EOR Rd, Rn, operand */
nkeynes@7
   253
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   254
				snprintf(buf, len, "EOR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   255
				break;
nkeynes@4
   256
			case 3: /* EORS Rd, Rn, operand */
nkeynes@7
   257
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   258
				snprintf(buf, len, "EORS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   259
				break;
nkeynes@4
   260
			case 4: /* SUB Rd, Rn, operand */
nkeynes@7
   261
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   262
				snprintf(buf, len, "SUB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   263
				break;
nkeynes@4
   264
			case 5: /* SUBS Rd, Rn, operand */
nkeynes@7
   265
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   266
				snprintf(buf, len, "SUBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   267
				break;
nkeynes@7
   268
			case 6: /* RSB Rd, Rn, operand */
nkeynes@7
   269
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   270
				snprintf(buf, len, "RSB%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   271
				break;
nkeynes@7
   272
			case 7: /* RSBS Rd, Rn, operand */
nkeynes@7
   273
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   274
				snprintf(buf, len, "RSBS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   275
				break;
nkeynes@4
   276
			case 8: /* ADD Rd, Rn, operand */
nkeynes@7
   277
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   278
				snprintf(buf, len, "ADD%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   279
				break;
nkeynes@4
   280
			case 9: /* ADDS Rd, Rn, operand */
nkeynes@7
   281
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   282
				snprintf(buf, len, "ADDS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   283
				break;
nkeynes@7
   284
			case 10: /* ADC Rd, Rn, operand */
nkeynes@7
   285
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   286
				snprintf(buf, len, "ADC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   287
				break;
nkeynes@7
   288
			case 11: /* ADCS Rd, Rn, operand */
nkeynes@7
   289
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   290
				snprintf(buf, len, "ADCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   291
				break;
nkeynes@7
   292
			case 12: /* SBC Rd, Rn, operand */
nkeynes@7
   293
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   294
				snprintf(buf, len, "SBC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   295
				break;
nkeynes@7
   296
			case 13: /* SBCS Rd, Rn, operand */
nkeynes@7
   297
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   298
				snprintf(buf, len, "SBCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   299
				break;
nkeynes@7
   300
			case 14: /* RSC Rd, Rn, operand */
nkeynes@7
   301
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   302
				snprintf(buf, len, "RSC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   303
				break;
nkeynes@7
   304
			case 15: /* RSCS Rd, Rn, operand */
nkeynes@7
   305
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   306
				snprintf(buf, len, "RSCS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   307
				break;
nkeynes@7
   308
			case 16: /* TST Rd, Rn, operand */
nkeynes@7
   309
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   310
				snprintf(buf, len, "TST%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   311
				break;
nkeynes@7
   312
			case 18: /* TEQ Rd, Rn, operand */
nkeynes@7
   313
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   314
				snprintf(buf, len, "TEQ%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   315
				break;
nkeynes@7
   316
			case 20: /* CMP Rd, Rn, operand */
nkeynes@7
   317
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   318
				snprintf(buf, len, "CMP%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@7
   319
				break;
nkeynes@7
   320
			case 22: /* CMN Rd, Rn, operand */
nkeynes@7
   321
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   322
				snprintf(buf, len, "CMN%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   323
				break;
nkeynes@4
   324
			case 24: /* ORR Rd, Rn, operand */
nkeynes@7
   325
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   326
				snprintf(buf, len, "ORR%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   327
				break;
nkeynes@4
   328
			case 25: /* ORRS Rd, Rn, operand */
nkeynes@7
   329
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   330
				snprintf(buf, len, "ORRS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   331
				break;
nkeynes@7
   332
			case 26: /* MOV Rd, Rn, operand */
nkeynes@7
   333
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   334
				snprintf(buf, len, "MOV%s    R%d, %s", cond, RD(ir), operand);
nkeynes@4
   335
				break;
nkeynes@7
   336
			case 27: /* MOVS Rd, Rn, operand */
nkeynes@7
   337
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   338
				snprintf(buf, len, "MOVS%s   R%d, %s", cond, RD(ir), operand);
nkeynes@4
   339
				break;
nkeynes@4
   340
			case 28: /* BIC Rd, Rn, operand */
nkeynes@7
   341
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   342
				snprintf(buf, len, "BIC%s    R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   343
				break;
nkeynes@4
   344
			case 29: /* BICS Rd, Rn, operand */
nkeynes@7
   345
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   346
				snprintf(buf, len, "BICS%s   R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
nkeynes@4
   347
				break;
nkeynes@7
   348
			case 30: /* MVN Rd, Rn, operand */
nkeynes@7
   349
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   350
				snprintf(buf, len, "MVN%s    R%d, %s", cond, RD(ir), operand);
nkeynes@4
   351
				break;
nkeynes@7
   352
			case 31: /* MVNS Rd, Rn, operand */
nkeynes@7
   353
				arm_disasm_shift_operand(ir, operand, sizeof(operand));
nkeynes@7
   354
				snprintf(buf, len, "MVNS%s   R%d, %s", cond, RD(ir), operand);
nkeynes@4
   355
				break;
nkeynes@4
   356
			default:
nkeynes@4
   357
				UNIMP(ir);
nkeynes@4
   358
			}
nkeynes@4
   359
		}
nkeynes@4
   360
		break;
nkeynes@4
   361
	case 1: /* Load/store */
nkeynes@7
   362
		arm_disasm_address_operand( ir, operand, sizeof(operand) );
nkeynes@7
   363
		switch( (ir>>20)&0x17 ) {
nkeynes@7
   364
			case 0:
nkeynes@7
   365
			case 16:
nkeynes@7
   366
			case 18:
nkeynes@7
   367
				snprintf(buf, len, "STR%s    R%d, %s", cond, RD(ir), operand );
nkeynes@7
   368
				break;
nkeynes@7
   369
			case 1:
nkeynes@7
   370
			case 17:
nkeynes@7
   371
			case 19:
nkeynes@7
   372
				snprintf(buf, len, "LDR%s    R%d, %s", cond, RD(ir), operand );
nkeynes@7
   373
				break;
nkeynes@7
   374
			case 2:
nkeynes@7
   375
				snprintf(buf, len, "STRT%s   R%d, %s", cond, RD(ir), operand );
nkeynes@7
   376
				break;
nkeynes@7
   377
			case 3:
nkeynes@7
   378
				snprintf(buf, len, "LDRT%s   R%d, %s", cond, RD(ir), operand );
nkeynes@7
   379
				break;
nkeynes@7
   380
			case 4:
nkeynes@7
   381
			case 20:
nkeynes@7
   382
			case 22:
nkeynes@7
   383
				snprintf(buf, len, "STRB%s   R%d, %s", cond, RD(ir), operand );
nkeynes@7
   384
				break;
nkeynes@7
   385
			case 5:
nkeynes@7
   386
			case 21:
nkeynes@7
   387
			case 23:
nkeynes@7
   388
				snprintf(buf, len, "LDRB%s   R%d, %s", cond, RD(ir), operand );
nkeynes@7
   389
				break;
nkeynes@7
   390
			case 6:
nkeynes@7
   391
				snprintf(buf, len, "STRBT%s  R%d, %s", cond, RD(ir), operand );
nkeynes@7
   392
				break;
nkeynes@7
   393
			case 7: 
nkeynes@7
   394
				snprintf(buf, len, "LDRBT%s  R%d, %s", cond, RD(ir), operand );
nkeynes@7
   395
				break;
nkeynes@7
   396
		}
nkeynes@4
   397
		break;
nkeynes@4
   398
	case 2: /* Load/store multiple, branch*/
nkeynes@7
   399
		j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s  R%d%c,":"STM%s%s  R%d%c,", 
nkeynes@7
   400
	              ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
nkeynes@7
   401
		buf += j;
nkeynes@7
   402
		len -= j;
nkeynes@7
   403
		for( i = 0; i<16 && len > 2; i++ ) {
nkeynes@7
   404
			if( (ir >> i)&1 ) {
nkeynes@7
   405
				j = snprintf( buf, len, "R%d", i );
nkeynes@7
   406
				buf+=j;
nkeynes@7
   407
				len-=j;
nkeynes@7
   408
			}
nkeynes@7
   409
		}
nkeynes@7
   410
		if( SFLAG(ir) && len > 0 ) {
nkeynes@7
   411
			buf[0] = '^';
nkeynes@7
   412
			buf[1] = '\0';
nkeynes@7
   413
		}
nkeynes@4
   414
		break;
nkeynes@4
   415
	case 3: /* Copro */
nkeynes@7
   416
		UNIMP(ir);
nkeynes@4
   417
		break;
nkeynes@4
   418
	}
nkeynes@4
   419
	
nkeynes@4
   420
	
nkeynes@4
   421
	
nkeynes@4
   422
	return pc+4;
nkeynes@4
   423
}
.