]> Git Repo - binutils.git/blob - gdb/sparc-pinsn.c
gdb-2.8.1
[binutils.git] / gdb / sparc-pinsn.c
1 /* Print sparc 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 "param.h"
26 #include "symtab.h"
27 #include "sparc-opcode.h"
28
29 /* sparc instructions are never longer than this many bytes.  */
30 #define MAXLEN 4
31 \f
32 /* Print the sparc instruction at address MEMADDR in debugged memory,
33    on STREAM.  Returns length of the instruction, in bytes, which
34    is always 4.  */
35
36 struct op1_fmt
37 {
38   unsigned op1 : 2;
39   unsigned dummy : 30;
40 };
41
42 struct op2_fmt
43 {
44   unsigned dummy1 : 7;
45   unsigned op2 : 3;
46   unsigned dummy2 : 22;
47 };
48
49 struct op3_fmt
50 {
51   unsigned dummy1 : 7;
52   unsigned op3 : 6;
53   unsigned dummy2 : 19;
54 };
55
56 struct call_fmt
57 {
58   unsigned op : 2;
59   unsigned disp : 30;
60 };
61
62 struct sethi_fmt
63 {
64   unsigned op : 2;
65   unsigned rd : 5;
66   unsigned op2 : 3;
67   unsigned imm : 22;
68 };
69
70 struct branch_fmt
71 {
72   unsigned op : 2;
73   unsigned a : 1;
74   unsigned cond : 4;
75   unsigned op2 : 3;
76   unsigned disp : 22;           /* this should really be signed.  */
77 };
78
79 struct ldst_fmt
80 {
81   unsigned op : 2;
82   unsigned rd : 5;
83   unsigned op3 : 6;
84   unsigned rs1 : 5;
85   unsigned i : 1;
86   unsigned asi : 8;
87   unsigned rs2 : 5;
88 };
89
90 struct arith_imm_fmt
91 {
92   unsigned op : 2;
93   unsigned rd : 5;
94   unsigned op3 : 6;
95   unsigned rs1 : 5;
96   unsigned i : 1;
97   unsigned simm : 13;
98 };
99
100 struct arith_fmt
101 {
102   unsigned op : 2;
103   unsigned rd : 5;
104   unsigned op3 : 6;
105   unsigned rs1 : 5;
106   unsigned i : 1;
107   unsigned opf : 8;
108   unsigned rs2 : 5;
109 };
110
111 union insn_fmt
112 {
113   struct op1_fmt op1;
114   struct op2_fmt op2;
115   struct op3_fmt op3;
116   struct call_fmt call;
117   struct sethi_fmt sethi;
118   struct branch_fmt branch;
119   struct ldst_fmt ldst;
120   struct arith_imm_fmt arith_imm;
121   struct arith_fmt arith;
122   int intval;
123   float floatval;               /* ?? */
124 };
125
126 typedef enum
127 {
128   Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
129 } branch_type;
130
131 static char *icc_name[] =
132 { "~", "eq", "le", "lt", "leu", "ltu", "neg", "vs",
133   "", "ne", "gt", "ge", "gtu", "geu", "pos", "vc"};
134
135 static char *fcc_name[] =
136 { "~fb", "fbne", "fblg", "fbul", "fbl", "fbug", "fbg", "fbu",
137   "fb", "fbe", "fbue", "fbge", "fbuge", "fble", "fbule", "fbo"};
138
139 static char *ccc_name[] =
140 { "~cb", "cb123", "cb12", "cb13", "cb1", "cb23", "cb2", "cb3",
141   "cb", "cb0", "cb03", "cb02", "cb023", "cb01", "cb013", "cb012"};
142
143 static char *arith_name[] =
144 { "add", "and", "or", "xor", "sub", "andn", "orn", "xnor",
145   "addx", 0, 0, 0, "subx", 0, 0, 0};
146
147 static char *xarith_name[] =
148 { "taddcc", "tsubcc", "taddcctv", "tsubcctv", "mulscc", "sll", "srl", "sra"};
149
150 static char *state_reg_name[] =
151 { "%y", "%psr", "%wim", "%tbr", 0, 0, 0, 0};
152
153 static char *ldst_i_name[] =
154 { "ld", "ldub", "lduh", "ldd", "st", "stb", "sth", "std",
155   0, "ldsb", "ldsh", 0, 0, "ldstub", 0, "swap",
156   "lda", "lduba", "lduha", "ldda", "sta", "stba", "stha", "stda",
157   0, "ldsba", "ldsha", 0, 0, "ldstuba", 0, "swapa"};
158
159 static char *ldst_f_name[] =
160 { "ldf", "ldfsr", 0, "lddf", "stf", "stfsr", "stdfq", "stdf"};
161
162 static char *ldst_c_name[] =
163 { "ldc", "ldcsr", 0, "lddc", "stc", "stcsr", "stdcq", "stdc"};
164
165 static int this_sethi_target = -1;
166 static int last_sethi_target = -1;
167 static int sethi_value = 0;
168
169 static void fprint_addr1 ();
170 static void fprint_ldst ();
171 static void fprint_f_ldst ();
172 static void fprint_c_ldst ();
173 static void fprint_fpop ();
174
175 int
176 print_insn (memaddr, stream)
177      CORE_ADDR memaddr;
178      FILE *stream;
179 {
180   union insn_fmt insn;
181   int disp22;
182
183   read_memory (memaddr, &insn, MAXLEN);
184
185   this_sethi_target = -1;
186   switch (insn.op1.op1)
187     {
188     case 1:
189       /* CALL format.  */
190       fprintf (stream, "call ");
191       print_address (memaddr + (insn.call.disp << 2), stream);
192       break;
193     case 0:
194       /* Bicc, FBfcc, CBccc, SETHI format.  */
195       switch (insn.op2.op2)
196         {
197         case 0:
198           fprintf (stream, "unimp");
199           break;
200         case 2:
201           /* Bicc.  */
202           fprintf (stream, "b%s", icc_name[insn.branch.cond]);
203           if (insn.branch.a) fprintf (stream, ",a ");
204           else fprintf (stream, " ");
205           disp22 = insn.branch.disp;
206           disp22 = ((disp22 << 10) >> 10);
207           print_address (memaddr + (disp22 << 2), stream);
208           break;
209         case 4:
210           /* SETHI.  */
211           fprintf (stream, "sethi %%hi(0x%x),%s",
212                    insn.sethi.imm << 10, reg_names[insn.sethi.rd]);
213           this_sethi_target = insn.sethi.rd;
214           sethi_value = insn.sethi.imm << 12;
215           break;
216         case 6:
217           /* FBdfcc.  */
218           fprintf (stream, "fb%s", fcc_name[insn.branch.cond]);
219           if (insn.branch.a) fprintf (stream, ",a ");
220           else fprintf (stream, " ");
221           disp22 = insn.branch.disp;
222           disp22 = ((disp22 << 10) >> 10);
223           print_address (memaddr + (disp22 << 2), stream);
224           break;
225         case 7:
226           /* CBccc.  */
227           fprintf (stream, "cb%s", ccc_name[insn.branch.cond]);
228           if (insn.branch.a) fprintf (stream, ",a ");
229           else fprintf (stream, " ");
230           disp22 = insn.branch.disp;
231           disp22 = ((disp22 << 10) >> 10);
232           print_address (memaddr + (disp22 << 2), stream);
233           break;
234         default:
235           fprintf (stream, "0x%x (illegal op2 format)", insn.intval);
236           break;
237         }
238       break;
239     case 2:
240       {
241         /* vaguely arithmetic insns.  */
242         char *rd = reg_names[insn.arith.rd];
243         char *rs1 = reg_names[insn.arith.rs1];
244
245         if (insn.op3.op3 <= 28)
246           {
247             /* Arithmetic insns, with a few unimplemented.  */
248             register int affect_cc = insn.op3.op3 & 16;
249             char *name = arith_name[insn.op3.op3 ^ affect_cc];
250             char *tmp = affect_cc ? "cc" : "";
251
252             if (name == 0)
253               {
254                 fprintf (stream, "0x%08x (unimplemented arithmetic insn)",
255                          insn.intval);
256               }
257             else if (insn.arith.i)
258               {
259                 fprintf (stream, "%s%s %s,0x%x,%s",
260                          name, tmp, rs1, insn.arith_imm.simm, rd);
261                 if (last_sethi_target == insn.arith.rd)
262                   {
263                     fprintf (stream, "\t! ");
264                     print_address (sethi_value + insn.arith_imm.simm);
265                   }
266               }
267             else
268               {
269                 fprintf (stream, "%s%s %s,%s,%s",
270                          name, tmp, rs1, reg_names[insn.arith.rs2], rd);
271               }
272             break;
273           }
274         if (insn.op3.op3 < 32)
275           {
276             fprintf (stream, "0x%08x (unimplemented arithmetic insn)",
277                      insn.intval);
278             break;
279           }
280         else
281           {
282             int op = insn.op3.op3 ^ 32;
283
284             if (op < 8)
285               {
286                 char *name = xarith_name[op];
287                 /* tagged add/sub insns and shift insns.  */
288                 if (insn.arith.i)
289                   {
290                     int i = insn.arith_imm.simm;
291                     if (op > 4)
292                       /* Its a shift insn.  */
293                       i &= 31;
294
295                     fprintf (stream, "%s %s,0x%x,%s",
296                              name, rs1, i, rd);
297                   }
298                 else
299                   {
300                     fprintf (stream, "%s %s,%s,%s",
301                              name, rs1, reg_names[insn.arith.rs2], rd);
302                   }
303                 break;
304               }
305             if (op < 20)
306               {
307                 /* read/write state registers.  */
308                 char *sr = state_reg_name[op & 7];
309                 if (sr == 0)
310                   fprintf (stream, "0x%08x (unimplemented state register insn",
311                            insn.intval);
312                 else
313                   fprintf (stream, "%s %s,%s", op & 16 ? "wr" : "rd", sr, rd);
314                 break;
315               }
316             if (op < 22)
317               {
318                 /* floating point insns.  */
319                 int opcode = insn.arith.opf;
320
321                 fprint_fpop (stream, insn, op & 3, opcode);
322                 break;
323               }
324             if (op < 24)
325               {
326                 /* coprocessor insns.  */
327                 char *rs2 = reg_names[insn.arith.rs2];
328                 int opcode = insn.arith.opf;
329
330                 fprintf (stream, "cpop%d rs1=%s,rs2=%s,op=0x%x,rd=%s",
331                          op & 1, rs1, rs2, opcode, rd);
332                 break;
333               }
334
335             switch (op)
336               {
337                 char *rndop_ptr;
338
339               case 24:
340                 fprint_addr1 (stream, "jumpl", insn);
341                 break;
342               case 25:
343                 fprint_addr1 (stream, "rett", insn);
344                 break;
345               case 26:
346                 {
347                   char rndop_buf[32];
348                   sprintf (rndop_buf, "t%s", icc_name[insn.branch.cond]);
349                   fprint_addr1 (stream, rndop_buf, insn);
350                 }
351                 break;
352               case 27:
353                 fprint_addr1 (stream, "iflush", insn);
354                 break;
355
356               case 28:
357                 rndop_ptr = "save";
358               case 29:
359                 if (op == 29)
360                   rndop_ptr = "restore";
361
362                 if (insn.arith.i)
363                   {
364                     fprintf (stream, "%s %s,0x%x,%s",
365                              rndop_ptr, rs1,
366                              ((insn.arith_imm.simm << 19) >> 19), rd);
367                   }
368                 else
369                   {
370                     fprintf (stream, "%s %s,%s,%s",
371                              rndop_ptr, rs1, reg_names[insn.arith.rs2], rd);
372                   }
373                 break;
374               case 30:
375               case 31:
376                 fprintf (stream, "0x%08x (unimplemented op3 insn)",
377                          insn.intval);
378                 break;
379               }
380             break;
381           }
382       }
383     case 3:
384       /* load and store insns.  */
385       {
386         char *rd = reg_names[insn.arith.rd];
387         char *rs1 = reg_names[insn.arith.rs1];
388         int op = insn.arith.op3;
389
390         if ((op & 32) == 0)
391           {
392             /* Integer ops.  */
393             fprint_ldst (stream, insn, op);
394             break;
395           }
396         if ((op & 16) == 0)
397           {
398             /* Float ops.  */
399             op ^= 32;
400             if (op <= 7)
401               {
402                 fprint_f_ldst (stream, insn, op);
403               }
404             else
405               fprintf (stream, "0x%08x (unimplemented float load/store insn)",
406                        insn.intval);
407           }
408         else
409           {
410             /* Coprocessor ops.  */
411             op ^= (32+16);
412             if (op <= 7)
413               {
414                 fprint_c_ldst (stream, insn, op);
415               }
416             else
417               fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)",
418                        insn.intval);
419           }
420         break;
421       }
422     }
423   return 4;
424 }
425
426 /* It would be nice if this routine could print out a symbolic address
427    when appropriate.  */
428 static void
429 fprint_addr1 (stream, name, insn)
430      FILE *stream;
431      char *name;
432      union insn_fmt insn;
433 {
434   char *rs1 = reg_names[insn.arith.rs1];
435   char *rd = reg_names[insn.arith.rd];
436
437   if (insn.arith.i)
438     {
439       fprintf (stream, "%s %s,0x%x,%s",
440                name, rs1, insn.arith_imm.simm, rd);
441     }
442   else
443     {
444       fprintf (stream, "%s %s,%s,%s",
445                name, rs1, reg_names[insn.arith.rs2], rd);
446     }
447 }
448
449 static void
450 fprint_mem (stream, insn)
451      FILE *stream;
452      union insn_fmt insn;
453 {
454   char *reg_name = reg_names[insn.arith.rs1];
455   if (insn.arith.i)
456     {
457       if (insn.arith_imm.simm == 0)
458         fprintf (stream, "[%s]", reg_name);
459       else if (insn.arith_imm.simm & 0x1000)
460         fprintf (stream, "[%s-0x%x]", reg_name,
461                  - (insn.arith_imm.simm | 0xffffe000));
462       else
463         fprintf (stream, "[%s+0x%x]", reg_name, insn.arith_imm.simm);
464     }
465   else
466     {
467       if (insn.arith.rs2 == 0)
468         fprintf (stream, "[%s]", reg_name);
469       else
470         fprintf (stream, "[%s,%s]", reg_names[insn.arith.rs2], reg_name);
471     }
472 }
473
474 static void
475 fprint_ldst (stream, insn, op)
476      FILE *stream;
477      union insn_fmt insn;
478      int op;
479 {
480   char *name = ldst_i_name[op];
481   char *rd = reg_names[insn.arith.rd];
482
483   if (name)
484     {
485       if (name[0] == 's')
486         {
487           fprintf (stream, "%s %s,", name, rd);
488           fprint_mem (stream, insn);
489         }
490       else
491         {
492           fprintf (stream, "%s ", name);
493           fprint_mem (stream, insn);
494           fprintf (stream, ",%s", rd);
495         }
496     }
497   else
498     fprintf (stream, "0x%08x (unimplemented load/store insn)", insn.intval);
499 }
500
501 static void
502 fprint_f_ldst (stream, insn, op)
503      FILE *stream;
504      union insn_fmt insn;
505      int op;
506 {
507   char *name = ldst_f_name[op];
508   if (name)
509     {
510       char *rd = reg_names[insn.arith.rd + 32];
511
512       if (name[0] == 's')
513         {
514           fprintf (stream, "%s %s,", name, rd);
515           fprint_mem (stream, insn);
516         }
517       else
518         {
519           fprintf (stream, "%s ", name);
520           fprint_mem (stream, insn);
521           fprintf (stream, ",%s", rd);
522         }
523     }
524   else
525     fprintf (stream, "0x%08x (unimplemented float load/store insn)", insn.intval);
526 }
527
528 static void
529 fprint_c_ldst (stream, insn, op)
530      FILE *stream;
531      union insn_fmt insn;
532      int op;
533 {
534   char *name = ldst_c_name[op];
535   if (name)
536     {
537       if (name[0] == 's')
538         {
539           fprintf (stream, "%s %%cpreg(%d),", name, insn.arith.rs1);
540           fprint_mem (stream, insn);
541         }
542       else
543         {
544           fprintf (stream, "%s ");
545           fprint_mem (stream, insn);
546           fprintf (stream, ",%%cpreg(%d)", insn.arith.rd);
547         }
548     }
549   else
550     fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)",
551              insn.intval);
552 }
553
554 static void
555 fprint_fpop (stream, insn, op, opcode)
556      FILE *stream;
557      union insn_fmt insn;
558      int op, opcode;
559 {
560   char *name;
561   char *rs1, *rs2, *rd;
562
563   switch (op)
564     {
565     case 0:
566       rs2 = reg_names[insn.arith.rs2 + 32];
567       rd = reg_names[insn.arith.rd + 32];
568       if ((opcode ^ 0x2f) <= 0x2f)
569         {
570           switch (opcode)
571             {
572             case 0x1:
573               name = "fmovs";
574               break;
575             case 0x5:
576               name = "fnegs";
577               break;
578             case 0x9:
579               name = "fabss";
580               break;
581             case 0x29:
582               name = "fsqrts";
583               break;
584             case 0x2a:
585               name = "fsqrtd";
586               break;
587             case 0x2b:
588               name = "fsqrtx";
589               break;
590             }
591           fprintf (stream, "%s %s,%s", name, rs2, rd);
592           return;
593         }
594       if ((opcode ^ 0x5f) <= 0x5f)
595         {
596           rs1 = reg_names[insn.arith.rs1 + 32];
597           switch (opcode)
598             {
599             case 0x41:
600               name = "fadds";
601               break;
602             case 0x42:
603               name = "faddd";
604               break;
605             case 0x43:
606               name = "faddx";
607               break;
608             case 0x45:
609               name = "fsubs";
610               break;
611             case 0x46:
612               name = "fsubd";
613               break;
614             case 0x47:
615               name = "fsubx";
616               break;
617             case 0x49:
618               name = "fmuls";
619               break;
620             case 0x4a:
621               name = "fmuld";
622               break;
623             case 0x4b:
624               name = "fmulx";
625               break;
626             case 0x4d:
627               name = "fdivs";
628               break;
629             case 0x4e:
630               name = "fdivd";
631               break;
632             case 0x4f:
633               name = "fdivx";
634               break;
635             default:
636               goto unimplemented;
637             }
638           if ((opcode & 0x10) == 0)
639             fprintf (stream, "%s %s,%s,%s", name, rs1, rs2, rd);
640           else
641             fprintf (stream, "%s %s,%s", name, rs1, rs2);
642           return;
643         }
644       if ((opcode ^ 0xdf) <= 0xdf)
645         {
646           switch (opcode)
647             {
648             case 0xc4:
649               name = "fitos";
650               break;
651             case 0xc8:
652               name = "fitod";
653               break;
654             case 0xcc:
655               name = "fitox";
656               break;
657             case 0xd1:
658               name = "fstoi";
659               break;
660             case 0xd2:
661               name = "fdtoi";
662               break;
663             case 0xd3:
664               name = "fxtoi";
665               break;
666             case 0xc9:
667               name = "fstod";
668               break;
669             case 0xcd:
670               name = "fstox";
671               break;
672             case 0xc6:
673               name = "fdtos";
674               break;
675             case 0xce:
676               name = "fdtox";
677               break;
678             case 0xc7:
679               name = "fxtos";
680               break;
681             case 0xcb:
682               name = "fxtod";
683               break;
684             default:
685               goto unimplemented;
686             }
687           fprintf (stream, "%s %s,%s", name, rs2, rd);
688           return;
689         }
690       goto unimplemented;
691
692     case 1:
693       rs1 = reg_names[insn.arith.rs1 + 32];
694       rs2 = reg_names[insn.arith.rs2 + 32];
695       if ((opcode ^ 0x57) <= 0x57)
696         {
697           switch (opcode)
698             {
699             case 0x51:
700               name = "fcmps";
701               break;
702             case 0x52:
703               name = "fcmpd";
704               break;
705             case 0x53:
706               name = "fcmpx";
707               break;
708             case 0x55:
709               name = "fcmpes";
710               break;
711             case 0x56:
712               name = "fcmped";
713               break;
714             case 0x57:
715               name = "fcmpex";
716               break;
717             default:
718               goto unimplemented;
719             }
720           fprintf (stream, "%s %s,%s", name, rs1, rs2);
721           return;
722         }
723       else goto unimplemented;
724
725     case 2:
726     case 3:
727       goto unimplemented;
728     }
729  unimplemented:
730   fprintf (stream, "0x%08x (unimplemented fpop insn)", insn.intval);
731 }
732
733 /* Set *target if we find a branch */
734 branch_type
735 isabranch (addr,  target)
736      CORE_ADDR addr, *target;
737 {
738   union insn_fmt instr;
739   branch_type val = not_branch;
740   long offset; /* Must be signed for sign-extend */
741
742   *target = 0;
743   instr.intval = read_memory_integer (addr, 4);
744   /* printf("intval = %x\n",instr.intval); */
745   switch (instr.op1.op1)
746     {
747     case 0:                     /* Format 2 */
748       switch(instr.op2.op2)
749         {
750         case 2: case 6:         /* BICC & FBCC */
751           if (instr.branch.cond == 8)
752             val = instr.branch.a ? baa : ba;
753           else
754             val = instr.branch.a ? bicca : bicc;
755           /* 22 bits, sign extended */
756           offset = ((instr.branch.disp << 10) >> 10);
757           *target = addr + offset;
758           break;
759         }
760       break;
761     }
762   /*printf("isabranch ret: %d\n",val); */
763   return val;
764 }
765
766 CORE_ADDR skip_prologue (pc)
767      CORE_ADDR pc;
768 {
769   union
770     {
771       struct insn_fmt insn;
772       int i;
773     } x;
774   int dest = -1;
775
776   x.i = read_memory_integer (pc, 4);
777   if (x.insn.sethi.op == 0 && x.insn.sethi.op2 == 4)
778     {
779       dest = x.insn.sethi.rd;
780       pc += 4;
781       x.i = read_memory_integer (pc, 4);
782     }
783   if (x.insn.arith_imm.op == 2 && x.insn.arith_imm.i == 1
784       && (x.insn.arith_imm.rd == 1 || x.insn.arith_imm.rd == dest))
785     {
786       pc += 4;
787       x.i = read_memory_integer (pc, 4);
788     }
789   if (x.insn.arith.op == 2 && (x.insn.arith.op3 ^ 32) == 28)
790     {
791       pc += 4;
792     }
793   return pc;
794 }
795
796 CORE_ADDR
797 frame_saved_pc (frame, next_frame)
798      CORE_ADDR frame;
799      CORE_ADDR next_frame;
800 {
801   CORE_ADDR prev_pc;
802
803   if (next_frame)
804     prev_pc = GET_RWINDOW_REG (next_frame, rw_in[7]);
805   else if (frame)
806     prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]);
807   else
808     error ("frame_saved_pc called without a frame");
809
810   return PC_ADJUST (prev_pc);
811 }
This page took 0.072002 seconds and 4 git commands to generate.