2 // m68kdasm.c: 68000 instruction disassembly
4 // Originally part of the UAE 68000 cpu core
7 // Adapted to Virtual Jaguar by James Hammons
9 // This file is distributed under the GNU Public License, version 3 or at your
10 // option any later version. Read the file GPLv3 for details.
20 // Stuff from m68kinterface.c
21 extern unsigned long IllegalOpcode(uint32_t opcode);
22 extern cpuop_func * cpuFunctionTable[65536];
24 // Local "global" variables
25 static long int m68kpc_offset;
28 #define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
29 #define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
30 #define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
32 #define get_ibyte_1(o) m68k_read_memory_8(regs.pc + (o) + 1)
33 #define get_iword_1(o) m68k_read_memory_16(regs.pc + (o))
34 #define get_ilong_1(o) m68k_read_memory_32(regs.pc + (o))
38 int32_t ShowEA(FILE * f, int reg, amodes mode, wordsizes size, char * buf)
52 sprintf(buffer,"D%d", reg);
55 sprintf(buffer,"A%d", reg);
58 sprintf(buffer,"(A%d)", reg);
61 sprintf(buffer,"(A%d)+", reg);
64 sprintf(buffer,"-(A%d)", reg);
67 disp16 = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
68 addr = m68k_areg(regs,reg) + (int16_t)disp16;
69 sprintf(buffer,"(A%d,$%04X) == $%08lX", reg, disp16 & 0xFFFF,
73 dp = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
75 r = (dp & 0x7000) >> 12;
76 dispreg = (dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r));
79 dispreg = (int32_t)(int16_t)(dispreg);
81 dispreg <<= (dp >> 9) & 3;
85 int32_t outer = 0, disp = 0;
86 int32_t base = m68k_areg(regs,reg);
88 sprintf (name,"A%d, ",reg);
89 if (dp & 0x80) { base = 0; name[0] = 0; }
90 if (dp & 0x40) dispreg = 0;
91 if ((dp & 0x30) == 0x20) { disp = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
92 if ((dp & 0x30) == 0x30) { disp = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
95 if ((dp & 0x3) == 0x2) { outer = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
96 if ((dp & 0x3) == 0x3) { outer = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
98 if (!(dp & 4)) base += dispreg;
99 if (dp & 3) base = m68k_read_memory_32(base);
100 if (dp & 4) base += dispreg;
103 sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lX", name,
104 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
105 1 << ((dp >> 9) & 3),
106 (long)disp, (long)outer, (unsigned long)addr);
110 addr = m68k_areg(regs,reg) + (int32_t)((int8_t)disp8) + dispreg;
111 sprintf (buffer,"(A%d, %c%d.%c*%d, $%02X) == $%08lX", reg,
112 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
113 1 << ((dp >> 9) & 3), disp8, (unsigned long)addr);
117 addr = m68k_getpc() + m68kpc_offset;
118 disp16 = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
119 addr += (int16_t)disp16;
120 sprintf(buffer,"(PC,$%04X) == $%08lX", disp16 & 0xffff,(unsigned long)addr);
123 addr = m68k_getpc() + m68kpc_offset;
124 dp = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
126 r = (dp & 0x7000) >> 12;
127 dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
130 dispreg = (int32_t)(int16_t)(dispreg);
132 dispreg <<= (dp >> 9) & 3;
136 int32_t outer = 0,disp = 0;
139 sprintf (name,"PC, ");
140 if (dp & 0x80) { base = 0; name[0] = 0; }
141 if (dp & 0x40) dispreg = 0;
142 if ((dp & 0x30) == 0x20) { disp = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
143 if ((dp & 0x30) == 0x30) { disp = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
146 if ((dp & 0x3) == 0x2)
148 outer = (int32_t)(int16_t)get_iword_1(m68kpc_offset);
152 if ((dp & 0x3) == 0x3)
154 outer = get_ilong_1(m68kpc_offset);
158 if (!(dp & 4)) base += dispreg;
159 if (dp & 3) base = m68k_read_memory_32(base);
160 if (dp & 4) base += dispreg;
163 sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lX", name,
164 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
165 1 << ((dp >> 9) & 3), (long)disp, (long)outer, (unsigned long)addr);
169 addr += (int32_t)((int8_t)disp8) + dispreg;
170 sprintf(buffer,"(PC, %c%d.%c*%d, $%02X) == $%08lX", dp & 0x8000 ? 'A' : 'D',
171 (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
172 disp8, (unsigned long)addr);
176 sprintf(buffer,"$%08lX", (unsigned long)(int32_t)(int16_t)get_iword_1(m68kpc_offset));
180 sprintf(buffer,"$%08lX", (unsigned long)get_ilong_1(m68kpc_offset));
187 sprintf(buffer,"#$%02X", (unsigned int)(get_iword_1(m68kpc_offset) & 0xFF));
191 sprintf(buffer,"#$%04X", (unsigned int)(get_iword_1(m68kpc_offset) & 0xFFFF));
195 sprintf(buffer,"#$%08lX", (unsigned long)(get_ilong_1(m68kpc_offset)));
203 offset = (int32_t)(int8_t)get_iword_1(m68kpc_offset);
205 sprintf (buffer,"#$%02X", (unsigned int)(offset & 0xFF));
208 offset = (int32_t)(int16_t)get_iword_1(m68kpc_offset);
210 sprintf (buffer,"#$%04X", (unsigned int)(offset & 0xFFFF));
213 offset = (int32_t)get_ilong_1(m68kpc_offset);
215 sprintf(buffer,"#$%08lX", (unsigned long)offset);
218 offset = (int32_t)(int8_t)(reg & 0xFF);
219 sprintf(buffer,"#$%08lX", (unsigned long)offset);
226 fprintf(f, "%s", buffer);
234 //void m68k_disasm(FILE * f, uint32_t addr, uint32_t * nextpc, int cnt)
235 unsigned int m68k_disasm(char * output, uint32_t addr, uint32_t * nextpc, int cnt)
237 // Sanity checking...
238 // if (addr > 0xFFFFFF)
241 char f[256], str[256];
242 static const char * const ccnames[] =
243 { "T ","F ","HI","LS","CC","CS","NE","EQ",
244 "VC","VS","PL","MI","GE","LT","GT","LE" };
249 m68kpc_offset = addr - m68k_getpc();
250 long int pcOffsetSave = m68kpc_offset;
255 char instrname[20], * ccpt;
257 const struct mnemolookup * lookup;
259 // sprintf(f, "%06lX: ", m68k_getpc() + m68kpc_offset);
263 for(opwords=0; opwords<5; opwords++)
265 sprintf(f, "%04X ", get_iword_1(m68kpc_offset + opwords * 2));
270 opcode = get_iword_1(m68kpc_offset);
273 if (cpuFunctionTable[opcode] == IllegalOpcode)
278 dp = table68k + opcode;
280 for(lookup=lookuptab; lookup->mnemo!=dp->mnemo; lookup++)
283 strcpy(instrname, lookup->name);
284 ccpt = strstr(instrname, "cc");
288 strncpy(ccpt, ccnames[dp->cc], 2);
291 sprintf(f, "%s", instrname);
297 case sz_byte: sprintf(f, ".B "); break;
298 case sz_word: sprintf(f, ".W "); break;
299 case sz_long: sprintf(f, ".L "); break;
300 default: sprintf(f, " "); break;
306 case sz_byte: strcat(str, ".B "); break;
307 case sz_word: strcat(str, ".W "); break;
308 case sz_long: strcat(str, ".L "); break;
309 default: strcat(str, " "); break;
316 newpc = m68k_getpc() + m68kpc_offset;
317 newpc += ShowEA(0, dp->sreg, dp->smode, dp->size, f);
322 if (dp->suse && dp->duse)
333 newpc = m68k_getpc() + m68kpc_offset;
334 newpc += ShowEA(0, dp->dreg, dp->dmode, dp->size, f);
341 sprintf(f, " == %08lX (TRUE)", (long)newpc);
343 sprintf(f, " == %08lX (FALSE)", (long)newpc);
347 else if ((opcode & 0xFF00) == 0x6100) // BSR
349 sprintf(f, " == %08lX", (long)newpc);
357 // *nextpc = m68k_getpc() + m68kpc_offset;
359 long int numberOfBytes = m68kpc_offset - pcOffsetSave;
361 for(opwords=0; opwords<5; opwords++)
363 if (((opwords + 1) * 2) <= numberOfBytes)
364 sprintf(f, "%04X ", get_iword_1(pcOffsetSave + opwords * 2));
373 return numberOfBytes;
377 // Disasemble one instruction at pc and store in str_buff
379 unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type)
381 return m68k_disasm(str_buff, pc, 0, 1);