|
|
1.1 root 1: /***************************************************************************
2:
3: i860dis.c
4:
5: Disassembler for the Intel i860 emulator.
6:
7: Copyright (C) 1995-present Jason Eckhardt ([email protected])
8: Released for general non-commercial use under the MAME license
9: with the additional requirement that you are free to use and
10: redistribute this code in modified or unmodified form, provided
11: you list me in the credits.
12: Visit http://mamedev.org for licensing and usage restrictions.
13:
14: Changes for previous/NeXTdimension by Simon Schubiger (SC)
15:
16: ***************************************************************************/
17:
18: #include <string.h>
19: #include <stdio.h>
20: #include "i860.hpp"
21:
22: /* Macros for accessing register fields in instruction word. */
23: #define get_isrc1(bits) (((bits) >> 11) & 0x1f)
24: #define get_isrc2(bits) (((bits) >> 21) & 0x1f)
25: #define get_idest(bits) (((bits) >> 16) & 0x1f)
26: #define get_fsrc1(bits) (((bits) >> 11) & 0x1f)
27: #define get_fsrc2(bits) (((bits) >> 21) & 0x1f)
28: #define get_fdest(bits) (((bits) >> 16) & 0x1f)
29: #define get_creg(bits) (((bits) >> 21) & 0x7)
30:
31: /* Macros for accessing immediate fields. */
32: /* 16-bit immediate. */
33: #define get_imm16(insn) ((insn) & 0xffff)
34:
35:
36: /* Control register names. */
37: static const char *const cr2str[] =
38: {"fir", "psr", "dirbase", "db", "fsr", "epsr", "!", "!"};
39:
40:
41: /* Sign extend N-bit number. */
42: static INT32 sign_ext(UINT32 x, int n)
43: {
44: INT32 t;
45: t = x >> (n - 1);
46: t = ((-t) << n) | x;
47: return t;
48: }
49:
50:
51: /* Basic integer 3-address register format:
52: * mnemonic %rs1,%rs2,%rd */
53: static void int_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
54: {
55: /* Possibly prefix shrd with 'd.' */
56: if (((insn & 0xfc000000) == 0xb0000000) && (insn & 0x200))
57: sprintf(buf, "d.%s\t%%r%d,%%r%d,%%r%d", mnemonic,
58: get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
59: else
60: sprintf(buf, " %s\t%%r%d,%%r%d,%%r%d", mnemonic,
61: get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
62: }
63:
64:
65: /* Basic integer 3-address imm16 format:
66: * mnemonic #imm16,%rs2,%rd */
67: static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
68: {
69: /* Sign extend the 16-bit immediate.
70: Print as hex for the bitwise operations. */
71: int upper_6bits = (insn >> 26) & 0x3f;
72: if (upper_6bits >= 0x30 && upper_6bits <= 0x3f)
73: sprintf(buf, " %s\t0x%04x,%%r%d,%%r%d", mnemonic,
74: (UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn));
75: else
76: sprintf(buf, " %s\t%d,%%r%d,%%r%d", mnemonic,
77: sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn));
78: }
79:
80:
81: /* Integer (mixed) 2-address isrc1ni,fdest. */
82: static void int_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
83: {
84: sprintf(buf, " %s\t%%r%d,%%f%d", mnemonic, get_isrc1 (insn), get_fdest (insn));
85: }
86:
87:
88: /* Integer (mixed) 2-address csrc2,idest. */
89: static void int_cd(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
90: {
91: sprintf(buf, " %s\t%%%s,%%r%d", mnemonic, cr2str[get_creg (insn)], get_idest (insn));
92: }
93:
94:
95: /* Integer (mixed) 2-address isrc1,csrc2. */
96: static void int_1c(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
97: {
98: sprintf(buf, " %s\t%%r%d,%%%s", mnemonic, get_isrc1(insn), cr2str[get_creg (insn)]);
99: }
100:
101:
102: /* Integer 1-address register format:
103: * mnemonic %rs1 */
104: static void int_1(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
105: {
106: sprintf(buf, " %s\t%%r%d", mnemonic, get_isrc1 (insn));
107: }
108:
109:
110: /* Integer no-address register format:
111: * mnemonic */
112: static void int_0(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
113: {
114: sprintf(buf, " %s", mnemonic);
115: }
116:
117:
118: /* Basic floating-point 3-address register format:
119: * mnemonic %fs1,%fs2,%fd */
120: static void flop_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
121: {
122: const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
123: const char *prefix_d, *prefix_p;
124: prefix_p = (insn & 0x400) ? "p" : "";
125: prefix_d = (insn & 0x200) ? "d." : " ";
126:
127: /* Special case: pf[m]am and pf[m]sm families are always pipelined, so they
128: do not have a prefix. Also, for the pfmam and pfmsm families, replace
129: any 'a' in the mnemonic with 'm' and prepend an 'm'. */
130: if ((insn & 0x7f) < 0x20)
131: {
132: int is_pfam = insn & 0x400;
133: if (!is_pfam)
134: {
135: char newname[256];
136: char *op = mnemonic;
137: char *np = newname + 1;
138: newname[0] = 'm';
139: while (*op)
140: {
141: if (*op == 'a')
142: *np = 'm';
143: else
144: *np = *op;
145: np++;
146: op++;
147: }
148: *np = 0;
149: mnemonic = newname;
150: }
151: prefix_p = "";
152: }
153:
154: /* Special case: pfgt/pfle-- R-bit distinguishes the two. */
155: if ((insn & 0x7f) == 0x34)
156: {
157: const char *const mn[2] = { "fgt.", "fle." };
158: int r = (insn & 0x080) >> 7;
159: int s = (insn & 0x100) ? 3 : 0;
160: sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mn[r],
161: suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
162: }
163: else
164: {
165: int s = (insn & 0x180) >> 7;
166: sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
167: suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
168: }
169: }
170:
171:
172: /* Floating-point 2-address register format:
173: * mnemonic %fs1,%fd */
174: static void flop_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
175: {
176: const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
177: const char *prefix_d, *prefix_p;
178: int s = (insn & 0x180) >> 7;
179: prefix_p = (insn & 0x400) ? "p" : "";
180: prefix_d = (insn & 0x200) ? "d." : " ";
181: sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
182: suffix[s], get_fsrc1 (insn), get_fdest (insn));
183: }
184:
185:
186: /* Floating-point 2-address register format:
187: * mnemonic %fs2,%fd */
188: static void flop_2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
189: {
190: const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
191: const char *prefix_d;
192: int s = (insn & 0x180) >> 7;
193: prefix_d = (insn & 0x200) ? "d." : " ";
194: sprintf(buf, "%s%s%s\t%%f%d,%%f%d", prefix_d, mnemonic, suffix[s],
195: get_fsrc2 (insn), get_fdest (insn));
196: }
197:
198:
199: /* Floating-point (mixed) 2-address register format:
200: * fxfr fsrc1,idest. */
201: static void flop_fxfr(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
202: {
203: const char *prefix_d = (insn & 0x200) ? "d." : " ";
204: sprintf(buf, "%s%s\t%%f%d,%%r%d", prefix_d, mnemonic, get_fsrc1 (insn),
205: get_idest (insn));
206: }
207:
208:
209: /* Branch with reg,reg,sbroff format:
210: * mnemonic %rs1,%rs2,sbroff */
211: static void int_12S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
212: {
213: INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
214: INT32 rel = (INT32)pc + (sbroff << 2) + 4;
215:
216: sprintf(buf, " %s\t%%r%d,%%r%d,0x%08x", mnemonic, get_isrc1 (insn),
217: get_isrc2 (insn), (UINT32)rel);
218: }
219:
220:
221: /* Branch with #const5,reg,sbroff format:
222: * mnemonic #const5,%rs2,sbroff */
223: static void int_i2S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
224: {
225: INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
226: INT32 rel = (INT32)pc + (sbroff << 2) + 4;
227:
228: sprintf(buf, " %s\t%d,%%r%d,0x%08x", mnemonic, ((insn >> 11) & 0x1f),
229: get_isrc2 (insn), (UINT32)rel);
230: }
231:
232:
233: /* Branch with lbroff format:
234: * mnemonic lbroff */
235: static void int_L(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
236: {
237: INT32 lbroff = sign_ext ((insn & 0x03ffffff), 26);
238: INT32 rel = (INT32)pc + (lbroff << 2) + 4;
239:
240: sprintf(buf, " %s\t0x%08x", mnemonic, (UINT32)rel);
241: }
242:
243:
244: /* Integer load.
245: * ld.{b,s,l} isrc1(isrc2),idest
246: * ld.{b,s,l} #const(isrc2),idest */
247: static void int_ldx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
248: {
249: /* Operand size, in bytes. */
250: int sizes[4] = { 1, 1, 2, 4 };
251: const char *const suffix[4] = { "b", "b", "s", "l" };
252: UINT32 idx = 0;
253:
254: /* Bits 28 and 0 determine the operand size. */
255: idx = ((insn >> 27) & 2) | (insn & 1);
256:
257: /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
258: if (insn & 0x04000000)
259: {
260: /* Chop off lower bits of displacement. */
261: INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
262: int size = sizes[idx];
263: immsrc1 &= ~(size - 1);
264: sprintf(buf, " %s%s\t%d(%%r%d),%%r%d", mnemonic, suffix[idx],
265: immsrc1, get_isrc2 (insn), get_idest (insn));
266: }
267: else
268: sprintf(buf, " %s%s\t%%r%d(%%r%d),%%r%d", mnemonic, suffix[idx],
269: get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
270: }
271:
272:
273: /* Integer store: st.b isrc1ni,#const(isrc2) */
274: static void int_stx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
275: {
276: /* Operand size, in bytes. */
277: int sizes[4] = { 1, 1, 2, 4 };
278: const char *const suffix[4] = { "b", "b", "s", "l" };
279: int idx = 0;
280: int size;
281: INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
282:
283: /* Bits 28 and 0 determine the operand size. */
284: idx = ((insn >> 27) & 2) | (insn & 1);
285:
286: /* Chop off lower bits of displacement. */
287: size = sizes[idx];
288: immsrc &= ~(size - 1);
289: sprintf(buf, " %s%s\t%%r%d,%d(%%r%d)", mnemonic, suffix[idx],
290: get_isrc1 (insn), immsrc, get_isrc2 (insn));
291: }
292:
293:
294: /* Disassemble:
295: * "[p]fld.y isrc1(isrc2),fdest", "[p]fld.y isrc1(isrc2)++,idest",
296: * "[p]fld.y #const(isrc2),fdest" or "[p]fld.y #const(isrc2)++,idest".
297: * "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
298: * "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
299: * Where y = {l,d,q}. Note, there is no pfld.q, though. */
300: static void int_fldst(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
301: {
302: INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
303: /* Operand size, in bytes. */
304: int sizes[4] = { 8, 4, 16, 4 };
305: const char *const suffix[4] = { "d", "l", "q", "l" };
306: int idx = 0;
307: int size = 0;
308: int auto_inc = (insn & 1);
309: const char *const auto_suff[2] = { "", "++" };
310: int piped = (insn & 0x40000000) >> 30;
311: const char *const piped_suff[2] = { "", "p" };
312: int upper_6bits = (insn >> 26) & 0x3f;
313: int is_load = (upper_6bits == 8 || upper_6bits == 9 || upper_6bits == 24
314: || upper_6bits == 25);
315:
316: /* Bits 2 and 1 determine the operand size. */
317: idx = ((insn >> 1) & 3);
318: size = sizes[idx];
319:
320: /* There is no pipelined load quad on XR. */
321: if (piped && size == 16)
322: {
323: sprintf (buf, ".long\t%#08x; *", insn);
324: return;
325: }
326:
327: /* There is only a 64-bit pixel store. */
328: if ((upper_6bits == 15) && size != 8)
329: {
330: sprintf (buf, ".long\t%#08x", insn);
331: return;
332: }
333:
334: /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
335: if (insn & 0x04000000)
336: {
337: /* Chop off lower bits of displacement. */
338: immsrc1 &= ~(size - 1);
339: if (is_load)
340: sprintf(buf, " %s%s%s\t%d(%%r%d)%s,%%f%d", piped_suff[piped], mnemonic,
341: suffix[idx], immsrc1, get_isrc2 (insn), auto_suff[auto_inc],
342: get_fdest (insn));
343: else
344: sprintf(buf, " %s%s\t%%f%d,%d(%%r%d)%s", mnemonic, suffix[idx],
345: get_fdest (insn), immsrc1, get_isrc2 (insn), auto_suff[auto_inc]);
346: }
347: else
348: {
349: if (is_load)
350: sprintf(buf, " %s%s%s\t%%r%d(%%r%d)%s,%%f%d", piped_suff[piped],
351: mnemonic, suffix[idx], get_isrc1 (insn), get_isrc2 (insn),
352: auto_suff[auto_inc], get_fdest (insn));
353: else
354: sprintf(buf, " %s%s\t%%f%d,%%r%d(%%r%d)%s", mnemonic, suffix[idx],
355: get_fdest (insn), get_isrc1 (insn), get_isrc2 (insn),
356: auto_suff[auto_inc]);
357: }
358: }
359:
360:
361: /* flush #const(isrc2)[++]. */
362: static void int_flush(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
363: {
364: const char *const auto_suff[2] = { "", "++" };
365: INT32 immsrc = sign_ext (get_imm16 (insn), 16);
366: immsrc &= ~(16-1);
367: sprintf(buf, " %s\t%d(%%r%d)%s", mnemonic, immsrc, get_isrc2 (insn),
368: auto_suff[(insn & 1)]);
369: }
370:
371:
372: /* Flags for the decode table. */
373: enum
374: {
375: DEC_MORE = 1, /* More decoding necessary. */
376: DEC_DECODED = 2 /* Fully decoded, go. */
377: };
378:
379:
380: struct decode_tbl_t
381: {
382: /* Disassembly function for this opcode.
383: Call with buffer, mnemonic, pc, insn. */
384: void (*insn_dis)(char *, char *, UINT32, UINT32);
385:
386: /* Flags for this opcode. */
387: char flags;
388:
389: /* Mnemonic of this opcode (sometimes partial when more decode is
390: done in disassembly routines-- e.g., loads and stores). */
391: const char *mnemonic;
392: };
393:
394:
395: /* First-level decode table (i.e., for the 6 primary opcode bits). */
396: static const decode_tbl_t decode_tbl[64] =
397: {
398: /* A slight bit of decoding for loads and stores is done in the
399: execution routines (operand size and addressing mode), which
400: is why their respective entries are identical. */
401: { int_ldx, DEC_DECODED, "ld." }, /* ld.b isrc1(isrc2),idest. */
402: { int_ldx, DEC_DECODED, "ld." }, /* ld.b #const(isrc2),idest. */
403: { int_1d, DEC_DECODED, "ixfr" }, /* ixfr isrc1ni,fdest. */
404: { int_stx, DEC_DECODED, "st." }, /* st.b isrc1ni,#const(isrc2). */
405: { int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} isrc1(isrc2),idest. */
406: { int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} #const(isrc2),idest. */
407: { 0, 0 , 0 },
408: { int_stx, DEC_DECODED, "st." }, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
409: { int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */
410: { int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
411: { int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */
412: { int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,#const(isrc2)[++] */
413: { int_cd, DEC_DECODED, "ld.c" }, /* ld.c csrc2,idest. */
414: { int_flush, DEC_DECODED, "flush" }, /* flush #const(isrc2) (or autoinc). */
415: { int_1c, DEC_DECODED, "st.c" }, /* st.c isrc1,csrc2. */
416: { int_fldst, DEC_DECODED, "pstd." }, /* pst.d fdest,#const(isrc2)[++]. */
417: { int_1, DEC_DECODED, "bri" }, /* bri isrc1ni. */
418: { int_12d, DEC_DECODED, "trap" }, /* trap isrc1ni,isrc2,idest. */
419: { 0, DEC_MORE, 0 }, /* FP ESCAPE FORMAT, more decode. */
420: { 0, DEC_MORE, 0 }, /* CORE ESCAPE FORMAT, more decode. */
421: { int_12S, DEC_DECODED, "btne" }, /* btne isrc1,isrc2,sbroff. */
422: { int_i2S, DEC_DECODED, "btne" }, /* btne #const,isrc2,sbroff. */
423: { int_12S, DEC_DECODED, "bte" }, /* bte isrc1,isrc2,sbroff. */
424: { int_i2S, DEC_DECODED, "bte" }, /* bte #const5,isrc2,idest. */
425: { int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest. */
426: { int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
427: { int_L, DEC_DECODED, "br" }, /* br lbroff. */
428: { int_L, DEC_DECODED, "call" }, /* call lbroff . */
429: { int_L, DEC_DECODED, "bc" }, /* bc lbroff. */
430: { int_L, DEC_DECODED, "bc.t" }, /* bc.t lbroff. */
431: { int_L, DEC_DECODED, "bnc" }, /* bnc lbroff. */
432: { int_L, DEC_DECODED, "bnc.t" }, /* bnc.t lbroff. */
433: { int_12d, DEC_DECODED, "addu" }, /* addu isrc1,isrc2,idest. */
434: { int_i2d, DEC_DECODED, "addu" }, /* addu #const,isrc2,idest. */
435: { int_12d, DEC_DECODED, "subu" }, /* subu isrc1,isrc2,idest. */
436: { int_i2d, DEC_DECODED, "subu" }, /* subu #const,isrc2,idest. */
437: { int_12d, DEC_DECODED, "adds" }, /* adds isrc1,isrc2,idest. */
438: { int_i2d, DEC_DECODED, "adds" }, /* adds #const,isrc2,idest. */
439: { int_12d, DEC_DECODED, "subs" }, /* subs isrc1,isrc2,idest. */
440: { int_i2d, DEC_DECODED, "subs" }, /* subs #const,isrc2,idest. */
441: { int_12d, DEC_DECODED, "shl" }, /* shl isrc1,isrc2,idest. */
442: { int_i2d, DEC_DECODED, "shl" }, /* shl #const,isrc2,idest. */
443: { int_12d, DEC_DECODED, "shr" }, /* shr isrc1,isrc2,idest. */
444: { int_i2d, DEC_DECODED, "shr" }, /* shr #const,isrc2,idest. */
445: { int_12d, DEC_DECODED, "shrd" }, /* shrd isrc1ni,isrc2,idest. */
446: { int_12S, DEC_DECODED, "bla" }, /* bla isrc1ni,isrc2,sbroff. */
447: { int_12d, DEC_DECODED, "shra" }, /* shra isrc1,isrc2,idest. */
448: { int_i2d, DEC_DECODED, "shra" }, /* shra #const,isrc2,idest. */
449: { int_12d, DEC_DECODED, "and" }, /* and isrc1,isrc2,idest. */
450: { int_i2d, DEC_DECODED, "and" }, /* and #const,isrc2,idest. */
451: { 0, 0 , 0 },
452: { int_i2d, DEC_DECODED, "andh" }, /* andh #const,isrc2,idest. */
453: { int_12d, DEC_DECODED, "andnot" }, /* andnot isrc1,isrc2,idest. */
454: { int_i2d, DEC_DECODED, "andnot" }, /* andnot #const,isrc2,idest. */
455: { 0, 0 , 0 },
456: { int_i2d, DEC_DECODED, "andnoth" }, /* andnoth #const,isrc2,idest.*/
457: { int_12d, DEC_DECODED, "or" }, /* or isrc1,isrc2,idest. */
458: { int_i2d, DEC_DECODED, "or" }, /* or #const,isrc2,idest. */
459: { 0, 0 , 0 },
460: { int_i2d, DEC_DECODED, "orh" }, /* orh #const,isrc2,idest. */
461: { int_12d, DEC_DECODED, "xor" }, /* xor isrc1,isrc2,idest. */
462: { int_i2d, DEC_DECODED, "xor" }, /* xor #const,isrc2,idest. */
463: { 0, 0 , 0 },
464: { int_i2d, DEC_DECODED, "xorh" }, /* xorh #const,isrc2,idest. */
465: };
466:
467:
468: /* Second-level decode table (i.e., for the 3 core escape opcode bits). */
469: static const decode_tbl_t core_esc_decode_tbl[8] =
470: {
471: { 0, 0 , 0 },
472: { int_0, DEC_DECODED, "lock" }, /* lock. */
473: { int_1, DEC_DECODED, "calli" }, /* calli isrc1ni. */
474: { 0, 0 , 0 },
475: { int_0, DEC_DECODED, "intovr" }, /* intovr. */
476: { 0, 0 , 0 },
477: { 0, 0 , 0 },
478: { int_0, DEC_DECODED, "unlock" }, /* unlock. */
479: };
480:
481:
482: /* Second-level decode table (i.e., for the 7 FP extended opcode bits). */
483: static const decode_tbl_t fp_decode_tbl[128] =
484: {
485: /* Floating point instructions. The least significant 7 bits are
486: the (extended) opcode and bits 10:7 are P,D,S,R respectively
487: ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
488: For some operations, I defer decoding the P,S,R bits to the
489: emulation routine for them. */
490: { flop_12d, DEC_DECODED, "r2p1." }, /* 0x00 pf[m]am */
491: { flop_12d, DEC_DECODED, "r2pt." }, /* 0x01 pf[m]am */
492: { flop_12d, DEC_DECODED, "r2ap1." }, /* 0x02 pf[m]am */
493: { flop_12d, DEC_DECODED, "r2apt." }, /* 0x03 pf[m]am */
494: { flop_12d, DEC_DECODED, "i2p1." }, /* 0x04 pf[m]am */
495: { flop_12d, DEC_DECODED, "i2pt." }, /* 0x05 pf[m]am */
496: { flop_12d, DEC_DECODED, "i2ap1." }, /* 0x06 pf[m]am */
497: { flop_12d, DEC_DECODED, "i2apt." }, /* 0x07 pf[m]am */
498: { flop_12d, DEC_DECODED, "rat1p2." }, /* 0x08 pf[m]am */
499: { flop_12d, DEC_DECODED, "m12apm." }, /* 0x09 pf[m]am */
500: { flop_12d, DEC_DECODED, "ra1p2." }, /* 0x0A pf[m]am */
501: { flop_12d, DEC_DECODED, "m12ttpa." }, /* 0x0B pf[m]am */
502: { flop_12d, DEC_DECODED, "iat1p2." }, /* 0x0C pf[m]am */
503: { flop_12d, DEC_DECODED, "m12tpm." }, /* 0x0D pf[m]am */
504: { flop_12d, DEC_DECODED, "ia1p2." }, /* 0x0E pf[m]am */
505: { flop_12d, DEC_DECODED, "m12tpa." }, /* 0x0F pf[m]am */
506: { flop_12d, DEC_DECODED, "r2s1." }, /* 0x10 pf[m]sm */
507: { flop_12d, DEC_DECODED, "r2st." }, /* 0x11 pf[m]sm */
508: { flop_12d, DEC_DECODED, "r2as1." }, /* 0x12 pf[m]sm */
509: { flop_12d, DEC_DECODED, "r2ast." }, /* 0x13 pf[m]sm */
510: { flop_12d, DEC_DECODED, "i2s1." }, /* 0x14 pf[m]sm */
511: { flop_12d, DEC_DECODED, "i2st." }, /* 0x15 pf[m]sm */
512: { flop_12d, DEC_DECODED, "i2as1." }, /* 0x16 pf[m]sm */
513: { flop_12d, DEC_DECODED, "i2ast." }, /* 0x17 pf[m]sm */
514: { flop_12d, DEC_DECODED, "rat1s2." }, /* 0x18 pf[m]sm */
515: { flop_12d, DEC_DECODED, "m12asm." }, /* 0x19 pf[m]sm */
516: { flop_12d, DEC_DECODED, "ra1s2." }, /* 0x1A pf[m]sm */
517: { flop_12d, DEC_DECODED, "m12ttsa." }, /* 0x1B pf[m]sm */
518: { flop_12d, DEC_DECODED, "iat1s2." }, /* 0x1C pf[m]sm */
519: { flop_12d, DEC_DECODED, "m12tsm." }, /* 0x1D pf[m]sm */
520: { flop_12d, DEC_DECODED, "ia1s2." }, /* 0x1E pf[m]sm */
521: { flop_12d, DEC_DECODED, "m12tsa." }, /* 0x1F pf[m]sm */
522: { flop_12d, DEC_DECODED, "fmul." }, /* 0x20 [p]fmul */
523: { flop_12d, DEC_DECODED, "fmlow." }, /* 0x21 fmlow.dd */
524: { flop_2d, DEC_DECODED, "frcp." }, /* 0x22 frcp.{ss,sd,dd} */
525: { flop_2d, DEC_DECODED, "frsqr." }, /* 0x23 frsqr.{ss,sd,dd} */
526: { flop_12d, DEC_DECODED, "pfmul3.dd" }, /* 0x24 pfmul3.dd */
527: { 0, 0 , 0 }, /* 0x25 */
528: { 0, 0 , 0 }, /* 0x26 */
529: { 0, 0 , 0 }, /* 0x27 */
530: { 0, 0 , 0 }, /* 0x28 */
531: { 0, 0 , 0 }, /* 0x29 */
532: { 0, 0 , 0 }, /* 0x2A */
533: { 0, 0 , 0 }, /* 0x2B */
534: { 0, 0 , 0 }, /* 0x2C */
535: { 0, 0 , 0 }, /* 0x2D */
536: { 0, 0 , 0 }, /* 0x2E */
537: { 0, 0 , 0 }, /* 0x2F */
538: { flop_12d, DEC_DECODED, "fadd." }, /* 0x30, [p]fadd.{ss,sd,dd} */
539: { flop_12d, DEC_DECODED, "fsub." }, /* 0x31, [p]fsub.{ss,sd,dd} */
540: { flop_1d, DEC_DECODED, "fix." }, /* 0x32, [p]fix.{ss,sd,dd} */
541: { flop_1d, DEC_DECODED, "famov." }, /* 0x33, [p]famov.{ss,sd,ds,dd} */
542: { flop_12d, DEC_DECODED, "f{gt,le}" }, /* 0x34, pf{gt,le}.{ss,dd} */
543: { flop_12d, DEC_DECODED, "feq." }, /* 0x35, pfeq.{ss,dd} */
544: { 0, 0 , 0 }, /* 0x36 */
545: { 0, 0 , 0 }, /* 0x37 */
546: { 0, 0 , 0 }, /* 0x38 */
547: { 0, 0 , 0 }, /* 0x39 */
548: { flop_1d, DEC_DECODED, "ftrunc." }, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
549: { 0, 0 , 0 }, /* 0x3B */
550: { 0, 0 , 0 }, /* 0x3C */
551: { 0, 0 , 0 }, /* 0x3D */
552: { 0, 0 , 0 }, /* 0x3E */
553: { 0, 0 , 0 }, /* 0x3F */
554: { flop_fxfr, DEC_DECODED, "fxfr" }, /* 0x40, fxfr fsrc1,idest. */
555: { 0, 0 , 0 }, /* 0x41 */
556: { 0, 0 , 0 }, /* 0x42 */
557: { 0, 0 , 0 }, /* 0x43 */
558: { 0, 0 , 0 }, /* 0x44 */
559: { 0, 0 , 0 }, /* 0x45 */
560: { 0, 0 , 0 }, /* 0x46 */
561: { 0, 0 , 0 }, /* 0x47 */
562: { 0, 0 , 0 }, /* 0x48 */
563: { flop_12d, DEC_DECODED, "fiadd." }, /* 0x49, [p]fiadd.{ss,dd} */
564: { 0, 0 , 0 }, /* 0x4A */
565: { 0, 0 , 0 }, /* 0x4B */
566: { 0, 0 , 0 }, /* 0x4C */
567: { flop_12d, DEC_DECODED, "fisub." }, /* 0x4D, [p]fisub.{ss,dd} */
568: { 0, 0 , 0 }, /* 0x4E */
569: { 0, 0 , 0 }, /* 0x4F */
570: { flop_12d, DEC_DECODED, "faddp" }, /* 0x50, [p]faddp */
571: { flop_12d, DEC_DECODED, "faddz" }, /* 0x51, [p]faddz */
572: { 0, 0 , 0 }, /* 0x52 */
573: { 0, 0 , 0 }, /* 0x53 */
574: { 0, 0 , 0 }, /* 0x54 */
575: { 0, 0 , 0 }, /* 0x55 */
576: { 0, 0 , 0 }, /* 0x56 */
577: { flop_12d, DEC_DECODED, "fzchkl" }, /* 0x57, [p]fzchkl */
578: { 0, 0 , 0 }, /* 0x58 */
579: { 0, 0 , 0 }, /* 0x59 */
580: { flop_1d, DEC_DECODED, "form" }, /* 0x5A, [p]form.dd */
581: { 0, 0 , 0 }, /* 0x5B */
582: { 0, 0 , 0 }, /* 0x5C */
583: { 0, 0 , 0 }, /* 0x5D */
584: { 0, 0 , 0 }, /* 0x5E */
585: { flop_12d, DEC_DECODED, "fzchks" }, /* 0x5F, [p]fzchks */
586: { 0, 0 , 0 }, /* 0x60 */
587: { 0, 0 , 0 }, /* 0x61 */
588: { 0, 0 , 0 }, /* 0x62 */
589: { 0, 0 , 0 }, /* 0x63 */
590: { 0, 0 , 0 }, /* 0x64 */
591: { 0, 0 , 0 }, /* 0x65 */
592: { 0, 0 , 0 }, /* 0x66 */
593: { 0, 0 , 0 }, /* 0x67 */
594: { 0, 0 , 0 }, /* 0x68 */
595: { 0, 0 , 0 }, /* 0x69 */
596: { 0, 0 , 0 }, /* 0x6A */
597: { 0, 0 , 0 }, /* 0x6B */
598: { 0, 0 , 0 }, /* 0x6C */
599: { 0, 0 , 0 }, /* 0x6D */
600: { 0, 0 , 0 }, /* 0x6E */
601: { 0, 0 , 0 }, /* 0x6F */
602: { 0, 0 , 0 }, /* 0x70 */
603: { 0, 0 , 0 }, /* 0x71 */
604: { 0, 0 , 0 }, /* 0x72 */
605: { 0, 0 , 0 }, /* 0x73 */
606: { 0, 0 , 0 }, /* 0x74 */
607: { 0, 0 , 0 }, /* 0x75 */
608: { 0, 0 , 0 }, /* 0x76 */
609: { 0, 0 , 0 }, /* 0x77 */
610: { 0, 0 , 0 }, /* 0x78 */
611: { 0, 0 , 0 }, /* 0x79 */
612: { 0, 0 , 0 }, /* 0x7A */
613: { 0, 0 , 0 }, /* 0x7B */
614: { 0, 0 , 0 }, /* 0x7C */
615: { 0, 0 , 0 }, /* 0x7D */
616: { 0, 0 , 0 }, /* 0x7E */
617: { 0, 0 , 0 }, /* 0x7F */
618: };
619:
620:
621: /* Replaces tabs with spaces. */
622: static void i860_dasm_tab_replacer(char* buf, int tab_size)
623: {
624: int i = 0;
625: int tab_count = 0;
626: char tab_buf[1024];
627: memset(tab_buf, 0, 1024);
628:
629: while (i != strlen(buf))
630: {
631: if (buf[i] != '\t')
632: {
633: tab_buf[tab_count] = buf[i];
634: tab_count++;
635: }
636: else
637: {
638: while (tab_count % tab_size != 0)
639: {
640: strcat(tab_buf, " ");
641: tab_count++;
642: }
643: }
644: i++;
645: }
646:
647: tab_buf[tab_count] = 0x00;
648: strcpy(buf, tab_buf);
649: }
650:
651:
652: int i860_disassembler(UINT32 pc, UINT32 insn, char* buffer) {
653: int unrecognized_op = 1;
654:
655: int upper_6bits = (insn >> 26) & 0x3f;
656: char flags = decode_tbl[upper_6bits].flags;
657: if(insn == INSN_NOP) {
658: strcpy(buffer, " nop");
659: unrecognized_op = 0;
660: } else if(insn == INSN_FNOP) {
661: strcpy(buffer, " fnop");
662: unrecognized_op = 0;
663: } else if(insn == INSN_FNOP_DIM) {
664: strcpy(buffer, "d.fnop");
665: unrecognized_op = 0;
666: } else if (flags & DEC_DECODED) {
667: const char *s = decode_tbl[upper_6bits].mnemonic;
668: decode_tbl[upper_6bits].insn_dis (buffer, (char *)s, pc, insn);
669: unrecognized_op = 0;
670: } else if (flags & DEC_MORE) {
671: if (upper_6bits == 0x12) {
672: /* FP instruction format handled here. */
673: char fp_flags = fp_decode_tbl[insn & 0x7f].flags;
674: const char *s = fp_decode_tbl[insn & 0x7f].mnemonic;
675: if (fp_flags & DEC_DECODED) {
676: fp_decode_tbl[insn & 0x7f].insn_dis (buffer, (char *)s, pc, insn);
677: unrecognized_op = 0;
678: }
679: }
680: else if (upper_6bits == 0x13) {
681: /* Core escape instruction format handled here. */
682: char esc_flags = core_esc_decode_tbl[insn & 0x3].flags;
683: const char *s = core_esc_decode_tbl[insn & 0x3].mnemonic;
684: if (esc_flags & DEC_DECODED)
685: {
686: core_esc_decode_tbl[insn & 0x3].insn_dis (buffer, (char *)s, pc, insn);
687: unrecognized_op = 0;
688: }
689: }
690: }
691:
692: if (unrecognized_op)
693: sprintf (buffer, " .long\t%#08x", insn);
694:
695: /* Replace tabs with spaces */
696: i860_dasm_tab_replacer(buffer, 10);
697:
698: /* Return number of bytes disassembled. */
699: /* MAME dasm flags haven't been added yet */
700: return (4);
701: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.