nkeynes@1 | 1 | #include "sh4core.h"
|
nkeynes@1 | 2 | #include "sh4dasm.h"
|
nkeynes@1 | 3 | #include "mem.h"
|
nkeynes@1 | 4 |
|
nkeynes@1 | 5 | #define UNIMP(ir) snprintf( buf, len, "??? " )
|
nkeynes@1 | 6 |
|
nkeynes@1 | 7 | int sh4_disasm_instruction( int pc, char *buf, int len )
|
nkeynes@1 | 8 | {
|
nkeynes@1 | 9 | uint16_t ir = mem_read_word(pc);
|
nkeynes@1 | 10 |
|
nkeynes@1 | 11 | #define RN(ir) ((ir&0x0F00)>>8)
|
nkeynes@1 | 12 | #define RN_BANK(ir) ((ir&0x0070)>>4)
|
nkeynes@1 | 13 | #define RM(ir) ((ir&0x00F0)>>4)
|
nkeynes@1 | 14 | #define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *not* sign extended */
|
nkeynes@1 | 15 | #define DISP8(ir) (ir&0x00FF)
|
nkeynes@1 | 16 | #define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
|
nkeynes@1 | 17 | #define UIMM8(ir) (ir&0x00FF)
|
nkeynes@1 | 18 | #define IMM8(ir) SIGNEXT8(ir&0x00FF)
|
nkeynes@1 | 19 | #define DISP12(ir) SIGNEXT12(ir&0x0FFF)
|
nkeynes@1 | 20 | #define FVN(ir) ((ir&0x0C00)>>10)
|
nkeynes@1 | 21 | #define FVM(ir) ((ir&0x0300)>>8)
|
nkeynes@1 | 22 |
|
nkeynes@1 | 23 | switch( (ir&0xF000)>>12 ) {
|
nkeynes@1 | 24 | case 0: /* 0000nnnnmmmmxxxx */
|
nkeynes@1 | 25 | switch( ir&0x000F ) {
|
nkeynes@1 | 26 | case 2:
|
nkeynes@1 | 27 | switch( (ir&0x00F0)>>4 ) {
|
nkeynes@1 | 28 | case 0: snprintf( buf, len, "STC SR, R%d", RN(ir) ); break;
|
nkeynes@1 | 29 | case 1: snprintf( buf, len, "STC GBR, R%d", RN(ir) ); break;
|
nkeynes@1 | 30 | case 2: snprintf( buf, len, "STC VBR, R%d", RN(ir) ); break;
|
nkeynes@1 | 31 | case 3: snprintf( buf, len, "STC SSR, R%d", RN(ir) ); break;
|
nkeynes@1 | 32 | case 4: snprintf( buf, len, "STC SPC, R%d", RN(ir) ); break;
|
nkeynes@1 | 33 | case 8: case 9: case 10: case 11: case 12: case 13: case 14:
|
nkeynes@1 | 34 | case 15:snprintf( buf, len, "STC R%d_bank, R%d", RN_BANK(ir), RN(ir) ); break;
|
nkeynes@1 | 35 | default: UNIMP(ir);
|
nkeynes@1 | 36 | }
|
nkeynes@1 | 37 | break;
|
nkeynes@1 | 38 | case 3:
|
nkeynes@1 | 39 | switch( (ir&0x00F0)>>4 ) {
|
nkeynes@1 | 40 | case 0: snprintf( buf, len, "BSRF R%d", RN(ir) ); break;
|
nkeynes@1 | 41 | case 2: snprintf( buf, len, "BRAF R%d", RN(ir) ); break;
|
nkeynes@1 | 42 | case 8: snprintf( buf, len, "PREF [R%d]", RN(ir) ); break;
|
nkeynes@1 | 43 | case 9: snprintf( buf, len, "OCBI [R%d]", RN(ir) ); break;
|
nkeynes@1 | 44 | case 10:snprintf( buf, len, "OCBP [R%d]", RN(ir) ); break;
|
nkeynes@1 | 45 | case 11:snprintf( buf, len, "OCBWB [R%d]", RN(ir) ); break;
|
nkeynes@1 | 46 | case 12:snprintf( buf, len, "MOVCA.L R0, [R%d]", RN(ir) ); break;
|
nkeynes@1 | 47 | default: UNIMP(ir);
|
nkeynes@1 | 48 | }
|
nkeynes@1 | 49 | break;
|
nkeynes@1 | 50 | case 4: snprintf( buf, len, "MOV.B R%d, [R0+R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 51 | case 5: snprintf( buf, len, "MOV.W R%d, [R0+R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 52 | case 6: snprintf( buf, len, "MOV.L R%d, [R0+R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 53 | case 7: snprintf( buf, len, "MUL.L R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 54 | case 8:
|
nkeynes@1 | 55 | switch( (ir&0x0FF0)>>4 ) {
|
nkeynes@1 | 56 | case 0: snprintf( buf, len, "CLRT " ); break;
|
nkeynes@1 | 57 | case 1: snprintf( buf, len, "SETT " ); break;
|
nkeynes@1 | 58 | case 2: snprintf( buf, len, "CLRMAC " ); break;
|
nkeynes@1 | 59 | case 3: snprintf( buf, len, "LDTLB " ); break;
|
nkeynes@1 | 60 | case 4: snprintf( buf, len, "CLRS " ); break;
|
nkeynes@1 | 61 | case 5: snprintf( buf, len, "SETS " ); break;
|
nkeynes@1 | 62 | default: UNIMP(ir);
|
nkeynes@1 | 63 | }
|
nkeynes@1 | 64 | break;
|
nkeynes@1 | 65 | case 9:
|
nkeynes@1 | 66 | if( (ir&0x00F0) == 0x20 )
|
nkeynes@1 | 67 | snprintf( buf, len, "MOVT R%d", RN(ir) );
|
nkeynes@1 | 68 | else if( ir == 0x0019 )
|
nkeynes@1 | 69 | snprintf( buf, len, "DIV0U " );
|
nkeynes@1 | 70 | else if( ir == 0x0009 )
|
nkeynes@1 | 71 | snprintf( buf, len, "NOP " );
|
nkeynes@1 | 72 | else UNIMP(ir);
|
nkeynes@1 | 73 | break;
|
nkeynes@1 | 74 | case 10:
|
nkeynes@1 | 75 | switch( (ir&0x00F0) >> 4 ) {
|
nkeynes@1 | 76 | case 0: snprintf( buf, len, "STS MACH, R%d", RN(ir) ); break;
|
nkeynes@1 | 77 | case 1: snprintf( buf, len, "STS MACL, R%d", RN(ir) ); break;
|
nkeynes@1 | 78 | case 2: snprintf( buf, len, "STS PR, R%d", RN(ir) ); break;
|
nkeynes@1 | 79 | case 3: snprintf( buf, len, "STC SGR, R%d", RN(ir) ); break;
|
nkeynes@1 | 80 | case 5: snprintf( buf, len, "STS FPUL, R%d", RN(ir) ); break;
|
nkeynes@1 | 81 | case 6: snprintf( buf, len, "STS FPSCR, R%d", RN(ir) ); break;
|
nkeynes@1 | 82 | case 15:snprintf( buf, len, "STC DBR, R%d", RN(ir) ); break;
|
nkeynes@1 | 83 | default: UNIMP(ir);
|
nkeynes@1 | 84 | }
|
nkeynes@1 | 85 | break;
|
nkeynes@1 | 86 | case 11:
|
nkeynes@1 | 87 | switch( (ir&0x0FF0)>>4 ) {
|
nkeynes@1 | 88 | case 0: snprintf( buf, len, "RTS " ); break;
|
nkeynes@1 | 89 | case 1: snprintf( buf, len, "SLEEP " ); break;
|
nkeynes@1 | 90 | case 2: snprintf( buf, len, "RTE " ); break;
|
nkeynes@1 | 91 | default:UNIMP(ir);
|
nkeynes@1 | 92 | }
|
nkeynes@1 | 93 | break;
|
nkeynes@1 | 94 | case 12:snprintf( buf, len, "MOV.B [R0+R%d], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 95 | case 13:snprintf( buf, len, "MOV.W [R0+R%d], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 96 | case 14:snprintf( buf, len, "MOV.L [R0+R%d], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 97 | case 15:snprintf( buf, len, "MAC.L [R%d++], [R%d++]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 98 | default: UNIMP(ir);
|
nkeynes@1 | 99 | }
|
nkeynes@1 | 100 | break;
|
nkeynes@1 | 101 | case 1: /* 0001nnnnmmmmdddd */
|
nkeynes@1 | 102 | snprintf( buf, len, "MOV.L R%d, [R%d%+d]", RM(ir), RN(ir), DISP4(ir)<<2 ); break;
|
nkeynes@1 | 103 | case 2: /* 0010nnnnmmmmxxxx */
|
nkeynes@1 | 104 | switch( ir&0x000F ) {
|
nkeynes@1 | 105 | case 0: snprintf( buf, len, "MOV.B R%d, [R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 106 | case 1: snprintf( buf, len, "MOV.W R%d, [R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 107 | case 2: snprintf( buf, len, "MOV.L R%d, [R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 108 | case 3: UNIMP(ir); break;
|
nkeynes@1 | 109 | case 4: snprintf( buf, len, "MOV.B R%d, [--R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 110 | case 5: snprintf( buf, len, "MOV.W R%d, [--R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 111 | case 6: snprintf( buf, len, "MOV.L R%d, [--R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 112 | case 7: snprintf( buf, len, "DIV0S R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 113 | case 8: snprintf( buf, len, "TST R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 114 | case 9: snprintf( buf, len, "AND R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 115 | case 10:snprintf( buf, len, "XOR R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 116 | case 11:snprintf( buf, len, "OR R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 117 | case 12:snprintf( buf, len, "CMP/STR R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 118 | case 13:snprintf( buf, len, "XTRCT R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 119 | case 14:snprintf( buf, len, "MULU.W R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 120 | case 15:snprintf( buf, len, "MULS.W R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 121 | }
|
nkeynes@1 | 122 | break;
|
nkeynes@1 | 123 | case 3: /* 0011nnnnmmmmxxxx */
|
nkeynes@1 | 124 | switch( ir&0x000F ) {
|
nkeynes@1 | 125 | case 0: snprintf( buf, len, "CMP/EQ R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 126 | case 2: snprintf( buf, len, "CMP/HS R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 127 | case 3: snprintf( buf, len, "CMP/GE R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 128 | case 4: snprintf( buf, len, "DIV1 R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 129 | case 5: snprintf( buf, len, "DMULU.L R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 130 | case 6: snprintf( buf, len, "CMP/HI R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 131 | case 7: snprintf( buf, len, "CMP/GT R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 132 | case 8: snprintf( buf, len, "SUB R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 133 | case 10:snprintf( buf, len, "SUBC R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 134 | case 11:snprintf( buf, len, "SUBV R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 135 | case 12:snprintf( buf, len, "ADD R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 136 | case 13:snprintf( buf, len, "DMULS.L R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 137 | case 14:snprintf( buf, len, "ADDC R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 138 | case 15:snprintf( buf, len, "ADDV R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 139 | default: UNIMP(ir);
|
nkeynes@1 | 140 | }
|
nkeynes@1 | 141 | break;
|
nkeynes@1 | 142 | case 4: /* 0100nnnnxxxxxxxx */
|
nkeynes@1 | 143 | switch( ir&0x00FF ) {
|
nkeynes@1 | 144 | case 0x00: snprintf( buf, len, "SHLL R%d", RN(ir) ); break;
|
nkeynes@1 | 145 | case 0x01: snprintf( buf, len, "SHLR R%d", RN(ir) ); break;
|
nkeynes@1 | 146 | case 0x02: snprintf( buf, len, "STS.L MACH, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 147 | case 0x03: snprintf( buf, len, "STC.L SR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 148 | case 0x04: snprintf( buf, len, "ROTL R%d", RN(ir) ); break;
|
nkeynes@1 | 149 | case 0x05: snprintf( buf, len, "ROTR R%d", RN(ir) ); break;
|
nkeynes@1 | 150 | case 0x06: snprintf( buf, len, "LDS.L [R%d++], MACH", RN(ir) ); break;
|
nkeynes@1 | 151 | case 0x07: snprintf( buf, len, "LDC.L [R%d++], SR", RN(ir) ); break;
|
nkeynes@1 | 152 | case 0x08: snprintf( buf, len, "SHLL2 R%d", RN(ir) ); break;
|
nkeynes@1 | 153 | case 0x09: snprintf( buf, len, "SHLR2 R%d", RN(ir) ); break;
|
nkeynes@1 | 154 | case 0x0A: snprintf( buf, len, "LDS R%d, MACH", RN(ir) ); break;
|
nkeynes@1 | 155 | case 0x0B: snprintf( buf, len, "JSR [R%d]", RN(ir) ); break;
|
nkeynes@1 | 156 | case 0x0E: snprintf( buf, len, "LDC R%d, SR", RN(ir) ); break;
|
nkeynes@1 | 157 | case 0x10: snprintf( buf, len, "DT R%d", RN(ir) ); break;
|
nkeynes@1 | 158 | case 0x11: snprintf( buf, len, "CMP/PZ R%d", RN(ir) ); break;
|
nkeynes@1 | 159 | case 0x12: snprintf( buf, len, "STS.L MACL, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 160 | case 0x13: snprintf( buf, len, "STC.L GBR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 161 | case 0x15: snprintf( buf, len, "CMP/PL R%d", RN(ir) ); break;
|
nkeynes@1 | 162 | case 0x16: snprintf( buf, len, "LDS.L [R%d++], MACL", RN(ir) ); break;
|
nkeynes@1 | 163 | case 0x17: snprintf( buf, len, "LDC.L [R%d++], GBR", RN(ir) ); break;
|
nkeynes@1 | 164 | case 0x18: snprintf( buf, len, "SHLL8 R%d", RN(ir) ); break;
|
nkeynes@1 | 165 | case 0x19: snprintf( buf, len, "SHLR8 R%d", RN(ir) ); break;
|
nkeynes@1 | 166 | case 0x1A: snprintf( buf, len, "LDS R%d, MACL", RN(ir) ); break;
|
nkeynes@1 | 167 | case 0x1B: snprintf( buf, len, "TAS.B [R%d]", RN(ir) ); break;
|
nkeynes@1 | 168 | case 0x1E: snprintf( buf, len, "LDC R%d, GBR", RN(ir) ); break;
|
nkeynes@1 | 169 | case 0x20: snprintf( buf, len, "SHAL R%d", RN(ir) ); break;
|
nkeynes@1 | 170 | case 0x21: snprintf( buf, len, "SHAR R%d", RN(ir) ); break;
|
nkeynes@1 | 171 | case 0x22: snprintf( buf, len, "STS.L PR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 172 | case 0x23: snprintf( buf, len, "STC.L VBR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 173 | case 0x24: snprintf( buf, len, "ROTCL R%d", RN(ir) ); break;
|
nkeynes@1 | 174 | case 0x25: snprintf( buf, len, "ROTCR R%d", RN(ir) ); break;
|
nkeynes@1 | 175 | case 0x26: snprintf( buf, len, "LDS.L [R%d++], PR", RN(ir) ); break;
|
nkeynes@1 | 176 | case 0x27: snprintf( buf, len, "LDC.L [R%d++], VBR", RN(ir) ); break;
|
nkeynes@1 | 177 | case 0x28: snprintf( buf, len, "SHLL16 R%d", RN(ir) ); break;
|
nkeynes@1 | 178 | case 0x29: snprintf( buf, len, "SHLR16 R%d", RN(ir) ); break;
|
nkeynes@1 | 179 | case 0x2A: snprintf( buf, len, "LDS R%d, PR", RN(ir) ); break;
|
nkeynes@1 | 180 | case 0x2B: snprintf( buf, len, "JMP [R%d]", RN(ir) ); break;
|
nkeynes@1 | 181 | case 0x2E: snprintf( buf, len, "LDC R%d, VBR", RN(ir) ); break;
|
nkeynes@1 | 182 | case 0x32: snprintf( buf, len, "STC.L SGR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 183 | case 0x33: snprintf( buf, len, "STC.L SSR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 184 | case 0x37: snprintf( buf, len, "LDC.L [R%d++], SSR", RN(ir) ); break;
|
nkeynes@1 | 185 | case 0x3E: snprintf( buf, len, "LDC R%d, SSR", RN(ir) ); break;
|
nkeynes@1 | 186 | case 0x43: snprintf( buf, len, "STC.L SPC, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 187 | case 0x47: snprintf( buf, len, "LDC.L [R%d++], SPC", RN(ir) ); break;
|
nkeynes@1 | 188 | case 0x4E: snprintf( buf, len, "LDC R%d, SPC", RN(ir) ); break;
|
nkeynes@1 | 189 | case 0x52: snprintf( buf, len, "STS.L FPUL, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 190 | case 0x56: snprintf( buf, len, "LDS.L [R%d++], FPUL", RN(ir) ); break;
|
nkeynes@1 | 191 | case 0x5A: snprintf( buf, len, "LDS R%d, FPUL", RN(ir) ); break;
|
nkeynes@1 | 192 | case 0x62: snprintf( buf, len, "STS.L FPSCR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 193 | case 0x66: snprintf( buf, len, "LDS.L [R%d++], FPSCR", RN(ir) ); break;
|
nkeynes@1 | 194 | case 0x6A: snprintf( buf, len, "LDS R%d, FPSCR", RN(ir) ); break;
|
nkeynes@1 | 195 | case 0xF2: snprintf( buf, len, "STC.L DBR, [--R%d]", RN(ir) ); break;
|
nkeynes@1 | 196 | case 0xF6: snprintf( buf, len, "LDC.L [R%d++], DBR", RN(ir) ); break;
|
nkeynes@1 | 197 | case 0xFA: snprintf( buf, len, "LDC R%d, DBR", RN(ir) ); break;
|
nkeynes@1 | 198 | case 0x83: case 0x93: case 0xA3: case 0xB3: case 0xC3: case 0xD3: case 0xE3:
|
nkeynes@1 | 199 | case 0xF3: snprintf( buf, len, "STC.L R%d_BANK, [--R%d]", RN_BANK(ir), RN(ir) ); break;
|
nkeynes@1 | 200 | case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7: case 0xD7: case 0xE7:
|
nkeynes@1 | 201 | case 0xF7: snprintf( buf, len, "LDC.L [R%d++], R%d_BANK", RN(ir), RN_BANK(ir) ); break;
|
nkeynes@1 | 202 | case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE: case 0xDE: case 0xEE:
|
nkeynes@1 | 203 | case 0xFE: snprintf( buf, len, "LDC R%d, R%d_BANK", RN(ir), RN_BANK(ir) ); break;
|
nkeynes@1 | 204 | default:
|
nkeynes@1 | 205 | if( (ir&0x000F) == 0x0F ) {
|
nkeynes@1 | 206 | snprintf( buf, len, "MAC.W [R%d++], [R%d++]", RM(ir), RN(ir) );
|
nkeynes@1 | 207 | } else if( (ir&0x000F) == 0x0C ) {
|
nkeynes@1 | 208 | snprintf( buf, len, "SHAD R%d, R%d", RM(ir), RN(ir) );
|
nkeynes@1 | 209 | } else if( (ir&0x000F) == 0x0D ) {
|
nkeynes@1 | 210 | snprintf( buf, len, "SHLD R%d, R%d", RM(ir), RN(ir) );
|
nkeynes@1 | 211 | } else UNIMP(ir);
|
nkeynes@1 | 212 | }
|
nkeynes@1 | 213 | break;
|
nkeynes@1 | 214 | case 5: /* 0101nnnnmmmmdddd */
|
nkeynes@1 | 215 | snprintf( buf, len, "MOV.L [R%d%+d], R%d", RM(ir), DISP4(ir)<<2, RN(ir) ); break;
|
nkeynes@1 | 216 | case 6: /* 0110xxxxxxxxxxxx */
|
nkeynes@1 | 217 | switch( ir&0x000f ) {
|
nkeynes@1 | 218 | case 0: snprintf( buf, len, "MOV.B [R%d], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 219 | case 1: snprintf( buf, len, "MOV.W [R%d], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 220 | case 2: snprintf( buf, len, "MOV.L [R%d], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 221 | case 3: snprintf( buf, len, "MOV R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 222 | case 4: snprintf( buf, len, "MOV.B [R%d++], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 223 | case 5: snprintf( buf, len, "MOV.W [R%d++], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 224 | case 6: snprintf( buf, len, "MOV.L [R%d++], R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 225 | case 7: snprintf( buf, len, "NOT R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 226 | case 8: snprintf( buf, len, "SWAP.B R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 227 | case 9: snprintf( buf, len, "SWAP.W R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 228 | case 10:snprintf( buf, len, "NEGC R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 229 | case 11:snprintf( buf, len, "NEG R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 230 | case 12:snprintf( buf, len, "EXTU.B R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 231 | case 13:snprintf( buf, len, "EXTU.W R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 232 | case 14:snprintf( buf, len, "EXTS.B R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 233 | case 15:snprintf( buf, len, "EXTS.W R%d, R%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 234 | }
|
nkeynes@1 | 235 | break;
|
nkeynes@1 | 236 | case 7: /* 0111nnnniiiiiiii */
|
nkeynes@1 | 237 | snprintf( buf, len, "ADD #%d, R%d", SIGNEXT8(ir&0x00FF), RN(ir) ); break;
|
nkeynes@1 | 238 | case 8: /* 1000xxxxxxxxxxxx */
|
nkeynes@1 | 239 | switch( (ir&0x0F00) >> 8 ) {
|
nkeynes@1 | 240 | case 0: snprintf( buf, len, "MOV.B R0, [R%d%+d]", RM(ir), DISP4(ir) ); break;
|
nkeynes@1 | 241 | case 1: snprintf( buf, len, "MOV.W R0, [R%d%+d]", RM(ir), DISP4(ir)<<1 ); break;
|
nkeynes@1 | 242 | case 4: snprintf( buf, len, "MOV.B [R%d%+d], R0", RM(ir), DISP4(ir) ); break;
|
nkeynes@1 | 243 | case 5: snprintf( buf, len, "MOV.W [R%d%+d], R0", RM(ir), DISP4(ir)<<1 ); break;
|
nkeynes@1 | 244 | case 8: snprintf( buf, len, "CMP/EQ #%d, R0", IMM8(ir) ); break;
|
nkeynes@1 | 245 | case 9: snprintf( buf, len, "BT $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
|
nkeynes@1 | 246 | case 11:snprintf( buf, len, "BF $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
|
nkeynes@1 | 247 | case 13:snprintf( buf, len, "BT/S $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
|
nkeynes@1 | 248 | case 15:snprintf( buf, len, "BF/S $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
|
nkeynes@1 | 249 | default: UNIMP(ir);
|
nkeynes@1 | 250 | }
|
nkeynes@1 | 251 | break;
|
nkeynes@1 | 252 | case 9: /* 1001xxxxxxxxxxxx */
|
nkeynes@1 | 253 | snprintf( buf, len, "MOV.W [$%xh], R%-2d ; <- #%08x", (DISP8(ir)<<1)+pc+4, RN(ir),
|
nkeynes@1 | 254 | mem_read_word( (DISP8(ir)<<1)+pc+4 ) ); break;
|
nkeynes@1 | 255 | case 10:/* 1010xxxxxxxxxxxx */
|
nkeynes@1 | 256 | snprintf( buf, len, "BRA $%xh", (DISP12(ir)<<1)+pc+4 ); break;
|
nkeynes@1 | 257 | case 11:/* 1011xxxxxxxxxxxx */
|
nkeynes@1 | 258 | snprintf( buf, len, "BSR $%xh", (DISP12(ir)<<1)+pc+4 ); break;
|
nkeynes@1 | 259 | case 12:/* 1100xxxxdddddddd */
|
nkeynes@1 | 260 | switch( (ir&0x0F00)>>8 ) {
|
nkeynes@1 | 261 | case 0: snprintf( buf, len, "MOV.B R0, [GBR%+d]", DISP8(ir) ); break;
|
nkeynes@1 | 262 | case 1: snprintf( buf, len, "MOV.W R0, [GBR%+d]", DISP8(ir)<<1 ); break;
|
nkeynes@1 | 263 | case 2: snprintf( buf, len, "MOV.L R0, [GBR%+d]", DISP8(ir)<<2 ); break;
|
nkeynes@1 | 264 | case 3: snprintf( buf, len, "TRAPA #%d", UIMM8(ir) ); break;
|
nkeynes@1 | 265 | case 4: snprintf( buf, len, "MOV.B [GBR%+d], R0", DISP8(ir) ); break;
|
nkeynes@1 | 266 | case 5: snprintf( buf, len, "MOV.W [GBR%+d], R0", DISP8(ir)<<1 ); break;
|
nkeynes@1 | 267 | case 6: snprintf( buf, len, "MOV.L [GBR%+d], R0", DISP8(ir)<<2 ); break;
|
nkeynes@1 | 268 | case 7: snprintf( buf, len, "MOVA $%xh, R0", (DISP8(ir)<<2)+(pc&~3)+4 ); break;
|
nkeynes@1 | 269 | case 8: snprintf( buf, len, "TST #%02Xh, R0", UIMM8(ir) ); break;
|
nkeynes@1 | 270 | case 9: snprintf( buf, len, "AND #%02Xh, R0", UIMM8(ir) ); break;
|
nkeynes@1 | 271 | case 10:snprintf( buf, len, "XOR #%02Xh, R0", UIMM8(ir) ); break;
|
nkeynes@1 | 272 | case 11:snprintf( buf, len, "OR #%02Xh, R0", UIMM8(ir) ); break;
|
nkeynes@1 | 273 | case 12:snprintf( buf, len, "TST.B #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
|
nkeynes@1 | 274 | case 13:snprintf( buf, len, "AND.B #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
|
nkeynes@1 | 275 | case 14:snprintf( buf, len, "XOR.B #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
|
nkeynes@1 | 276 | case 15:snprintf( buf, len, "OR.B #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
|
nkeynes@1 | 277 | }
|
nkeynes@1 | 278 | break;
|
nkeynes@1 | 279 | case 13:/* 1101xxxxxxxxxxxx */
|
nkeynes@1 | 280 | snprintf( buf, len, "MOV.L [$%xh], R%-2d ; <- #%08x", (DISP8(ir)<<2)+(pc&~3)+4, RN(ir),
|
nkeynes@1 | 281 | mem_read_long( (DISP8(ir)<<2)+(pc&~3)+4 ) ); break;
|
nkeynes@1 | 282 | case 14:/* 1110xxxxxxxxxxxx */
|
nkeynes@1 | 283 | snprintf( buf, len, "MOV #%d, R%d", DISP8(ir), RN(ir)); break;
|
nkeynes@1 | 284 | case 15:/* 1111xxxxxxxxxxxx */
|
nkeynes@1 | 285 | switch( ir&0x000F ) {
|
nkeynes@1 | 286 | case 0: snprintf( buf, len, "FADD FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 287 | case 1: snprintf( buf, len, "FSUB FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 288 | case 2: snprintf( buf, len, "FMUL FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 289 | case 3: snprintf( buf, len, "FDIV FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 290 | case 4: snprintf( buf, len, "FCMP/EQ FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 291 | case 5: snprintf( buf, len, "FCMP/GT FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 292 | case 6: snprintf( buf, len, "FMOV.S [R%d+R0], FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 293 | case 7: snprintf( buf, len, "FMOV.S FR%d, [R%d+R0]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 294 | case 8: snprintf( buf, len, "FMOV.S [R%d], FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 295 | case 9: snprintf( buf, len, "FMOV.S [R%d++], FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 296 | case 10:snprintf( buf, len, "FMOV.S FR%d, [R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 297 | case 11:snprintf( buf, len, "FMOV.S FR%d, [--R%d]", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 298 | case 12:snprintf( buf, len, "FMOV FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 299 | case 13:
|
nkeynes@1 | 300 | switch( (ir&0x00F0) >> 4 ) {
|
nkeynes@1 | 301 | case 0: snprintf( buf, len, "FSTS FPUL, FR%d", RN(ir) ); break;
|
nkeynes@1 | 302 | case 1: snprintf( buf, len, "FLDS FR%d, FPUL", RN(ir) ); break;
|
nkeynes@1 | 303 | case 2: snprintf( buf, len, "FLOAT FPUL, FR%d", RN(ir) ); break;
|
nkeynes@1 | 304 | case 3: snprintf( buf, len, "FTRC FR%d, FPUL", RN(ir) ); break;
|
nkeynes@1 | 305 | case 4: snprintf( buf, len, "FNEG FR%d", RN(ir) ); break;
|
nkeynes@1 | 306 | case 5: snprintf( buf, len, "FABS FR%d", RN(ir) ); break;
|
nkeynes@1 | 307 | case 6: snprintf( buf, len, "FSQRT FR%d", RN(ir) ); break;
|
nkeynes@2 | 308 | case 7: snprintf( buf, len, "FSRRA FR%d", RN(ir) ); break;
|
nkeynes@1 | 309 | case 8: snprintf( buf, len, "FLDI0 FR%d", RN(ir) ); break;
|
nkeynes@1 | 310 | case 9: snprintf( buf, len, "FLDI1 FR%d", RN(ir) ); break;
|
nkeynes@1 | 311 | case 10:snprintf( buf, len, "FCNVSD FPUL, DR%d", RN(ir)>>1 ); break;
|
nkeynes@1 | 312 | case 11:snprintf( buf, len, "FCNVDS DR%d, FPUL", RN(ir)>>1 ); break;
|
nkeynes@1 | 313 | case 14:snprintf( buf, len, "FIPR FV%d, FV%d", FVM(ir), FVN(ir) ); break;
|
nkeynes@1 | 314 | case 15:
|
nkeynes@2 | 315 | if( (ir & 0x0300) == 0x0100 )
|
nkeynes@1 | 316 | snprintf( buf, len, "FTRV XMTRX,FV%d", FVN(ir) );
|
nkeynes@2 | 317 | else if( (ir & 0x0100) == 0 )
|
nkeynes@2 | 318 | snprintf( buf, len, "FSCA FPUL, DR%d", RN(ir) );
|
nkeynes@1 | 319 | else if( ir == 0xFBFD )
|
nkeynes@1 | 320 | snprintf( buf, len, "FRCHG " );
|
nkeynes@1 | 321 | else if( ir == 0xF3FD )
|
nkeynes@1 | 322 | snprintf( buf, len, "FSCHG " );
|
nkeynes@2 | 323 | else UNIMP(ir);
|
nkeynes@1 | 324 | break;
|
nkeynes@1 | 325 | default: UNIMP(ir);
|
nkeynes@1 | 326 | }
|
nkeynes@1 | 327 | break;
|
nkeynes@1 | 328 | case 14:snprintf( buf, len, "FMAC FR0, FR%d, FR%d", RM(ir), RN(ir) ); break;
|
nkeynes@1 | 329 | default: UNIMP(ir);
|
nkeynes@1 | 330 | }
|
nkeynes@1 | 331 | break;
|
nkeynes@1 | 332 | }
|
nkeynes@1 | 333 | return pc+2;
|
nkeynes@1 | 334 | }
|
nkeynes@1 | 335 |
|
nkeynes@1 | 336 |
|
nkeynes@1 | 337 | void sh4_disasm_region( FILE *f, int from, int to, int load_addr )
|
nkeynes@1 | 338 | {
|
nkeynes@1 | 339 | int pc;
|
nkeynes@1 | 340 | char buf[80];
|
nkeynes@1 | 341 |
|
nkeynes@1 | 342 | for( pc = from; pc < to; pc+=2 ) {
|
nkeynes@1 | 343 | uint16_t op = mem_read_word( pc );
|
nkeynes@1 | 344 | buf[0] = '\0';
|
nkeynes@1 | 345 | sh4_disasm_instruction( pc,
|
nkeynes@1 | 346 | buf, sizeof(buf) );
|
nkeynes@1 | 347 | fprintf( f, " %08x: %04x %s\n", pc + load_addr, op, buf );
|
nkeynes@1 | 348 | }
|
nkeynes@1 | 349 | }
|