1 /* Print i860 instructions for GDB, the GNU debugger.
2 Copyright (C) 1992 Free Software Foundation, Inc.
3 Contributed by Peggy Fieland (pfieland@stratus.com)
5 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
6 WARRANTY. No author or distributor accepts responsibility to anyone
7 for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing.
9 Refer to the GDB General Public License for full details.
11 Everyone is granted permission to copy, modify and redistribute GDB,
12 but only under the conditions described in the GDB General Public
13 License. A copy of this license is supposed to have been given to you
14 along with GDB so you can know your rights and responsibilities. It
15 should be in a file named COPYING. Among other things, the copyright
16 notice and this notice must be preserved on all copies.
18 In other words, go ahead and share GDB, but don't try to stop
19 anyone else from sharing it farther. Help stamp out software hoarding!
26 #include "i860-opcode.h"
28 /* i860 instructions are never longer than this many bytes. */
31 static int fp_instr();
32 static void fld_offset();
33 static void gen_rrr();
34 static void gen_irr();
38 * integer registers names
40 static char *ireg
[32] =
42 "r0", "r1", "sp", "fp", "r4", "r5", "r6", "r7",
43 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
44 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
45 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
49 * Control registers of the ld.c and st.c instructions
51 static char *ctlreg
[32] =
53 "fir", "psr", "dirbase", "db", "fsr", "?", "?", "?",
54 "?", "?", "?", "?", "?", "?", "?", "?",
55 "?", "?", "?", "?", "?", "?", "?", "?",
56 "?", "?", "?", "?", "?", "?", "?", "?"
60 /***********************************************************************
61 * Print the i860 instruction at address MEMADDR in debugged memory,
62 * on STREAM. Returns length of the instruction, in bytes, which
67 print_insn (memaddr
, stream
)
68 CORE_ADDR memaddr
; /* address of the instruction */
69 FILE *stream
; /* stream on which to write result */
71 union insn_fmt insn
; /* the instruction we're decoding */
72 long offset
; /* the (decoded) offset from the instruction */
73 long split_offset
; /* the value of a ld/st-style split offset */
74 int ai
; /* autoincrement flag */
75 char suffix
; /* length suffix */
77 adj_read_memory (memaddr
, &insn
, MAXLEN
);
79 /* These offsets used in ld, st, bte, etc. instructions and are formed by
80 * combining 2 separate fields within the instruction and sign-extending
84 split_offset
= (insn
.gen
.dest
<< 11) | insn
.gen
.offset
;
85 split_offset
= SIGN_EXT(16, split_offset
);
91 fprintf (stream
, "ld.b %s(%s),%s", ireg
[insn
.gen
.src1
],
92 ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
95 offset
= SIGN_EXT(16, insn
.geni
.offset
);
96 fprintf (stream
, "ld.b 0x%x(%s),%s", offset
,
97 ireg
[insn
.geni
.src2
], ireg
[insn
.geni
.dest
]);
100 fprintf (stream
, "ixfr %s,f%d", ireg
[insn
.gen
.src1
], insn
.gen
.dest
);
103 fprintf (stream
, "st.b %s,0x%x(%s)", ireg
[insn
.gen
.src1
], split_offset
,
104 ireg
[insn
.geni
.src2
]);
107 fprintf (stream
, "ld.%c %s(%s),%s", (insn
.gen
.offset
& 1) ? 'l' : 's',
108 ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
111 offset
= SIGN_EXT(16, insn
.geni
.offset
);
112 fprintf (stream
, "ld.%c 0x%x(%s),%s", (insn
.geni
.offset
& 1) ? 'l' : 's',
113 (offset
& ~1), ireg
[insn
.geni
.src2
], ireg
[insn
.geni
.dest
]);
117 fprintf (stream
, "st.%c %s,0x%x(%s)", (insn
.geni
.offset
& 1) ? 'l' : 's',
118 ireg
[insn
.gen
.src1
], (split_offset
& ~1), ireg
[insn
.geni
.src2
]);
122 offset
= insn
.gen
.offset
;
123 fld_offset(&offset
, &suffix
, &ai
);
125 fprintf (stream
, "fld.%c %s(%s)%s,f%d", suffix
,
126 ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
], ai
? "++" : "",
130 offset
= SIGN_EXT(16, insn
.geni
.offset
);
131 fld_offset(&offset
, &suffix
, &ai
);
133 fprintf (stream
, "fld.%c 0x%x(%s)%s,f%d", suffix
,
134 offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "", insn
.gen
.dest
);
137 offset
= insn
.gen
.offset
;
138 fld_offset(&offset
, &suffix
, &ai
);
140 fprintf (stream
, "fst.%c f%d,%s(%s)%s", suffix
,
141 insn
.gen
.dest
, ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
],
145 offset
= SIGN_EXT(16, insn
.geni
.offset
);
146 fld_offset(&offset
, &suffix
, &ai
);
148 fprintf (stream
, "fst.%c f%d,0x%x(%s)%s", suffix
,
149 insn
.gen
.dest
, offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "");
152 fprintf (stream
, "ld.c %s,%s", ctlreg
[insn
.gen
.src2
],
153 ireg
[insn
.gen
.dest
]);
156 offset
= SIGN_EXT(16, insn
.geni
.offset
);
157 fld_offset(&offset
, &suffix
, &ai
);
159 fprintf (stream
, "flush 0x%x(%s)%s", offset
, ireg
[insn
.gen
.src2
],
163 fprintf (stream
, "st.c %s,%s", ireg
[insn
.gen
.src1
],
164 ctlreg
[insn
.gen
.src2
]);
167 offset
= SIGN_EXT(16, insn
.geni
.offset
);
168 fld_offset(&offset
, &suffix
, &ai
);
170 fprintf (stream
, "pst.d f%d,0x%x(%s)%s", insn
.gen
.dest
,
171 offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "");
175 fprintf (stream
, "bri %s", ireg
[insn
.gen
.src1
]);
178 gen_rrr("trap", insn
, stream
);
182 * Floating-point Opcodes
184 if (!fp_instr(insn
.fp
, stream
))
185 fprintf (stream
, "0x%08x (invalid instruction)", insn
.int_val
);
189 * Core Escape Opcodes
191 switch (insn
.esc
.op2
)
194 fprintf (stream
, "lock");
197 fprintf (stream
, "calli %s", ireg
[insn
.esc
.src1
]);
200 fprintf (stream
, "intovr");
203 fprintf (stream
, "unlock");
206 fprintf (stream
, "0x%08x (invalid instruction)", insn
.int_val
);
212 fprintf (stream
, "btne %s,%s,", ireg
[insn
.gen
.src1
],
213 ireg
[insn
.gen
.src2
]);
214 offset
= split_offset
<< 2;
215 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
218 fprintf (stream
, "btne 0x%x,%s,", insn
.gen
.src1
, ireg
[insn
.gen
.src2
]);
219 offset
= split_offset
<< 2;
220 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
223 fprintf (stream
, "bte %s,%s,", ireg
[insn
.gen
.src1
],
224 ireg
[insn
.gen
.src2
]);
225 offset
= split_offset
<< 2;
226 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
229 fprintf (stream
, "bte 0x%x,%s,", insn
.gen
.src1
, ireg
[insn
.gen
.src2
]);
230 offset
= split_offset
<< 2;
231 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
235 offset
= insn
.gen
.offset
;
236 fld_offset(&offset
, &suffix
, &ai
);
238 fprintf (stream
, "pfld.%c %s(%s)%s,f%d", suffix
,
239 ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
], ai
? "++" : "",
243 offset
= SIGN_EXT(16, insn
.geni
.offset
);
244 fld_offset(&offset
, &suffix
, &ai
);
246 fprintf (stream
, "pfld.%c 0x%x(%s)%s,f%d", suffix
,
247 offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "", insn
.gen
.dest
);
250 ctrl_a("br", insn
, memaddr
, stream
);
253 ctrl_a("call", insn
, memaddr
, stream
);
256 ctrl_a("bc", insn
, memaddr
, stream
);
259 ctrl_a("bc.t", insn
, memaddr
, stream
);
262 ctrl_a("bnc", insn
, memaddr
, stream
);
265 ctrl_a("bnc.t", insn
, memaddr
, stream
);
269 gen_rrr("addu", insn
, stream
);
272 gen_irr("addu", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
275 gen_rrr("subu", insn
, stream
);
278 gen_irr("subu", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
281 gen_rrr("adds", insn
, stream
);
284 gen_irr("adds", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
287 gen_rrr("subs", insn
, stream
);
290 gen_irr("subs", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
294 if (insn
.gen
.src1
== 0)
296 if (insn
.gen
.src2
== 0 && insn
.gen
.dest
== 0)
297 fprintf (stream
, "nop");
299 fprintf (stream
, "mov %s,%s", ireg
[insn
.gen
.src2
],
300 ireg
[insn
.gen
.dest
]);
303 gen_rrr("shl", insn
, stream
);
306 gen_irr("shl", insn
, insn
.geni
.offset
, stream
);
309 gen_rrr("shr", insn
, stream
);
312 gen_irr("shr", insn
, insn
.geni
.offset
, stream
);
315 if (insn
.gen
.src1
== 0 && insn
.gen
.src2
== 0 && insn
.gen
.dest
== 0)
317 if ((insn
.int_val
& (1 << 9)) != 0)
318 fprintf (stream
, "d.");
319 fprintf (stream
, "fnop");
322 gen_rrr("shrd", insn
, stream
);
325 fprintf (stream
, "bla %s,%s,", ireg
[insn
.gen
.src1
],
326 ireg
[insn
.gen
.src2
]);
327 offset
= split_offset
<< 2;
328 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
331 gen_rrr("shra", insn
, stream
);
334 gen_irr("shra", insn
, insn
.geni
.offset
, stream
);
338 gen_rrr("and", insn
, stream
);
341 gen_irr("and", insn
, insn
.geni
.offset
, stream
);
345 gen_irr("andh", insn
, insn
.geni
.offset
, stream
);
348 gen_rrr("andnot", insn
, stream
);
351 gen_irr("andnot", insn
, insn
.geni
.offset
, stream
);
355 gen_irr("andnoth", insn
, insn
.geni
.offset
, stream
);
359 gen_rrr("or", insn
, stream
);
362 gen_irr("or", insn
, insn
.geni
.offset
, stream
);
366 gen_irr("orh", insn
, insn
.geni
.offset
, stream
);
369 gen_rrr("xor", insn
, stream
);
372 gen_irr("xor", insn
, insn
.geni
.offset
, stream
);
376 gen_irr("xorh", insn
, insn
.geni
.offset
, stream
);
380 fprintf (stream
, "0x%08x (invalid instruction)", insn
.int_val
);
387 /* A full list of floating point opcodes - if the entry is NULL, there is
388 * no corresponding instruction
391 static char *fp_ops
[] =
393 "r2p1", "r2pt", "r2ap1", "r2apt",
394 "i2p1", "i2pt", "i2ap1", "i2apt",
395 "rat1p2", "m12apm", "ra1p2", "m12ttpa",
396 "iat1p2", "m12tpm", "ia1p2", "m12tpa",
398 "r2s1", "r2st", "r2as1", "r2ast",
399 "i2s1", "i2st", "i2as1", "i2ast",
400 "rat1s2", "m12asm", "ra1s2", "m12ttsa",
401 "iat1s2", "m12tsm", "ia1s2", "m12tsa",
403 "fmul", "fmlow", "frcp", "frsqr",
404 "fmul3", NULL
, NULL
, NULL
,
405 NULL
, NULL
, NULL
, NULL
,
406 NULL
, NULL
, NULL
, NULL
,
408 "fadd", "fsub", "fix", "famov",
409 "fgt", "feq", NULL
, NULL
,
410 NULL
, NULL
, "ftrunc", NULL
,
411 NULL
, NULL
, NULL
, NULL
,
413 "fxfr", NULL
, NULL
, NULL
,
414 NULL
, NULL
, NULL
, NULL
,
415 NULL
, "fiadd", NULL
, NULL
,
416 NULL
, "fisub", NULL
, NULL
,
418 "faddp", "faddz", NULL
, NULL
,
419 NULL
, NULL
, NULL
, "fzchkl",
420 NULL
, NULL
, "form", NULL
,
421 NULL
, NULL
, NULL
, "fzchks",
424 /* Alternate list of floating point opcodes for PFMAM/PFMSM instructions
427 static char *alt_fp_ops
[] =
429 "mr2p1", "mr2pt", "mr2mp1", "mr2mpt",
430 "mi2p1", "mi2pt", "mi2mp1", "mi2mpt",
431 "mrmt1p2", "mm12mpm", "mrm1p2", "mm12ttpm",
432 "mimt1p2", "mm12tpm", "mim1p2", "mm12tpm",
434 "mr2s1", "mr2st", "mr2ms1", "mr2mst",
435 "mi2s1", "mi2st", "mi2ms1", "mi2mst",
436 "mrmt1s2", "mm12msm", "mrm1s2", "mm12ttsm",
437 "mimt1s2", "mm12tsm", "mim1s2", "mm12tsm",
441 /* Floating point precision suffix values - indexed by s and r bits of
445 static char precision
[2] =
450 /***********************************************************************
451 * Print floating-point instruction 'insn' on the indicated stream
452 * Returns 1 if successful, 0 on failure (invalid instruction)
456 fp_instr(insn
, stream
)
457 struct fp_fmt insn
; /* instruction to decode */
458 FILE *stream
; /* stream to print on */
460 char *name
; /* the opcode name */
462 name
= fp_ops
[insn
.op2
];
464 fprintf(stream
, "d.");
472 if (insn
.p
== 0) /* use PFMAM/PFMSM ops if p=0 */
473 name
= alt_fp_ops
[insn
.op2
];
475 fprintf (stream
, "%s.%c%c f%d,f%d,f%d", name
,
476 precision
[insn
.s
], precision
[insn
.r
],
477 insn
.src1
, insn
.src2
, insn
.dest
);
483 case 0x21: /* fmlow (no pipeline allowed) */
484 fprintf (stream
, "%s.%c%c f%d,f%d,f%d", name
,
485 precision
[insn
.s
], precision
[insn
.r
],
486 insn
.src1
, insn
.src2
, insn
.dest
);
489 case 0x22: /* frcp */
490 case 0x23: /* fsqrt */
491 fprintf (stream
, "%s.%c%c f%d,f%d", name
,
492 precision
[insn
.s
], precision
[insn
.r
],
493 insn
.src2
, insn
.dest
);
496 case 0x24: /* pfmul3 */
497 fprintf (stream
, "pfmul3.dd f%d,f%d,f%d",
498 insn
.src1
, insn
.src2
, insn
.dest
);
501 case 0x30: /* fadd */
502 case 0x49: /* fiadd */
508 fprintf (stream
, "%sfmov.%c%c f%d,f%d", insn
.p
? "p" : "",
509 precision
[insn
.s
], precision
[insn
.r
],
510 insn
.src1
, insn
.dest
);
514 fprintf (stream
, "%s%s.%c%c f%d,f%d,f%d", insn
.p
? "p" : "", name
,
515 precision
[insn
.s
], precision
[insn
.r
],
516 insn
.src1
, insn
.src2
, insn
.dest
);
521 case 0x3A: /* ftrunc */
522 fprintf (stream
, "%s%s.%c%c f%d,f%d", insn
.p
? "p" : "", name
,
523 precision
[insn
.s
], precision
[insn
.r
],
524 insn
.src1
, insn
.dest
);
527 case 0x34: /* pfgt/pfle */
530 fprintf (stream
, "p%s.%c%c f%d,f%d,f%d", name
,
531 precision
[insn
.s
], precision
[insn
.s
],
532 insn
.src1
, insn
.src2
, insn
.dest
);
535 case 0x35: /* pfeq */
536 fprintf (stream
, "pfeq.%c%c f%d,f%d,f%d",
537 precision
[insn
.s
], precision
[insn
.r
],
538 insn
.src1
, insn
.src2
, insn
.dest
);
541 case 0x40: /* fxfr */
542 fprintf (stream
, "fxfr f%d,%s", insn
.src1
, ireg
[insn
.dest
]);
545 case 0x50: /* faddp */
546 case 0x51: /* faddz */
547 case 0x57: /* fzchkl */
548 case 0x5F: /* fzchks */
550 * Graphics ops with no precision
552 fprintf (stream
, "%s%s f%d,f%d,f%d", insn
.p
? "p" : "", name
,
553 insn
.src1
, insn
.src2
, insn
.dest
);
556 case 0x5A: /* form */
557 fprintf (stream
, "%sform f%d,f%d", insn
.p
? "p" : "",
558 insn
.src1
, insn
.dest
);
563 * All the rest are uniform 3-address, optionally pipelined, etc
566 fprintf (stream
, "%s%s.%c%c f%d,f%d,f%d", insn
.p
? "p" : "", name
,
567 precision
[insn
.s
], precision
[insn
.r
],
568 insn
.src1
, insn
.src2
, insn
.dest
);
577 /***********************************************************************
578 * Decode fld/fst-style offset encodings into actual offset, precision suffix,
579 * and autoincrement flag
583 fld_offset(offset
, suffix
, autoincrement
)
584 long *offset
; /* original and returned offset */
585 char *suffix
; /* returned suffix character */
586 int *autoincrement
; /* autoincrement flag (1 if ai) */
588 long off
= *offset
; /* working copy of *offset */
590 *autoincrement
= ((off
& 1) != 0);
595 *offset
= (off
& ~3);
600 *offset
= (off
& ~7);
605 *offset
= (off
& ~7);
609 /***********************************************************************
610 * Print a general format instruction of the three register form:
615 gen_rrr(name
, insn
, stream
)
620 fprintf (stream
, "%s %s,%s,%s", name
, ireg
[insn
.gen
.src1
],
621 ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
624 /***********************************************************************
625 * Print a general format instruction of the immed + two register form:
630 gen_irr(name
, insn
, immed
, stream
)
636 fprintf (stream
, "%s 0x%x,%s,%s", name
, immed
,
637 ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
640 /***********************************************************************
641 * Print a ctrl format instruction with a 26-bit displacement:
646 ctrl_a(name
, insn
, memaddr
, stream
)
654 fprintf (stream
, "%s ", name
);
655 offset
= SIGN_EXT(28, insn
.ctrl
.offset
<< 2);
657 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
This page took 0.043889 seconds and 4 git commands to generate.