pavone@467
|
1 /*
|
pavone@467
|
2 Copyright 2013 Michael Pavone
|
pavone@518
|
3 This file is part of BlastEm.
|
pavone@467
|
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
|
pavone@467
|
5 */
|
pavone@0
|
6 #include "68kinst.h"
|
pavone@2
|
7 #include <string.h>
|
pavone@2
|
8 #include <stdio.h>
|
pavone@0
|
9
|
pavone@2
|
10 uint32_t sign_extend16(uint32_t val)
|
pavone@0
|
11 {
|
pavone@2
|
12 return (val & 0x8000) ? val | 0xFFFF0000 : val;
|
pavone@2
|
13 }
|
pavone@2
|
14
|
pavone@2
|
15 uint32_t sign_extend8(uint32_t val)
|
pavone@2
|
16 {
|
pavone@2
|
17 return (val & 0x80) ? val | 0xFFFFFF00 : val;
|
pavone@2
|
18 }
|
pavone@2
|
19
|
pavone@2
|
20 uint16_t *m68k_decode_op_ex(uint16_t *cur, uint8_t mode, uint8_t reg, uint8_t size, m68k_op_info *dst)
|
pavone@2
|
21 {
|
pavone@638
|
22 uint16_t ext, tmp;
|
pavone@0
|
23 dst->addr_mode = mode;
|
pavone@0
|
24 switch(mode)
|
pavone@0
|
25 {
|
pavone@0
|
26 case MODE_REG:
|
pavone@0
|
27 case MODE_AREG:
|
pavone@2
|
28 case MODE_AREG_INDIRECT:
|
pavone@2
|
29 case MODE_AREG_POSTINC:
|
pavone@2
|
30 case MODE_AREG_PREDEC:
|
pavone@0
|
31 dst->params.regs.pri = reg;
|
pavone@0
|
32 break;
|
pavone@2
|
33 case MODE_AREG_DISPLACE:
|
pavone@2
|
34 ext = *(++cur);
|
pavone@2
|
35 dst->params.regs.pri = reg;
|
pavone@2
|
36 dst->params.regs.displacement = sign_extend16(ext);
|
pavone@2
|
37 break;
|
pavone@2
|
38 case MODE_AREG_INDEX_MEM:
|
pavone@638
|
39 dst->params.regs.pri = reg;
|
pavone@638
|
40 ext = *(++cur);
|
pavone@638
|
41 dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit
|
pavone@638
|
42 #ifdef M68020
|
pavone@638
|
43 dst->params.regs.scale = ext >> 9 & 3;
|
pavone@638
|
44 if (ext & 0x100)
|
pavone@638
|
45 {
|
pavone@638
|
46 dst->params.regs.disp_sizes = ext >> 4 & 3;
|
pavone@638
|
47 switch (dst->params.regs.disp_sizes)
|
pavone@638
|
48 {
|
pavone@638
|
49 case 0:
|
pavone@638
|
50 //reserved
|
pavone@638
|
51 return NULL;
|
pavone@638
|
52 case 1:
|
pavone@638
|
53 dst->params.regs.displacement = 0;
|
pavone@638
|
54 break;
|
pavone@638
|
55 case 2:
|
pavone@638
|
56 dst->params.regs.displacement = sign_extend16(*(cur++));
|
pavone@638
|
57 break;
|
pavone@638
|
58 case 3:
|
pavone@638
|
59 tmp = *(cur++);
|
pavone@638
|
60 dst->params.regs.displacement = tmp << 16 | *(cur++);
|
pavone@638
|
61 break;
|
pavone@638
|
62 }
|
pavone@638
|
63 if (ext & 0x3)
|
pavone@638
|
64 {
|
pavone@638
|
65 //memory indirect
|
pavone@638
|
66 switch (ext & 0xC4)
|
pavone@638
|
67 {
|
pavone@638
|
68 case 0x00:
|
pavone@638
|
69 dst->addr_mode = MODE_AREG_PREINDEX;
|
pavone@638
|
70 break;
|
pavone@638
|
71 case 0x04:
|
pavone@638
|
72 dst->addr_mode = MODE_AREG_POSTINDEX;
|
pavone@638
|
73 break;
|
pavone@638
|
74 case 0x40:
|
pavone@638
|
75 dst->addr_mode = MODE_AREG_MEM_INDIRECT;
|
pavone@638
|
76 break;
|
pavone@638
|
77 case 0x80:
|
pavone@638
|
78 dst->addr_mode = MODE_PREINDEX;
|
pavone@638
|
79 break;
|
pavone@638
|
80 case 0x84:
|
pavone@638
|
81 dst->addr_mode = MODE_POSTINDEX;
|
pavone@638
|
82 break;
|
pavone@638
|
83 case 0xC0:
|
pavone@638
|
84 dst->addr_mode = MODE_MEM_INDIRECT;
|
pavone@638
|
85 break;
|
pavone@638
|
86 }
|
pavone@638
|
87 dst->params.regs.disp_sizes |= ext << 4 & 0x30;
|
pavone@638
|
88 switch (ext & 0x3)
|
pavone@638
|
89 {
|
pavone@638
|
90 case 0:
|
pavone@638
|
91 //reserved
|
pavone@638
|
92 return NULL;
|
pavone@638
|
93 case 1:
|
pavone@638
|
94 dst->params.regs.outer_disp = 0;
|
pavone@638
|
95 break;
|
pavone@638
|
96 case 2:
|
pavone@638
|
97 dst->params.regs.outer_disp = sign_extend16(*(cur++));
|
pavone@638
|
98 break;
|
pavone@638
|
99 case 3:
|
pavone@638
|
100 tmp = *(cur++);
|
pavone@638
|
101 dst->params.regs.outer_disp = tmp << 16 | *(cur++);
|
pavone@638
|
102 break;
|
pavone@638
|
103 }
|
pavone@638
|
104 } else {
|
pavone@638
|
105 switch (ext >> 6 & 3)
|
pavone@638
|
106 {
|
pavone@638
|
107 case 0:
|
pavone@638
|
108 dst->addr_mode = MODE_AREG_INDEX_BASE_DISP;
|
pavone@638
|
109 break;
|
pavone@638
|
110 case 1:
|
pavone@638
|
111 dst->addr_mode = MODE_AREG_BASE_DISP;
|
pavone@638
|
112 break;
|
pavone@638
|
113 case 2:
|
pavone@638
|
114 dst->addr_mode = MODE_INDEX_BASE_DISP;
|
pavone@638
|
115 break;
|
pavone@638
|
116 case 3:
|
pavone@638
|
117 dst->addr_mode = MODE_BASE_DISP;
|
pavone@638
|
118 break;
|
pavone@638
|
119 }
|
pavone@638
|
120 }
|
pavone@638
|
121 } else {
|
pavone@638
|
122 #endif
|
pavone@79
|
123 dst->addr_mode = MODE_AREG_INDEX_DISP8;
|
pavone@79
|
124 dst->params.regs.displacement = sign_extend8(ext&0xFF);
|
pavone@638
|
125 #ifdef M68020
|
pavone@638
|
126 }
|
pavone@638
|
127 #endif
|
pavone@2
|
128 break;
|
pavone@2
|
129 case MODE_PC_INDIRECT_ABS_IMMED:
|
pavone@2
|
130 switch(reg)
|
pavone@2
|
131 {
|
pavone@2
|
132 case 0:
|
pavone@2
|
133 dst->addr_mode = MODE_ABSOLUTE_SHORT;
|
pavone@2
|
134 ext = *(++cur);
|
pavone@15
|
135 dst->params.immed = sign_extend16(ext);
|
pavone@2
|
136 break;
|
pavone@2
|
137 case 1:
|
pavone@2
|
138 dst->addr_mode = MODE_ABSOLUTE;
|
pavone@2
|
139 ext = *(++cur);
|
pavone@15
|
140 dst->params.immed = ext << 16 | *(++cur);
|
pavone@2
|
141 break;
|
pavone@79
|
142 case 3:
|
pavone@638
|
143 ext = *(++cur);
|
pavone@638
|
144 dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit
|
pavone@638
|
145 #ifdef M68020
|
pavone@638
|
146 dst->params.regs.scale = ext >> 9 & 3;
|
pavone@638
|
147 if (ext & 0x100)
|
pavone@638
|
148 {
|
pavone@638
|
149 dst->params.regs.disp_sizes = ext >> 4 & 3;
|
pavone@638
|
150 switch (dst->params.regs.disp_sizes)
|
pavone@638
|
151 {
|
pavone@638
|
152 case 0:
|
pavone@638
|
153 //reserved
|
pavone@638
|
154 return NULL;
|
pavone@638
|
155 case 1:
|
pavone@638
|
156 dst->params.regs.displacement = 0;
|
pavone@638
|
157 break;
|
pavone@638
|
158 case 2:
|
pavone@638
|
159 dst->params.regs.displacement = sign_extend16(*(cur++));
|
pavone@638
|
160 break;
|
pavone@638
|
161 case 3:
|
pavone@638
|
162 tmp = *(cur++);
|
pavone@638
|
163 dst->params.regs.displacement = tmp << 16 | *(cur++);
|
pavone@638
|
164 break;
|
pavone@638
|
165 }
|
pavone@638
|
166 if (ext & 0x3)
|
pavone@638
|
167 {
|
pavone@638
|
168 //memory indirect
|
pavone@638
|
169 switch (ext & 0xC4)
|
pavone@638
|
170 {
|
pavone@638
|
171 case 0x00:
|
pavone@638
|
172 dst->addr_mode = MODE_PC_PREINDEX;
|
pavone@638
|
173 break;
|
pavone@638
|
174 case 0x04:
|
pavone@638
|
175 dst->addr_mode = MODE_PC_POSTINDEX;
|
pavone@638
|
176 break;
|
pavone@638
|
177 case 0x40:
|
pavone@638
|
178 dst->addr_mode = MODE_PC_MEM_INDIRECT;
|
pavone@638
|
179 break;
|
pavone@638
|
180 case 0x80:
|
pavone@638
|
181 dst->addr_mode = MODE_ZPC_PREINDEX;
|
pavone@638
|
182 break;
|
pavone@638
|
183 case 0x84:
|
pavone@638
|
184 dst->addr_mode = MODE_ZPC_POSTINDEX;
|
pavone@638
|
185 break;
|
pavone@638
|
186 case 0xC0:
|
pavone@638
|
187 dst->addr_mode = MODE_ZPC_MEM_INDIRECT;
|
pavone@638
|
188 break;
|
pavone@638
|
189 }
|
pavone@638
|
190 dst->params.regs.disp_sizes |= ext << 4 & 0x30;
|
pavone@638
|
191 switch (ext & 0x3)
|
pavone@638
|
192 {
|
pavone@638
|
193 case 0:
|
pavone@638
|
194 //reserved
|
pavone@638
|
195 return NULL;
|
pavone@638
|
196 case 1:
|
pavone@638
|
197 dst->params.regs.outer_disp = 0;
|
pavone@638
|
198 break;
|
pavone@638
|
199 case 2:
|
pavone@638
|
200 dst->params.regs.outer_disp = sign_extend16(*(cur++));
|
pavone@638
|
201 break;
|
pavone@638
|
202 case 3:
|
pavone@638
|
203 tmp = *(cur++);
|
pavone@638
|
204 dst->params.regs.outer_disp = tmp << 16 | *(cur++);
|
pavone@638
|
205 break;
|
pavone@638
|
206 }
|
pavone@638
|
207 } else {
|
pavone@638
|
208 switch (ext >> 6 & 3)
|
pavone@638
|
209 {
|
pavone@638
|
210 case 0:
|
pavone@638
|
211 dst->addr_mode = MODE_PC_INDEX_BASE_DISP;
|
pavone@638
|
212 break;
|
pavone@638
|
213 case 1:
|
pavone@638
|
214 dst->addr_mode = MODE_PC_BASE_DISP;
|
pavone@638
|
215 break;
|
pavone@638
|
216 case 2:
|
pavone@638
|
217 dst->addr_mode = MODE_ZPC_INDEX_BASE_DISP;
|
pavone@638
|
218 break;
|
pavone@638
|
219 case 3:
|
pavone@638
|
220 dst->addr_mode = MODE_ZPC_BASE_DISP;
|
pavone@638
|
221 break;
|
pavone@638
|
222 }
|
pavone@638
|
223 }
|
pavone@638
|
224 } else {
|
pavone@638
|
225 #endif
|
pavone@638
|
226 dst->addr_mode = MODE_PC_INDEX_DISP8;
|
pavone@638
|
227 dst->params.regs.displacement = sign_extend8(ext&0xFF);
|
pavone@638
|
228 #ifdef M68020
|
pavone@638
|
229 }
|
pavone@638
|
230 #endif
|
pavone@95
|
231 break;
|
pavone@2
|
232 case 2:
|
pavone@2
|
233 dst->addr_mode = MODE_PC_DISPLACE;
|
pavone@2
|
234 ext = *(++cur);
|
pavone@2
|
235 dst->params.regs.displacement = sign_extend16(ext);
|
pavone@2
|
236 break;
|
pavone@2
|
237 case 4:
|
pavone@2
|
238 dst->addr_mode = MODE_IMMEDIATE;
|
pavone@2
|
239 ext = *(++cur);
|
pavone@2
|
240 switch (size)
|
pavone@2
|
241 {
|
pavone@2
|
242 case OPSIZE_BYTE:
|
pavone@15
|
243 dst->params.immed = ext & 0xFF;
|
pavone@2
|
244 break;
|
pavone@2
|
245 case OPSIZE_WORD:
|
pavone@15
|
246 dst->params.immed = ext;
|
pavone@2
|
247 break;
|
pavone@2
|
248 case OPSIZE_LONG:
|
pavone@15
|
249 dst->params.immed = ext << 16 | *(++cur);
|
pavone@2
|
250 break;
|
pavone@2
|
251 }
|
pavone@2
|
252 break;
|
pavone@176
|
253 default:
|
pavone@176
|
254 return NULL;
|
pavone@2
|
255 }
|
pavone@2
|
256 break;
|
pavone@0
|
257 }
|
pavone@2
|
258 return cur;
|
pavone@2
|
259 }
|
pavone@2
|
260
|
pavone@823
|
261 uint8_t m68k_valid_immed_dst(m68k_op_info *dst)
|
pavone@823
|
262 {
|
pavone@823
|
263 if (dst->addr_mode == MODE_AREG || dst->addr_mode == MODE_IMMEDIATE) {
|
pavone@823
|
264 return 0;
|
pavone@823
|
265 }
|
pavone@823
|
266 return 1;
|
pavone@823
|
267 }
|
pavone@823
|
268
|
pavone@823
|
269 uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst)
|
pavone@823
|
270 {
|
pavone@823
|
271 if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) {
|
pavone@823
|
272 return 0;
|
pavone@823
|
273 }
|
pavone@823
|
274 return 1;
|
pavone@823
|
275 }
|
pavone@823
|
276
|
pavone@2
|
277 uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst)
|
pavone@2
|
278 {
|
pavone@2
|
279 uint8_t mode = (*cur >> 3) & 0x7;
|
pavone@2
|
280 uint8_t reg = *cur & 0x7;
|
pavone@2
|
281 return m68k_decode_op_ex(cur, mode, reg, size, dst);
|
pavone@2
|
282 }
|
pavone@2
|
283
|
pavone@2
|
284 void m68k_decode_cond(uint16_t op, m68kinst * decoded)
|
pavone@2
|
285 {
|
pavone@2
|
286 decoded->extra.cond = (op >> 0x8) & 0xF;
|
pavone@2
|
287 }
|
pavone@2
|
288
|
pavone@18
|
289 uint8_t m68k_reg_quick_field(uint16_t op)
|
pavone@2
|
290 {
|
pavone@2
|
291 return (op >> 9) & 0x7;
|
pavone@0
|
292 }
|
pavone@0
|
293
|
pavone@18
|
294 uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
|
pavone@0
|
295 {
|
pavone@176
|
296 uint16_t *start = istream;
|
pavone@0
|
297 uint8_t optype = *istream >> 12;
|
pavone@0
|
298 uint8_t size;
|
pavone@4
|
299 uint8_t reg;
|
pavone@4
|
300 uint8_t opmode;
|
pavone@2
|
301 uint32_t immed;
|
pavone@2
|
302 decoded->op = M68K_INVALID;
|
pavone@2
|
303 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED;
|
pavone@2
|
304 decoded->variant = VAR_NORMAL;
|
pavone@18
|
305 decoded->address = address;
|
pavone@0
|
306 switch(optype)
|
pavone@0
|
307 {
|
pavone@0
|
308 case BIT_MOVEP_IMMED:
|
pavone@163
|
309 if ((*istream & 0x138) == 0x108) {
|
pavone@163
|
310 //MOVEP
|
pavone@163
|
311 decoded->op = M68K_MOVEP;
|
pavone@163
|
312 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
|
pavone@163
|
313 if (*istream & 0x80) {
|
pavone@163
|
314 //memory dest
|
pavone@163
|
315 decoded->src.addr_mode = MODE_REG;
|
pavone@163
|
316 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@163
|
317 decoded->dst.addr_mode = MODE_AREG_DISPLACE;
|
pavone@163
|
318 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@163
|
319 decoded->dst.params.regs.displacement = *(++istream);
|
pavone@163
|
320 } else {
|
pavone@163
|
321 //memory source
|
pavone@163
|
322 decoded->dst.addr_mode = MODE_REG;
|
pavone@163
|
323 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@163
|
324 decoded->src.addr_mode = MODE_AREG_DISPLACE;
|
pavone@163
|
325 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@163
|
326 decoded->src.params.regs.displacement = *(++istream);
|
pavone@163
|
327 }
|
pavone@163
|
328 } else if (*istream & 0x100) {
|
pavone@4
|
329 //BTST, BCHG, BCLR, BSET
|
pavone@4
|
330 switch ((*istream >> 6) & 0x3)
|
pavone@4
|
331 {
|
pavone@4
|
332 case 0:
|
pavone@4
|
333 decoded->op = M68K_BTST;
|
pavone@4
|
334 break;
|
pavone@4
|
335 case 1:
|
pavone@4
|
336 decoded->op = M68K_BCHG;
|
pavone@4
|
337 break;
|
pavone@4
|
338 case 2:
|
pavone@4
|
339 decoded->op = M68K_BCLR;
|
pavone@4
|
340 break;
|
pavone@4
|
341 case 3:
|
pavone@4
|
342 decoded->op = M68K_BSET;
|
pavone@4
|
343 break;
|
pavone@4
|
344 }
|
pavone@4
|
345 decoded->src.addr_mode = MODE_REG;
|
pavone@18
|
346 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@61
|
347 decoded->extra.size = OPSIZE_BYTE;
|
pavone@61
|
348 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
|
pavone@176
|
349 if (!istream) {
|
pavone@176
|
350 decoded->op = M68K_INVALID;
|
pavone@630
|
351 break;
|
pavone@176
|
352 }
|
pavone@61
|
353 if (decoded->dst.addr_mode == MODE_REG) {
|
pavone@61
|
354 decoded->extra.size = OPSIZE_LONG;
|
pavone@61
|
355 }
|
pavone@8
|
356 } else if ((*istream & 0xF00) == 0x800) {
|
pavone@12
|
357 //BTST, BCHG, BCLR, BSET
|
pavone@12
|
358 switch ((*istream >> 6) & 0x3)
|
pavone@12
|
359 {
|
pavone@12
|
360 case 0:
|
pavone@12
|
361 decoded->op = M68K_BTST;
|
pavone@12
|
362 break;
|
pavone@12
|
363 case 1:
|
pavone@12
|
364 decoded->op = M68K_BCHG;
|
pavone@12
|
365 break;
|
pavone@12
|
366 case 2:
|
pavone@12
|
367 decoded->op = M68K_BCLR;
|
pavone@12
|
368 break;
|
pavone@12
|
369 case 3:
|
pavone@12
|
370 decoded->op = M68K_BSET;
|
pavone@12
|
371 break;
|
pavone@12
|
372 }
|
pavone@12
|
373 opmode = (*istream >> 3) & 0x7;
|
pavone@12
|
374 reg = *istream & 0x7;
|
pavone@61
|
375 decoded->src.addr_mode = MODE_IMMEDIATE_WORD;
|
pavone@15
|
376 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@12
|
377 decoded->extra.size = OPSIZE_BYTE;
|
pavone@61
|
378 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
|
pavone@176
|
379 if (!istream) {
|
pavone@176
|
380 decoded->op = M68K_INVALID;
|
pavone@630
|
381 break;
|
pavone@176
|
382 }
|
pavone@61
|
383 if (decoded->dst.addr_mode == MODE_REG) {
|
pavone@61
|
384 decoded->extra.size = OPSIZE_LONG;
|
pavone@61
|
385 }
|
pavone@8
|
386 } else if ((*istream & 0xC0) == 0xC0) {
|
pavone@8
|
387 #ifdef M68020
|
pavone@8
|
388 //CMP2, CHK2, CAS, CAS2, RTM, CALLM
|
pavone@8
|
389 #endif
|
pavone@4
|
390 } else {
|
pavone@4
|
391 switch ((*istream >> 9) & 0x7)
|
pavone@4
|
392 {
|
pavone@4
|
393 case 0:
|
pavone@4
|
394 if ((*istream & 0xFF) == 0x3C) {
|
pavone@4
|
395 decoded->op = M68K_ORI_CCR;
|
pavone@4
|
396 decoded->extra.size = OPSIZE_BYTE;
|
pavone@4
|
397 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
398 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@4
|
399 } else if((*istream & 0xFF) == 0x7C) {
|
pavone@4
|
400 decoded->op = M68K_ORI_SR;
|
pavone@4
|
401 decoded->extra.size = OPSIZE_WORD;
|
pavone@4
|
402 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
403 decoded->src.params.immed = *(++istream);
|
pavone@4
|
404 } else {
|
pavone@8
|
405 decoded->op = M68K_OR;
|
pavone@8
|
406 decoded->variant = VAR_IMMEDIATE;
|
pavone@8
|
407 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@8
|
408 decoded->extra.size = size = (*istream >> 6) & 3;
|
pavone@8
|
409 reg = *istream & 0x7;
|
pavone@8
|
410 opmode = (*istream >> 3) & 0x7;
|
pavone@8
|
411 switch (size)
|
pavone@8
|
412 {
|
pavone@8
|
413 case OPSIZE_BYTE:
|
pavone@15
|
414 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@8
|
415 break;
|
pavone@8
|
416 case OPSIZE_WORD:
|
pavone@15
|
417 decoded->src.params.immed = *(++istream);
|
pavone@8
|
418 break;
|
pavone@8
|
419 case OPSIZE_LONG:
|
pavone@8
|
420 immed = *(++istream);
|
pavone@15
|
421 decoded->src.params.immed = immed << 16 | *(++istream);
|
pavone@8
|
422 break;
|
pavone@4
|
423 }
|
pavone@8
|
424 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
|
pavone@823
|
425 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
|
pavone@176
|
426 decoded->op = M68K_INVALID;
|
pavone@630
|
427 break;
|
pavone@176
|
428 }
|
pavone@4
|
429 }
|
pavone@4
|
430 break;
|
pavone@4
|
431 case 1:
|
pavone@8
|
432 //ANDI, ANDI to CCR, ANDI to SR
|
pavone@5
|
433 if ((*istream & 0xFF) == 0x3C) {
|
pavone@5
|
434 decoded->op = M68K_ANDI_CCR;
|
pavone@5
|
435 decoded->extra.size = OPSIZE_BYTE;
|
pavone@5
|
436 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
437 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@5
|
438 } else if((*istream & 0xFF) == 0x7C) {
|
pavone@5
|
439 decoded->op = M68K_ANDI_SR;
|
pavone@5
|
440 decoded->extra.size = OPSIZE_WORD;
|
pavone@5
|
441 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
442 decoded->src.params.immed = *(++istream);
|
pavone@5
|
443 } else {
|
pavone@8
|
444 decoded->op = M68K_AND;
|
pavone@8
|
445 decoded->variant = VAR_IMMEDIATE;
|
pavone@5
|
446 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@5
|
447 decoded->extra.size = size = (*istream >> 6) & 3;
|
pavone@5
|
448 reg = *istream & 0x7;
|
pavone@5
|
449 opmode = (*istream >> 3) & 0x7;
|
pavone@5
|
450 switch (size)
|
pavone@5
|
451 {
|
pavone@5
|
452 case OPSIZE_BYTE:
|
pavone@15
|
453 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@5
|
454 break;
|
pavone@5
|
455 case OPSIZE_WORD:
|
pavone@15
|
456 decoded->src.params.immed = *(++istream);
|
pavone@5
|
457 break;
|
pavone@5
|
458 case OPSIZE_LONG:
|
pavone@5
|
459 immed = *(++istream);
|
pavone@15
|
460 decoded->src.params.immed = immed << 16 | *(++istream);
|
pavone@5
|
461 break;
|
pavone@5
|
462 }
|
pavone@5
|
463 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
|
pavone@823
|
464 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
|
pavone@176
|
465 decoded->op = M68K_INVALID;
|
pavone@630
|
466 break;
|
pavone@176
|
467 }
|
pavone@5
|
468 }
|
pavone@4
|
469 break;
|
pavone@8
|
470 case 2:
|
pavone@8
|
471 decoded->op = M68K_SUB;
|
pavone@8
|
472 decoded->variant = VAR_IMMEDIATE;
|
pavone@8
|
473 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@8
|
474 decoded->extra.size = size = (*istream >> 6) & 3;
|
pavone@8
|
475 reg = *istream & 0x7;
|
pavone@8
|
476 opmode = (*istream >> 3) & 0x7;
|
pavone@8
|
477 switch (size)
|
pavone@8
|
478 {
|
pavone@8
|
479 case OPSIZE_BYTE:
|
pavone@15
|
480 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@8
|
481 break;
|
pavone@8
|
482 case OPSIZE_WORD:
|
pavone@15
|
483 decoded->src.params.immed = *(++istream);
|
pavone@8
|
484 break;
|
pavone@8
|
485 case OPSIZE_LONG:
|
pavone@8
|
486 immed = *(++istream);
|
pavone@15
|
487 decoded->src.params.immed = immed << 16 | *(++istream);
|
pavone@8
|
488 break;
|
pavone@8
|
489 }
|
pavone@8
|
490 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
|
pavone@823
|
491 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
|
pavone@176
|
492 decoded->op = M68K_INVALID;
|
pavone@630
|
493 break;
|
pavone@176
|
494 }
|
pavone@8
|
495 break;
|
pavone@4
|
496 case 3:
|
pavone@8
|
497 decoded->op = M68K_ADD;
|
pavone@8
|
498 decoded->variant = VAR_IMMEDIATE;
|
pavone@8
|
499 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@8
|
500 decoded->extra.size = size = (*istream >> 6) & 3;
|
pavone@8
|
501 reg = *istream & 0x7;
|
pavone@8
|
502 opmode = (*istream >> 3) & 0x7;
|
pavone@8
|
503 switch (size)
|
pavone@8
|
504 {
|
pavone@8
|
505 case OPSIZE_BYTE:
|
pavone@15
|
506 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@8
|
507 break;
|
pavone@8
|
508 case OPSIZE_WORD:
|
pavone@15
|
509 decoded->src.params.immed = *(++istream);
|
pavone@8
|
510 break;
|
pavone@8
|
511 case OPSIZE_LONG:
|
pavone@8
|
512 immed = *(++istream);
|
pavone@15
|
513 decoded->src.params.immed = immed << 16 | *(++istream);
|
pavone@8
|
514 break;
|
pavone@5
|
515 }
|
pavone@8
|
516 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
|
pavone@823
|
517 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
|
pavone@176
|
518 decoded->op = M68K_INVALID;
|
pavone@630
|
519 break;
|
pavone@176
|
520 }
|
pavone@4
|
521 break;
|
pavone@4
|
522 case 4:
|
pavone@5
|
523 //BTST, BCHG, BCLR, BSET
|
pavone@5
|
524 switch ((*istream >> 6) & 0x3)
|
pavone@5
|
525 {
|
pavone@5
|
526 case 0:
|
pavone@5
|
527 decoded->op = M68K_BTST;
|
pavone@5
|
528 break;
|
pavone@5
|
529 case 1:
|
pavone@5
|
530 decoded->op = M68K_BCHG;
|
pavone@5
|
531 break;
|
pavone@5
|
532 case 2:
|
pavone@5
|
533 decoded->op = M68K_BCLR;
|
pavone@5
|
534 break;
|
pavone@5
|
535 case 3:
|
pavone@5
|
536 decoded->op = M68K_BSET;
|
pavone@5
|
537 break;
|
pavone@5
|
538 }
|
pavone@5
|
539 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
540 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@5
|
541 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
|
pavone@176
|
542 if (!istream) {
|
pavone@176
|
543 decoded->op = M68K_INVALID;
|
pavone@630
|
544 break;
|
pavone@176
|
545 }
|
pavone@4
|
546 break;
|
pavone@4
|
547 case 5:
|
pavone@5
|
548 //EORI, EORI to CCR, EORI to SR
|
pavone@5
|
549 if ((*istream & 0xFF) == 0x3C) {
|
pavone@5
|
550 decoded->op = M68K_EORI_CCR;
|
pavone@5
|
551 decoded->extra.size = OPSIZE_BYTE;
|
pavone@5
|
552 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
553 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@5
|
554 } else if((*istream & 0xFF) == 0x7C) {
|
pavone@5
|
555 decoded->op = M68K_EORI_SR;
|
pavone@5
|
556 decoded->extra.size = OPSIZE_WORD;
|
pavone@5
|
557 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
558 decoded->src.params.immed = *(++istream);
|
pavone@5
|
559 } else {
|
pavone@8
|
560 decoded->op = M68K_EOR;
|
pavone@8
|
561 decoded->variant = VAR_IMMEDIATE;
|
pavone@8
|
562 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@8
|
563 decoded->extra.size = size = (*istream >> 6) & 3;
|
pavone@8
|
564 reg = *istream & 0x7;
|
pavone@8
|
565 opmode = (*istream >> 3) & 0x7;
|
pavone@8
|
566 switch (size)
|
pavone@8
|
567 {
|
pavone@8
|
568 case OPSIZE_BYTE:
|
pavone@15
|
569 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@8
|
570 break;
|
pavone@8
|
571 case OPSIZE_WORD:
|
pavone@15
|
572 decoded->src.params.immed = *(++istream);
|
pavone@8
|
573 break;
|
pavone@8
|
574 case OPSIZE_LONG:
|
pavone@8
|
575 immed = *(++istream);
|
pavone@15
|
576 decoded->src.params.immed = immed << 16 | *(++istream);
|
pavone@8
|
577 break;
|
pavone@5
|
578 }
|
pavone@8
|
579 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
|
pavone@823
|
580 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
|
pavone@176
|
581 decoded->op = M68K_INVALID;
|
pavone@630
|
582 break;
|
pavone@176
|
583 }
|
pavone@5
|
584 }
|
pavone@4
|
585 break;
|
pavone@4
|
586 case 6:
|
pavone@8
|
587 decoded->op = M68K_CMP;
|
pavone@8
|
588 decoded->variant = VAR_IMMEDIATE;
|
pavone@8
|
589 decoded->extra.size = (*istream >> 6) & 0x3;
|
pavone@8
|
590 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@8
|
591 reg = *istream & 0x7;
|
pavone@8
|
592 opmode = (*istream >> 3) & 0x7;
|
pavone@8
|
593 switch (decoded->extra.size)
|
pavone@8
|
594 {
|
pavone@8
|
595 case OPSIZE_BYTE:
|
pavone@15
|
596 decoded->src.params.immed = *(++istream) & 0xFF;
|
pavone@8
|
597 break;
|
pavone@8
|
598 case OPSIZE_WORD:
|
pavone@15
|
599 decoded->src.params.immed = *(++istream);
|
pavone@8
|
600 break;
|
pavone@8
|
601 case OPSIZE_LONG:
|
pavone@8
|
602 immed = *(++istream);
|
pavone@15
|
603 decoded->src.params.immed = (immed << 16) | *(++istream);
|
pavone@8
|
604 break;
|
pavone@8
|
605 }
|
pavone@630
|
606 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
|
pavone@823
|
607 if (!istream || !m68k_valid_immed_dst(&(decoded->dst))) {
|
pavone@176
|
608 decoded->op = M68K_INVALID;
|
pavone@630
|
609 break;
|
pavone@176
|
610 }
|
pavone@4
|
611 break;
|
pavone@4
|
612 case 7:
|
pavone@630
|
613 #ifdef M68010
|
pavone@630
|
614 decoded->op = M68K_MOVES;
|
pavone@630
|
615 decoded->extra.size = *istream >> 6 & 0x3;
|
pavone@630
|
616 immed = *(++istream);
|
pavone@630
|
617 reg = immed >> 12 & 0x7;
|
pavone@630
|
618 opmode = immed & 0x8000 ? MODE_AREG : MODE_REG;
|
pavone@630
|
619 if (immed & 0x800) {
|
pavone@642
|
620 decoded->src.addr_mode = opmode;
|
pavone@642
|
621 decoded->src.params.regs.pri = reg;
|
pavone@642
|
622 m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->dst));
|
pavone@642
|
623 } else {
|
pavone@630
|
624 m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->src));
|
pavone@630
|
625 decoded->dst.addr_mode = opmode;
|
pavone@630
|
626 decoded->dst.params.regs.pri = reg;
|
pavone@630
|
627 }
|
pavone@630
|
628 #endif
|
pavone@4
|
629 break;
|
pavone@4
|
630 }
|
pavone@4
|
631 }
|
pavone@0
|
632 break;
|
pavone@0
|
633 case MOVE_BYTE:
|
pavone@0
|
634 case MOVE_LONG:
|
pavone@0
|
635 case MOVE_WORD:
|
pavone@0
|
636 decoded->op = M68K_MOVE;
|
pavone@0
|
637 decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG);
|
pavone@18
|
638 opmode = (*istream >> 6) & 0x7;
|
pavone@18
|
639 reg = m68k_reg_quick_field(*istream);
|
pavone@2
|
640 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
641 if (!istream) {
|
pavone@176
|
642 decoded->op = M68K_INVALID;
|
pavone@630
|
643 break;
|
pavone@176
|
644 }
|
pavone@18
|
645 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
|
pavone@197
|
646 if (!istream || decoded->dst.addr_mode == MODE_IMMEDIATE) {
|
pavone@176
|
647 decoded->op = M68K_INVALID;
|
pavone@630
|
648 break;
|
pavone@176
|
649 }
|
pavone@0
|
650 break;
|
pavone@0
|
651 case MISC:
|
pavone@518
|
652
|
pavone@2
|
653 if ((*istream & 0x1C0) == 0x1C0) {
|
pavone@2
|
654 decoded->op = M68K_LEA;
|
pavone@2
|
655 decoded->extra.size = OPSIZE_LONG;
|
pavone@2
|
656 decoded->dst.addr_mode = MODE_AREG;
|
pavone@18
|
657 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
658 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
659 if (!istream) {
|
pavone@176
|
660 decoded->op = M68K_INVALID;
|
pavone@630
|
661 break;
|
pavone@176
|
662 }
|
pavone@2
|
663 } else {
|
pavone@2
|
664 if (*istream & 0x100) {
|
pavone@2
|
665 decoded->op = M68K_CHK;
|
pavone@2
|
666 if ((*istream & 0x180) == 0x180) {
|
pavone@2
|
667 decoded->extra.size = OPSIZE_WORD;
|
pavone@2
|
668 } else {
|
pavone@2
|
669 //only on M68020+
|
pavone@9
|
670 #ifdef M68020
|
pavone@2
|
671 decoded->extra.size = OPSIZE_LONG;
|
pavone@9
|
672 #else
|
pavone@9
|
673 decoded->op = M68K_INVALID;
|
pavone@9
|
674 break;
|
pavone@9
|
675 #endif
|
pavone@2
|
676 }
|
pavone@184
|
677 decoded->dst.addr_mode = MODE_REG;
|
pavone@325
|
678 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
679 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
680 if (!istream) {
|
pavone@176
|
681 decoded->op = M68K_INVALID;
|
pavone@630
|
682 break;
|
pavone@176
|
683 }
|
pavone@2
|
684 } else {
|
pavone@13
|
685 opmode = (*istream >> 3) & 0x7;
|
pavone@61
|
686 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG) {
|
pavone@61
|
687 //TODO: Check for invalid modes that are dependent on direction
|
pavone@9
|
688 decoded->op = M68K_MOVEM;
|
pavone@9
|
689 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
|
pavone@13
|
690 reg = *istream & 0x7;
|
pavone@9
|
691 if(*istream & 0x400) {
|
pavone@9
|
692 decoded->dst.addr_mode = MODE_REG;
|
pavone@68
|
693 decoded->dst.params.immed = *(++istream);
|
pavone@9
|
694 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src));
|
pavone@176
|
695 if (!istream) {
|
pavone@176
|
696 decoded->op = M68K_INVALID;
|
pavone@630
|
697 break;
|
pavone@176
|
698 }
|
pavone@412
|
699 if (decoded->src.addr_mode == MODE_PC_DISPLACE || decoded->src.addr_mode == MODE_PC_INDEX_DISP8) {
|
pavone@412
|
700 //adjust displacement to account for extra instruction word
|
pavone@412
|
701 decoded->src.params.regs.displacement += 2;
|
pavone@412
|
702 }
|
pavone@2
|
703 } else {
|
pavone@9
|
704 decoded->src.addr_mode = MODE_REG;
|
pavone@68
|
705 decoded->src.params.immed = *(++istream);
|
pavone@9
|
706 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
|
pavone@176
|
707 if (!istream) {
|
pavone@176
|
708 decoded->op = M68K_INVALID;
|
pavone@630
|
709 break;
|
pavone@176
|
710 }
|
pavone@9
|
711 }
|
pavone@9
|
712 } else {
|
pavone@9
|
713 optype = (*istream >> 9) & 0x7;
|
pavone@9
|
714 size = (*istream >> 6) & 0x3;
|
pavone@9
|
715 switch(optype)
|
pavone@9
|
716 {
|
pavone@9
|
717 case 0:
|
pavone@9
|
718 //Move from SR or NEGX
|
pavone@2
|
719 if (size == OPSIZE_INVALID) {
|
pavone@9
|
720 decoded->op = M68K_MOVE_FROM_SR;
|
pavone@9
|
721 size = OPSIZE_WORD;
|
pavone@2
|
722 } else {
|
pavone@9
|
723 decoded->op = M68K_NEGX;
|
pavone@2
|
724 }
|
pavone@9
|
725 decoded->extra.size = size;
|
pavone@9
|
726 istream= m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
727 if (!istream) {
|
pavone@176
|
728 decoded->op = M68K_INVALID;
|
pavone@630
|
729 break;
|
pavone@176
|
730 }
|
pavone@9
|
731 break;
|
pavone@9
|
732 case 1:
|
pavone@9
|
733 //MOVE from CCR or CLR
|
pavone@9
|
734 if (size == OPSIZE_INVALID) {
|
pavone@9
|
735 #ifdef M68010
|
pavone@9
|
736 decoded->op = M68K_MOVE_FROM_CCR;
|
pavone@9
|
737 size = OPSIZE_WORD;
|
pavone@9
|
738 #else
|
pavone@630
|
739 break;
|
pavone@9
|
740 #endif
|
pavone@9
|
741 } else {
|
pavone@9
|
742 decoded->op = M68K_CLR;
|
pavone@9
|
743 }
|
pavone@9
|
744 decoded->extra.size = size;
|
pavone@9
|
745 istream= m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
746 if (!istream) {
|
pavone@176
|
747 decoded->op = M68K_INVALID;
|
pavone@630
|
748 break;
|
pavone@176
|
749 }
|
pavone@9
|
750 break;
|
pavone@9
|
751 case 2:
|
pavone@9
|
752 //MOVE to CCR or NEG
|
pavone@9
|
753 if (size == OPSIZE_INVALID) {
|
pavone@9
|
754 decoded->op = M68K_MOVE_CCR;
|
pavone@9
|
755 size = OPSIZE_WORD;
|
pavone@9
|
756 istream= m68k_decode_op(istream, size, &(decoded->src));
|
pavone@176
|
757 if (!istream) {
|
pavone@176
|
758 decoded->op = M68K_INVALID;
|
pavone@630
|
759 break;
|
pavone@176
|
760 }
|
pavone@9
|
761 } else {
|
pavone@9
|
762 decoded->op = M68K_NEG;
|
pavone@9
|
763 istream= m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
764 if (!istream) {
|
pavone@176
|
765 decoded->op = M68K_INVALID;
|
pavone@630
|
766 break;
|
pavone@176
|
767 }
|
pavone@9
|
768 }
|
pavone@9
|
769 decoded->extra.size = size;
|
pavone@9
|
770 break;
|
pavone@9
|
771 case 3:
|
pavone@9
|
772 //MOVE to SR or NOT
|
pavone@9
|
773 if (size == OPSIZE_INVALID) {
|
pavone@9
|
774 decoded->op = M68K_MOVE_SR;
|
pavone@9
|
775 size = OPSIZE_WORD;
|
pavone@9
|
776 istream= m68k_decode_op(istream, size, &(decoded->src));
|
pavone@176
|
777 if (!istream) {
|
pavone@176
|
778 decoded->op = M68K_INVALID;
|
pavone@630
|
779 break;
|
pavone@176
|
780 }
|
pavone@9
|
781 } else {
|
pavone@9
|
782 decoded->op = M68K_NOT;
|
pavone@9
|
783 istream= m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
784 if (!istream) {
|
pavone@176
|
785 decoded->op = M68K_INVALID;
|
pavone@630
|
786 break;
|
pavone@176
|
787 }
|
pavone@9
|
788 }
|
pavone@9
|
789 decoded->extra.size = size;
|
pavone@9
|
790 break;
|
pavone@9
|
791 case 4:
|
pavone@9
|
792 //EXT, EXTB, LINK.l, NBCD, SWAP, BKPT, PEA
|
pavone@9
|
793 switch((*istream >> 3) & 0x3F)
|
pavone@2
|
794 {
|
pavone@2
|
795 case 1:
|
pavone@9
|
796 #ifdef M68020
|
pavone@9
|
797 decoded->op = M68K_LINK;
|
pavone@9
|
798 decoded->extra.size = OPSIZE_LONG;
|
pavone@9
|
799 reg = *istream & 0x7;
|
pavone@9
|
800 immed = *(++istream) << 16;
|
pavone@9
|
801 immed |= *(++istream);
|
pavone@9
|
802 #endif
|
pavone@2
|
803 break;
|
pavone@9
|
804 case 8:
|
pavone@9
|
805 decoded->op = M68K_SWAP;
|
pavone@9
|
806 decoded->src.addr_mode = MODE_REG;
|
pavone@9
|
807 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@9
|
808 decoded->extra.size = OPSIZE_WORD;
|
pavone@2
|
809 break;
|
pavone@9
|
810 case 9:
|
pavone@9
|
811 #ifdef M68010
|
pavone@9
|
812 decoded->op = M68K_BKPT;
|
pavone@9
|
813 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@10
|
814 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@15
|
815 decoded->src.params.immed = *istream & 0x7;
|
pavone@9
|
816 #endif
|
pavone@2
|
817 break;
|
pavone@9
|
818 case 0x10:
|
pavone@9
|
819 decoded->op = M68K_EXT;
|
pavone@93
|
820 decoded->dst.addr_mode = MODE_REG;
|
pavone@93
|
821 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@9
|
822 decoded->extra.size = OPSIZE_WORD;
|
pavone@2
|
823 break;
|
pavone@9
|
824 case 0x18:
|
pavone@9
|
825 decoded->op = M68K_EXT;
|
pavone@93
|
826 decoded->dst.addr_mode = MODE_REG;
|
pavone@93
|
827 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@9
|
828 decoded->extra.size = OPSIZE_LONG;
|
pavone@9
|
829 break;
|
pavone@9
|
830 case 0x38:
|
pavone@9
|
831 #ifdef M68020
|
pavone@9
|
832 #endif
|
pavone@9
|
833 break;
|
pavone@9
|
834 default:
|
pavone@9
|
835 if (!(*istream & 0x1C0)) {
|
pavone@9
|
836 decoded->op = M68K_NBCD;
|
pavone@9
|
837 decoded->extra.size = OPSIZE_BYTE;
|
pavone@9
|
838 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
|
pavone@176
|
839 if (!istream) {
|
pavone@176
|
840 decoded->op = M68K_INVALID;
|
pavone@630
|
841 break;
|
pavone@176
|
842 }
|
pavone@13
|
843 } else if((*istream & 0x1C0) == 0x40) {
|
pavone@9
|
844 decoded->op = M68K_PEA;
|
pavone@9
|
845 decoded->extra.size = OPSIZE_LONG;
|
pavone@116
|
846 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
|
pavone@176
|
847 if (!istream) {
|
pavone@176
|
848 decoded->op = M68K_INVALID;
|
pavone@630
|
849 break;
|
pavone@176
|
850 }
|
pavone@9
|
851 }
|
pavone@9
|
852 }
|
pavone@9
|
853 break;
|
pavone@9
|
854 case 5:
|
pavone@9
|
855 //BGND, ILLEGAL, TAS, TST
|
pavone@9
|
856 optype = *istream & 0xFF;
|
pavone@9
|
857 if (optype == 0xFA) {
|
pavone@9
|
858 //BGND - CPU32 only
|
pavone@9
|
859 } else if (optype == 0xFC) {
|
pavone@9
|
860 decoded->op = M68K_ILLEGAL;
|
pavone@10
|
861 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@9
|
862 } else {
|
pavone@9
|
863 if (size == OPSIZE_INVALID) {
|
pavone@9
|
864 decoded->op = M68K_TAS;
|
pavone@835
|
865 decoded->extra.size = OPSIZE_BYTE;
|
pavone@835
|
866 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
|
pavone@835
|
867 if (!istream) {
|
pavone@835
|
868 decoded->op = M68K_INVALID;
|
pavone@835
|
869 break;
|
pavone@835
|
870 }
|
pavone@9
|
871 } else {
|
pavone@9
|
872 decoded->op = M68K_TST;
|
pavone@9
|
873 decoded->extra.size = size;
|
pavone@9
|
874 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
875 if (!istream) {
|
pavone@176
|
876 decoded->op = M68K_INVALID;
|
pavone@630
|
877 break;
|
pavone@176
|
878 }
|
pavone@9
|
879 }
|
pavone@9
|
880 }
|
pavone@518
|
881 break;
|
pavone@9
|
882 case 6:
|
pavone@9
|
883 //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL
|
pavone@9
|
884 #ifdef M68020
|
pavone@9
|
885 //TODO: Implement these for 68020+ support
|
pavone@9
|
886 #endif
|
pavone@9
|
887 break;
|
pavone@9
|
888 case 7:
|
pavone@9
|
889 //TRAP, LINK.w, UNLNK, MOVE USP, RESET, NOP, STOP, RTE, RTD, RTS, TRAPV, RTR, MOVEC, JSR, JMP
|
pavone@9
|
890 if (*istream & 0x80) {
|
pavone@9
|
891 //JSR, JMP
|
pavone@9
|
892 if (*istream & 0x40) {
|
pavone@9
|
893 decoded->op = M68K_JMP;
|
pavone@9
|
894 } else {
|
pavone@9
|
895 decoded->op = M68K_JSR;
|
pavone@9
|
896 }
|
pavone@10
|
897 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@10
|
898 istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src));
|
pavone@176
|
899 if (!istream) {
|
pavone@176
|
900 decoded->op = M68K_INVALID;
|
pavone@630
|
901 break;
|
pavone@176
|
902 }
|
pavone@9
|
903 } else {
|
pavone@9
|
904 //it would appear bit 6 needs to be set for it to be a valid instruction here
|
pavone@9
|
905 switch((*istream >> 3) & 0x7)
|
pavone@2
|
906 {
|
pavone@2
|
907 case 0:
|
pavone@2
|
908 case 1:
|
pavone@9
|
909 //TRAP
|
pavone@9
|
910 decoded->op = M68K_TRAP;
|
pavone@10
|
911 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@9
|
912 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
913 decoded->src.params.immed = *istream & 0xF;
|
pavone@2
|
914 break;
|
pavone@2
|
915 case 2:
|
pavone@9
|
916 //LINK.w
|
pavone@9
|
917 decoded->op = M68K_LINK;
|
pavone@2
|
918 decoded->extra.size = OPSIZE_WORD;
|
pavone@9
|
919 decoded->src.addr_mode = MODE_AREG;
|
pavone@9
|
920 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@9
|
921 decoded->dst.addr_mode = MODE_IMMEDIATE;
|
pavone@93
|
922 decoded->dst.params.immed = sign_extend16(*(++istream));
|
pavone@2
|
923 break;
|
pavone@2
|
924 case 3:
|
pavone@9
|
925 //UNLK
|
pavone@9
|
926 decoded->op = M68K_UNLK;
|
pavone@10
|
927 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@9
|
928 decoded->dst.addr_mode = MODE_AREG;
|
pavone@9
|
929 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@2
|
930 break;
|
pavone@2
|
931 case 4:
|
pavone@9
|
932 case 5:
|
pavone@9
|
933 //MOVE USP
|
pavone@9
|
934 decoded->op = M68K_MOVE_USP;
|
pavone@9
|
935 if (*istream & 0x8) {
|
pavone@9
|
936 decoded->dst.addr_mode = MODE_AREG;
|
pavone@9
|
937 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@9
|
938 } else {
|
pavone@9
|
939 decoded->src.addr_mode = MODE_AREG;
|
pavone@9
|
940 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@9
|
941 }
|
pavone@9
|
942 break;
|
pavone@9
|
943 case 6:
|
pavone@10
|
944 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@9
|
945 switch(*istream & 0x7)
|
pavone@9
|
946 {
|
pavone@9
|
947 case 0:
|
pavone@9
|
948 decoded->op = M68K_RESET;
|
pavone@9
|
949 break;
|
pavone@9
|
950 case 1:
|
pavone@9
|
951 decoded->op = M68K_NOP;
|
pavone@9
|
952 break;
|
pavone@9
|
953 case 2:
|
pavone@9
|
954 decoded->op = M68K_STOP;
|
pavone@9
|
955 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
956 decoded->src.params.immed =*(++istream);
|
pavone@9
|
957 break;
|
pavone@9
|
958 case 3:
|
pavone@9
|
959 decoded->op = M68K_RTE;
|
pavone@9
|
960 break;
|
pavone@9
|
961 case 4:
|
pavone@2
|
962 #ifdef M68010
|
pavone@9
|
963 decoded->op = M68K_RTD;
|
pavone@9
|
964 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
965 decoded->src.params.immed =*(++istream);
|
pavone@9
|
966 #endif
|
pavone@9
|
967 break;
|
pavone@9
|
968 case 5:
|
pavone@9
|
969 decoded->op = M68K_RTS;
|
pavone@9
|
970 break;
|
pavone@9
|
971 case 6:
|
pavone@9
|
972 decoded->op = M68K_TRAPV;
|
pavone@9
|
973 break;
|
pavone@9
|
974 case 7:
|
pavone@9
|
975 decoded->op = M68K_RTR;
|
pavone@9
|
976 break;
|
pavone@9
|
977 }
|
pavone@9
|
978 break;
|
pavone@9
|
979 case 7:
|
pavone@9
|
980 //MOVEC
|
pavone@9
|
981 #ifdef M68010
|
pavone@630
|
982 decoded->op = M68K_MOVEC;
|
pavone@630
|
983 immed = *(++istream);
|
pavone@630
|
984 reg = immed >> 12 & 0x7;
|
pavone@630
|
985 opmode = immed & 0x8000 ? MODE_AREG : MODE_REG;
|
pavone@641
|
986 immed &= 0xFFF;
|
pavone@630
|
987 if (immed & 0x800) {
|
pavone@630
|
988 if (immed > MAX_HIGH_CR) {
|
pavone@630
|
989 decoded->op = M68K_INVALID;
|
pavone@630
|
990 break;
|
pavone@630
|
991 } else {
|
pavone@630
|
992 immed = immed - 0x800 + CR_USP;
|
pavone@630
|
993 }
|
pavone@630
|
994 } else {
|
pavone@630
|
995 if (immed > MAX_LOW_CR) {
|
pavone@630
|
996 decoded->op = M68K_INVALID;
|
pavone@630
|
997 break;
|
pavone@630
|
998 }
|
pavone@630
|
999 }
|
pavone@630
|
1000 if (*start & 1) {
|
pavone@630
|
1001 decoded->src.addr_mode = opmode;
|
pavone@630
|
1002 decoded->src.params.regs.pri = reg;
|
pavone@630
|
1003 decoded->dst.params.immed = immed;
|
pavone@630
|
1004 } else {
|
pavone@630
|
1005 decoded->dst.addr_mode = opmode;
|
pavone@630
|
1006 decoded->dst.params.regs.pri = reg;
|
pavone@630
|
1007 decoded->src.params.immed = immed;
|
pavone@630
|
1008 }
|
pavone@2
|
1009 #endif
|
pavone@2
|
1010 break;
|
pavone@2
|
1011 }
|
pavone@2
|
1012 }
|
pavone@9
|
1013 break;
|
pavone@2
|
1014 }
|
pavone@2
|
1015 }
|
pavone@2
|
1016 }
|
pavone@2
|
1017 }
|
pavone@0
|
1018 break;
|
pavone@0
|
1019 case QUICK_ARITH_LOOP:
|
pavone@0
|
1020 size = (*istream >> 6) & 3;
|
pavone@0
|
1021 if (size == 0x3) {
|
pavone@0
|
1022 //DBcc, TRAPcc or Scc
|
pavone@2
|
1023 m68k_decode_cond(*istream, decoded);
|
pavone@111
|
1024 if (((*istream >> 3) & 0x7) == 1) {
|
pavone@0
|
1025 decoded->op = M68K_DBCC;
|
pavone@2
|
1026 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@0
|
1027 decoded->dst.addr_mode = MODE_REG;
|
pavone@2
|
1028 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@46
|
1029 decoded->src.params.immed = sign_extend16(*(++istream));
|
pavone@111
|
1030 } else if(((*istream >> 3) & 0x7) == 1 && (*istream & 0x7) > 1 && (*istream & 0x7) < 5) {
|
pavone@2
|
1031 #ifdef M68020
|
pavone@0
|
1032 decoded->op = M68K_TRAPCC;
|
pavone@2
|
1033 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@0
|
1034 //TODO: Figure out what to do with OPMODE and optional extention words
|
pavone@2
|
1035 #endif
|
pavone@111
|
1036 } else {
|
pavone@0
|
1037 decoded->op = M68K_SCC;
|
pavone@111
|
1038 decoded->extra.cond = (*istream >> 8) & 0xF;
|
pavone@2
|
1039 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
|
pavone@176
|
1040 if (!istream) {
|
pavone@176
|
1041 decoded->op = M68K_INVALID;
|
pavone@630
|
1042 break;
|
pavone@176
|
1043 }
|
pavone@0
|
1044 }
|
pavone@0
|
1045 } else {
|
pavone@0
|
1046 //ADDQ, SUBQ
|
pavone@0
|
1047 decoded->variant = VAR_QUICK;
|
pavone@0
|
1048 decoded->extra.size = size;
|
pavone@2
|
1049 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@91
|
1050 immed = m68k_reg_quick_field(*istream);
|
pavone@0
|
1051 if (!immed) {
|
pavone@0
|
1052 immed = 8;
|
pavone@0
|
1053 }
|
pavone@15
|
1054 decoded->src.params.immed = immed;
|
pavone@2
|
1055 if (*istream & 0x100) {
|
pavone@0
|
1056 decoded->op = M68K_SUB;
|
pavone@0
|
1057 } else {
|
pavone@0
|
1058 decoded->op = M68K_ADD;
|
pavone@0
|
1059 }
|
pavone@94
|
1060 istream = m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
1061 if (!istream) {
|
pavone@176
|
1062 decoded->op = M68K_INVALID;
|
pavone@630
|
1063 break;
|
pavone@176
|
1064 }
|
pavone@0
|
1065 }
|
pavone@0
|
1066 break;
|
pavone@2
|
1067 case BRANCH:
|
pavone@2
|
1068 m68k_decode_cond(*istream, decoded);
|
pavone@2
|
1069 decoded->op = decoded->extra.cond == COND_FALSE ? M68K_BSR : M68K_BCC;
|
pavone@2
|
1070 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@2
|
1071 immed = *istream & 0xFF;
|
pavone@2
|
1072 if (immed == 0) {
|
pavone@2
|
1073 decoded->variant = VAR_WORD;
|
pavone@2
|
1074 immed = *(++istream);
|
pavone@2
|
1075 immed = sign_extend16(immed);
|
pavone@154
|
1076 #ifdef M68020
|
pavone@2
|
1077 } else if (immed == 0xFF) {
|
pavone@2
|
1078 decoded->variant = VAR_LONG;
|
pavone@2
|
1079 immed = *(++istream) << 16;
|
pavone@2
|
1080 immed |= *(++istream);
|
pavone@154
|
1081 #endif
|
pavone@2
|
1082 } else {
|
pavone@2
|
1083 decoded->variant = VAR_BYTE;
|
pavone@2
|
1084 immed = sign_extend8(immed);
|
pavone@2
|
1085 }
|
pavone@15
|
1086 decoded->src.params.immed = immed;
|
pavone@2
|
1087 break;
|
pavone@2
|
1088 case MOVEQ:
|
pavone@208
|
1089 if (*istream & 0x100) {
|
pavone@208
|
1090 decoded->op = M68K_INVALID;
|
pavone@630
|
1091 break;
|
pavone@208
|
1092 }
|
pavone@2
|
1093 decoded->op = M68K_MOVE;
|
pavone@2
|
1094 decoded->variant = VAR_QUICK;
|
pavone@15
|
1095 decoded->extra.size = OPSIZE_LONG;
|
pavone@2
|
1096 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@15
|
1097 decoded->src.params.immed = sign_extend8(*istream & 0xFF);
|
pavone@2
|
1098 decoded->dst.addr_mode = MODE_REG;
|
pavone@18
|
1099 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1100 immed = *istream & 0xFF;
|
pavone@2
|
1101 break;
|
pavone@2
|
1102 case OR_DIV_SBCD:
|
pavone@11
|
1103 //for OR, if opmode bit 2 is 1, then src = Dn, dst = <ea>
|
pavone@11
|
1104 opmode = (*istream >> 6) & 0x7;
|
pavone@11
|
1105 size = opmode & 0x3;
|
pavone@11
|
1106 if (size == OPSIZE_INVALID || (opmode & 0x4 && !(*istream & 0x30))) {
|
pavone@11
|
1107 switch(opmode)
|
pavone@11
|
1108 {
|
pavone@11
|
1109 case 3:
|
pavone@11
|
1110 decoded->op = M68K_DIVU;
|
pavone@11
|
1111 decoded->extra.size = OPSIZE_WORD;
|
pavone@11
|
1112 decoded->dst.addr_mode = MODE_REG;
|
pavone@11
|
1113 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
|
pavone@11
|
1114 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
|
pavone@183
|
1115 if (!istream || decoded->src.addr_mode == MODE_AREG) {
|
pavone@176
|
1116 decoded->op = M68K_INVALID;
|
pavone@630
|
1117 break;
|
pavone@176
|
1118 }
|
pavone@11
|
1119 break;
|
pavone@11
|
1120 case 4:
|
pavone@11
|
1121 decoded->op = M68K_SBCD;
|
pavone@613
|
1122 decoded->extra.size = OPSIZE_BYTE;
|
pavone@11
|
1123 decoded->dst.addr_mode = decoded->src.addr_mode = *istream & 0x8 ? MODE_AREG_PREDEC : MODE_REG;
|
pavone@11
|
1124 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@11
|
1125 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
|
pavone@11
|
1126 break;
|
pavone@11
|
1127 case 5:
|
pavone@11
|
1128 #ifdef M68020
|
pavone@11
|
1129 #endif
|
pavone@11
|
1130 break;
|
pavone@11
|
1131 case 6:
|
pavone@11
|
1132 #ifdef M68020
|
pavone@11
|
1133 #endif
|
pavone@11
|
1134 break;
|
pavone@11
|
1135 case 7:
|
pavone@11
|
1136 decoded->op = M68K_DIVS;
|
pavone@11
|
1137 decoded->extra.size = OPSIZE_WORD;
|
pavone@11
|
1138 decoded->dst.addr_mode = MODE_REG;
|
pavone@11
|
1139 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
|
pavone@11
|
1140 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
|
pavone@183
|
1141 if (!istream || decoded->src.addr_mode == MODE_AREG) {
|
pavone@176
|
1142 decoded->op = M68K_INVALID;
|
pavone@630
|
1143 break;
|
pavone@176
|
1144 }
|
pavone@518
|
1145 break;
|
pavone@11
|
1146 }
|
pavone@11
|
1147 } else {
|
pavone@11
|
1148 decoded->op = M68K_OR;
|
pavone@11
|
1149 decoded->extra.size = size;
|
pavone@11
|
1150 if (opmode & 0x4) {
|
pavone@11
|
1151 decoded->src.addr_mode = MODE_REG;
|
pavone@11
|
1152 decoded->src.params.regs.pri = (*istream >> 9) & 0x7;
|
pavone@11
|
1153 istream = m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
1154 if (!istream) {
|
pavone@176
|
1155 decoded->op = M68K_INVALID;
|
pavone@630
|
1156 break;
|
pavone@176
|
1157 }
|
pavone@11
|
1158 } else {
|
pavone@11
|
1159 decoded->dst.addr_mode = MODE_REG;
|
pavone@11
|
1160 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
|
pavone@11
|
1161 istream = m68k_decode_op(istream, size, &(decoded->src));
|
pavone@176
|
1162 if (!istream) {
|
pavone@176
|
1163 decoded->op = M68K_INVALID;
|
pavone@630
|
1164 break;
|
pavone@176
|
1165 }
|
pavone@11
|
1166 }
|
pavone@11
|
1167 }
|
pavone@2
|
1168 break;
|
pavone@2
|
1169 case SUB_SUBX:
|
pavone@101
|
1170 size = (*istream >> 6) & 0x3;
|
pavone@2
|
1171 decoded->op = M68K_SUB;
|
pavone@2
|
1172 if (*istream & 0x100) {
|
pavone@2
|
1173 //<ea> destination, SUBA.l or SUBX
|
pavone@101
|
1174 if (*istream & 0x30 || size == OPSIZE_INVALID) {
|
pavone@2
|
1175 if (size == OPSIZE_INVALID) {
|
pavone@2
|
1176 //SUBA.l
|
pavone@2
|
1177 decoded->extra.size = OPSIZE_LONG;
|
pavone@2
|
1178 decoded->dst.addr_mode = MODE_AREG;
|
pavone@18
|
1179 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1180 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
|
pavone@176
|
1181 if (!istream) {
|
pavone@176
|
1182 decoded->op = M68K_INVALID;
|
pavone@630
|
1183 break;
|
pavone@176
|
1184 }
|
pavone@2
|
1185 } else {
|
pavone@2
|
1186 decoded->extra.size = size;
|
pavone@2
|
1187 decoded->src.addr_mode = MODE_REG;
|
pavone@18
|
1188 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1189 istream = m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
1190 if (!istream) {
|
pavone@176
|
1191 decoded->op = M68K_INVALID;
|
pavone@630
|
1192 break;
|
pavone@176
|
1193 }
|
pavone@2
|
1194 }
|
pavone@2
|
1195 } else {
|
pavone@2
|
1196 //SUBX
|
pavone@2
|
1197 decoded->op = M68K_SUBX;
|
pavone@2
|
1198 decoded->extra.size = size;
|
pavone@184
|
1199 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@184
|
1200 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@184
|
1201 if (*istream & 0x8) {
|
pavone@184
|
1202 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC;
|
pavone@184
|
1203 } else {
|
pavone@184
|
1204 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG;
|
pavone@176
|
1205 }
|
pavone@2
|
1206 }
|
pavone@2
|
1207 } else {
|
pavone@2
|
1208 if (size == OPSIZE_INVALID) {
|
pavone@2
|
1209 //SUBA.w
|
pavone@2
|
1210 decoded->extra.size = OPSIZE_WORD;
|
pavone@2
|
1211 decoded->dst.addr_mode = MODE_AREG;
|
pavone@2
|
1212 } else {
|
pavone@2
|
1213 decoded->extra.size = size;
|
pavone@2
|
1214 decoded->dst.addr_mode = MODE_REG;
|
pavone@2
|
1215 }
|
pavone@18
|
1216 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1217 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
1218 if (!istream) {
|
pavone@176
|
1219 decoded->op = M68K_INVALID;
|
pavone@630
|
1220 break;
|
pavone@176
|
1221 }
|
pavone@2
|
1222 }
|
pavone@2
|
1223 break;
|
pavone@2
|
1224 case RESERVED:
|
pavone@2
|
1225 break;
|
pavone@2
|
1226 case CMP_XOR:
|
pavone@120
|
1227 size = (*istream >> 6) & 0x3;
|
pavone@2
|
1228 decoded->op = M68K_CMP;
|
pavone@2
|
1229 if (*istream & 0x100) {
|
pavone@120
|
1230 //CMPM or CMPA.l or EOR
|
pavone@120
|
1231 if (size == OPSIZE_INVALID) {
|
pavone@120
|
1232 decoded->extra.size = OPSIZE_LONG;
|
pavone@120
|
1233 decoded->dst.addr_mode = MODE_AREG;
|
pavone@18
|
1234 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@136
|
1235 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
1236 if (!istream) {
|
pavone@176
|
1237 decoded->op = M68K_INVALID;
|
pavone@630
|
1238 break;
|
pavone@176
|
1239 }
|
pavone@2
|
1240 } else {
|
pavone@184
|
1241 reg = m68k_reg_quick_field(*istream);
|
pavone@120
|
1242 istream = m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
1243 if (!istream) {
|
pavone@176
|
1244 decoded->op = M68K_INVALID;
|
pavone@630
|
1245 break;
|
pavone@176
|
1246 }
|
pavone@181
|
1247 decoded->extra.size = size;
|
pavone@181
|
1248 if (decoded->dst.addr_mode == MODE_AREG) {
|
pavone@120
|
1249 //CMPM
|
pavone@120
|
1250 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC;
|
pavone@120
|
1251 decoded->src.params.regs.pri = decoded->dst.params.regs.pri;
|
pavone@184
|
1252 decoded->dst.params.regs.pri = reg;
|
pavone@120
|
1253 } else {
|
pavone@120
|
1254 //EOR
|
pavone@120
|
1255 decoded->op = M68K_EOR;
|
pavone@120
|
1256 decoded->src.addr_mode = MODE_REG;
|
pavone@184
|
1257 decoded->src.params.regs.pri = reg;
|
pavone@120
|
1258 }
|
pavone@2
|
1259 }
|
pavone@2
|
1260 } else {
|
pavone@120
|
1261 //CMP or CMPA.w
|
pavone@120
|
1262 if (size == OPSIZE_INVALID) {
|
pavone@120
|
1263 decoded->extra.size = OPSIZE_WORD;
|
pavone@120
|
1264 decoded->dst.addr_mode = MODE_AREG;
|
pavone@120
|
1265 } else {
|
pavone@120
|
1266 decoded->extra.size = size;
|
pavone@120
|
1267 decoded->dst.addr_mode = MODE_REG;
|
pavone@120
|
1268 }
|
pavone@18
|
1269 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@136
|
1270 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
1271 if (!istream) {
|
pavone@176
|
1272 decoded->op = M68K_INVALID;
|
pavone@630
|
1273 break;
|
pavone@176
|
1274 }
|
pavone@2
|
1275 }
|
pavone@2
|
1276 break;
|
pavone@2
|
1277 case AND_MUL_ABCD_EXG:
|
pavone@2
|
1278 //page 575 for summary
|
pavone@2
|
1279 //EXG opmodes:
|
pavone@2
|
1280 //01000 -data regs
|
pavone@2
|
1281 //01001 -addr regs
|
pavone@2
|
1282 //10001 -one of each
|
pavone@2
|
1283 //AND opmodes:
|
pavone@2
|
1284 //operand order bit + 2 size bits (00 - 10)
|
pavone@2
|
1285 //no address register direct addressing
|
pavone@2
|
1286 //data register direct not allowed when <ea> is the source (operand order bit of 1)
|
pavone@2
|
1287 if (*istream & 0x100) {
|
pavone@2
|
1288 if ((*istream & 0xC0) == 0xC0) {
|
pavone@2
|
1289 decoded->op = M68K_MULS;
|
pavone@2
|
1290 decoded->extra.size = OPSIZE_WORD;
|
pavone@3
|
1291 decoded->dst.addr_mode = MODE_REG;
|
pavone@18
|
1292 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1293 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
|
pavone@176
|
1294 if (!istream) {
|
pavone@176
|
1295 decoded->op = M68K_INVALID;
|
pavone@630
|
1296 break;
|
pavone@176
|
1297 }
|
pavone@2
|
1298 } else if(!(*istream & 0xF0)) {
|
pavone@2
|
1299 decoded->op = M68K_ABCD;
|
pavone@3
|
1300 decoded->extra.size = OPSIZE_BYTE;
|
pavone@3
|
1301 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@18
|
1302 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@3
|
1303 decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG;
|
pavone@2
|
1304 } else if(!(*istream & 0x30)) {
|
pavone@2
|
1305 decoded->op = M68K_EXG;
|
pavone@2
|
1306 decoded->extra.size = OPSIZE_LONG;
|
pavone@18
|
1307 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1308 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@2
|
1309 if (*istream & 0x8) {
|
pavone@2
|
1310 if (*istream & 0x80) {
|
pavone@2
|
1311 decoded->src.addr_mode = MODE_REG;
|
pavone@2
|
1312 decoded->dst.addr_mode = MODE_AREG;
|
pavone@2
|
1313 } else {
|
pavone@2
|
1314 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG;
|
pavone@2
|
1315 }
|
pavone@2
|
1316 } else {
|
pavone@2
|
1317 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG;
|
pavone@2
|
1318 }
|
pavone@2
|
1319 } else {
|
pavone@2
|
1320 decoded->op = M68K_AND;
|
pavone@90
|
1321 decoded->extra.size = (*istream >> 6) & 0x3;
|
pavone@60
|
1322 decoded->src.addr_mode = MODE_REG;
|
pavone@60
|
1323 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@60
|
1324 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
|
pavone@176
|
1325 if (!istream) {
|
pavone@176
|
1326 decoded->op = M68K_INVALID;
|
pavone@630
|
1327 break;
|
pavone@176
|
1328 }
|
pavone@2
|
1329 }
|
pavone@2
|
1330 } else {
|
pavone@2
|
1331 if ((*istream & 0xC0) == 0xC0) {
|
pavone@2
|
1332 decoded->op = M68K_MULU;
|
pavone@2
|
1333 decoded->extra.size = OPSIZE_WORD;
|
pavone@3
|
1334 decoded->dst.addr_mode = MODE_REG;
|
pavone@18
|
1335 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1336 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
|
pavone@176
|
1337 if (!istream) {
|
pavone@176
|
1338 decoded->op = M68K_INVALID;
|
pavone@630
|
1339 break;
|
pavone@176
|
1340 }
|
pavone@2
|
1341 } else {
|
pavone@2
|
1342 decoded->op = M68K_AND;
|
pavone@90
|
1343 decoded->extra.size = (*istream >> 6) & 0x3;
|
pavone@60
|
1344 decoded->dst.addr_mode = MODE_REG;
|
pavone@60
|
1345 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@60
|
1346 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
1347 if (!istream) {
|
pavone@176
|
1348 decoded->op = M68K_INVALID;
|
pavone@630
|
1349 break;
|
pavone@176
|
1350 }
|
pavone@2
|
1351 }
|
pavone@2
|
1352 }
|
pavone@2
|
1353 break;
|
pavone@2
|
1354 case ADD_ADDX:
|
pavone@101
|
1355 size = (*istream >> 6) & 0x3;
|
pavone@2
|
1356 decoded->op = M68K_ADD;
|
pavone@2
|
1357 if (*istream & 0x100) {
|
pavone@2
|
1358 //<ea> destination, ADDA.l or ADDX
|
pavone@101
|
1359 if (*istream & 0x30 || size == OPSIZE_INVALID) {
|
pavone@2
|
1360 if (size == OPSIZE_INVALID) {
|
pavone@2
|
1361 //ADDA.l
|
pavone@2
|
1362 decoded->extra.size = OPSIZE_LONG;
|
pavone@2
|
1363 decoded->dst.addr_mode = MODE_AREG;
|
pavone@18
|
1364 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1365 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
|
pavone@176
|
1366 if (!istream) {
|
pavone@176
|
1367 decoded->op = M68K_INVALID;
|
pavone@630
|
1368 break;
|
pavone@176
|
1369 }
|
pavone@2
|
1370 } else {
|
pavone@2
|
1371 decoded->extra.size = size;
|
pavone@2
|
1372 decoded->src.addr_mode = MODE_REG;
|
pavone@18
|
1373 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1374 istream = m68k_decode_op(istream, size, &(decoded->dst));
|
pavone@176
|
1375 if (!istream) {
|
pavone@176
|
1376 decoded->op = M68K_INVALID;
|
pavone@630
|
1377 break;
|
pavone@176
|
1378 }
|
pavone@2
|
1379 }
|
pavone@2
|
1380 } else {
|
pavone@2
|
1381 //ADDX
|
pavone@2
|
1382 decoded->op = M68K_ADDX;
|
pavone@2
|
1383 decoded->extra.size = size;
|
pavone@184
|
1384 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@184
|
1385 decoded->src.params.regs.pri = *istream & 0x7;
|
pavone@184
|
1386 if (*istream & 0x8) {
|
pavone@184
|
1387 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC;
|
pavone@184
|
1388 } else {
|
pavone@184
|
1389 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG;
|
pavone@176
|
1390 }
|
pavone@2
|
1391 }
|
pavone@2
|
1392 } else {
|
pavone@2
|
1393 if (size == OPSIZE_INVALID) {
|
pavone@2
|
1394 //ADDA.w
|
pavone@2
|
1395 decoded->extra.size = OPSIZE_WORD;
|
pavone@2
|
1396 decoded->dst.addr_mode = MODE_AREG;
|
pavone@2
|
1397 } else {
|
pavone@2
|
1398 decoded->extra.size = size;
|
pavone@2
|
1399 decoded->dst.addr_mode = MODE_REG;
|
pavone@2
|
1400 }
|
pavone@18
|
1401 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
|
pavone@2
|
1402 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
|
pavone@176
|
1403 if (!istream) {
|
pavone@176
|
1404 decoded->op = M68K_INVALID;
|
pavone@630
|
1405 break;
|
pavone@176
|
1406 }
|
pavone@2
|
1407 }
|
pavone@2
|
1408 break;
|
pavone@2
|
1409 case SHIFT_ROTATE:
|
pavone@9
|
1410 if ((*istream & 0x8C0) == 0xC0) {
|
pavone@9
|
1411 switch((*istream >> 8) & 0x7)
|
pavone@9
|
1412 {
|
pavone@9
|
1413 case 0:
|
pavone@9
|
1414 decoded->op = M68K_ASR;
|
pavone@9
|
1415 break;
|
pavone@9
|
1416 case 1:
|
pavone@9
|
1417 decoded->op = M68K_ASL;
|
pavone@9
|
1418 break;
|
pavone@9
|
1419 case 2:
|
pavone@9
|
1420 decoded->op = M68K_LSR;
|
pavone@9
|
1421 break;
|
pavone@9
|
1422 case 3:
|
pavone@9
|
1423 decoded->op = M68K_LSL;
|
pavone@9
|
1424 break;
|
pavone@9
|
1425 case 4:
|
pavone@9
|
1426 decoded->op = M68K_ROXR;
|
pavone@9
|
1427 break;
|
pavone@9
|
1428 case 5:
|
pavone@9
|
1429 decoded->op = M68K_ROXL;
|
pavone@9
|
1430 break;
|
pavone@9
|
1431 case 6:
|
pavone@9
|
1432 decoded->op = M68K_ROR;
|
pavone@9
|
1433 break;
|
pavone@9
|
1434 case 7:
|
pavone@9
|
1435 decoded->op = M68K_ROL;
|
pavone@9
|
1436 break;
|
pavone@9
|
1437 }
|
pavone@9
|
1438 decoded->extra.size = OPSIZE_WORD;
|
pavone@9
|
1439 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst));
|
pavone@176
|
1440 if (!istream) {
|
pavone@176
|
1441 decoded->op = M68K_INVALID;
|
pavone@630
|
1442 break;
|
pavone@176
|
1443 }
|
pavone@9
|
1444 } else if((*istream & 0xC0) != 0xC0) {
|
pavone@9
|
1445 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1))
|
pavone@9
|
1446 {
|
pavone@9
|
1447 case 0:
|
pavone@9
|
1448 decoded->op = M68K_ASR;
|
pavone@9
|
1449 break;
|
pavone@9
|
1450 case 1:
|
pavone@9
|
1451 decoded->op = M68K_ASL;
|
pavone@9
|
1452 break;
|
pavone@9
|
1453 case 2:
|
pavone@9
|
1454 decoded->op = M68K_LSR;
|
pavone@9
|
1455 break;
|
pavone@9
|
1456 case 3:
|
pavone@9
|
1457 decoded->op = M68K_LSL;
|
pavone@9
|
1458 break;
|
pavone@9
|
1459 case 4:
|
pavone@9
|
1460 decoded->op = M68K_ROXR;
|
pavone@9
|
1461 break;
|
pavone@9
|
1462 case 5:
|
pavone@9
|
1463 decoded->op = M68K_ROXL;
|
pavone@9
|
1464 break;
|
pavone@9
|
1465 case 6:
|
pavone@9
|
1466 decoded->op = M68K_ROR;
|
pavone@9
|
1467 break;
|
pavone@9
|
1468 case 7:
|
pavone@9
|
1469 decoded->op = M68K_ROL;
|
pavone@9
|
1470 break;
|
pavone@9
|
1471 }
|
pavone@9
|
1472 decoded->extra.size = (*istream >> 6) & 0x3;
|
pavone@9
|
1473 immed = (*istream >> 9) & 0x7;
|
pavone@51
|
1474 if (*istream & 0x20) {
|
pavone@9
|
1475 decoded->src.addr_mode = MODE_REG;
|
pavone@9
|
1476 decoded->src.params.regs.pri = immed;
|
pavone@50
|
1477 } else {
|
pavone@50
|
1478 decoded->src.addr_mode = MODE_IMMEDIATE;
|
pavone@50
|
1479 if (!immed) {
|
pavone@50
|
1480 immed = 8;
|
pavone@50
|
1481 }
|
pavone@50
|
1482 decoded->src.params.immed = immed;
|
pavone@9
|
1483 }
|
pavone@9
|
1484 decoded->dst.addr_mode = MODE_REG;
|
pavone@9
|
1485 decoded->dst.params.regs.pri = *istream & 0x7;
|
pavone@518
|
1486
|
pavone@9
|
1487 } else {
|
pavone@9
|
1488 #ifdef M68020
|
pavone@9
|
1489 //TODO: Implement bitfield instructions for M68020+ support
|
pavone@636
|
1490 switch (*istream >> 8 & 7)
|
pavone@636
|
1491 {
|
pavone@636
|
1492 case 0:
|
pavone@636
|
1493 decoded->op = M68K_BFTST; //<ea>
|
pavone@636
|
1494 break;
|
pavone@636
|
1495 case 1:
|
pavone@636
|
1496 decoded->op = M68K_BFEXTU; //<ea>, Dn
|
pavone@636
|
1497 break;
|
pavone@636
|
1498 case 2:
|
pavone@636
|
1499 decoded->op = M68K_BFCHG; //<ea>
|
pavone@636
|
1500 break;
|
pavone@636
|
1501 case 3:
|
pavone@636
|
1502 decoded->op = M68K_BFEXTS; //<ea>, Dn
|
pavone@636
|
1503 break;
|
pavone@636
|
1504 case 4:
|
pavone@636
|
1505 decoded->op = M68K_BFCLR; //<ea>
|
pavone@636
|
1506 break;
|
pavone@636
|
1507 case 5:
|
pavone@636
|
1508 decoded->op = M68K_BFFFO; //<ea>, Dn
|
pavone@636
|
1509 break;
|
pavone@636
|
1510 case 6:
|
pavone@636
|
1511 decoded->op = M68K_BFSET; //<ea>
|
pavone@636
|
1512 break;
|
pavone@636
|
1513 case 7:
|
pavone@636
|
1514 decoded->op = M68K_BFINS; //Dn, <ea>
|
pavone@636
|
1515 break;
|
pavone@636
|
1516 }
|
pavone@636
|
1517 opmode = *istream >> 3 & 0x7;
|
pavone@636
|
1518 reg = *istream & 0x7;
|
pavone@636
|
1519 m68k_op_info *ea, *other;
|
pavone@636
|
1520 if (decoded->op == M68K_BFEXTU || decoded->op == M68K_BFEXTS || decoded->op == M68K_BFFFO)
|
pavone@636
|
1521 {
|
pavone@636
|
1522 ea = &(decoded->src);
|
pavone@636
|
1523 other = &(decoded->dst);
|
pavone@636
|
1524 } else {
|
pavone@636
|
1525 ea = &(decoded->dst);
|
pavone@636
|
1526 other = &(decoded->dst);
|
pavone@636
|
1527 }
|
pavone@636
|
1528 if (*istream & 0x100)
|
pavone@636
|
1529 {
|
pavone@636
|
1530 immed = *(istream++);
|
pavone@636
|
1531 other->addr_mode = MODE_REG;
|
pavone@636
|
1532 other->params.regs.pri = immed >> 12 & 0x7;
|
pavone@636
|
1533 } else {
|
pavone@636
|
1534 immed = *(istream++);
|
pavone@636
|
1535 }
|
pavone@636
|
1536 decoded->extra.size = OPSIZE_UNSIZED;
|
pavone@636
|
1537 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, ea);
|
pavone@636
|
1538 ea->addr_mode |= M68K_FLAG_BITFIELD;
|
pavone@636
|
1539 ea->bitfield = immed & 0xFFF;
|
pavone@9
|
1540 #endif
|
pavone@9
|
1541 }
|
pavone@2
|
1542 break;
|
pavone@2
|
1543 case COPROC:
|
pavone@2
|
1544 //TODO: Implement me
|
pavone@2
|
1545 break;
|
pavone@2
|
1546 }
|
pavone@630
|
1547 if (decoded->op == M68K_INVALID) {
|
pavone@630
|
1548 decoded->src.params.immed = *start;
|
pavone@981
|
1549 decoded->bytes = 2;
|
pavone@630
|
1550 return start + 1;
|
pavone@630
|
1551 }
|
pavone@981
|
1552 decoded->bytes = 2 * (istream + 1 - start);
|
pavone@2
|
1553 return istream+1;
|
pavone@2
|
1554 }
|
pavone@2
|
1555
|
pavone@518
|
1556 uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs)
|
pavone@518
|
1557 {
|
pavone@518
|
1558 if(inst->op == M68K_BCC || inst->op == M68K_BSR || inst->op == M68K_DBCC) {
|
pavone@518
|
1559 return inst->address + 2 + inst->src.params.immed;
|
pavone@518
|
1560 } else if(inst->op == M68K_JMP || inst->op == M68K_JSR) {
|
pavone@518
|
1561 uint32_t ret = 0;
|
pavone@518
|
1562 switch(inst->src.addr_mode)
|
pavone@518
|
1563 {
|
pavone@518
|
1564 case MODE_AREG_INDIRECT:
|
pavone@518
|
1565 ret = aregs[inst->src.params.regs.pri];
|
pavone@518
|
1566 break;
|
pavone@518
|
1567 case MODE_AREG_INDEX_DISP8: {
|
pavone@518
|
1568 uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
|
pavone@518
|
1569 ret = aregs[inst->src.params.regs.pri];
|
pavone@518
|
1570 uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
|
pavone@518
|
1571 if (inst->src.params.regs.sec & 1) {
|
pavone@518
|
1572 //32-bit index register
|
pavone@518
|
1573 ret += regfile[sec_reg];
|
pavone@518
|
1574 } else {
|
pavone@518
|
1575 //16-bit index register
|
pavone@518
|
1576 if (regfile[sec_reg] & 0x8000) {
|
pavone@518
|
1577 ret += (0xFFFF0000 | regfile[sec_reg]);
|
pavone@518
|
1578 } else {
|
pavone@518
|
1579 ret += regfile[sec_reg];
|
pavone@518
|
1580 }
|
pavone@518
|
1581 }
|
pavone@518
|
1582 ret += inst->src.params.regs.displacement;
|
pavone@518
|
1583 break;
|
pavone@518
|
1584 }
|
pavone@518
|
1585 case MODE_PC_DISPLACE:
|
pavone@518
|
1586 ret = inst->src.params.regs.displacement + inst->address + 2;
|
pavone@518
|
1587 break;
|
pavone@518
|
1588 case MODE_PC_INDEX_DISP8: {
|
pavone@518
|
1589 uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
|
pavone@518
|
1590 ret = inst->address + 2;
|
pavone@518
|
1591 uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
|
pavone@518
|
1592 if (inst->src.params.regs.sec & 1) {
|
pavone@518
|
1593 //32-bit index register
|
pavone@518
|
1594 ret += regfile[sec_reg];
|
pavone@518
|
1595 } else {
|
pavone@518
|
1596 //16-bit index register
|
pavone@518
|
1597 if (regfile[sec_reg] & 0x8000) {
|
pavone@518
|
1598 ret += (0xFFFF0000 | regfile[sec_reg]);
|
pavone@518
|
1599 } else {
|
pavone@518
|
1600 ret += regfile[sec_reg];
|
pavone@518
|
1601 }
|
pavone@518
|
1602 }
|
pavone@518
|
1603 ret += inst->src.params.regs.displacement;
|
pavone@518
|
1604 break;
|
pavone@518
|
1605 }
|
pavone@518
|
1606 case MODE_ABSOLUTE:
|
pavone@518
|
1607 case MODE_ABSOLUTE_SHORT:
|
pavone@518
|
1608 ret = inst->src.params.immed;
|
pavone@518
|
1609 break;
|
pavone@518
|
1610 }
|
pavone@518
|
1611 return ret;
|
pavone@518
|
1612 }
|
pavone@518
|
1613 return 0;
|
pavone@518
|
1614 }
|
pavone@518
|
1615
|
pavone@518
|
1616 uint8_t m68k_is_branch(m68kinst * inst)
|
pavone@518
|
1617 {
|
pavone@518
|
1618 return (inst->op == M68K_BCC && inst->extra.cond != COND_FALSE)
|
pavone@518
|
1619 || (inst->op == M68K_DBCC && inst->extra.cond != COND_TRUE)
|
pavone@518
|
1620 || inst->op == M68K_BSR || inst->op == M68K_JMP || inst->op == M68K_JSR;
|
pavone@518
|
1621 }
|
pavone@518
|
1622
|
pavone@518
|
1623 uint8_t m68k_is_noncall_branch(m68kinst * inst)
|
pavone@518
|
1624 {
|
pavone@518
|
1625 return m68k_is_branch(inst) && inst->op != M68K_BSR && inst->op != M68K_JSR;
|
pavone@518
|
1626 }
|
pavone@518
|
1627
|
pavone@518
|
1628
|
pavone@2
|
1629 char * mnemonics[] = {
|
pavone@2
|
1630 "abcd",
|
pavone@2
|
1631 "add",
|
pavone@2
|
1632 "addx",
|
pavone@2
|
1633 "and",
|
pavone@13
|
1634 "andi",//ccr
|
pavone@13
|
1635 "andi",//sr
|
pavone@2
|
1636 "asl",
|
pavone@2
|
1637 "asr",
|
pavone@2
|
1638 "bcc",
|
pavone@2
|
1639 "bchg",
|
pavone@2
|
1640 "bclr",
|
pavone@2
|
1641 "bset",
|
pavone@2
|
1642 "bsr",
|
pavone@2
|
1643 "btst",
|
pavone@2
|
1644 "chk",
|
pavone@2
|
1645 "clr",
|
pavone@2
|
1646 "cmp",
|
pavone@2
|
1647 "dbcc",
|
pavone@2
|
1648 "divs",
|
pavone@2
|
1649 "divu",
|
pavone@2
|
1650 "eor",
|
pavone@13
|
1651 "eori",//ccr
|
pavone@13
|
1652 "eori",//sr
|
pavone@2
|
1653 "exg",
|
pavone@2
|
1654 "ext",
|
pavone@2
|
1655 "illegal",
|
pavone@2
|
1656 "jmp",
|
pavone@2
|
1657 "jsr",
|
pavone@2
|
1658 "lea",
|
pavone@2
|
1659 "link",
|
pavone@2
|
1660 "lsl",
|
pavone@2
|
1661 "lsr",
|
pavone@2
|
1662 "move",
|
pavone@13
|
1663 "move",//ccr
|
pavone@13
|
1664 "move",//from_sr
|
pavone@13
|
1665 "move",//sr
|
pavone@50
|
1666 "move",//usp
|
pavone@2
|
1667 "movem",
|
pavone@2
|
1668 "movep",
|
pavone@2
|
1669 "muls",
|
pavone@2
|
1670 "mulu",
|
pavone@2
|
1671 "nbcd",
|
pavone@2
|
1672 "neg",
|
pavone@2
|
1673 "negx",
|
pavone@2
|
1674 "nop",
|
pavone@2
|
1675 "not",
|
pavone@2
|
1676 "or",
|
pavone@13
|
1677 "ori",//ccr
|
pavone@13
|
1678 "ori",//sr
|
pavone@2
|
1679 "pea",
|
pavone@2
|
1680 "reset",
|
pavone@2
|
1681 "rol",
|
pavone@2
|
1682 "ror",
|
pavone@2
|
1683 "roxl",
|
pavone@2
|
1684 "roxr",
|
pavone@2
|
1685 "rte",
|
pavone@2
|
1686 "rtr",
|
pavone@2
|
1687 "rts",
|
pavone@2
|
1688 "sbcd",
|
pavone@2
|
1689 "scc",
|
pavone@2
|
1690 "stop",
|
pavone@2
|
1691 "sub",
|
pavone@2
|
1692 "subx",
|
pavone@2
|
1693 "swap",
|
pavone@2
|
1694 "tas",
|
pavone@2
|
1695 "trap",
|
pavone@2
|
1696 "trapv",
|
pavone@2
|
1697 "tst",
|
pavone@12
|
1698 "unlk",
|
pavone@630
|
1699 "invalid",
|
pavone@630
|
1700 #ifdef M68010
|
pavone@630
|
1701 "bkpt",
|
pavone@630
|
1702 "move", //from ccr
|
pavone@630
|
1703 "movec",
|
pavone@630
|
1704 "moves",
|
pavone@636
|
1705 "rtd",
|
pavone@630
|
1706 #endif
|
pavone@630
|
1707 #ifdef M68020
|
pavone@630
|
1708 "bfchg",
|
pavone@630
|
1709 "bfclr",
|
pavone@630
|
1710 "bfexts",
|
pavone@630
|
1711 "bfextu",
|
pavone@630
|
1712 "bfffo",
|
pavone@630
|
1713 "bfins",
|
pavone@630
|
1714 "bfset",
|
pavone@630
|
1715 "bftst",
|
pavone@630
|
1716 "callm",
|
pavone@630
|
1717 "cas",
|
pavone@630
|
1718 "cas2",
|
pavone@630
|
1719 "chk2",
|
pavone@630
|
1720 "cmp2",
|
pavone@630
|
1721 "cpbcc",
|
pavone@630
|
1722 "cpdbcc",
|
pavone@630
|
1723 "cpgen",
|
pavone@630
|
1724 "cprestore",
|
pavone@630
|
1725 "cpsave",
|
pavone@630
|
1726 "cpscc",
|
pavone@630
|
1727 "cptrapcc",
|
pavone@630
|
1728 "divsl",
|
pavone@630
|
1729 "divul",
|
pavone@630
|
1730 "extb",
|
pavone@630
|
1731 "pack",
|
pavone@630
|
1732 "rtm",
|
pavone@630
|
1733 "trapcc",
|
pavone@630
|
1734 "unpk"
|
pavone@630
|
1735 #endif
|
pavone@2
|
1736 };
|
pavone@2
|
1737
|
pavone@2
|
1738 char * cond_mnem[] = {
|
pavone@2
|
1739 "ra",
|
pavone@2
|
1740 "f",
|
pavone@2
|
1741 "hi",
|
pavone@2
|
1742 "ls",
|
pavone@2
|
1743 "cc",
|
pavone@2
|
1744 "cs",
|
pavone@2
|
1745 "ne",
|
pavone@2
|
1746 "eq",
|
pavone@2
|
1747 "vc",
|
pavone@2
|
1748 "vs",
|
pavone@2
|
1749 "pl",
|
pavone@2
|
1750 "mi",
|
pavone@2
|
1751 "ge",
|
pavone@2
|
1752 "lt",
|
pavone@2
|
1753 "gt",
|
pavone@2
|
1754 "le"
|
pavone@2
|
1755 };
|
pavone@630
|
1756 #ifdef M68010
|
pavone@630
|
1757 char * cr_mnem[] = {
|
pavone@630
|
1758 "SFC",
|
pavone@630
|
1759 "DFC",
|
pavone@630
|
1760 #ifdef M68020
|
pavone@630
|
1761 "CACR",
|
pavone@630
|
1762 #endif
|
pavone@630
|
1763 "USP",
|
pavone@630
|
1764 "VBR",
|
pavone@630
|
1765 #ifdef M68020
|
pavone@630
|
1766 "CAAR",
|
pavone@630
|
1767 "MSP",
|
pavone@630
|
1768 "ISP"
|
pavone@630
|
1769 #endif
|
pavone@630
|
1770 };
|
pavone@630
|
1771 #endif
|
pavone@2
|
1772
|
pavone@634
|
1773 int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data)
|
pavone@2
|
1774 {
|
pavone@2
|
1775 char * c = need_comma ? "," : "";
|
pavone@636
|
1776 int ret = 0;
|
pavone@636
|
1777 #ifdef M68020
|
pavone@636
|
1778 uint8_t addr_mode = decoded->addr_mode & (~M68K_FLAG_BITFIELD);
|
pavone@636
|
1779 #else
|
pavone@636
|
1780 uint8_t addr_mode = decoded->addr_mode;
|
pavone@636
|
1781 #endif
|
pavone@636
|
1782 switch(addr_mode)
|
pavone@2
|
1783 {
|
pavone@2
|
1784 case MODE_REG:
|
pavone@636
|
1785 ret = sprintf(dst, "%s d%d", c, decoded->params.regs.pri);
|
pavone@636
|
1786 break;
|
pavone@2
|
1787 case MODE_AREG:
|
pavone@636
|
1788 ret = sprintf(dst, "%s a%d", c, decoded->params.regs.pri);
|
pavone@636
|
1789 break;
|
pavone@2
|
1790 case MODE_AREG_INDIRECT:
|
pavone@636
|
1791 ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
|
pavone@636
|
1792 break;
|
pavone@2
|
1793 case MODE_AREG_POSTINC:
|
pavone@636
|
1794 ret = sprintf(dst, "%s (a%d)+", c, decoded->params.regs.pri);
|
pavone@636
|
1795 break;
|
pavone@2
|
1796 case MODE_AREG_PREDEC:
|
pavone@636
|
1797 ret = sprintf(dst, "%s -(a%d)", c, decoded->params.regs.pri);
|
pavone@636
|
1798 break;
|
pavone@13
|
1799 case MODE_AREG_DISPLACE:
|
pavone@636
|
1800 ret = sprintf(dst, "%s (%d, a%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri);
|
pavone@636
|
1801 break;
|
pavone@79
|
1802 case MODE_AREG_INDEX_DISP8:
|
pavone@638
|
1803 #ifdef M68020
|
pavone@638
|
1804 if (decoded->params.regs.scale)
|
pavone@638
|
1805 {
|
pavone@638
|
1806 ret = sprintf(dst, "%s (%d, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1807 } else {
|
pavone@638
|
1808 #endif
|
pavone@638
|
1809 ret = sprintf(dst, "%s (%d, a%d, %c%d.%c)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
|
pavone@638
|
1810 #ifdef M68020
|
pavone@638
|
1811 }
|
pavone@638
|
1812 #endif
|
pavone@636
|
1813 break;
|
pavone@638
|
1814 #ifdef M68020
|
pavone@638
|
1815 case MODE_AREG_INDEX_BASE_DISP:
|
pavone@638
|
1816 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
1817 {
|
pavone@638
|
1818 ret = sprintf(dst, "%s (%d.%c, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
1819 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri,
|
pavone@638
|
1820 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1821 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1822 } else {
|
pavone@638
|
1823 ret = sprintf(dst, "%s (a%d, %c%d.%c*%d)", c, decoded->params.regs.pri,
|
pavone@638
|
1824 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1825 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1826 }
|
pavone@638
|
1827 break;
|
pavone@638
|
1828 case MODE_AREG_PREINDEX:
|
pavone@638
|
1829 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
1830 {
|
pavone@638
|
1831 case 0x11:
|
pavone@638
|
1832 //no base displacement or outer displacement
|
pavone@638
|
1833 ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d])", c, decoded->params.regs.pri,
|
pavone@638
|
1834 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1835 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1836 break;
|
pavone@638
|
1837 case 0x12:
|
pavone@638
|
1838 case 0x13:
|
pavone@638
|
1839 //base displacement only
|
pavone@638
|
1840 ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d])", c, decoded->params.regs.displacement,
|
pavone@638
|
1841 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
|
pavone@638
|
1842 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1843 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1844 break;
|
pavone@638
|
1845 case 0x21:
|
pavone@638
|
1846 case 0x31:
|
pavone@638
|
1847 //outer displacement only
|
pavone@638
|
1848 ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.pri,
|
pavone@638
|
1849 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1850 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
1851 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1852 break;
|
pavone@638
|
1853 case 0x22:
|
pavone@638
|
1854 case 0x23:
|
pavone@638
|
1855 case 0x32:
|
pavone@638
|
1856 case 0x33:
|
pavone@638
|
1857 //both outer and inner displacement
|
pavone@638
|
1858 ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
1859 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
|
pavone@638
|
1860 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1861 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
1862 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1863 break;
|
pavone@638
|
1864 }
|
pavone@638
|
1865 break;
|
pavone@638
|
1866 case MODE_AREG_POSTINDEX:
|
pavone@638
|
1867 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
1868 {
|
pavone@638
|
1869 case 0x11:
|
pavone@638
|
1870 //no base displacement or outer displacement
|
pavone@638
|
1871 ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d)", c, decoded->params.regs.pri,
|
pavone@638
|
1872 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1873 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1874 break;
|
pavone@638
|
1875 case 0x12:
|
pavone@638
|
1876 case 0x13:
|
pavone@638
|
1877 //base displacement only
|
pavone@638
|
1878 ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
1879 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
|
pavone@638
|
1880 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1881 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1882 break;
|
pavone@638
|
1883 case 0x21:
|
pavone@638
|
1884 case 0x31:
|
pavone@638
|
1885 //outer displacement only
|
pavone@638
|
1886 ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.pri,
|
pavone@638
|
1887 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1888 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
1889 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1890 break;
|
pavone@638
|
1891 case 0x22:
|
pavone@638
|
1892 case 0x23:
|
pavone@638
|
1893 case 0x32:
|
pavone@638
|
1894 case 0x33:
|
pavone@638
|
1895 //both outer and inner displacement
|
pavone@638
|
1896 ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
1897 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
|
pavone@638
|
1898 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1899 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
1900 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1901 break;
|
pavone@638
|
1902 }
|
pavone@638
|
1903 break;
|
pavone@638
|
1904 case MODE_AREG_MEM_INDIRECT:
|
pavone@638
|
1905 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
1906 {
|
pavone@638
|
1907 case 0x11:
|
pavone@638
|
1908 //no base displacement or outer displacement
|
pavone@638
|
1909 ret = sprintf(dst, "%s ([a%d])", c, decoded->params.regs.pri);
|
pavone@638
|
1910 break;
|
pavone@638
|
1911 case 0x12:
|
pavone@638
|
1912 case 0x13:
|
pavone@638
|
1913 //base displacement only
|
pavone@638
|
1914 ret = sprintf(dst, "%s ([%d.%c, a%d])", c, decoded->params.regs.displacement,
|
pavone@638
|
1915 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri);
|
pavone@638
|
1916 break;
|
pavone@638
|
1917 case 0x21:
|
pavone@638
|
1918 case 0x31:
|
pavone@638
|
1919 //outer displacement only
|
pavone@638
|
1920 ret = sprintf(dst, "%s ([a%d], %d.%c)", c, decoded->params.regs.pri, decoded->params.regs.outer_disp,
|
pavone@638
|
1921 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1922 break;
|
pavone@638
|
1923 case 0x22:
|
pavone@638
|
1924 case 0x23:
|
pavone@638
|
1925 case 0x32:
|
pavone@638
|
1926 case 0x33:
|
pavone@638
|
1927 //both outer and inner displacement
|
pavone@638
|
1928 ret = sprintf(dst, "%s ([%d.%c, a%d], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
1929 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
|
pavone@638
|
1930 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1931 break;
|
pavone@638
|
1932 }
|
pavone@638
|
1933 break;
|
pavone@638
|
1934 case MODE_AREG_BASE_DISP:
|
pavone@638
|
1935 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
1936 {
|
pavone@638
|
1937 ret = sprintf(dst, "%s (%d.%c, a%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
1938 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri);
|
pavone@638
|
1939 } else {
|
pavone@638
|
1940 //this is a lossy representation of the encoded instruction
|
pavone@638
|
1941 //not sure if there's a better way to print it though
|
pavone@638
|
1942 ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
|
pavone@638
|
1943 }
|
pavone@638
|
1944 break;
|
pavone@638
|
1945 case MODE_INDEX_BASE_DISP:
|
pavone@638
|
1946 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
1947 {
|
pavone@638
|
1948 ret = sprintf(dst, "%s (%d.%c, %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
1949 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
|
pavone@638
|
1950 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1951 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1952 } else {
|
pavone@638
|
1953 ret = sprintf(dst, "%s (%c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
1954 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
1955 1 << decoded->params.regs.scale);
|
pavone@638
|
1956 }
|
pavone@638
|
1957 break;
|
pavone@638
|
1958 case MODE_PREINDEX:
|
pavone@638
|
1959 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
1960 {
|
pavone@638
|
1961 case 0x11:
|
pavone@638
|
1962 //no base displacement or outer displacement
|
pavone@638
|
1963 ret = sprintf(dst, "%s ([%c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
1964 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
1965 1 << decoded->params.regs.scale);
|
pavone@638
|
1966 break;
|
pavone@638
|
1967 case 0x12:
|
pavone@638
|
1968 case 0x13:
|
pavone@638
|
1969 //base displacement only
|
pavone@638
|
1970 ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d])", c, decoded->params.regs.displacement,
|
pavone@638
|
1971 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
1972 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1973 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
1974 break;
|
pavone@638
|
1975 case 0x21:
|
pavone@638
|
1976 case 0x31:
|
pavone@638
|
1977 //outer displacement only
|
pavone@638
|
1978 ret = sprintf(dst, "%s ([%c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
1979 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
1980 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
|
pavone@638
|
1981 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1982 break;
|
pavone@638
|
1983 case 0x22:
|
pavone@638
|
1984 case 0x23:
|
pavone@638
|
1985 case 0x32:
|
pavone@638
|
1986 case 0x33:
|
pavone@638
|
1987 //both outer and inner displacement
|
pavone@638
|
1988 ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
1989 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
1990 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
1991 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
1992 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
1993 break;
|
pavone@638
|
1994 }
|
pavone@638
|
1995 break;
|
pavone@638
|
1996 case MODE_POSTINDEX:
|
pavone@638
|
1997 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
1998 {
|
pavone@638
|
1999 case 0x11:
|
pavone@638
|
2000 //no base displacement or outer displacement
|
pavone@638
|
2001 ret = sprintf(dst, "%s ([], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2002 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2003 1 << decoded->params.regs.scale);
|
pavone@638
|
2004 break;
|
pavone@638
|
2005 case 0x12:
|
pavone@638
|
2006 case 0x13:
|
pavone@638
|
2007 //base displacement only
|
pavone@638
|
2008 ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
2009 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2010 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2011 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2012 break;
|
pavone@638
|
2013 case 0x21:
|
pavone@638
|
2014 case 0x31:
|
pavone@638
|
2015 //outer displacement only
|
pavone@638
|
2016 ret = sprintf(dst, "%s ([], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2017 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2018 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
|
pavone@638
|
2019 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2020 break;
|
pavone@638
|
2021 case 0x22:
|
pavone@638
|
2022 case 0x23:
|
pavone@638
|
2023 case 0x32:
|
pavone@638
|
2024 case 0x33:
|
pavone@638
|
2025 //both outer and inner displacement
|
pavone@638
|
2026 ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2027 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2028 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2029 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
2030 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2031 break;
|
pavone@638
|
2032 }
|
pavone@638
|
2033 break;
|
pavone@638
|
2034 case MODE_MEM_INDIRECT:
|
pavone@638
|
2035 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2036 {
|
pavone@638
|
2037 case 0x11:
|
pavone@638
|
2038 //no base displacement or outer displacement
|
pavone@638
|
2039 ret = sprintf(dst, "%s ([])", c);
|
pavone@638
|
2040 break;
|
pavone@638
|
2041 case 0x12:
|
pavone@638
|
2042 case 0x13:
|
pavone@638
|
2043 //base displacement only
|
pavone@638
|
2044 ret = sprintf(dst, "%s ([%d.%c])", c, decoded->params.regs.displacement,
|
pavone@638
|
2045 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
|
pavone@638
|
2046 break;
|
pavone@638
|
2047 case 0x21:
|
pavone@638
|
2048 case 0x31:
|
pavone@638
|
2049 //outer displacement only
|
pavone@638
|
2050 ret = sprintf(dst, "%s ([], %d.%c)", c, decoded->params.regs.outer_disp,
|
pavone@638
|
2051 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2052 break;
|
pavone@638
|
2053 case 0x22:
|
pavone@638
|
2054 case 0x23:
|
pavone@638
|
2055 case 0x32:
|
pavone@638
|
2056 case 0x33:
|
pavone@638
|
2057 //both outer and inner displacement
|
pavone@638
|
2058 ret = sprintf(dst, "%s ([%d.%c], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2059 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
|
pavone@638
|
2060 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2061 break;
|
pavone@638
|
2062 }
|
pavone@638
|
2063 break;
|
pavone@638
|
2064 case MODE_BASE_DISP:
|
pavone@638
|
2065 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
2066 {
|
pavone@638
|
2067 ret = sprintf(dst, "%s (%d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2068 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
|
pavone@638
|
2069 } else {
|
pavone@638
|
2070 ret = sprintf(dst, "%s ()", c);
|
pavone@638
|
2071 }
|
pavone@638
|
2072 break;
|
pavone@638
|
2073 #endif
|
pavone@2
|
2074 case MODE_IMMEDIATE:
|
pavone@61
|
2075 case MODE_IMMEDIATE_WORD:
|
pavone@636
|
2076 ret = sprintf(dst, (decoded->params.immed <= 128 ? "%s #%d" : "%s #$%X"), c, decoded->params.immed);
|
pavone@636
|
2077 break;
|
pavone@13
|
2078 case MODE_ABSOLUTE_SHORT:
|
pavone@638
|
2079 if (labels) {
|
pavone@636
|
2080 ret = sprintf(dst, "%s ", c);
|
pavone@634
|
2081 ret += label_fun(dst+ret, decoded->params.immed, data);
|
pavone@634
|
2082 strcat(dst+ret, ".w");
|
pavone@636
|
2083 ret = ret + 2;
|
pavone@134
|
2084 } else {
|
pavone@636
|
2085 ret = sprintf(dst, "%s $%X.w", c, decoded->params.immed);
|
pavone@134
|
2086 }
|
pavone@636
|
2087 break;
|
pavone@13
|
2088 case MODE_ABSOLUTE:
|
pavone@134
|
2089 if (labels) {
|
pavone@636
|
2090 ret = sprintf(dst, "%s ", c);
|
pavone@634
|
2091 ret += label_fun(dst+ret, decoded->params.immed, data);
|
pavone@634
|
2092 strcat(dst+ret, ".l");
|
pavone@636
|
2093 ret = ret + 2;
|
pavone@134
|
2094 } else {
|
pavone@636
|
2095 ret = sprintf(dst, "%s $%X", c, decoded->params.immed);
|
pavone@134
|
2096 }
|
pavone@636
|
2097 break;
|
pavone@13
|
2098 case MODE_PC_DISPLACE:
|
pavone@134
|
2099 if (labels) {
|
pavone@636
|
2100 ret = sprintf(dst, "%s ", c);
|
pavone@634
|
2101 ret += label_fun(dst+ret, address + 2 + decoded->params.regs.displacement, data);
|
pavone@634
|
2102 strcat(dst+ret, "(pc)");
|
pavone@636
|
2103 ret = ret + 4;
|
pavone@134
|
2104 } else {
|
pavone@636
|
2105 ret = sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement);
|
pavone@134
|
2106 }
|
pavone@636
|
2107 break;
|
pavone@79
|
2108 case MODE_PC_INDEX_DISP8:
|
pavone@638
|
2109 #ifdef M68020
|
pavone@638
|
2110 if (decoded->params.regs.scale)
|
pavone@638
|
2111 {
|
pavone@638
|
2112 ret = sprintf(dst, "%s (%d, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2113 } else {
|
pavone@638
|
2114 #endif
|
pavone@638
|
2115 ret = sprintf(dst, "%s (%d, pc, %c%d.%c)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
|
pavone@638
|
2116 #ifdef M68020
|
pavone@638
|
2117 }
|
pavone@638
|
2118 #endif
|
pavone@638
|
2119 break;
|
pavone@638
|
2120 #ifdef M68020
|
pavone@638
|
2121 case MODE_PC_INDEX_BASE_DISP:
|
pavone@638
|
2122 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
2123 {
|
pavone@638
|
2124 ret = sprintf(dst, "%s (%d.%c, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
2125 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
|
pavone@638
|
2126 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2127 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2128 } else {
|
pavone@638
|
2129 ret = sprintf(dst, "%s (pc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2130 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2131 1 << decoded->params.regs.scale);
|
pavone@638
|
2132 }
|
pavone@638
|
2133 break;
|
pavone@638
|
2134 case MODE_PC_PREINDEX:
|
pavone@638
|
2135 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2136 {
|
pavone@638
|
2137 case 0x11:
|
pavone@638
|
2138 //no base displacement or outer displacement
|
pavone@638
|
2139 ret = sprintf(dst, "%s ([pc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2140 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2141 1 << decoded->params.regs.scale);
|
pavone@638
|
2142 break;
|
pavone@638
|
2143 case 0x12:
|
pavone@638
|
2144 case 0x13:
|
pavone@638
|
2145 //base displacement only
|
pavone@638
|
2146 ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d])", c, decoded->params.regs.displacement,
|
pavone@638
|
2147 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2148 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2149 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2150 break;
|
pavone@638
|
2151 case 0x21:
|
pavone@638
|
2152 case 0x31:
|
pavone@638
|
2153 //outer displacement only
|
pavone@638
|
2154 ret = sprintf(dst, "%s ([pc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2155 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2156 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
|
pavone@638
|
2157 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2158 break;
|
pavone@638
|
2159 case 0x22:
|
pavone@638
|
2160 case 0x23:
|
pavone@638
|
2161 case 0x32:
|
pavone@638
|
2162 case 0x33:
|
pavone@638
|
2163 //both outer and inner displacement
|
pavone@638
|
2164 ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2165 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2166 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2167 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
2168 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2169 break;
|
pavone@638
|
2170 }
|
pavone@638
|
2171 break;
|
pavone@638
|
2172 case MODE_PC_POSTINDEX:
|
pavone@638
|
2173 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2174 {
|
pavone@638
|
2175 case 0x11:
|
pavone@638
|
2176 //no base displacement or outer displacement
|
pavone@638
|
2177 ret = sprintf(dst, "%s ([pc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2178 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2179 1 << decoded->params.regs.scale);
|
pavone@638
|
2180 break;
|
pavone@638
|
2181 case 0x12:
|
pavone@638
|
2182 case 0x13:
|
pavone@638
|
2183 //base displacement only
|
pavone@638
|
2184 ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
2185 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2186 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2187 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2188 break;
|
pavone@638
|
2189 case 0x21:
|
pavone@638
|
2190 case 0x31:
|
pavone@638
|
2191 //outer displacement only
|
pavone@638
|
2192 ret = sprintf(dst, "%s ([pc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2193 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2194 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
|
pavone@638
|
2195 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2196 break;
|
pavone@638
|
2197 case 0x22:
|
pavone@638
|
2198 case 0x23:
|
pavone@638
|
2199 case 0x32:
|
pavone@638
|
2200 case 0x33:
|
pavone@638
|
2201 //both outer and inner displacement
|
pavone@638
|
2202 ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2203 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2204 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2205 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
2206 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2207 break;
|
pavone@638
|
2208 }
|
pavone@638
|
2209 break;
|
pavone@638
|
2210 case MODE_PC_MEM_INDIRECT:
|
pavone@638
|
2211 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2212 {
|
pavone@638
|
2213 case 0x11:
|
pavone@638
|
2214 //no base displacement or outer displacement
|
pavone@638
|
2215 ret = sprintf(dst, "%s ([pc])", c);
|
pavone@638
|
2216 break;
|
pavone@638
|
2217 case 0x12:
|
pavone@638
|
2218 case 0x13:
|
pavone@638
|
2219 //base displacement only
|
pavone@638
|
2220 ret = sprintf(dst, "%s ([%d.%c, pc])", c, decoded->params.regs.displacement,
|
pavone@638
|
2221 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
|
pavone@638
|
2222 break;
|
pavone@638
|
2223 case 0x21:
|
pavone@638
|
2224 case 0x31:
|
pavone@638
|
2225 //outer displacement only
|
pavone@638
|
2226 ret = sprintf(dst, "%s ([pc], %d.%c)", c, decoded->params.regs.outer_disp,
|
pavone@638
|
2227 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2228 break;
|
pavone@638
|
2229 case 0x22:
|
pavone@638
|
2230 case 0x23:
|
pavone@638
|
2231 case 0x32:
|
pavone@638
|
2232 case 0x33:
|
pavone@638
|
2233 //both outer and inner displacement
|
pavone@638
|
2234 ret = sprintf(dst, "%s ([%d.%c, pc], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2235 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
|
pavone@638
|
2236 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2237 break;
|
pavone@638
|
2238 }
|
pavone@638
|
2239 break;
|
pavone@638
|
2240 case MODE_PC_BASE_DISP:
|
pavone@638
|
2241 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
2242 {
|
pavone@638
|
2243 ret = sprintf(dst, "%s (%d.%c, pc)", c, decoded->params.regs.displacement,
|
pavone@638
|
2244 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
|
pavone@638
|
2245 } else {
|
pavone@638
|
2246 ret = sprintf(dst, "%s (pc)", c);
|
pavone@638
|
2247 }
|
pavone@638
|
2248 break;
|
pavone@638
|
2249 case MODE_ZPC_INDEX_BASE_DISP:
|
pavone@638
|
2250 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
2251 {
|
pavone@638
|
2252 ret = sprintf(dst, "%s (%d.%c, zpc, %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
2253 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
|
pavone@638
|
2254 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2255 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2256 } else {
|
pavone@638
|
2257 ret = sprintf(dst, "%s (zpc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2258 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2259 1 << decoded->params.regs.scale);
|
pavone@638
|
2260 }
|
pavone@638
|
2261 break;
|
pavone@638
|
2262 case MODE_ZPC_PREINDEX:
|
pavone@638
|
2263 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2264 {
|
pavone@638
|
2265 case 0x11:
|
pavone@638
|
2266 //no base displacement or outer displacement
|
pavone@638
|
2267 ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2268 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2269 1 << decoded->params.regs.scale);
|
pavone@638
|
2270 break;
|
pavone@638
|
2271 case 0x12:
|
pavone@638
|
2272 case 0x13:
|
pavone@638
|
2273 //base displacement only
|
pavone@638
|
2274 ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d])", c, decoded->params.regs.displacement,
|
pavone@638
|
2275 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2276 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2277 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2278 break;
|
pavone@638
|
2279 case 0x21:
|
pavone@638
|
2280 case 0x31:
|
pavone@638
|
2281 //outer displacement only
|
pavone@638
|
2282 ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2283 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2284 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
|
pavone@638
|
2285 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2286 break;
|
pavone@638
|
2287 case 0x22:
|
pavone@638
|
2288 case 0x23:
|
pavone@638
|
2289 case 0x32:
|
pavone@638
|
2290 case 0x33:
|
pavone@638
|
2291 //both outer and inner displacement
|
pavone@638
|
2292 ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2293 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2294 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2295 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
2296 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2297 break;
|
pavone@638
|
2298 }
|
pavone@638
|
2299 break;
|
pavone@638
|
2300 case MODE_ZPC_POSTINDEX:
|
pavone@638
|
2301 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2302 {
|
pavone@638
|
2303 case 0x11:
|
pavone@638
|
2304 //no base displacement or outer displacement
|
pavone@638
|
2305 ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2306 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2307 1 << decoded->params.regs.scale);
|
pavone@638
|
2308 break;
|
pavone@638
|
2309 case 0x12:
|
pavone@638
|
2310 case 0x13:
|
pavone@638
|
2311 //base displacement only
|
pavone@638
|
2312 ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d)", c, decoded->params.regs.displacement,
|
pavone@638
|
2313 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2314 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2315 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
|
pavone@638
|
2316 break;
|
pavone@638
|
2317 case 0x21:
|
pavone@638
|
2318 case 0x31:
|
pavone@638
|
2319 //outer displacement only
|
pavone@638
|
2320 ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
|
pavone@638
|
2321 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
|
pavone@638
|
2322 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
|
pavone@638
|
2323 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2324 break;
|
pavone@638
|
2325 case 0x22:
|
pavone@638
|
2326 case 0x23:
|
pavone@638
|
2327 case 0x32:
|
pavone@638
|
2328 case 0x33:
|
pavone@638
|
2329 //both outer and inner displacement
|
pavone@638
|
2330 ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2331 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
|
pavone@638
|
2332 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
|
pavone@638
|
2333 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
|
pavone@638
|
2334 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2335 break;
|
pavone@638
|
2336 }
|
pavone@638
|
2337 break;
|
pavone@638
|
2338 case MODE_ZPC_MEM_INDIRECT:
|
pavone@638
|
2339 switch (decoded->params.regs.disp_sizes)
|
pavone@638
|
2340 {
|
pavone@638
|
2341 case 0x11:
|
pavone@638
|
2342 //no base displacement or outer displacement
|
pavone@638
|
2343 ret = sprintf(dst, "%s ([zpc])", c);
|
pavone@638
|
2344 break;
|
pavone@638
|
2345 case 0x12:
|
pavone@638
|
2346 case 0x13:
|
pavone@638
|
2347 //base displacement only
|
pavone@638
|
2348 ret = sprintf(dst, "%s ([%d.%c, zpc])", c, decoded->params.regs.displacement,
|
pavone@638
|
2349 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
|
pavone@638
|
2350 break;
|
pavone@638
|
2351 case 0x21:
|
pavone@638
|
2352 case 0x31:
|
pavone@638
|
2353 //outer displacement only
|
pavone@638
|
2354 ret = sprintf(dst, "%s ([zpc], %d.%c)", c, decoded->params.regs.outer_disp,
|
pavone@638
|
2355 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2356 break;
|
pavone@638
|
2357 case 0x22:
|
pavone@638
|
2358 case 0x23:
|
pavone@638
|
2359 case 0x32:
|
pavone@638
|
2360 case 0x33:
|
pavone@638
|
2361 //both outer and inner displacement
|
pavone@638
|
2362 ret = sprintf(dst, "%s ([%d.%c, zpc], %d.%c)", c, decoded->params.regs.displacement,
|
pavone@638
|
2363 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
|
pavone@638
|
2364 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
|
pavone@638
|
2365 break;
|
pavone@638
|
2366 }
|
pavone@638
|
2367 break;
|
pavone@638
|
2368 case MODE_ZPC_BASE_DISP:
|
pavone@638
|
2369 if (decoded->params.regs.disp_sizes > 1)
|
pavone@638
|
2370 {
|
pavone@638
|
2371 ret = sprintf(dst, "%s (%d.%c, zpc)", c, decoded->params.regs.displacement,
|
pavone@638
|
2372 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
|
pavone@638
|
2373 } else {
|
pavone@638
|
2374 ret = sprintf(dst, "%s (zpc)", c);
|
pavone@638
|
2375 }
|
pavone@638
|
2376 break;
|
pavone@638
|
2377 #endif
|
pavone@2
|
2378 default:
|
pavone@636
|
2379 ret = 0;
|
pavone@0
|
2380 }
|
pavone@636
|
2381 #ifdef M68020
|
pavone@636
|
2382 if (decoded->addr_mode & M68K_FLAG_BITFIELD)
|
pavone@636
|
2383 {
|
pavone@636
|
2384 switch (decoded->bitfield & 0x820)
|
pavone@636
|
2385 {
|
pavone@636
|
2386 case 0:
|
pavone@636
|
2387 return ret + sprintf(dst+ret, " {$%X:%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32);
|
pavone@636
|
2388 case 0x20:
|
pavone@636
|
2389 return ret + sprintf(dst+ret, " {$%X:d%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x7);
|
pavone@636
|
2390 case 0x800:
|
pavone@636
|
2391 return ret + sprintf(dst+ret, " {d%d:%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32);
|
pavone@636
|
2392 case 0x820:
|
pavone@636
|
2393 return ret + sprintf(dst+ret, " {d%d:d%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x7);
|
pavone@636
|
2394 }
|
pavone@636
|
2395 }
|
pavone@636
|
2396 #endif
|
pavone@636
|
2397 return ret;
|
pavone@0
|
2398 }
|
pavone@2
|
2399
|
pavone@634
|
2400 int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data)
|
pavone@13
|
2401 {
|
pavone@13
|
2402 int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1;
|
pavone@13
|
2403 char *rtype, *last_rtype;
|
pavone@13
|
2404 int oplen;
|
pavone@13
|
2405 if (decoded->addr_mode == MODE_REG) {
|
pavone@13
|
2406 if (other->addr_mode == MODE_AREG_PREDEC) {
|
pavone@13
|
2407 bit = 15;
|
pavone@13
|
2408 dir = -1;
|
pavone@13
|
2409 } else {
|
pavone@69
|
2410 dir = 1;
|
pavone@69
|
2411 bit = 0;
|
pavone@13
|
2412 }
|
pavone@68
|
2413 if (need_comma) {
|
pavone@68
|
2414 strcat(dst, ", ");
|
pavone@68
|
2415 oplen = 2;
|
pavone@68
|
2416 } else {
|
pavone@68
|
2417 strcat(dst, " ");
|
pavone@68
|
2418 oplen = 1;
|
pavone@68
|
2419 }
|
pavone@68
|
2420 for (reg=0; bit < 16 && bit > -1; bit += dir, reg++) {
|
pavone@15
|
2421 if (decoded->params.immed & (1 << bit)) {
|
pavone@13
|
2422 if (reg > 7) {
|
pavone@13
|
2423 rtype = "a";
|
pavone@13
|
2424 regnum = reg - 8;
|
pavone@13
|
2425 } else {
|
pavone@13
|
2426 rtype = "d";
|
pavone@13
|
2427 regnum = reg;
|
pavone@13
|
2428 }
|
pavone@13
|
2429 if (last >= 0 && last == regnum - 1 && lastreg == reg - 1) {
|
pavone@13
|
2430 last = regnum;
|
pavone@13
|
2431 lastreg = reg;
|
pavone@13
|
2432 } else if(last >= 0) {
|
pavone@13
|
2433 if (first != last) {
|
pavone@13
|
2434 oplen += sprintf(dst + oplen, "-%s%d/%s%d",last_rtype, last, rtype, regnum);
|
pavone@13
|
2435 } else {
|
pavone@13
|
2436 oplen += sprintf(dst + oplen, "/%s%d", rtype, regnum);
|
pavone@13
|
2437 }
|
pavone@13
|
2438 first = last = regnum;
|
pavone@13
|
2439 last_rtype = rtype;
|
pavone@13
|
2440 lastreg = reg;
|
pavone@13
|
2441 } else {
|
pavone@13
|
2442 oplen += sprintf(dst + oplen, "%s%d", rtype, regnum);
|
pavone@13
|
2443 first = last = regnum;
|
pavone@13
|
2444 last_rtype = rtype;
|
pavone@13
|
2445 lastreg = reg;
|
pavone@13
|
2446 }
|
pavone@13
|
2447 }
|
pavone@13
|
2448 }
|
pavone@13
|
2449 if (last >= 0 && last != first) {
|
pavone@13
|
2450 oplen += sprintf(dst + oplen, "-%s%d", last_rtype, last);
|
pavone@13
|
2451 }
|
pavone@13
|
2452 return oplen;
|
pavone@13
|
2453 } else {
|
pavone@634
|
2454 return m68k_disasm_op(decoded, dst, need_comma, labels, address, label_fun, data);
|
pavone@13
|
2455 }
|
pavone@13
|
2456 }
|
pavone@13
|
2457
|
pavone@634
|
2458 int m68k_default_label_fun(char * dst, uint32_t address, void * data)
|
pavone@634
|
2459 {
|
pavone@634
|
2460 return sprintf(dst, "ADR_%X", address);
|
pavone@634
|
2461 }
|
pavone@634
|
2462
|
pavone@634
|
2463 int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels, format_label_fun label_fun, void * data)
|
pavone@2
|
2464 {
|
pavone@2
|
2465 int ret,op1len;
|
pavone@2
|
2466 uint8_t size;
|
pavone@13
|
2467 char * special_op = "CCR";
|
pavone@13
|
2468 switch (decoded->op)
|
pavone@13
|
2469 {
|
pavone@13
|
2470 case M68K_BCC:
|
pavone@13
|
2471 case M68K_DBCC:
|
pavone@13
|
2472 case M68K_SCC:
|
pavone@2
|
2473 ret = strlen(mnemonics[decoded->op]) - 2;
|
pavone@2
|
2474 memcpy(dst, mnemonics[decoded->op], ret);
|
pavone@2
|
2475 dst[ret] = 0;
|
pavone@50
|
2476 strcpy(dst+ret, cond_mnem[decoded->extra.cond]);
|
pavone@2
|
2477 ret = strlen(dst);
|
pavone@50
|
2478 if (decoded->op != M68K_SCC) {
|
pavone@134
|
2479 if (labels) {
|
pavone@134
|
2480 if (decoded->op == M68K_DBCC) {
|
pavone@634
|
2481 ret += sprintf(dst+ret, " d%d, ", decoded->dst.params.regs.pri);
|
pavone@634
|
2482 ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
|
pavone@134
|
2483 } else {
|
pavone@634
|
2484 dst[ret++] = ' ';
|
pavone@634
|
2485 ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
|
pavone@134
|
2486 }
|
pavone@54
|
2487 } else {
|
pavone@134
|
2488 if (decoded->op == M68K_DBCC) {
|
pavone@134
|
2489 ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
|
pavone@134
|
2490 } else {
|
pavone@134
|
2491 ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
|
pavone@134
|
2492 }
|
pavone@54
|
2493 }
|
pavone@50
|
2494 return ret;
|
pavone@50
|
2495 }
|
pavone@13
|
2496 break;
|
pavone@13
|
2497 case M68K_BSR:
|
pavone@134
|
2498 if (labels) {
|
pavone@634
|
2499 ret = sprintf(dst, "bsr%s ", decoded->variant == VAR_BYTE ? ".s" : "");
|
pavone@634
|
2500 ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
|
pavone@134
|
2501 } else {
|
pavone@134
|
2502 ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
|
pavone@134
|
2503 }
|
pavone@50
|
2504 return ret;
|
pavone@13
|
2505 case M68K_MOVE_FROM_SR:
|
pavone@13
|
2506 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
|
pavone@13
|
2507 ret += sprintf(dst + ret, " SR");
|
pavone@634
|
2508 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1, labels, decoded->address, label_fun, data);
|
pavone@13
|
2509 return ret;
|
pavone@13
|
2510 case M68K_ANDI_SR:
|
pavone@13
|
2511 case M68K_EORI_SR:
|
pavone@13
|
2512 case M68K_MOVE_SR:
|
pavone@13
|
2513 case M68K_ORI_SR:
|
pavone@13
|
2514 special_op = "SR";
|
pavone@13
|
2515 case M68K_ANDI_CCR:
|
pavone@13
|
2516 case M68K_EORI_CCR:
|
pavone@13
|
2517 case M68K_MOVE_CCR:
|
pavone@13
|
2518 case M68K_ORI_CCR:
|
pavone@13
|
2519 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
|
pavone@634
|
2520 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@13
|
2521 ret += sprintf(dst + ret, ", %s", special_op);
|
pavone@13
|
2522 return ret;
|
pavone@50
|
2523 case M68K_MOVE_USP:
|
pavone@50
|
2524 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
|
pavone@50
|
2525 if (decoded->src.addr_mode != MODE_UNUSED) {
|
pavone@634
|
2526 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@50
|
2527 ret += sprintf(dst + ret, ", USP");
|
pavone@50
|
2528 } else {
|
pavone@50
|
2529 ret += sprintf(dst + ret, "USP, ");
|
pavone@634
|
2530 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@50
|
2531 }
|
pavone@50
|
2532 return ret;
|
pavone@630
|
2533 case M68K_INVALID:
|
pavone@630
|
2534 ret = sprintf(dst, "dc.w $%X", decoded->src.params.immed);
|
pavone@630
|
2535 return ret;
|
pavone@630
|
2536 #ifdef M68010
|
pavone@630
|
2537 case M68K_MOVEC:
|
pavone@630
|
2538 ret = sprintf(dst, "%s ", mnemonics[decoded->op]);
|
pavone@630
|
2539 if (decoded->src.addr_mode == MODE_UNUSED) {
|
pavone@630
|
2540 ret += sprintf(dst + ret, "%s, ", cr_mnem[decoded->src.params.immed]);
|
pavone@634
|
2541 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@630
|
2542 } else {
|
pavone@634
|
2543 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@630
|
2544 ret += sprintf(dst + ret, ", %s", cr_mnem[decoded->dst.params.immed]);
|
pavone@630
|
2545 }
|
pavone@630
|
2546 return ret;
|
pavone@630
|
2547 #endif
|
pavone@13
|
2548 default:
|
pavone@2
|
2549 size = decoded->extra.size;
|
pavone@518
|
2550 ret = sprintf(dst, "%s%s%s",
|
pavone@518
|
2551 mnemonics[decoded->op],
|
pavone@518
|
2552 decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
|
pavone@13
|
2553 size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
|
pavone@2
|
2554 }
|
pavone@13
|
2555 if (decoded->op == M68K_MOVEM) {
|
pavone@634
|
2556 op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@13
|
2557 ret += op1len;
|
pavone@634
|
2558 ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len, labels, decoded->address, label_fun, data);
|
pavone@13
|
2559 } else {
|
pavone@634
|
2560 op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
|
pavone@13
|
2561 ret += op1len;
|
pavone@634
|
2562 ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len, labels, decoded->address, label_fun, data);
|
pavone@13
|
2563 }
|
pavone@2
|
2564 return ret;
|
pavone@2
|
2565 }
|
pavone@2
|
2566
|
pavone@134
|
2567 int m68k_disasm(m68kinst * decoded, char * dst)
|
pavone@134
|
2568 {
|
pavone@634
|
2569 return m68k_disasm_ex(decoded, dst, 0, NULL, NULL);
|
pavone@134
|
2570 }
|
pavone@134
|
2571
|
pavone@634
|
2572 int m68k_disasm_labels(m68kinst * decoded, char * dst, format_label_fun label_fun, void * data)
|
pavone@134
|
2573 {
|
pavone@634
|
2574 if (!label_fun)
|
pavone@634
|
2575 {
|
pavone@634
|
2576 label_fun = m68k_default_label_fun;
|
pavone@634
|
2577 }
|
pavone@634
|
2578 return m68k_disasm_ex(decoded, dst, 1, label_fun, data);
|
pavone@134
|
2579 }
|