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