]> Git Repo - binutils.git/blob - gdb/i960-pinsn.c
* mips-xdep.c (REGISTER_PTRACE_ADDR, fetch_inferior_registers,
[binutils.git] / gdb / i960-pinsn.c
1 /* i80960 instruction disassembler for GDB.
2    Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "frame.h"
22 #include "inferior.h"
23
24 static FILE *stream;            /* Output goes here */
25 static void print_addr();
26 static void ctrl();
27 static void cobr();
28 static void reg();
29 static int mem();
30 static void ea();
31 static void dstop();
32 static void regop();
33 static void invalid();
34 static int pinsn();
35 static void put_abs();
36
37
38 /* Print the i960 instruction at address 'memaddr' in debugged memory,
39    on stream 's'.  Returns length of the instruction, in bytes.  */
40 int
41 print_insn( memaddr, s )
42     CORE_ADDR memaddr;
43     FILE *s;
44 {
45         unsigned int word1, word2;
46
47         stream = s;
48         word1 = read_memory_integer( memaddr, 4 );
49         word2 = read_memory_integer( memaddr+4, 4 );
50         return pinsn( memaddr, word1, word2 );
51 }
52
53
54 /* Read the i960 instruction at 'memaddr' and return the address of 
55    the next instruction after that, or 0 if 'memaddr' is not the
56    address of a valid instruction.  The first word of the instruction
57    is stored at 'pword1', and the second word, if any, is stored at
58    'pword2'.  */
59
60 CORE_ADDR
61 next_insn (memaddr, pword1, pword2)
62      unsigned long *pword1, *pword2;
63      CORE_ADDR memaddr;
64 {
65   int len;
66   unsigned long buf[2];
67
68   /* Read the two (potential) words of the instruction at once,
69      to eliminate the overhead of two calls to read_memory ().
70      TODO: read more instructions at once and cache them.  */
71
72   read_memory (memaddr, buf, sizeof (buf));
73   *pword1 = buf[0];
74   SWAP_TARGET_AND_HOST (pword1, sizeof (long));
75   *pword2 = buf[1];
76   SWAP_TARGET_AND_HOST (pword2, sizeof (long));
77
78   /* Divide instruction set into classes based on high 4 bits of opcode*/
79
80   switch ((*pword1 >> 28) & 0xf)
81     {
82     case 0x0:
83     case 0x1:   /* ctrl */
84
85     case 0x2:
86     case 0x3:   /* cobr */
87
88     case 0x5:
89     case 0x6:
90     case 0x7:   /* reg */
91       len = 4;
92       break;
93
94     case 0x8:
95     case 0x9:
96     case 0xa:
97     case 0xb:
98     case 0xc:
99       len = mem (memaddr, *pword1, *pword2, 1);
100       break;
101
102     default:    /* invalid instruction */
103       len = 0;
104       break;
105     }
106
107   if (len)
108     return memaddr + len;
109   else
110     return 0;
111 }
112 \f
113 #define IN_GDB
114
115 /*****************************************************************************
116  *      All code below this point should be identical with that of
117  *      the disassembler in gdmp960.
118  *****************************************************************************/
119
120 struct tabent {
121         char    *name;
122         char    numops;
123 };
124
125 static int
126 pinsn( memaddr, word1, word2 )
127     unsigned long memaddr;
128     unsigned long word1, word2;
129 {
130         int instr_len;
131
132         instr_len = 4;
133         put_abs( word1, word2 );
134
135         /* Divide instruction set into classes based on high 4 bits of opcode*/
136
137         switch ( (word1 >> 28) & 0xf ){
138         case 0x0:
139         case 0x1:
140                 ctrl( memaddr, word1, word2 );
141                 break;
142         case 0x2:
143         case 0x3:
144                 cobr( memaddr, word1, word2 );
145                 break;
146         case 0x5:
147         case 0x6:
148         case 0x7:
149                 reg( word1 );
150                 break;
151         case 0x8:
152         case 0x9:
153         case 0xa:
154         case 0xb:
155         case 0xc:
156                 instr_len = mem( memaddr, word1, word2, 0 );
157                 break;
158         default:
159                 /* invalid instruction, print as data word */ 
160                 invalid( word1 );
161                 break;
162         }
163         return instr_len;
164 }
165
166 /****************************************/
167 /* CTRL format                          */
168 /****************************************/
169 static void
170 ctrl( memaddr, word1, word2 )
171     unsigned long memaddr;
172     unsigned long word1, word2;
173 {
174         int i;
175         static struct tabent ctrl_tab[] = {
176                 NULL,           0,      /* 0x00 */
177                 NULL,           0,      /* 0x01 */
178                 NULL,           0,      /* 0x02 */
179                 NULL,           0,      /* 0x03 */
180                 NULL,           0,      /* 0x04 */
181                 NULL,           0,      /* 0x05 */
182                 NULL,           0,      /* 0x06 */
183                 NULL,           0,      /* 0x07 */
184                 "b",            1,      /* 0x08 */
185                 "call",         1,      /* 0x09 */
186                 "ret",          0,      /* 0x0a */
187                 "bal",          1,      /* 0x0b */
188                 NULL,           0,      /* 0x0c */
189                 NULL,           0,      /* 0x0d */
190                 NULL,           0,      /* 0x0e */
191                 NULL,           0,      /* 0x0f */
192                 "bno",          1,      /* 0x10 */
193                 "bg",           1,      /* 0x11 */
194                 "be",           1,      /* 0x12 */
195                 "bge",          1,      /* 0x13 */
196                 "bl",           1,      /* 0x14 */
197                 "bne",          1,      /* 0x15 */
198                 "ble",          1,      /* 0x16 */
199                 "bo",           1,      /* 0x17 */
200                 "faultno",      0,      /* 0x18 */
201                 "faultg",       0,      /* 0x19 */
202                 "faulte",       0,      /* 0x1a */
203                 "faultge",      0,      /* 0x1b */
204                 "faultl",       0,      /* 0x1c */
205                 "faultne",      0,      /* 0x1d */
206                 "faultle",      0,      /* 0x1e */
207                 "faulto",       0,      /* 0x1f */
208         };
209
210         i = (word1 >> 24) & 0xff;
211         if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
212                 invalid( word1 );
213                 return;
214         }
215
216         fputs( ctrl_tab[i].name, stream );
217         if ( word1 & 2 ){               /* Predicts branch not taken */
218                 fputs( ".f", stream );
219         }
220
221         if ( ctrl_tab[i].numops == 1 ){
222                 /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
223                 word1 &= 0x00ffffff;
224                 if ( word1 & 0x00800000 ){              /* Sign bit is set */
225                         word1 |= (-1 & ~0xffffff);      /* Sign extend */
226                 }
227                 putc( '\t', stream );
228                 print_addr( word1 + memaddr );
229         }
230 }
231
232 /****************************************/
233 /* COBR format                          */
234 /****************************************/
235 static void
236 cobr( memaddr, word1, word2 )
237     unsigned long memaddr;
238     unsigned long word1, word2;
239 {
240         int src1;
241         int src2;
242         int i;
243
244         static struct tabent cobr_tab[] = {
245                 "testno",       1,      /* 0x20 */
246                 "testg",        1,      /* 0x21 */
247                 "teste",        1,      /* 0x22 */
248                 "testge",       1,      /* 0x23 */
249                 "testl",        1,      /* 0x24 */
250                 "testne",       1,      /* 0x25 */
251                 "testle",       1,      /* 0x26 */
252                 "testo",        1,      /* 0x27 */
253                 NULL,           0,      /* 0x28 */
254                 NULL,           0,      /* 0x29 */
255                 NULL,           0,      /* 0x2a */
256                 NULL,           0,      /* 0x2b */
257                 NULL,           0,      /* 0x2c */
258                 NULL,           0,      /* 0x2d */
259                 NULL,           0,      /* 0x2e */
260                 NULL,           0,      /* 0x2f */
261                 "bbc",          3,      /* 0x30 */
262                 "cmpobg",       3,      /* 0x31 */
263                 "cmpobe",       3,      /* 0x32 */
264                 "cmpobge",      3,      /* 0x33 */
265                 "cmpobl",       3,      /* 0x34 */
266                 "cmpobne",      3,      /* 0x35 */
267                 "cmpoble",      3,      /* 0x36 */
268                 "bbs",          3,      /* 0x37 */
269                 "cmpibno",      3,      /* 0x38 */
270                 "cmpibg",       3,      /* 0x39 */
271                 "cmpibe",       3,      /* 0x3a */
272                 "cmpibge",      3,      /* 0x3b */
273                 "cmpibl",       3,      /* 0x3c */
274                 "cmpibne",      3,      /* 0x3d */
275                 "cmpible",      3,      /* 0x3e */
276                 "cmpibo",       3,      /* 0x3f */
277         };
278
279         i = ((word1 >> 24) & 0xff) - 0x20;
280         if ( cobr_tab[i].name == NULL ){
281                 invalid( word1 );
282                 return;
283         }
284
285         fputs( cobr_tab[i].name, stream );
286         if ( word1 & 2 ){               /* Predicts branch not taken */
287                 fputs( ".f", stream );
288         }
289         putc( '\t', stream );
290
291         src1 = (word1 >> 19) & 0x1f;
292         src2 = (word1 >> 14) & 0x1f;
293
294         if ( word1 & 0x02000 ){         /* M1 is 1 */
295                 fprintf( stream, "%d", src1 );
296         } else {                        /* M1 is 0 */
297                 fputs( reg_names[src1], stream );
298         }
299
300         if ( cobr_tab[i].numops > 1 ){
301                 if ( word1 & 1 ){               /* S2 is 1 */
302                         fprintf( stream, ",sf%d,", src2 );
303                 } else {                        /* S1 is 0 */
304                         fprintf( stream, ",%s,", reg_names[src2] );
305                 }
306
307                 /* Extract displacement and convert to address
308                  */
309                 word1 &= 0x00001ffc;
310                 if ( word1 & 0x00001000 ){      /* Negative displacement */
311                         word1 |= (-1 & ~0x1fff);        /* Sign extend */
312                 }
313                 print_addr( memaddr + word1 );
314         }
315 }
316
317 /****************************************/
318 /* MEM format                           */
319 /****************************************/
320 static int                              /* returns instruction length: 4 or 8 */
321 mem( memaddr, word1, word2, noprint )
322     unsigned long memaddr;
323     unsigned long word1, word2;
324     int noprint;                /* If TRUE, return instruction length, but
325                                    don't output any text.  */
326 {
327         int i, j;
328         int len;
329         int mode;
330         int offset;
331         const char *reg1, *reg2, *reg3;
332
333         /* This lookup table is too sparse to make it worth typing in, but not
334          * so large as to make a sparse array necessary.  We allocate the
335          * table at runtime, initialize all entries to empty, and copy the
336          * real ones in from an initialization table.
337          *
338          * NOTE: In this table, the meaning of 'numops' is:
339          *       1: single operand
340          *       2: 2 operands, load instruction
341          *      -2: 2 operands, store instruction
342          */
343         static struct tabent *mem_tab = NULL;
344         static struct { int opcode; char *name; char numops; } mem_init[] = {
345 #define MEM_MIN 0x80
346                 0x80,   "ldob",  2,
347                 0x82,   "stob", -2,
348                 0x84,   "bx",    1,
349                 0x85,   "balx",  2,
350                 0x86,   "callx", 1,
351                 0x88,   "ldos",  2,
352                 0x8a,   "stos", -2,
353                 0x8c,   "lda",   2,
354                 0x90,   "ld",    2,
355                 0x92,   "st",   -2,
356                 0x98,   "ldl",   2,
357                 0x9a,   "stl",  -2,
358                 0xa0,   "ldt",   2,
359                 0xa2,   "stt",  -2,
360                 0xb0,   "ldq",   2,
361                 0xb2,   "stq",  -2,
362                 0xc0,   "ldib",  2,
363                 0xc2,   "stib", -2,
364                 0xc8,   "ldis",  2,
365                 0xca,   "stis", -2,
366 #define MEM_MAX 0xca
367 #define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
368                 0,      NULL,   0
369         };
370
371         if ( mem_tab == NULL ){
372                 mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
373                 bzero( mem_tab, MEM_SIZ );
374                 for ( i = 0; mem_init[i].opcode != 0; i++ ){
375                         j = mem_init[i].opcode - MEM_MIN;
376                         mem_tab[j].name = mem_init[i].name;
377                         mem_tab[j].numops = mem_init[i].numops;
378                 }
379         }
380
381         i = ((word1 >> 24) & 0xff) - MEM_MIN;
382         mode = (word1 >> 10) & 0xf;
383
384         if ( (mem_tab[i].name != NULL)          /* Valid instruction */
385         &&   ((mode == 5) || (mode >=12)) ){    /* With 32-bit displacement */
386                 len = 8;
387         } else {
388                 len = 4;
389         }
390
391         if ( noprint ){
392                 return len;
393         }
394
395         if ( (mem_tab[i].name == NULL) || (mode == 6) ){
396                 invalid( word1 );
397                 return len;
398         }
399
400         fprintf( stream, "%s\t", mem_tab[i].name );
401
402         reg1 = reg_names[ (word1 >> 19) & 0x1f ];       /* MEMB only */
403         reg2 = reg_names[ (word1 >> 14) & 0x1f ];
404         reg3 = reg_names[ word1 & 0x1f ];               /* MEMB only */
405         offset = word1 & 0xfff;                         /* MEMA only  */
406
407         switch ( mem_tab[i].numops ){
408
409         case 2: /* LOAD INSTRUCTION */
410                 if ( mode & 4 ){                        /* MEMB FORMAT */
411                         ea( memaddr, mode, reg2, reg3, word1, word2 );
412                         fprintf( stream, ",%s", reg1 );
413                 } else {                                /* MEMA FORMAT */
414                         fprintf( stream, "0x%x", offset );
415                         if (mode & 8) {
416                                 fprintf( stream, "(%s)", reg2 );
417                         }
418                         fprintf( stream, ",%s", reg1 );
419                 }
420                 break;
421
422         case -2: /* STORE INSTRUCTION */
423                 if ( mode & 4 ){                        /* MEMB FORMAT */
424                         fprintf( stream, "%s,", reg1 );
425                         ea( memaddr, mode, reg2, reg3, word1, word2 );
426                 } else {                                /* MEMA FORMAT */
427                         fprintf( stream, "%s,0x%x", reg1, offset );
428                         if (mode & 8) {
429                                 fprintf( stream, "(%s)", reg2 );
430                         }
431                 }
432                 break;
433
434         case 1: /* BX/CALLX INSTRUCTION */
435                 if ( mode & 4 ){                        /* MEMB FORMAT */
436                         ea( memaddr, mode, reg2, reg3, word1, word2 );
437                 } else {                                /* MEMA FORMAT */
438                         fprintf( stream, "0x%x", offset );
439                         if (mode & 8) {
440                                 fprintf( stream, "(%s)", reg2 );
441                         }
442                 }
443                 break;
444         }
445
446         return len;
447 }
448
449 /****************************************/
450 /* REG format                           */
451 /****************************************/
452 static void
453 reg( word1 )
454     unsigned long word1;
455 {
456         int i, j;
457         int opcode;
458         int fp;
459         int m1, m2, m3;
460         int s1, s2;
461         int src, src2, dst;
462         char *mnemp;
463
464         /* This lookup table is too sparse to make it worth typing in, but not
465          * so large as to make a sparse array necessary.  We allocate the
466          * table at runtime, initialize all entries to empty, and copy the
467          * real ones in from an initialization table.
468          *
469          * NOTE: In this table, the meaning of 'numops' is:
470          *       1: single operand, which is NOT a destination.
471          *      -1: single operand, which IS a destination.
472          *       2: 2 operands, the 2nd of which is NOT a destination.
473          *      -2: 2 operands, the 2nd of which IS a destination.
474          *       3: 3 operands
475          *
476          *      If an opcode mnemonic begins with "F", it is a floating-point
477          *      opcode (the "F" is not printed).
478          */
479
480         static struct tabent *reg_tab = NULL;
481         static struct { int opcode; char *name; char numops; } reg_init[] = {
482 #define REG_MIN 0x580
483                 0x580,  "notbit",       3,
484                 0x581,  "and",          3,
485                 0x582,  "andnot",       3,
486                 0x583,  "setbit",       3,
487                 0x584,  "notand",       3,
488                 0x586,  "xor",          3,
489                 0x587,  "or",           3,
490                 0x588,  "nor",          3,
491                 0x589,  "xnor",         3,
492                 0x58a,  "not",          -2,
493                 0x58b,  "ornot",        3,
494                 0x58c,  "clrbit",       3,
495                 0x58d,  "notor",        3,
496                 0x58e,  "nand",         3,
497                 0x58f,  "alterbit",     3,
498                 0x590,  "addo",         3,
499                 0x591,  "addi",         3,
500                 0x592,  "subo",         3,
501                 0x593,  "subi",         3,
502                 0x598,  "shro",         3,
503                 0x59a,  "shrdi",        3,
504                 0x59b,  "shri",         3,
505                 0x59c,  "shlo",         3,
506                 0x59d,  "rotate",       3,
507                 0x59e,  "shli",         3,
508                 0x5a0,  "cmpo",         2,
509                 0x5a1,  "cmpi",         2,
510                 0x5a2,  "concmpo",      2,
511                 0x5a3,  "concmpi",      2,
512                 0x5a4,  "cmpinco",      3,
513                 0x5a5,  "cmpinci",      3,
514                 0x5a6,  "cmpdeco",      3,
515                 0x5a7,  "cmpdeci",      3,
516                 0x5ac,  "scanbyte",     2,
517                 0x5ae,  "chkbit",       2,
518                 0x5b0,  "addc",         3,
519                 0x5b2,  "subc",         3,
520                 0x5cc,  "mov",          -2,
521                 0x5d8,  "eshro",        3,
522                 0x5dc,  "movl",         -2,
523                 0x5ec,  "movt",         -2,
524                 0x5fc,  "movq",         -2,
525                 0x600,  "synmov",       2,
526                 0x601,  "synmovl",      2,
527                 0x602,  "synmovq",      2,
528                 0x603,  "cmpstr",       3,
529                 0x604,  "movqstr",      3,
530                 0x605,  "movstr",       3,
531                 0x610,  "atmod",        3,
532                 0x612,  "atadd",        3,
533                 0x613,  "inspacc",      -2,
534                 0x614,  "ldphy",        -2,
535                 0x615,  "synld",        -2,
536                 0x617,  "fill",         3,
537                 0x630,  "sdma",         3,
538                 0x631,  "udma",         0,
539                 0x640,  "spanbit",      -2,
540                 0x641,  "scanbit",      -2,
541                 0x642,  "daddc",        3,
542                 0x643,  "dsubc",        3,
543                 0x644,  "dmovt",        -2,
544                 0x645,  "modac",        3,
545                 0x646,  "condrec",      -2,
546                 0x650,  "modify",       3,
547                 0x651,  "extract",      3,
548                 0x654,  "modtc",        3,
549                 0x655,  "modpc",        3,
550                 0x656,  "receive",      -2,
551                 0x659,  "sysctl",       3,
552                 0x660,  "calls",        1,
553                 0x662,  "send",         3,
554                 0x663,  "sendserv",     1,
555                 0x664,  "resumprcs",    1,
556                 0x665,  "schedprcs",    1,
557                 0x666,  "saveprcs",     0,
558                 0x668,  "condwait",     1,
559                 0x669,  "wait",         1,
560                 0x66a,  "signal",       1,
561                 0x66b,  "mark",         0,
562                 0x66c,  "fmark",        0,
563                 0x66d,  "flushreg",     0,
564                 0x66f,  "syncf",        0,
565                 0x670,  "emul",         3,
566                 0x671,  "ediv",         3,
567                 0x673,  "ldtime",       -1,
568                 0x674,  "Fcvtir",       -2,
569                 0x675,  "Fcvtilr",      -2,
570                 0x676,  "Fscalerl",     3,
571                 0x677,  "Fscaler",      3,
572                 0x680,  "Fatanr",       3,
573                 0x681,  "Flogepr",      3,
574                 0x682,  "Flogr",        3,
575                 0x683,  "Fremr",        3,
576                 0x684,  "Fcmpor",       2,
577                 0x685,  "Fcmpr",        2,
578                 0x688,  "Fsqrtr",       -2,
579                 0x689,  "Fexpr",        -2,
580                 0x68a,  "Flogbnr",      -2,
581                 0x68b,  "Froundr",      -2,
582                 0x68c,  "Fsinr",        -2,
583                 0x68d,  "Fcosr",        -2,
584                 0x68e,  "Ftanr",        -2,
585                 0x68f,  "Fclassr",      1,
586                 0x690,  "Fatanrl",      3,
587                 0x691,  "Flogeprl",     3,
588                 0x692,  "Flogrl",       3,
589                 0x693,  "Fremrl",       3,
590                 0x694,  "Fcmporl",      2,
591                 0x695,  "Fcmprl",       2,
592                 0x698,  "Fsqrtrl",      -2,
593                 0x699,  "Fexprl",       -2,
594                 0x69a,  "Flogbnrl",     -2,
595                 0x69b,  "Froundrl",     -2,
596                 0x69c,  "Fsinrl",       -2,
597                 0x69d,  "Fcosrl",       -2,
598                 0x69e,  "Ftanrl",       -2,
599                 0x69f,  "Fclassrl",     1,
600                 0x6c0,  "Fcvtri",       -2,
601                 0x6c1,  "Fcvtril",      -2,
602                 0x6c2,  "Fcvtzri",      -2,
603                 0x6c3,  "Fcvtzril",     -2,
604                 0x6c9,  "Fmovr",        -2,
605                 0x6d9,  "Fmovrl",       -2,
606                 0x6e1,  "Fmovre",       -2,
607                 0x6e2,  "Fcpysre",      3,
608                 0x6e3,  "Fcpyrsre",     3,
609                 0x701,  "mulo",         3,
610                 0x708,  "remo",         3,
611                 0x70b,  "divo",         3,
612                 0x741,  "muli",         3,
613                 0x748,  "remi",         3,
614                 0x749,  "modi",         3,
615                 0x74b,  "divi",         3,
616                 0x78b,  "Fdivr",        3,
617                 0x78c,  "Fmulr",        3,
618                 0x78d,  "Fsubr",        3,
619                 0x78f,  "Faddr",        3,
620                 0x79b,  "Fdivrl",       3,
621                 0x79c,  "Fmulrl",       3,
622                 0x79d,  "Fsubrl",       3,
623                 0x79f,  "Faddrl",       3,
624 #define REG_MAX 0x79f
625 #define REG_SIZ ((REG_MAX-REG_MIN+1) * sizeof(struct tabent))
626                 0,      NULL,   0
627         };
628
629         if ( reg_tab == NULL ){
630                 reg_tab = (struct tabent *) xmalloc( REG_SIZ );
631                 bzero( reg_tab, REG_SIZ );
632                 for ( i = 0; reg_init[i].opcode != 0; i++ ){
633                         j = reg_init[i].opcode - REG_MIN;
634                         reg_tab[j].name = reg_init[i].name;
635                         reg_tab[j].numops = reg_init[i].numops;
636                 }
637         }
638
639         opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf);
640         i = opcode - REG_MIN;
641
642         if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){
643                 invalid( word1 );
644                 return;
645         }
646
647         mnemp = reg_tab[i].name;
648         if ( *mnemp == 'F' ){
649                 fp = 1;
650                 mnemp++;
651         } else {
652                 fp = 0;
653         }
654
655         fputs( mnemp, stream );
656
657         s1   = (word1 >> 5)  & 1;
658         s2   = (word1 >> 6)  & 1;
659         m1   = (word1 >> 11) & 1;
660         m2   = (word1 >> 12) & 1;
661         m3   = (word1 >> 13) & 1;
662         src  =  word1        & 0x1f;
663         src2 = (word1 >> 14) & 0x1f;
664         dst  = (word1 >> 19) & 0x1f;
665
666         if  ( reg_tab[i].numops != 0 ){
667                 putc( '\t', stream );
668
669                 switch ( reg_tab[i].numops ){
670                 case 1:
671                         regop( m1, s1, src, fp );
672                         break;
673                 case -1:
674                         dstop( m3, dst, fp );
675                         break;
676                 case 2:
677                         regop( m1, s1, src, fp );
678                         putc( ',', stream );
679                         regop( m2, s2, src2, fp );
680                         break;
681                 case -2:
682                         regop( m1, s1, src, fp );
683                         putc( ',', stream );
684                         dstop( m3, dst, fp );
685                         break;
686                 case 3:
687                         regop( m1, s1, src, fp );
688                         putc( ',', stream );
689                         regop( m2, s2, src2, fp );
690                         putc( ',', stream );
691                         dstop( m3, dst, fp );
692                         break;
693                 }
694         }
695 }
696
697
698 /*
699  * Print out effective address for memb instructions.
700  */
701 static void
702 ea( memaddr, mode, reg2, reg3, word1, word2 )
703     unsigned long memaddr;
704     int mode;
705     char *reg2, *reg3;
706     unsigned int word2;
707 {
708         int scale;
709         static int scale_tab[] = { 1, 2, 4, 8, 16 };
710
711         scale = (word1 >> 7) & 0x07;
712         if ( (scale > 4) || ((word1 >> 5) & 0x03 != 0) ){
713                 invalid( word1 );
714                 return;
715         }
716         scale = scale_tab[scale];
717
718         switch (mode) {
719         case 4:                                         /* (reg) */
720                 fprintf( stream, "(%s)", reg2 );
721                 break;
722         case 5:                                         /* displ+8(ip) */
723                 print_addr( word2+8+memaddr );
724                 break;
725         case 7:                                         /* (reg)[index*scale] */
726                 if (scale == 1) {
727                         fprintf( stream, "(%s)[%s]", reg2, reg3 );
728                 } else {
729                         fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale);
730                 }
731                 break;
732         case 12:                                        /* displacement */
733                 print_addr( word2 );
734                 break;
735         case 13:                                        /* displ(reg) */
736                 print_addr( word2 );
737                 fprintf( stream, "(%s)", reg2 );
738                 break;
739         case 14:                                        /* displ[index*scale] */
740                 print_addr( word2 );
741                 if (scale == 1) {
742                         fprintf( stream, "[%s]", reg3 );
743                 } else {
744                         fprintf( stream, "[%s*%d]", reg3, scale );
745                 }
746                 break;
747         case 15:                                /* displ(reg)[index*scale] */
748                 print_addr( word2 );
749                 if (scale == 1) {
750                         fprintf( stream, "(%s)[%s]", reg2, reg3 );
751                 } else {
752                         fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale );
753                 }
754                 break;
755         default:
756                 invalid( word1 );
757                 return;
758         }
759 }
760
761
762 /************************************************/
763 /* Register Instruction Operand                 */
764 /************************************************/
765 static void
766 regop( mode, spec, reg, fp )
767     int mode, spec, reg, fp;
768 {
769         if ( fp ){                              /* FLOATING POINT INSTRUCTION */
770                 if ( mode == 1 ){                       /* FP operand */
771                         switch ( reg ){
772                         case 0:  fputs( "fp0", stream );        break;
773                         case 1:  fputs( "fp1", stream );        break;
774                         case 2:  fputs( "fp2", stream );        break;
775                         case 3:  fputs( "fp3", stream );        break;
776                         case 16: fputs( "0f0.0", stream );      break;
777                         case 22: fputs( "0f1.0", stream );      break;
778                         default: putc( '?', stream );           break;
779                         }
780                 } else {                                /* Non-FP register */
781                         fputs( reg_names[reg], stream );
782                 }
783         } else {                                /* NOT FLOATING POINT */
784                 if ( mode == 1 ){                       /* Literal */
785                         fprintf( stream, "%d", reg );
786                 } else {                                /* Register */
787                         if ( spec == 0 ){
788                                 fputs( reg_names[reg], stream );
789                         } else {
790                                 fprintf( stream, "sf%d", reg );
791                         }
792                 }
793         }
794 }
795
796 /************************************************/
797 /* Register Instruction Destination Operand     */
798 /************************************************/
799 static void
800 dstop( mode, reg, fp )
801     int mode, reg, fp;
802 {
803         /* 'dst' operand can't be a literal. On non-FP instructions,  register
804          * mode is assumed and "m3" acts as if were "s3";  on FP-instructions,
805          * sf registers are not allowed so m3 acts normally.
806          */
807          if ( fp ){
808                 regop( mode, 0, reg, fp );
809          } else {
810                 regop( 0, mode, reg, fp );
811          }
812 }
813
814
815 static void
816 invalid( word1 )
817     int word1;
818 {
819         fprintf( stream, ".word\t0x%08x", word1 );
820 }       
821
822 static void
823 print_addr(a)
824 {
825         print_address (a, stream);
826 }
827
828 static void
829 put_abs( word1, word2 )
830     unsigned long word1, word2;
831 {
832 #ifdef IN_GDB
833         return;
834 #else
835         int len;
836
837         switch ( (word1 >> 28) & 0xf ){
838         case 0x8:
839         case 0x9:
840         case 0xa:
841         case 0xb:
842         case 0xc:
843                 /* MEM format instruction */
844                 len = mem( 0, word1, word2, 1 );
845                 break;
846         default:
847                 len = 4;
848                 break;
849         }
850
851         if ( len == 8 ){
852                 fprintf( stream, "%08x %08x\t", word1, word2 );
853         } else {
854                 fprintf( stream, "%08x         \t", word1 );
855         }
856 ;
857
858 #endif
859 }
This page took 0.076362 seconds and 4 git commands to generate.