1 /* Print i860 instructions for GDB, the GNU debugger.
2 Copyright status of this module is unclear!!!
3 Copyright (C) 1992 Free Software Foundation, Inc.
4 SVR4 changes Contributed by Peggy Fieland (pfieland@stratus.com)
6 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
7 WARRANTY. No author or distributor accepts responsibility to anyone
8 for the consequences of using it or for whether it serves any
9 particular purpose or works at all, unless he says so in writing.
10 Refer to the GDB General Public License for full details.
12 Everyone is granted permission to copy, modify and redistribute GDB,
13 but only under the conditions described in the GDB General Public
14 License. A copy of this license is supposed to have been given to you
15 along with GDB so you can know your rights and responsibilities. It
16 should be in a file named COPYING. Among other things, the copyright
17 notice and this notice must be preserved on all copies.
19 In other words, go ahead and share GDB, but don't try to stop
20 anyone else from sharing it farther. Help stamp out software hoarding!
25 #include "i860-opcode.h"
27 /* i860 instructions are never longer than this many bytes. */
30 static int fp_instr();
31 static void fld_offset();
32 static void gen_rrr();
33 static void gen_irr();
37 * integer registers names
39 static char *ireg
[32] =
41 "r0", "r1", "sp", "fp", "r4", "r5", "r6", "r7",
42 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
43 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
44 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
48 * Control registers of the ld.c and st.c instructions
50 static char *ctlreg
[32] =
52 "fir", "psr", "dirbase", "db", "fsr", "?", "?", "?",
53 "?", "?", "?", "?", "?", "?", "?", "?",
54 "?", "?", "?", "?", "?", "?", "?", "?",
55 "?", "?", "?", "?", "?", "?", "?", "?"
59 /***********************************************************************
60 * Print the i860 instruction at address MEMADDR in debugged memory,
61 * on STREAM. Returns length of the instruction, in bytes, which
66 print_insn (memaddr
, stream
)
67 CORE_ADDR memaddr
; /* address of the instruction */
68 FILE *stream
; /* stream on which to write result */
70 union insn_fmt insn
; /* the instruction we're decoding */
71 long offset
; /* the (decoded) offset from the instruction */
72 long split_offset
; /* the value of a ld/st-style split offset */
73 int ai
; /* autoincrement flag */
74 char suffix
; /* length suffix */
76 adj_read_memory (memaddr
, &insn
, MAXLEN
);
78 /* These offsets used in ld, st, bte, etc. instructions and are formed by
79 * combining 2 separate fields within the instruction and sign-extending
83 split_offset
= (insn
.gen
.dest
<< 11) | insn
.gen
.offset
;
84 split_offset
= SIGN_EXT(16, split_offset
);
90 fprintf (stream
, "ld.b %s(%s),%s", ireg
[insn
.gen
.src1
],
91 ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
94 offset
= SIGN_EXT(16, insn
.geni
.offset
);
95 fprintf (stream
, "ld.b 0x%x(%s),%s", offset
,
96 ireg
[insn
.geni
.src2
], ireg
[insn
.geni
.dest
]);
99 fprintf (stream
, "ixfr %s,f%d", ireg
[insn
.gen
.src1
], insn
.gen
.dest
);
102 fprintf (stream
, "st.b %s,0x%x(%s)", ireg
[insn
.gen
.src1
], split_offset
,
103 ireg
[insn
.geni
.src2
]);
106 fprintf (stream
, "ld.%c %s(%s),%s", (insn
.gen
.offset
& 1) ? 'l' : 's',
107 ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
110 offset
= SIGN_EXT(16, insn
.geni
.offset
);
111 fprintf (stream
, "ld.%c 0x%x(%s),%s", (insn
.geni
.offset
& 1) ? 'l' : 's',
112 (offset
& ~1), ireg
[insn
.geni
.src2
], ireg
[insn
.geni
.dest
]);
116 fprintf (stream
, "st.%c %s,0x%x(%s)", (insn
.geni
.offset
& 1) ? 'l' : 's',
117 ireg
[insn
.gen
.src1
], (split_offset
& ~1), ireg
[insn
.geni
.src2
]);
121 offset
= insn
.gen
.offset
;
122 fld_offset(&offset
, &suffix
, &ai
);
124 fprintf (stream
, "fld.%c %s(%s)%s,f%d", suffix
,
125 ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
], ai
? "++" : "",
129 offset
= SIGN_EXT(16, insn
.geni
.offset
);
130 fld_offset(&offset
, &suffix
, &ai
);
132 fprintf (stream
, "fld.%c 0x%x(%s)%s,f%d", suffix
,
133 offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "", insn
.gen
.dest
);
136 offset
= insn
.gen
.offset
;
137 fld_offset(&offset
, &suffix
, &ai
);
139 fprintf (stream
, "fst.%c f%d,%s(%s)%s", suffix
,
140 insn
.gen
.dest
, ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
],
144 offset
= SIGN_EXT(16, insn
.geni
.offset
);
145 fld_offset(&offset
, &suffix
, &ai
);
147 fprintf (stream
, "fst.%c f%d,0x%x(%s)%s", suffix
,
148 insn
.gen
.dest
, offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "");
151 fprintf (stream
, "ld.c %s,%s", ctlreg
[insn
.gen
.src2
],
152 ireg
[insn
.gen
.dest
]);
155 offset
= SIGN_EXT(16, insn
.geni
.offset
);
156 fld_offset(&offset
, &suffix
, &ai
);
158 fprintf (stream
, "flush 0x%x(%s)%s", offset
, ireg
[insn
.gen
.src2
],
162 fprintf (stream
, "st.c %s,%s", ireg
[insn
.gen
.src1
],
163 ctlreg
[insn
.gen
.src2
]);
166 offset
= SIGN_EXT(16, insn
.geni
.offset
);
167 fld_offset(&offset
, &suffix
, &ai
);
169 fprintf (stream
, "pst.d f%d,0x%x(%s)%s", insn
.gen
.dest
,
170 offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "");
174 fprintf (stream
, "bri %s", ireg
[insn
.gen
.src1
]);
177 gen_rrr("trap", insn
, stream
);
181 * Floating-point Opcodes
183 if (!fp_instr(insn
.fp
, stream
))
184 fprintf (stream
, "0x%08x (invalid instruction)", insn
.int_val
);
188 * Core Escape Opcodes
190 switch (insn
.esc
.op2
)
193 fprintf (stream
, "lock");
196 fprintf (stream
, "calli %s", ireg
[insn
.esc
.src1
]);
199 fprintf (stream
, "intovr");
202 fprintf (stream
, "unlock");
205 fprintf (stream
, "0x%08x (invalid instruction)", insn
.int_val
);
211 fprintf (stream
, "btne %s,%s,", ireg
[insn
.gen
.src1
],
212 ireg
[insn
.gen
.src2
]);
213 offset
= split_offset
<< 2;
214 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
217 fprintf (stream
, "btne 0x%x,%s,", insn
.gen
.src1
, ireg
[insn
.gen
.src2
]);
218 offset
= split_offset
<< 2;
219 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
222 fprintf (stream
, "bte %s,%s,", ireg
[insn
.gen
.src1
],
223 ireg
[insn
.gen
.src2
]);
224 offset
= split_offset
<< 2;
225 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
228 fprintf (stream
, "bte 0x%x,%s,", insn
.gen
.src1
, ireg
[insn
.gen
.src2
]);
229 offset
= split_offset
<< 2;
230 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
234 offset
= insn
.gen
.offset
;
235 fld_offset(&offset
, &suffix
, &ai
);
237 fprintf (stream
, "pfld.%c %s(%s)%s,f%d", suffix
,
238 ireg
[insn
.gen
.src1
], ireg
[insn
.gen
.src2
], ai
? "++" : "",
242 offset
= SIGN_EXT(16, insn
.geni
.offset
);
243 fld_offset(&offset
, &suffix
, &ai
);
245 fprintf (stream
, "pfld.%c 0x%x(%s)%s,f%d", suffix
,
246 offset
, ireg
[insn
.gen
.src2
], ai
? "++" : "", insn
.gen
.dest
);
249 ctrl_a("br", insn
, memaddr
, stream
);
252 ctrl_a("call", insn
, memaddr
, stream
);
255 ctrl_a("bc", insn
, memaddr
, stream
);
258 ctrl_a("bc.t", insn
, memaddr
, stream
);
261 ctrl_a("bnc", insn
, memaddr
, stream
);
264 ctrl_a("bnc.t", insn
, memaddr
, stream
);
268 gen_rrr("addu", insn
, stream
);
271 gen_irr("addu", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
274 gen_rrr("subu", insn
, stream
);
277 gen_irr("subu", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
280 gen_rrr("adds", insn
, stream
);
283 gen_irr("adds", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
286 gen_rrr("subs", insn
, stream
);
289 gen_irr("subs", insn
, SIGN_EXT(16, insn
.geni
.offset
), stream
);
293 if (insn
.gen
.src1
== 0)
295 if (insn
.gen
.src2
== 0 && insn
.gen
.dest
== 0)
296 fprintf (stream
, "nop");
298 fprintf (stream
, "mov %s,%s", ireg
[insn
.gen
.src2
],
299 ireg
[insn
.gen
.dest
]);
302 gen_rrr("shl", insn
, stream
);
305 gen_irr("shl", insn
, insn
.geni
.offset
, stream
);
308 gen_rrr("shr", insn
, stream
);
311 gen_irr("shr", insn
, insn
.geni
.offset
, stream
);
314 if (insn
.gen
.src1
== 0 && insn
.gen
.src2
== 0 && insn
.gen
.dest
== 0)
316 if ((insn
.int_val
& (1 << 9)) != 0)
317 fprintf (stream
, "d.");
318 fprintf (stream
, "fnop");
321 gen_rrr("shrd", insn
, stream
);
324 fprintf (stream
, "bla %s,%s,", ireg
[insn
.gen
.src1
],
325 ireg
[insn
.gen
.src2
]);
326 offset
= split_offset
<< 2;
327 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
330 gen_rrr("shra", insn
, stream
);
333 gen_irr("shra", insn
, insn
.geni
.offset
, stream
);
337 gen_rrr("and", insn
, stream
);
340 gen_irr("and", insn
, insn
.geni
.offset
, stream
);
344 gen_irr("andh", insn
, insn
.geni
.offset
, stream
);
347 gen_rrr("andnot", insn
, stream
);
350 gen_irr("andnot", insn
, insn
.geni
.offset
, stream
);
354 gen_irr("andnoth", insn
, insn
.geni
.offset
, stream
);
358 gen_rrr("or", insn
, stream
);
361 gen_irr("or", insn
, insn
.geni
.offset
, stream
);
365 gen_irr("orh", insn
, insn
.geni
.offset
, stream
);
368 gen_rrr("xor", insn
, stream
);
371 gen_irr("xor", insn
, insn
.geni
.offset
, stream
);
375 gen_irr("xorh", insn
, insn
.geni
.offset
, stream
);
379 fprintf (stream
, "0x%08x (invalid instruction)", insn
.int_val
);
386 /* A full list of floating point opcodes - if the entry is NULL, there is
387 * no corresponding instruction
390 static char *fp_ops
[] =
392 "r2p1", "r2pt", "r2ap1", "r2apt",
393 "i2p1", "i2pt", "i2ap1", "i2apt",
394 "rat1p2", "m12apm", "ra1p2", "m12ttpa",
395 "iat1p2", "m12tpm", "ia1p2", "m12tpa",
397 "r2s1", "r2st", "r2as1", "r2ast",
398 "i2s1", "i2st", "i2as1", "i2ast",
399 "rat1s2", "m12asm", "ra1s2", "m12ttsa",
400 "iat1s2", "m12tsm", "ia1s2", "m12tsa",
402 "fmul", "fmlow", "frcp", "frsqr",
403 "fmul3", NULL
, NULL
, NULL
,
404 NULL
, NULL
, NULL
, NULL
,
405 NULL
, NULL
, NULL
, NULL
,
407 "fadd", "fsub", "fix", "famov",
408 "fgt", "feq", NULL
, NULL
,
409 NULL
, NULL
, "ftrunc", NULL
,
410 NULL
, NULL
, NULL
, NULL
,
412 "fxfr", NULL
, NULL
, NULL
,
413 NULL
, NULL
, NULL
, NULL
,
414 NULL
, "fiadd", NULL
, NULL
,
415 NULL
, "fisub", NULL
, NULL
,
417 "faddp", "faddz", NULL
, NULL
,
418 NULL
, NULL
, NULL
, "fzchkl",
419 NULL
, NULL
, "form", NULL
,
420 NULL
, NULL
, NULL
, "fzchks",
423 /* Alternate list of floating point opcodes for PFMAM/PFMSM instructions
426 static char *alt_fp_ops
[] =
428 "mr2p1", "mr2pt", "mr2mp1", "mr2mpt",
429 "mi2p1", "mi2pt", "mi2mp1", "mi2mpt",
430 "mrmt1p2", "mm12mpm", "mrm1p2", "mm12ttpm",
431 "mimt1p2", "mm12tpm", "mim1p2", "mm12tpm",
433 "mr2s1", "mr2st", "mr2ms1", "mr2mst",
434 "mi2s1", "mi2st", "mi2ms1", "mi2mst",
435 "mrmt1s2", "mm12msm", "mrm1s2", "mm12ttsm",
436 "mimt1s2", "mm12tsm", "mim1s2", "mm12tsm",
440 /* Floating point precision suffix values - indexed by s and r bits of
444 static char precision
[2] =
449 /***********************************************************************
450 * Print floating-point instruction 'insn' on the indicated stream
451 * Returns 1 if successful, 0 on failure (invalid instruction)
455 fp_instr(insn
, stream
)
456 struct fp_fmt insn
; /* instruction to decode */
457 FILE *stream
; /* stream to print on */
459 char *name
; /* the opcode name */
461 name
= fp_ops
[insn
.op2
];
463 fprintf(stream
, "d.");
471 if (insn
.p
== 0) /* use PFMAM/PFMSM ops if p=0 */
472 name
= alt_fp_ops
[insn
.op2
];
474 fprintf (stream
, "%s.%c%c f%d,f%d,f%d", name
,
475 precision
[insn
.s
], precision
[insn
.r
],
476 insn
.src1
, insn
.src2
, insn
.dest
);
482 case 0x21: /* fmlow (no pipeline allowed) */
483 fprintf (stream
, "%s.%c%c f%d,f%d,f%d", name
,
484 precision
[insn
.s
], precision
[insn
.r
],
485 insn
.src1
, insn
.src2
, insn
.dest
);
488 case 0x22: /* frcp */
489 case 0x23: /* fsqrt */
490 fprintf (stream
, "%s.%c%c f%d,f%d", name
,
491 precision
[insn
.s
], precision
[insn
.r
],
492 insn
.src2
, insn
.dest
);
495 case 0x24: /* pfmul3 */
496 fprintf (stream
, "pfmul3.dd f%d,f%d,f%d",
497 insn
.src1
, insn
.src2
, insn
.dest
);
500 case 0x30: /* fadd */
501 case 0x49: /* fiadd */
507 fprintf (stream
, "%sfmov.%c%c f%d,f%d", insn
.p
? "p" : "",
508 precision
[insn
.s
], precision
[insn
.r
],
509 insn
.src1
, insn
.dest
);
513 fprintf (stream
, "%s%s.%c%c f%d,f%d,f%d", insn
.p
? "p" : "", name
,
514 precision
[insn
.s
], precision
[insn
.r
],
515 insn
.src1
, insn
.src2
, insn
.dest
);
520 case 0x3A: /* ftrunc */
521 fprintf (stream
, "%s%s.%c%c f%d,f%d", insn
.p
? "p" : "", name
,
522 precision
[insn
.s
], precision
[insn
.r
],
523 insn
.src1
, insn
.dest
);
526 case 0x34: /* pfgt/pfle */
529 fprintf (stream
, "p%s.%c%c f%d,f%d,f%d", name
,
530 precision
[insn
.s
], precision
[insn
.s
],
531 insn
.src1
, insn
.src2
, insn
.dest
);
534 case 0x35: /* pfeq */
535 fprintf (stream
, "pfeq.%c%c f%d,f%d,f%d",
536 precision
[insn
.s
], precision
[insn
.r
],
537 insn
.src1
, insn
.src2
, insn
.dest
);
540 case 0x40: /* fxfr */
541 fprintf (stream
, "fxfr f%d,%s", insn
.src1
, ireg
[insn
.dest
]);
544 case 0x50: /* faddp */
545 case 0x51: /* faddz */
546 case 0x57: /* fzchkl */
547 case 0x5F: /* fzchks */
549 * Graphics ops with no precision
551 fprintf (stream
, "%s%s f%d,f%d,f%d", insn
.p
? "p" : "", name
,
552 insn
.src1
, insn
.src2
, insn
.dest
);
555 case 0x5A: /* form */
556 fprintf (stream
, "%sform f%d,f%d", insn
.p
? "p" : "",
557 insn
.src1
, insn
.dest
);
562 * All the rest are uniform 3-address, optionally pipelined, etc
565 fprintf (stream
, "%s%s.%c%c f%d,f%d,f%d", insn
.p
? "p" : "", name
,
566 precision
[insn
.s
], precision
[insn
.r
],
567 insn
.src1
, insn
.src2
, insn
.dest
);
576 /***********************************************************************
577 * Decode fld/fst-style offset encodings into actual offset, precision suffix,
578 * and autoincrement flag
582 fld_offset(offset
, suffix
, autoincrement
)
583 long *offset
; /* original and returned offset */
584 char *suffix
; /* returned suffix character */
585 int *autoincrement
; /* autoincrement flag (1 if ai) */
587 long off
= *offset
; /* working copy of *offset */
589 *autoincrement
= ((off
& 1) != 0);
594 *offset
= (off
& ~3);
599 *offset
= (off
& ~7);
604 *offset
= (off
& ~7);
608 /***********************************************************************
609 * Print a general format instruction of the three register form:
614 gen_rrr(name
, insn
, stream
)
619 fprintf (stream
, "%s %s,%s,%s", name
, ireg
[insn
.gen
.src1
],
620 ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
623 /***********************************************************************
624 * Print a general format instruction of the immed + two register form:
629 gen_irr(name
, insn
, immed
, stream
)
635 fprintf (stream
, "%s 0x%x,%s,%s", name
, immed
,
636 ireg
[insn
.gen
.src2
], ireg
[insn
.gen
.dest
]);
639 /***********************************************************************
640 * Print a ctrl format instruction with a 26-bit displacement:
645 ctrl_a(name
, insn
, memaddr
, stream
)
653 fprintf (stream
, "%s ", name
);
654 offset
= SIGN_EXT(28, insn
.ctrl
.offset
<< 2);
656 print_address ((CORE_ADDR
) (memaddr
+ 4 + offset
), stream
);
This page took 0.044158 seconds and 4 git commands to generate.