Search
lxdream.org :: lxdream/src/aica/armdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armdasm.c
changeset 4:7d6f596ce577
next7:976a16e92aab
author nkeynes
date Sat Oct 02 05:49:12 2004 +0000 (18 years ago)
permissions -rw-r--r--
last change Add armdasm
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@4
     8
#include "armcore.h"
nkeynes@4
     9
nkeynes@4
    10
#define COND(ir) (ir>>28)
nkeynes@4
    11
#define OPCODE(ir) ((ir>>20)&0x1F)
nkeynes@4
    12
#define GRP(ir) ((ir>>26)&0x03)
nkeynes@4
    13
#define IFLAG(ir) (ir&0x02000000)
nkeynes@4
    14
#define SFLAG(ir) (ir&0x00100000)
nkeynes@4
    15
#define PFLAG(ir) (ir&0x01000000)
nkeynes@4
    16
#define UFLAG(ir) (ir&0x00800000)
nkeynes@4
    17
#define BFLAG(ir) (ir&0x00400000)
nkeynes@4
    18
#define WFLAG(ir) (IR&0x00200000)
nkeynes@4
    19
#define LFLAG(ir) SFLAG(ir)
nkeynes@4
    20
#define RN(ir) ((ir>>16)&0x0F)
nkeynes@4
    21
#define RD(ir) ((ir>>12)&0x0F)
nkeynes@4
    22
#define RS(ir) ((ir>>8)&0x0F)
nkeynes@4
    23
#define RM(ir) (ir&0x0F)
nkeynes@4
    24
nkeynes@4
    25
#define IMM8(ir) (ir&0xFF)
nkeynes@4
    26
#define IMM12(ir) (ir&0xFFF)
nkeynes@4
    27
#define SHIFTIMM(ir) ((ir>>7)0x1F)
nkeynes@4
    28
#define IMMROT(ir) ((ir>>7)&1E)
nkeynes@4
    29
#define SHIFT(ir) ((ir>>4)&0x07)
nkeynes@4
    30
#define DISP24(ir) ((ir&0x00FFFFFF))
nkeynes@4
    31
#define FSXC(ir) msrFieldMask[RN(ir)]
nkeynes@4
    32
#define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
nkeynes@4
    33
nkeynes@4
    34
char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", 
nkeynes@4
    35
                           "HI", "LS", "GE", "LT", "GT", "LE", "  " /*AL*/, "NV" };
nkeynes@4
    36
                           
nkeynes@4
    37
                         /* fsxc */
nkeynes@4
    38
char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
nkeynes@4
    39
	                     "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
nkeynes@4
    40
nkeynes@4
    41
#define UNIMP(ir) snprintf( buf, len, "???     " )
nkeynes@4
    42
nkeynes@4
    43
int arm_disasm_instruction( int pc, char *buf, int len )
nkeynes@4
    44
{
nkeynes@4
    45
    uint32_t ir = arm_mem_read_long(pc);
nkeynes@4
    46
    
nkeynes@4
    47
    if( COND(ir) == 0x0F ) {
nkeynes@4
    48
    	UNIMP(ir);
nkeynes@4
    49
    	return pc+4;
nkeynes@4
    50
    }
nkeynes@4
    51
    char *cond = conditionNames[COND(ir)];
nkeynes@4
    52
nkeynes@4
    53
	switch( GRP(ir) ) {
nkeynes@4
    54
	case 0:
nkeynes@4
    55
		if( (ir & 0x0D900000) == 0x01000000 ) {
nkeynes@4
    56
			/* Instructions that aren't actual data processing */
nkeynes@4
    57
			switch( ir & 0x0FF000F0 ) {
nkeynes@4
    58
			case 0x01200010: /* BXcc */
nkeynes@4
    59
				snprintf(buf, len, "BX%s     R%d", cond, RM(ir));
nkeynes@4
    60
				break;
nkeynes@4
    61
			case 0x01000000: /* MRS Rd, CPSR */
nkeynes@4
    62
				snprintf(buf, len, "MRS%s    R%d, CPSR", cond, RD(ir));
nkeynes@4
    63
				break;
nkeynes@4
    64
			case 0x01400000: /* MRS Rd, SPSR */
nkeynes@4
    65
				snprintf(buf, len, "MRS%s    R%d, SPSR", cond, RD(ir));
nkeynes@4
    66
				break;
nkeynes@4
    67
			case 0x01200000: /* MSR CPSR, Rm */
nkeynes@4
    68
				snprintf(buf, len, "MSR%s    CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
nkeynes@4
    69
				break;
nkeynes@4
    70
			case 0x01600000: /* MSR SPSR, Rm */
nkeynes@4
    71
				snprintf(buf, len, "MSR%s    SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
nkeynes@4
    72
				break;
nkeynes@4
    73
			case 0x03200000: /* MSR CPSR, imm */
nkeynes@4
    74
				snprintf(buf, len, "MSR%s    CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
nkeynes@4
    75
				break;
nkeynes@4
    76
			case 0x03600000: /* MSR SPSR, imm */
nkeynes@4
    77
				snprintf(buf, len, "MSR%s    SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
nkeynes@4
    78
				break;
nkeynes@4
    79
			default:
nkeynes@4
    80
				UNIMP();
nkeynes@4
    81
			}
nkeynes@4
    82
		} else if( (ir & 0x0E000090) == 0x00000090 ) {
nkeynes@4
    83
			/* Neither are these */
nkeynes@4
    84
			switch( (ir>>5)&0x03 ) {
nkeynes@4
    85
			case 0:
nkeynes@4
    86
				/* Arithmetic extension area */
nkeynes@4
    87
				switch(OPCODE(ir)) {
nkeynes@4
    88
				case 0: /* MUL */
nkeynes@4
    89
					snprintf(buf,len, "MUL%s    R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
nkeynes@4
    90
					break;
nkeynes@4
    91
				case 1: /* MULS */
nkeynes@4
    92
					break;
nkeynes@4
    93
				case 2: /* MLA */
nkeynes@4
    94
					snprintf(buf,len, "MLA%s    R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
nkeynes@4
    95
					break;
nkeynes@4
    96
				case 3: /* MLAS */
nkeynes@4
    97
					break;
nkeynes@4
    98
				case 8: /* UMULL */
nkeynes@4
    99
					snprintf(buf,len, "UMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   100
					break;
nkeynes@4
   101
				case 9: /* UMULLS */
nkeynes@4
   102
					break;
nkeynes@4
   103
				case 10: /* UMLAL */
nkeynes@4
   104
					snprintf(buf,len, "UMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   105
					break;
nkeynes@4
   106
				case 11: /* UMLALS */
nkeynes@4
   107
					break;
nkeynes@4
   108
				case 12: /* SMULL */
nkeynes@4
   109
					snprintf(buf,len, "SMULL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   110
					break;
nkeynes@4
   111
				case 13: /* SMULLS */
nkeynes@4
   112
					break;
nkeynes@4
   113
				case 14: /* SMLAL */
nkeynes@4
   114
					snprintf(buf,len, "SMLAL%s  R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
nkeynes@4
   115
					break;
nkeynes@4
   116
				case 15: /* SMLALS */
nkeynes@4
   117
nkeynes@4
   118
					break;
nkeynes@4
   119
				case 16: /* SWP */
nkeynes@4
   120
					snprintf(buf,len, "SWP%s    R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
nkeynes@4
   121
					break;
nkeynes@4
   122
				case 20: /* SWPB */
nkeynes@4
   123
					snprintf(buf,len, "SWPB%s   R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
nkeynes@4
   124
					break;
nkeynes@4
   125
				default:
nkeynes@4
   126
					UNIMP(ir);
nkeynes@4
   127
				}
nkeynes@4
   128
				break;
nkeynes@4
   129
			case 1:
nkeynes@4
   130
				if( LFLAG(ir) ) {
nkeynes@4
   131
					/* LDRH */
nkeynes@4
   132
				} else {
nkeynes@4
   133
					/* STRH */
nkeynes@4
   134
				}
nkeynes@4
   135
				break;
nkeynes@4
   136
			case 2:
nkeynes@4
   137
				if( LFLAG(ir) ) {
nkeynes@4
   138
					/* LDRSB */
nkeynes@4
   139
				} else {
nkeynes@4
   140
					UNIMP(ir);
nkeynes@4
   141
				}
nkeynes@4
   142
				break;
nkeynes@4
   143
			case 3:
nkeynes@4
   144
				if( LFLAG(ir) ) {
nkeynes@4
   145
					/* LDRSH */
nkeynes@4
   146
				} else {
nkeynes@4
   147
					UNIMP(ir);
nkeynes@4
   148
				}
nkeynes@4
   149
				break;
nkeynes@4
   150
			}
nkeynes@4
   151
		} else {
nkeynes@4
   152
			/* Data processing */
nkeynes@4
   153
nkeynes@4
   154
			switch(OPCODE(ir)) {
nkeynes@4
   155
			case 0: /* AND Rd, Rn, operand */
nkeynes@4
   156
				RD(ir) = RN(ir) & arm_get_shift_operand(ir);
nkeynes@4
   157
				break;
nkeynes@4
   158
			case 1: /* ANDS Rd, Rn, operand */
nkeynes@4
   159
				operand = arm_get_shift_operand_s(ir) & RN(ir);
nkeynes@4
   160
				RD(ir) = operand;
nkeynes@4
   161
				if( RDn(ir) == 15 ) {
nkeynes@4
   162
					arm_restore_cpsr();
nkeynes@4
   163
				} else {
nkeynes@4
   164
					armr.n = operand>>31;
nkeynes@4
   165
					armr.z = (operand == 0);
nkeynes@4
   166
					armr.c = armr.shift_c;
nkeynes@4
   167
				}
nkeynes@4
   168
				break;
nkeynes@4
   169
			case 2: /* EOR Rd, Rn, operand */
nkeynes@4
   170
				RD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
nkeynes@4
   171
				break;
nkeynes@4
   172
			case 3: /* EORS Rd, Rn, operand */
nkeynes@4
   173
				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
nkeynes@4
   174
				RD(ir) = operand;
nkeynes@4
   175
				if( RDn(ir) == 15 ) {
nkeynes@4
   176
					arm_restore_cpsr();
nkeynes@4
   177
				} else {
nkeynes@4
   178
					armr.n = operand>>31;
nkeynes@4
   179
					armr.z = (operand == 0);
nkeynes@4
   180
					armr.c = armr.shift_c;
nkeynes@4
   181
				}
nkeynes@4
   182
				break;
nkeynes@4
   183
			case 4: /* SUB Rd, Rn, operand */
nkeynes@4
   184
				RD(ir) = RN(ir) - arm_get_shift_operand(ir);
nkeynes@4
   185
				break;
nkeynes@4
   186
			case 5: /* SUBS Rd, Rn, operand */
nkeynes@4
   187
			    operand = RN(ir);
nkeynes@4
   188
				operand2 = arm_get_shift_operand(ir)
nkeynes@4
   189
				tmp = operand - operand2;
nkeynes@4
   190
				RD(ir) = tmp;
nkeynes@4
   191
				if( RDn(ir) == 15 ) {
nkeynes@4
   192
					arm_restore_cpsr();
nkeynes@4
   193
				} else {
nkeynes@4
   194
					armr.n = tmp>>31;
nkeynes@4
   195
					armr.z = (tmp == 0);
nkeynes@4
   196
					armr.c = IS_NOTBORROW(tmp,operand,operand2);
nkeynes@4
   197
					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
nkeynes@4
   198
				}
nkeynes@4
   199
				break;
nkeynes@4
   200
			case 6: /* RSB Rd, operand, Rn */
nkeynes@4
   201
				RD(ir) = arm_get_shift_operand(ir) - RN(ir);
nkeynes@4
   202
				break;
nkeynes@4
   203
			case 7: /* RSBS Rd, operand, Rn */
nkeynes@4
   204
				operand = arm_get_shift_operand(ir);
nkeynes@4
   205
			    operand2 = RN(ir);
nkeynes@4
   206
				tmp = operand - operand2;
nkeynes@4
   207
				RD(ir) = tmp;
nkeynes@4
   208
				if( RDn(ir) == 15 ) {
nkeynes@4
   209
					arm_restore_cpsr();
nkeynes@4
   210
				} else {
nkeynes@4
   211
					armr.n = tmp>>31;
nkeynes@4
   212
					armr.z = (tmp == 0);
nkeynes@4
   213
					armr.c = IS_NOTBORROW(tmp,operand,operand2);
nkeynes@4
   214
					armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
nkeynes@4
   215
				}
nkeynes@4
   216
				break;
nkeynes@4
   217
			case 8: /* ADD Rd, Rn, operand */
nkeynes@4
   218
				RD(ir) = RN(ir) + arm_get_shift_operand(ir);
nkeynes@4
   219
				break;
nkeynes@4
   220
			case 9: /* ADDS Rd, Rn, operand */
nkeynes@4
   221
				operand = arm_get_shift_operand(ir);
nkeynes@4
   222
			    operand2 = RN(ir);
nkeynes@4
   223
				tmp = operand + operand2
nkeynes@4
   224
				RD(ir) = tmp;
nkeynes@4
   225
				if( RDn(ir) == 15 ) {
nkeynes@4
   226
					arm_restore_cpsr();
nkeynes@4
   227
				} else {
nkeynes@4
   228
					armr.n = tmp>>31;
nkeynes@4
   229
					armr.z = (tmp == 0);
nkeynes@4
   230
					armr.c = IS_CARRY(tmp,operand,operand2);
nkeynes@4
   231
					armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
nkeynes@4
   232
				}
nkeynes@4
   233
				break;			
nkeynes@4
   234
			case 10: /* ADC */
nkeynes@4
   235
			case 11: /* ADCS */
nkeynes@4
   236
			case 12: /* SBC */
nkeynes@4
   237
			case 13: /* SBCS */
nkeynes@4
   238
			case 14: /* RSC */
nkeynes@4
   239
			case 15: /* RSCS */
nkeynes@4
   240
				break;
nkeynes@4
   241
			case 17: /* TST Rn, operand */
nkeynes@4
   242
				operand = arm_get_shift_operand_s(ir) & RN(ir);
nkeynes@4
   243
				armr.n = operand>>31;
nkeynes@4
   244
				armr.z = (operand == 0);
nkeynes@4
   245
				armr.c = armr.shift_c;
nkeynes@4
   246
				break;
nkeynes@4
   247
			case 19: /* TEQ Rn, operand */
nkeynes@4
   248
				operand = arm_get_shift_operand_s(ir) ^ RN(ir);
nkeynes@4
   249
				armr.n = operand>>31;
nkeynes@4
   250
				armr.z = (operand == 0);
nkeynes@4
   251
				armr.c = armr.shift_c;
nkeynes@4
   252
				break;				
nkeynes@4
   253
			case 21: /* CMP Rn, operand */
nkeynes@4
   254
			    operand = RN(ir);
nkeynes@4
   255
				operand2 = arm_get_shift_operand(ir)
nkeynes@4
   256
				tmp = operand - operand2;
nkeynes@4
   257
				armr.n = tmp>>31;
nkeynes@4
   258
				armr.z = (tmp == 0);
nkeynes@4
   259
				armr.c = IS_NOTBORROW(tmp,operand,operand2);
nkeynes@4
   260
				armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
nkeynes@4
   261
				break;
nkeynes@4
   262
			case 23: /* CMN Rn, operand */
nkeynes@4
   263
			    operand = RN(ir);
nkeynes@4
   264
				operand2 = arm_get_shift_operand(ir)
nkeynes@4
   265
				tmp = operand + operand2;
nkeynes@4
   266
				armr.n = tmp>>31;
nkeynes@4
   267
				armr.z = (tmp == 0);
nkeynes@4
   268
				armr.c = IS_CARRY(tmp,operand,operand2);
nkeynes@4
   269
				armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
nkeynes@4
   270
				break;
nkeynes@4
   271
			case 24: /* ORR Rd, Rn, operand */
nkeynes@4
   272
				RD(ir) = RN(ir) | arm_get_shift_operand(ir);
nkeynes@4
   273
				break;
nkeynes@4
   274
			case 25: /* ORRS Rd, Rn, operand */
nkeynes@4
   275
				operand = arm_get_shift_operand_s(ir) | RN(ir);
nkeynes@4
   276
				RD(ir) = operand;
nkeynes@4
   277
				if( RDn(ir) == 15 ) {
nkeynes@4
   278
					arm_restore_cpsr();
nkeynes@4
   279
				} else {
nkeynes@4
   280
					armr.n = operand>>31;
nkeynes@4
   281
					armr.z = (operand == 0);
nkeynes@4
   282
					armr.c = armr.shift_c;
nkeynes@4
   283
				}
nkeynes@4
   284
				break;
nkeynes@4
   285
			case 26: /* MOV Rd, operand */
nkeynes@4
   286
				RD(ir) = arm_get_shift_operand(ir);
nkeynes@4
   287
				break;
nkeynes@4
   288
			case 27: /* MOVS Rd, operand */
nkeynes@4
   289
				operand = arm_get_shift_operand_s(ir);
nkeynes@4
   290
				RD(ir) = operand;
nkeynes@4
   291
				if( RDn(ir) == 15 ) {
nkeynes@4
   292
					arm_restore_cpsr();
nkeynes@4
   293
				} else {
nkeynes@4
   294
					armr.n = operand>>31;
nkeynes@4
   295
					armr.z = (operand == 0);
nkeynes@4
   296
					armr.c = armr.shift_c;
nkeynes@4
   297
				}
nkeynes@4
   298
				break;
nkeynes@4
   299
			case 28: /* BIC Rd, Rn, operand */
nkeynes@4
   300
				RD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
nkeynes@4
   301
				break;
nkeynes@4
   302
			case 29: /* BICS Rd, Rn, operand */
nkeynes@4
   303
				operand = RN(ir) & (~arm_get_shift_operand_s(ir));
nkeynes@4
   304
				RD(ir) = operand;
nkeynes@4
   305
				if( RDn(ir) == 15 ) {
nkeynes@4
   306
					arm_restore_cpsr();
nkeynes@4
   307
				} else {
nkeynes@4
   308
					armr.n = operand>>31;
nkeynes@4
   309
					armr.z = (operand == 0);
nkeynes@4
   310
					armr.c = armr.shift_c;
nkeynes@4
   311
				}
nkeynes@4
   312
				break;
nkeynes@4
   313
			case 30: /* MVN Rd, operand */
nkeynes@4
   314
				RD(ir) = ~arm_get_shift_operand(ir);
nkeynes@4
   315
				break;
nkeynes@4
   316
			case 31: /* MVNS Rd, operand */
nkeynes@4
   317
				operand = ~arm_get_shift_operand_s(ir);
nkeynes@4
   318
				RD(ir) = operand;
nkeynes@4
   319
				if( RDn(ir) == 15 ) {
nkeynes@4
   320
					arm_restore_cpsr();
nkeynes@4
   321
				} else {
nkeynes@4
   322
					armr.n = operand>>31;
nkeynes@4
   323
					armr.z = (operand == 0);
nkeynes@4
   324
					armr.c = armr.shift_c;
nkeynes@4
   325
				}
nkeynes@4
   326
				break;
nkeynes@4
   327
			default:
nkeynes@4
   328
				UNIMP(ir);
nkeynes@4
   329
			}
nkeynes@4
   330
		}
nkeynes@4
   331
		break;
nkeynes@4
   332
	case 1: /* Load/store */
nkeynes@4
   333
		break;
nkeynes@4
   334
	case 2: /* Load/store multiple, branch*/
nkeynes@4
   335
		break;
nkeynes@4
   336
	case 3: /* Copro */
nkeynes@4
   337
		break;
nkeynes@4
   338
	}
nkeynes@4
   339
	
nkeynes@4
   340
	
nkeynes@4
   341
	
nkeynes@4
   342
	return pc+4;
nkeynes@4
   343
}
.