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