]> Git Repo - binutils.git/blob - gdb/i860-pinsn.c
*** empty log message ***
[binutils.git] / gdb / i860-pinsn.c
1 /* Print i860 instructions for GDB, the GNU debugger.
2    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3    Contributed by Michael Tiemann ([email protected])
4
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.
10
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.
17
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!
20 */
21
22 #include <stdio.h>
23
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
31 static int fp_instr();
32 static void fld_offset();
33 static void gen_rrr();
34 static void gen_irr();
35 static void ctrl_a();
36 \f
37 /* 
38  * integer registers names
39  */
40 static 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  */
51 static 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
66 int
67 print_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  
391 static 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  
427 static 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
445 static 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
455 static int
456 fp_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
582 static void
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) */
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
614 static void
615 gen_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
629 static void
630 gen_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
645 static void
646 ctrl_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.06286 seconds and 4 git commands to generate.