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