* stabs.texinfo: Document the format for C++ nested types.
[deliverable/binutils-gdb.git] / gdb / i860-pinsn.c
CommitLineData
be9a2362 1/* Print i860 instructions for GDB, the GNU debugger.
67278683
FF
2 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@mcc.com)
be9a2362
FF
4
5GDB is distributed in the hope that it will be useful, but WITHOUT ANY
6WARRANTY. No author or distributor accepts responsibility to anyone
7for the consequences of using it or for whether it serves any
8particular purpose or works at all, unless he says so in writing.
9Refer to the GDB General Public License for full details.
10
11Everyone is granted permission to copy, modify and redistribute GDB,
12but only under the conditions described in the GDB General Public
13License. A copy of this license is supposed to have been given to you
14along with GDB so you can know your rights and responsibilities. It
15should be in a file named COPYING. Among other things, the copyright
16notice and this notice must be preserved on all copies.
17
18In other words, go ahead and share GDB, but don't try to stop
19anyone else from sharing it farther. Help stamp out software hoarding!
20*/
21
67278683
FF
22#include <stdio.h>
23
be9a2362
FF
24#include "defs.h"
25#include "tm-i860.h"
26#include "i860-opcode.h"
27
28/* i860 instructions are never longer than this many bytes. */
29#define MAXLEN 4
30
31static int fp_instr();
32static void fld_offset();
33static void gen_rrr();
34static void gen_irr();
35static void ctrl_a();
36\f
37/*
38 * integer registers names
39 */
40static char *ireg[32] =
41 {
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",
46 };
47
48/*
49 * Control registers of the ld.c and st.c instructions
50 */
51static char *ctlreg[32] =
52 {
53 "fir", "psr", "dirbase", "db", "fsr", "?", "?", "?",
54 "?", "?", "?", "?", "?", "?", "?", "?",
55 "?", "?", "?", "?", "?", "?", "?", "?",
56 "?", "?", "?", "?", "?", "?", "?", "?"
57 };
58
59
60/***********************************************************************
61 * Print the i860 instruction at address MEMADDR in debugged memory,
62 * on STREAM. Returns length of the instruction, in bytes, which
63 * is always 4.
64 */
65
66int
67print_insn (memaddr, stream)
68 CORE_ADDR memaddr; /* address of the instruction */
69 FILE *stream; /* stream on which to write result */
70{
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 */
76
77 adj_read_memory (memaddr, &insn, MAXLEN);
78
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
81 * the result
82 */
83
84 split_offset = (insn.gen.dest << 11) | insn.gen.offset;
85 split_offset = SIGN_EXT(16, split_offset);
86
87
88 switch (insn.gen.op1)
89 {
90 case 000:
91 fprintf (stream, "ld.b %s(%s),%s", ireg[insn.gen.src1],
92 ireg[insn.gen.src2], ireg[insn.gen.dest]);
93 break;
94 case 001:
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]);
98 break;
99 case 002:
100 fprintf (stream, "ixfr %s,f%d", ireg[insn.gen.src1], insn.gen.dest);
101 break;
102 case 003:
103 fprintf (stream, "st.b %s,0x%x(%s)", ireg[insn.gen.src1], split_offset,
104 ireg[insn.geni.src2]);
105 break;
106 case 004:
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]);
109 break;
110 case 005:
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]);
114 break;
115
116 case 007:
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]);
119 break;
120
121 case 010:
122 offset = insn.gen.offset;
123 fld_offset(&offset, &suffix, &ai);
124
125 fprintf (stream, "fld.%c %s(%s)%s,f%d", suffix,
126 ireg[insn.gen.src1], ireg[insn.gen.src2], ai ? "++" : "",
127 insn.gen.dest);
128 break;
129 case 011:
130 offset = SIGN_EXT(16, insn.geni.offset);
131 fld_offset(&offset, &suffix, &ai);
132
133 fprintf (stream, "fld.%c 0x%x(%s)%s,f%d", suffix,
134 offset, ireg[insn.gen.src2], ai ? "++" : "", insn.gen.dest);
135 break;
136 case 012:
137 offset = insn.gen.offset;
138 fld_offset(&offset, &suffix, &ai);
139
140 fprintf (stream, "fst.%c f%d,%s(%s)%s", suffix,
141 insn.gen.dest, ireg[insn.gen.src1], ireg[insn.gen.src2],
142 ai ? "++" : "");
143 break;
144 case 013:
145 offset = SIGN_EXT(16, insn.geni.offset);
146 fld_offset(&offset, &suffix, &ai);
147
148 fprintf (stream, "fst.%c f%d,0x%x(%s)%s", suffix,
149 insn.gen.dest, offset, ireg[insn.gen.src2], ai ? "++" : "");
150 break;
151 case 014:
152 fprintf (stream, "ld.c %s,%s", ctlreg[insn.gen.src2],
153 ireg[insn.gen.dest]);
154 break;
155 case 015:
156 offset = SIGN_EXT(16, insn.geni.offset);
157 fld_offset(&offset, &suffix, &ai);
158
159 fprintf (stream, "flush 0x%x(%s)%s", offset, ireg[insn.gen.src2],
160 ai ? "++" : "");
161 break;
162 case 016:
163 fprintf (stream, "st.c %s,%s", ireg[insn.gen.src1],
164 ctlreg[insn.gen.src2]);
165 break;
166 case 017:
167 offset = SIGN_EXT(16, insn.geni.offset);
168 fld_offset(&offset, &suffix, &ai);
169
170 fprintf (stream, "pst.d f%d,0x%x(%s)%s", insn.gen.dest,
171 offset, ireg[insn.gen.src2], ai ? "++" : "");
172 break;
173
174 case 020:
175 fprintf (stream, "bri %s", ireg[insn.gen.src1]);
176 break;
177 case 021:
178 gen_rrr("trap", insn, stream);
179 break;
180 case 022:
181 /*
182 * Floating-point Opcodes
183 */
184 if (!fp_instr(insn.fp, stream))
185 fprintf (stream, "0x%08x (invalid instruction)", insn.int_val);
186 break;
187 case 023:
188 /*
189 * Core Escape Opcodes
190 */
191 switch (insn.esc.op2)
192 {
193 case 1:
194 fprintf (stream, "lock");
195 break;
196 case 2:
197 fprintf (stream, "calli %s", ireg[insn.esc.src1]);
198 break;
199 case 4:
200 fprintf (stream, "intovr");
201 break;
202 case 7:
203 fprintf (stream, "unlock");
204 break;
205 default:
206 fprintf (stream, "0x%08x (invalid instruction)", insn.int_val);
207 break;
208 }
209 break;
210
211 case 024:
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);
216 break;
217 case 025:
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);
221 break;
222 case 026:
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);
227 break;
228 case 027:
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);
232 break;
233
234 case 030:
235 offset = insn.gen.offset;
236 fld_offset(&offset, &suffix, &ai);
237
238 fprintf (stream, "pfld.%c %s(%s)%s,f%d", suffix,
239 ireg[insn.gen.src1], ireg[insn.gen.src2], ai ? "++" : "",
240 insn.gen.dest);
241 break;
242 case 031:
243 offset = SIGN_EXT(16, insn.geni.offset);
244 fld_offset(&offset, &suffix, &ai);
245
246 fprintf (stream, "pfld.%c 0x%x(%s)%s,f%d", suffix,
247 offset, ireg[insn.gen.src2], ai ? "++" : "", insn.gen.dest);
248 break;
249 case 032:
250 ctrl_a("br", insn, memaddr, stream);
251 break;
252 case 033:
253 ctrl_a("call", insn, memaddr, stream);
254 break;
255 case 034:
256 ctrl_a("bc", insn, memaddr, stream);
257 break;
258 case 035:
259 ctrl_a("bc.t", insn, memaddr, stream);
260 break;
261 case 036:
262 ctrl_a("bnc", insn, memaddr, stream);
263 break;
264 case 037:
265 ctrl_a("bnc.t", insn, memaddr, stream);
266 break;
267
268 case 040:
269 gen_rrr("addu", insn, stream);
270 break;
271 case 041:
272 gen_irr("addu", insn, SIGN_EXT(16, insn.geni.offset), stream);
273 break;
274 case 042:
275 gen_rrr("subu", insn, stream);
276 break;
277 case 043:
278 gen_irr("subu", insn, SIGN_EXT(16, insn.geni.offset), stream);
279 break;
280 case 044:
281 gen_rrr("adds", insn, stream);
282 break;
283 case 045:
284 gen_irr("adds", insn, SIGN_EXT(16, insn.geni.offset), stream);
285 break;
286 case 046:
287 gen_rrr("subs", insn, stream);
288 break;
289 case 047:
290 gen_irr("subs", insn, SIGN_EXT(16, insn.geni.offset), stream);
291 break;
292
293 case 050:
294 if (insn.gen.src1 == 0)
295 {
296 if (insn.gen.src2 == 0 && insn.gen.dest == 0)
297 fprintf (stream, "nop");
298 else
299 fprintf (stream, "mov %s,%s", ireg[insn.gen.src2],
300 ireg[insn.gen.dest]);
301 }
302 else
303 gen_rrr("shl", insn, stream);
304 break;
305 case 051:
306 gen_irr("shl", insn, insn.geni.offset, stream);
307 break;
308 case 052:
309 gen_rrr("shr", insn, stream);
310 break;
311 case 053:
312 gen_irr("shr", insn, insn.geni.offset, stream);
313 break;
314 case 054:
315 if (insn.gen.src1 == 0 && insn.gen.src2 == 0 && insn.gen.dest == 0)
316 {
317 if ((insn.int_val & (1 << 9)) != 0)
318 fprintf (stream, "d.");
319 fprintf (stream, "fnop");
320 }
321 else
322 gen_rrr("shrd", insn, stream);
323 break;
324 case 055:
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);
329 break;
330 case 056:
331 gen_rrr("shra", insn, stream);
332 break;
333 case 057:
334 gen_irr("shra", insn, insn.geni.offset, stream);
335 break;
336
337 case 060:
338 gen_rrr("and", insn, stream);
339 break;
340 case 061:
341 gen_irr("and", insn, insn.geni.offset, stream);
342 break;
343
344 case 063:
345 gen_irr("andh", insn, insn.geni.offset, stream);
346 break;
347 case 064:
348 gen_rrr("andnot", insn, stream);
349 break;
350 case 065:
351 gen_irr("andnot", insn, insn.geni.offset, stream);
352 break;
353
354 case 067:
355 gen_irr("andnoth", insn, insn.geni.offset, stream);
356 break;
357
358 case 070:
359 gen_rrr("or", insn, stream);
360 break;
361 case 071:
362 gen_irr("or", insn, insn.geni.offset, stream);
363 break;
364
365 case 073:
366 gen_irr("orh", insn, insn.geni.offset, stream);
367 break;
368 case 074:
369 gen_rrr("xor", insn, stream);
370 break;
371 case 075:
372 gen_irr("xor", insn, insn.geni.offset, stream);
373 break;
374
375 case 077:
376 gen_irr("xorh", insn, insn.geni.offset, stream);
377 break;
378
379 default:
380 fprintf (stream, "0x%08x (invalid instruction)", insn.int_val);
381 break;
382 }
383
384 return(4);
385}
386\f
387/* A full list of floating point opcodes - if the entry is NULL, there is
388 * no corresponding instruction
389 */
390
391static char *fp_ops[] =
392 {
393 "r2p1", "r2pt", "r2ap1", "r2apt",
394 "i2p1", "i2pt", "i2ap1", "i2apt",
395 "rat1p2", "m12apm", "ra1p2", "m12ttpa",
396 "iat1p2", "m12tpm", "ia1p2", "m12tpa",
397
398 "r2s1", "r2st", "r2as1", "r2ast",
399 "i2s1", "i2st", "i2as1", "i2ast",
400 "rat1s2", "m12asm", "ra1s2", "m12ttsa",
401 "iat1s2", "m12tsm", "ia1s2", "m12tsa",
402
403 "fmul", "fmlow", "frcp", "frsqr",
404 "fmul3", NULL, NULL, NULL,
405 NULL, NULL, NULL, NULL,
406 NULL, NULL, NULL, NULL,
407
408 "fadd", "fsub", "fix", "famov",
409 "fgt", "feq", NULL, NULL,
410 NULL, NULL, "ftrunc", NULL,
411 NULL, NULL, NULL, NULL,
412
413 "fxfr", NULL, NULL, NULL,
414 NULL, NULL, NULL, NULL,
415 NULL, "fiadd", NULL, NULL,
416 NULL, "fisub", NULL, NULL,
417
418 "faddp", "faddz", NULL, NULL,
419 NULL, NULL, NULL, "fzchkl",
420 NULL, NULL, "form", NULL,
421 NULL, NULL, NULL, "fzchks",
422 };
423
424/* Alternate list of floating point opcodes for PFMAM/PFMSM instructions
425 */
426
427static char *alt_fp_ops[] =
428 {
429 "mr2p1", "mr2pt", "mr2mp1", "mr2mpt",
430 "mi2p1", "mi2pt", "mi2mp1", "mi2mpt",
431 "mrmt1p2", "mm12mpm", "mrm1p2", "mm12ttpm",
432 "mimt1p2", "mm12tpm", "mim1p2", "mm12tpm",
433
434 "mr2s1", "mr2st", "mr2ms1", "mr2mst",
435 "mi2s1", "mi2st", "mi2ms1", "mi2mst",
436 "mrmt1s2", "mm12msm", "mrm1s2", "mm12ttsm",
437 "mimt1s2", "mm12tsm", "mim1s2", "mm12tsm",
438 };
439
440
441/* Floating point precision suffix values - indexed by s and r bits of
442 * instructions.
443 */
444
445static char precision[2] =
446 {
447 's', 'd',
448 };
449
450/***********************************************************************
451 * Print floating-point instruction 'insn' on the indicated stream
452 * Returns 1 if successful, 0 on failure (invalid instruction)
453 */
454
455static int
456fp_instr(insn, stream)
457 struct fp_fmt insn; /* instruction to decode */
458 FILE *stream; /* stream to print on */
459{
460 char *name; /* the opcode name */
461
462 name = fp_ops[insn.op2];
463 if (name && insn.d)
464 fprintf(stream, "d.");
465
466
467 if (insn.op2 < 0x20)
468 {
469 /*
470 * DPC Ops
471 */
472 if (insn.p == 0) /* use PFMAM/PFMSM ops if p=0 */
473 name = alt_fp_ops[insn.op2];
474
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);
478 }
479 else
480 {
481 switch (insn.op2)
482 {
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);
487 break;
488
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);
494 break;
495
496 case 0x24: /* pfmul3 */
497 fprintf (stream, "pfmul3.dd f%d,f%d,f%d",
498 insn.src1, insn.src2, insn.dest);
499 break;
500
501 case 0x30: /* fadd */
502 case 0x49: /* fiadd */
503 if (insn.src2 == 0)
504 {
505 /*
506 * Really fmov
507 */
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);
511 }
512 else
513 {
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);
517 }
518 break;
519
520 case 0x32: /* fix */
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);
525 break;
526
527 case 0x34: /* pfgt/pfle */
528 if (insn.r)
529 name = "fle";
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);
533 break;
534
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);
539 break;
540
541 case 0x40: /* fxfr */
542 fprintf (stream, "fxfr f%d,%s", insn.src1, ireg[insn.dest]);
543 break;
544
545 case 0x50: /* faddp */
546 case 0x51: /* faddz */
547 case 0x57: /* fzchkl */
548 case 0x5F: /* fzchks */
549 /*
550 * Graphics ops with no precision
551 */
552 fprintf (stream, "%s%s f%d,f%d,f%d", insn.p ? "p" : "", name,
553 insn.src1, insn.src2, insn.dest);
554 break;
555
556 case 0x5A: /* form */
557 fprintf (stream, "%sform f%d,f%d", insn.p ? "p" : "",
558 insn.src1, insn.dest);
559 break;
560
561 default:
562 /*
563 * All the rest are uniform 3-address, optionally pipelined, etc
564 */
565 if (name)
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);
569 else
570 return (0);
571 break;
572 }
573 }
574 return (1);
575}
576
577/***********************************************************************
578 * Decode fld/fst-style offset encodings into actual offset, precision suffix,
579 * and autoincrement flag
580 */
581
582static void
583fld_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) */
587{
588 long off = *offset; /* working copy of *offset */
589
590 *autoincrement = ((off & 1) != 0);
591
592 if (off & 2)
593 {
594 *suffix = 'l';
595 *offset = (off & ~3);
596 }
597 else if (off & 4)
598 {
599 *suffix = 'q';
600 *offset = (off & ~7);
601 }
602 else
603 {
604 *suffix = 'd';
605 *offset = (off & ~7);
606 }
607}
608\f
609/***********************************************************************
610 * Print a general format instruction of the three register form:
611 * op rx,ry,rz
612 */
613
614static void
615gen_rrr(name, insn, stream)
616 char *name;
617 union insn_fmt insn;
618 FILE *stream;
619{
620 fprintf (stream, "%s %s,%s,%s", name, ireg[insn.gen.src1],
621 ireg[insn.gen.src2], ireg[insn.gen.dest]);
622}
623
624/***********************************************************************
625 * Print a general format instruction of the immed + two register form:
626 * op i,ry,rz
627 */
628
629static void
630gen_irr(name, insn, immed, stream)
631 char *name;
632 union insn_fmt insn;
633 long immed;
634 FILE *stream;
635{
636 fprintf (stream, "%s 0x%x,%s,%s", name, immed,
637 ireg[insn.gen.src2], ireg[insn.gen.dest]);
638}
639
640/***********************************************************************
641 * Print a ctrl format instruction with a 26-bit displacement:
642 * op addr
643 */
644
645static void
646ctrl_a(name, insn, memaddr, stream)
647 char *name;
648 union insn_fmt insn;
649 CORE_ADDR memaddr;
650 FILE *stream;
651{
652 long offset;
653
654 fprintf (stream, "%s ", name);
655 offset = SIGN_EXT(28, insn.ctrl.offset << 2);
656
657 print_address ((CORE_ADDR) (memaddr + 4 + offset), stream);
658}
This page took 0.064295 seconds and 4 git commands to generate.