OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [opcodes/] [hppa-dis.c] - Blame information for rev 1778

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
2
   Copyright 1989, 1990, 1992, 1993 Free Software Foundation, Inc.
3
 
4
   Contributed by the Center for Software Science at the
5
   University of Utah (pa-gdb-bugs@cs.utah.edu).
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include <ansidecl.h>
22
#include "sysdep.h"
23
#include "dis-asm.h"
24
#include "libhppa.h"
25
#include "opcode/hppa.h"
26
 
27
/* Integer register names, indexed by the numbers which appear in the
28
   opcodes.  */
29
static const char *const reg_names[] =
30
 {"flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
31
  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
32
  "r20", "r21", "r22", "r23", "r24", "r25", "r26", "dp", "ret0", "ret1",
33
  "sp", "r31"};
34
 
35
/* Floating point register names, indexed by the numbers which appear in the
36
   opcodes.  */
37
static const char *const fp_reg_names[] =
38
 {"fpsr", "fpe2", "fpe4", "fpe6",
39
  "fr4", "fr5", "fr6", "fr7", "fr8",
40
  "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
41
  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
42
  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31"};
43
 
44
typedef unsigned int CORE_ADDR;
45
 
46
/* Get at various relevent fields of an instruction word. */
47
 
48
#define MASK_5 0x1f
49
#define MASK_10 0x3ff
50
#define MASK_11 0x7ff
51
#define MASK_14 0x3fff
52
#define MASK_21 0x1fffff
53
 
54
/* This macro gets bit fields using HP's numbering (MSB = 0) */
55
 
56
#define GET_FIELD(X, FROM, TO) \
57
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
58
 
59
/* Some of these have been converted to 2-d arrays because they
60
   consume less storage this way.  If the maintenance becomes a
61
   problem, convert them back to const 1-d pointer arrays.  */
62
static const char *const control_reg[] = {
63
  "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
64
  "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
65
  "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
66
  "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
67
  "tr4", "tr5", "tr6", "tr7"
68
};
69
 
70
static const char *const compare_cond_names[] = {
71
  "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv", ",od",
72
  ",tr", ",<>", ",>=", ",>", ",>>=", ",>>", ",nsv", ",ev"
73
};
74
static const char *const compare_cond_64_names[] = {
75
  "", ",*=", ",*<", ",*<=", ",*<<", ",*<<=", ",*sv", ",*od",
76
  ",*tr", ",*<>", ",*>=", ",*>", ",*>>=", ",*>>", ",*nsv", ",*ev"
77
};
78
static const char *const cmpib_cond_64_names[] = {
79
  ",*<<", ",*=", ",*<", ",*<=", ",*>>=", ",*<>", ",*>=", ",*>"
80
};
81
static const char *const add_cond_names[] = {
82
  "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv", ",od",
83
  ",tr", ",<>", ",>=", ",>", ",uv", ",vnz", ",nsv", ",ev"
84
};
85
static const char *const add_cond_64_names[] = {
86
  "", ",*=", ",*<", ",*<=", ",*nuv", ",*znv", ",*sv", ",*od",
87
  ",*tr", ",*<>", ",*>=", ",*>", ",*uv", ",*vnz", ",*nsv", ",*ev"
88
};
89
static const char *const wide_add_cond_names[] = {
90
  "", ",=", ",<", ",<=", ",nuv", ",*=", ",*<", ",*<=",
91
  ",tr", ",<>", ",>=", ",>", ",uv", ",*<>", ",*>=", ",*>"
92
};
93
static const char *const logical_cond_names[] = {
94
  "", ",=", ",<", ",<=", 0, 0, 0, ",od",
95
  ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
96
static const char *const logical_cond_64_names[] = {
97
  "", ",*=", ",*<", ",*<=", 0, 0, 0, ",*od",
98
  ",*tr", ",*<>", ",*>=", ",*>", 0, 0, 0, ",*ev"};
99
static const char *const unit_cond_names[] = {
100
  "", ",swz", ",sbz", ",shz", ",sdc", ",swc", ",sbc", ",shc",
101
  ",tr", ",nwz", ",nbz", ",nhz", ",ndc", ",nwc", ",nbc", ",nhc"
102
};
103
static const char *const unit_cond_64_names[] = {
104
  "", ",*swz", ",*sbz", ",*shz", ",*sdc", ",*swc", ",*sbc", ",*shc",
105
  ",*tr", ",*nwz", ",*nbz", ",*nhz", ",*ndc", ",*nwc", ",*nbc", ",*nhc"
106
};
107
static const char *const shift_cond_names[] = {
108
  "", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"
109
};
110
static const char *const shift_cond_64_names[] = {
111
  "", ",*=", ",*<", ",*od", ",*tr", ",*<>", ",*>=", ",*ev"
112
};
113
static const char *const bb_cond_64_names[] = {
114
  ",*<", ",*>="
115
};
116
static const char *const index_compl_names[] = {"", ",m", ",s", ",sm"};
117
static const char *const short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
118
static const char *const short_bytes_compl_names[] = {
119
  "", ",b,m", ",e", ",e,m"
120
};
121
static const char *const float_format_names[] = {",sgl", ",dbl", "", ",quad"};
122
static const char *const float_comp_names[] =
123
{
124
  ",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
125
  ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
126
  ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
127
  ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
128
};
129
static const char *const signed_unsigned_names[] = {",u", ",s"};
130
static const char *const mix_half_names[] = {",l", ",r"};
131
static const char *const saturation_names[] = {",us", ",ss", 0, ""};
132
static const char *const read_write_names[] = {",r", ",w"};
133
static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
134
 
135
/* For a bunch of different instructions form an index into a
136
   completer name table. */
137
#define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
138
                         GET_FIELD (insn, 18, 18) << 1)
139
 
140
#define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
141
                        (GET_FIELD ((insn), 19, 19) ? 8 : 0))
142
 
143
/* Utility function to print registers.  Put these first, so gcc's function
144
   inlining can do its stuff.  */
145
 
146
#define fputs_filtered(STR,F)   (*info->fprintf_func) (info->stream, "%s", STR)
147
 
148
static void
149
fput_reg (reg, info)
150
     unsigned reg;
151
     disassemble_info *info;
152
{
153
  (*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
154
}
155
 
156
static void
157
fput_fp_reg (reg, info)
158
     unsigned reg;
159
     disassemble_info *info;
160
{
161
  (*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
162
}
163
 
164
static void
165
fput_fp_reg_r (reg, info)
166
     unsigned reg;
167
     disassemble_info *info;
168
{
169
  /* Special case floating point exception registers.  */
170
  if (reg < 4)
171
    (*info->fprintf_func) (info->stream, "fpe%d", reg * 2 + 1);
172
  else
173
    (*info->fprintf_func) (info->stream, "%sR", reg ? fp_reg_names[reg]
174
                                                    : "fr0");
175
}
176
 
177
static void
178
fput_creg (reg, info)
179
     unsigned reg;
180
     disassemble_info *info;
181
{
182
  (*info->fprintf_func) (info->stream, control_reg[reg]);
183
}
184
 
185
/* print constants with sign */
186
 
187
static void
188
fput_const (num, info)
189
     unsigned num;
190
     disassemble_info *info;
191
{
192
  if ((int)num < 0)
193
    (*info->fprintf_func) (info->stream, "-%x", -(int)num);
194
  else
195
    (*info->fprintf_func) (info->stream, "%x", num);
196
}
197
 
198
/* Routines to extract various sized constants out of hppa
199
   instructions. */
200
 
201
/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
202
static int
203
extract_3 (word)
204
     unsigned word;
205
{
206
  return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
207
}
208
 
209
static int
210
extract_5_load (word)
211
     unsigned word;
212
{
213
  return low_sign_extend (word >> 16 & MASK_5, 5);
214
}
215
 
216
/* extract the immediate field from a st{bhw}s instruction */
217
static int
218
extract_5_store (word)
219
     unsigned word;
220
{
221
  return low_sign_extend (word & MASK_5, 5);
222
}
223
 
224
/* extract the immediate field from a break instruction */
225
static unsigned
226
extract_5r_store (word)
227
     unsigned word;
228
{
229
  return (word & MASK_5);
230
}
231
 
232
/* extract the immediate field from a {sr}sm instruction */
233
static unsigned
234
extract_5R_store (word)
235
     unsigned word;
236
{
237
  return (word >> 16 & MASK_5);
238
}
239
 
240
/* extract the 10 bit immediate field from a {sr}sm instruction */
241
static unsigned
242
extract_10U_store (word)
243
     unsigned word;
244
{
245
  return (word >> 16 & MASK_10);
246
}
247
 
248
/* extract the immediate field from a bb instruction */
249
static unsigned
250
extract_5Q_store (word)
251
     unsigned word;
252
{
253
  return (word >> 21 & MASK_5);
254
}
255
 
256
/* extract an 11 bit immediate field */
257
static int
258
extract_11 (word)
259
     unsigned word;
260
{
261
  return low_sign_extend (word & MASK_11, 11);
262
}
263
 
264
/* extract a 14 bit immediate field */
265
static int
266
extract_14 (word)
267
     unsigned word;
268
{
269
  return low_sign_extend (word & MASK_14, 14);
270
}
271
 
272
/* extract a 21 bit constant */
273
 
274
static int
275
extract_21 (word)
276
     unsigned word;
277
{
278
  int val;
279
 
280
  word &= MASK_21;
281
  word <<= 11;
282
  val = GET_FIELD (word, 20, 20);
283
  val <<= 11;
284
  val |= GET_FIELD (word, 9, 19);
285
  val <<= 2;
286
  val |= GET_FIELD (word, 5, 6);
287
  val <<= 5;
288
  val |= GET_FIELD (word, 0, 4);
289
  val <<= 2;
290
  val |= GET_FIELD (word, 7, 8);
291
  return sign_extend (val, 21) << 11;
292
}
293
 
294
/* extract a 12 bit constant from branch instructions */
295
 
296
static int
297
extract_12 (word)
298
     unsigned word;
299
{
300
  return sign_extend (GET_FIELD (word, 19, 28) |
301
                      GET_FIELD (word, 29, 29) << 10 |
302
                      (word & 0x1) << 11, 12) << 2;
303
}
304
 
305
/* extract a 17 bit constant from branch instructions, returning the
306
   19 bit signed value. */
307
 
308
static int
309
extract_17 (word)
310
     unsigned word;
311
{
312
  return sign_extend (GET_FIELD (word, 19, 28) |
313
                      GET_FIELD (word, 29, 29) << 10 |
314
                      GET_FIELD (word, 11, 15) << 11 |
315
                      (word & 0x1) << 16, 17) << 2;
316
}
317
 
318
static int
319
extract_22 (word)
320
     unsigned word;
321
{
322
  return sign_extend (GET_FIELD (word, 19, 28) |
323
                      GET_FIELD (word, 29, 29) << 10 |
324
                      GET_FIELD (word, 11, 15) << 11 |
325
                      GET_FIELD (word, 6, 10) << 16 |
326
                      (word & 0x1) << 21, 22) << 2;
327
}
328
 
329
/* Print one instruction.  */
330
int
331
print_insn_hppa (memaddr, info)
332
     bfd_vma memaddr;
333
     disassemble_info *info;
334
{
335
  bfd_byte buffer[4];
336
  unsigned int insn, i;
337
 
338
  {
339
    int status =
340
      (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
341
    if (status != 0)
342
      {
343
        (*info->memory_error_func) (status, memaddr, info);
344
        return -1;
345
      }
346
  }
347
 
348
  insn = bfd_getb32 (buffer);
349
 
350
  for (i = 0; i < NUMOPCODES; ++i)
351
    {
352
      const struct pa_opcode *opcode = &pa_opcodes[i];
353
      if ((insn & opcode->mask) == opcode->match)
354
        {
355
          register const char *s;
356
 
357
          (*info->fprintf_func) (info->stream, "%s", opcode->name);
358
 
359
          if (!strchr ("cfCY?-+nHNZFIuv", opcode->args[0]))
360
            (*info->fprintf_func) (info->stream, " ");
361
          for (s = opcode->args; *s != '\0'; ++s)
362
            {
363
              switch (*s)
364
                {
365
                case 'x':
366
                  fput_reg (GET_FIELD (insn, 11, 15), info);
367
                  break;
368
                case 'a':
369
                case 'b':
370
                  fput_reg (GET_FIELD (insn, 6, 10), info);
371
                  break;
372
                case '^':
373
                  fput_creg (GET_FIELD (insn, 6, 10), info);
374
                  break;
375
                case 't':
376
                  fput_reg (GET_FIELD (insn, 27, 31), info);
377
                  break;
378
 
379
                /* Handle floating point registers.  */
380
                case 'f':
381
                  switch (*++s)
382
                    {
383
                    case 't':
384
                      fput_fp_reg (GET_FIELD (insn, 27, 31), info);
385
                      break;
386
                    case 'T':
387
                      if (GET_FIELD (insn, 25, 25))
388
                        fput_fp_reg_r (GET_FIELD (insn, 27, 31), info);
389
                      else
390
                        fput_fp_reg (GET_FIELD (insn, 27, 31), info);
391
                      break;
392
                    case 'a':
393
                      if (GET_FIELD (insn, 25, 25))
394
                        fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
395
                      else
396
                        fput_fp_reg (GET_FIELD (insn, 6, 10), info);
397
                      break;
398
 
399
                    /* 'fA' will not generate a space before the regsiter
400
                        name.  Normally that is fine.  Except that it
401
                        causes problems with xmpyu which has no FP format
402
                        completer.  */
403
                    case 'X':
404
                      fputs_filtered (" ", info);
405
 
406
                    /* FALLTHRU */
407
 
408
                    case 'A':
409
                      if (GET_FIELD (insn, 24, 24))
410
                        fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
411
                      else
412
                        fput_fp_reg (GET_FIELD (insn, 6, 10), info);
413
 
414
                      break;
415
                    case 'b':
416
                      if (GET_FIELD (insn, 25, 25))
417
                        fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
418
                      else
419
                        fput_fp_reg (GET_FIELD (insn, 11, 15), info);
420
                      break;
421
                    case 'B':
422
                      if (GET_FIELD (insn, 19, 19))
423
                        fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
424
                      else
425
                        fput_fp_reg (GET_FIELD (insn, 11, 15), info);
426
                      break;
427
                    case 'C':
428
                      {
429
                        int reg = GET_FIELD (insn, 21, 22);
430
                        reg |= GET_FIELD (insn, 16, 18) << 2;
431
                        if (GET_FIELD (insn, 23, 23) != 0)
432
                          fput_fp_reg_r (reg, info);
433
                        else
434
                          fput_fp_reg (reg, info);
435
                        break;
436
                      }
437
                    case 'i':
438
                      {
439
                        int reg = GET_FIELD (insn, 6, 10);
440
 
441
                        reg |= (GET_FIELD (insn, 26, 26) << 4);
442
                        fput_fp_reg (reg, info);
443
                        break;
444
                      }
445
                    case 'j':
446
                      {
447
                        int reg = GET_FIELD (insn, 11, 15);
448
 
449
                        reg |= (GET_FIELD (insn, 26, 26) << 4);
450
                        fput_fp_reg (reg, info);
451
                        break;
452
                      }
453
                    case 'k':
454
                      {
455
                        int reg = GET_FIELD (insn, 27, 31);
456
 
457
                        reg |= (GET_FIELD (insn, 26, 26) << 4);
458
                        fput_fp_reg (reg, info);
459
                        break;
460
                      }
461
                    case 'l':
462
                      {
463
                        int reg = GET_FIELD (insn, 21, 25);
464
 
465
                        reg |= (GET_FIELD (insn, 26, 26) << 4);
466
                        fput_fp_reg (reg, info);
467
                        break;
468
                      }
469
                    case 'm':
470
                      {
471
                        int reg = GET_FIELD (insn, 16, 20);
472
 
473
                        reg |= (GET_FIELD (insn, 26, 26) << 4);
474
                        fput_fp_reg (reg, info);
475
                        break;
476
                      }
477
                    case 'e':
478
                      if (GET_FIELD (insn, 25, 25))
479
                        fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
480
                      else
481
                        fput_fp_reg (GET_FIELD (insn, 11, 15), info);
482
                      break;
483
 
484
                    }
485
                  break;
486
 
487
                case '5':
488
                  fput_const (extract_5_load (insn), info);
489
                  break;
490
                case 's':
491
                  (*info->fprintf_func) (info->stream,
492
                                         "sr%d", GET_FIELD (insn, 16, 17));
493
                  break;
494
 
495
                case 'S':
496
                  (*info->fprintf_func) (info->stream, "sr%d", extract_3 (insn));
497
                  break;
498
 
499
                /* Handle completers.  */
500
                case 'c':
501
                  switch (*++s)
502
                    {
503
                    case 'x':
504
                      (*info->fprintf_func) (info->stream, "%s ",
505
                                             index_compl_names[GET_COMPL (insn)]);
506
                      break;
507
                    case 'm':
508
                      (*info->fprintf_func) (info->stream, "%s ",
509
                                             short_ldst_compl_names[GET_COMPL (insn)]);
510
                      break;
511
                    case 's':
512
                      (*info->fprintf_func) (info->stream, "%s ",
513
                                             short_bytes_compl_names[GET_COMPL (insn)]);
514
                      break;
515
                    case 'c':
516
                    case 'C':
517
                      switch (GET_FIELD (insn, 20, 21))
518
                        {
519
                        case 1:
520
                          (*info->fprintf_func) (info->stream, ",bc ");
521
                          break;
522
                        case 2:
523
                          (*info->fprintf_func) (info->stream, ",sl ");
524
                          break;
525
                        default:
526
                          (*info->fprintf_func) (info->stream, " ");
527
                        }
528
                      break;
529
                    case 'd':
530
                      switch (GET_FIELD (insn, 20, 21))
531
                        {
532
                        case 1:
533
                          (*info->fprintf_func) (info->stream, ",co ");
534
                          break;
535
                        default:
536
                          (*info->fprintf_func) (info->stream, " ");
537
                        }
538
                      break;
539
                    case 'o':
540
                      (*info->fprintf_func) (info->stream, ",o");
541
                      break;
542
                    case 'g':
543
                      (*info->fprintf_func) (info->stream, ",gate");
544
                      break;
545
                    case 'p':
546
                      (*info->fprintf_func) (info->stream, ",l,push");
547
                      break;
548
                    case 'P':
549
                      (*info->fprintf_func) (info->stream, ",pop");
550
                      break;
551
                    case 'l':
552
                    case 'L':
553
                      (*info->fprintf_func) (info->stream, ",l");
554
                      break;
555
                    case 'w':
556
                      (*info->fprintf_func) (info->stream, "%s ",
557
                                             read_write_names[GET_FIELD (insn, 25, 25)]);
558
                      break;
559
                    case 'W':
560
                      (*info->fprintf_func) (info->stream, ",w");
561
                      break;
562
                    case 'r':
563
                      if (GET_FIELD (insn, 23, 26) == 5)
564
                        (*info->fprintf_func) (info->stream, ",r");
565
                      break;
566
                    case 'Z':
567
                      if (GET_FIELD (insn, 26, 26))
568
                        (*info->fprintf_func) (info->stream, ",m ");
569
                      else
570
                        (*info->fprintf_func) (info->stream, " ");
571
                      break;
572
                    case 'i':
573
                      if (GET_FIELD (insn, 25, 25))
574
                        (*info->fprintf_func) (info->stream, ",i");
575
                      break;
576
                    case 'z':
577
                      if (!GET_FIELD (insn, 21, 21))
578
                        (*info->fprintf_func) (info->stream, ",z");
579
                      break;
580
                    case 'a':
581
                      (*info->fprintf_func)
582
                        (info->stream, "%s", add_compl_names[GET_FIELD
583
                                                            (insn, 20, 21)]);
584
                      break;
585
                    case 'Y':
586
                      (*info->fprintf_func)
587
                        (info->stream, ",dc%s", add_compl_names[GET_FIELD
588
                                                               (insn, 20, 21)]);
589
                      break;
590
                    case 'y':
591
                      (*info->fprintf_func)
592
                        (info->stream, ",c%s", add_compl_names[GET_FIELD
593
                                                              (insn, 20, 21)]);
594
                      break;
595
                    case 'v':
596
                      if (GET_FIELD (insn, 20, 20))
597
                        (*info->fprintf_func) (info->stream, ",tsv");
598
                      break;
599
                    case 't':
600
                      (*info->fprintf_func) (info->stream, ",tc");
601
                      if (GET_FIELD (insn, 20, 20))
602
                        (*info->fprintf_func) (info->stream, ",tsv");
603
                      break;
604
                    case 'B':
605
                      (*info->fprintf_func) (info->stream, ",db");
606
                      if (GET_FIELD (insn, 20, 20))
607
                        (*info->fprintf_func) (info->stream, ",tsv");
608
                      break;
609
                    case 'b':
610
                      (*info->fprintf_func) (info->stream, ",b");
611
                      if (GET_FIELD (insn, 20, 20))
612
                        (*info->fprintf_func) (info->stream, ",tsv");
613
                      break;
614
                    case 'T':
615
                      if (GET_FIELD (insn, 25, 25))
616
                        (*info->fprintf_func) (info->stream, ",tc");
617
                      break;
618
                    case 'S':
619
                      /* EXTRD/W has a following condition.  */
620
                      if (*(s + 1) == '?')
621
                        (*info->fprintf_func)
622
                          (info->stream, "%s", signed_unsigned_names[GET_FIELD
623
                                                                    (insn, 21, 21)]);
624
                      else
625
                        (*info->fprintf_func)
626
                          (info->stream, "%s ", signed_unsigned_names[GET_FIELD
627
                                                                     (insn, 21, 21)]);
628
                      break;
629
                    case 'h':
630
                      (*info->fprintf_func)
631
                          (info->stream, "%s", mix_half_names[GET_FIELD
632
                                                             (insn, 17, 17)]);
633
                      break;
634
                    case 'H':
635
                      (*info->fprintf_func)
636
                          (info->stream, "%s", saturation_names[GET_FIELD
637
                                                               (insn, 24, 25)]);
638
                      break;
639
                    case '*':
640
                      (*info->fprintf_func)
641
                          (info->stream, ",%d%d%d%d ",
642
                           GET_FIELD (insn, 17, 18), GET_FIELD (insn, 20, 21),
643
                           GET_FIELD (insn, 22, 23), GET_FIELD (insn, 24, 25));
644
                      break;
645
 
646
                    case 'q':
647
                      {
648
                        int m, a;
649
 
650
                        m = GET_FIELD (insn, 28, 28);
651
                        a = GET_FIELD (insn, 29, 29);
652
 
653
                        if (m && !a)
654
                          fputs_filtered (",ma ", info);
655
                        else if (m && a)
656
                          fputs_filtered (",mb ", info);
657
                        else
658
                          fputs_filtered (" ", info);
659
                        break;
660
                      }
661
 
662
                    case 'J':
663
                      {
664
                        int opcode = GET_FIELD (insn, 0, 5);
665
 
666
                        if (opcode == 0x16 || opcode == 0x1e)
667
                          {
668
                            if (GET_FIELD (insn, 29, 29) == 0)
669
                              fputs_filtered (",ma ", info);
670
                            else
671
                              fputs_filtered (",mb ", info);
672
                          }
673
                        else
674
                          fputs_filtered (" ", info);
675
                        break;
676
                      }
677
 
678
                    case 'e':
679
                      {
680
                        int opcode = GET_FIELD (insn, 0, 5);
681
 
682
                        if (opcode == 0x13 || opcode == 0x1b)
683
                          {
684
                            if (GET_FIELD (insn, 18, 18) == 1)
685
                              fputs_filtered (",mb ", info);
686
                            else
687
                              fputs_filtered (",ma ", info);
688
                          }
689
                        else if (opcode == 0x17 || opcode == 0x1f)
690
                          {
691
                            if (GET_FIELD (insn, 31, 31) == 1)
692
                              fputs_filtered (",ma ", info);
693
                            else
694
                              fputs_filtered (",mb ", info);
695
                          }
696
                        else
697
                          fputs_filtered (" ", info);
698
 
699
                        break;
700
                      }
701
                    }
702
                  break;
703
 
704
                /* Handle conditions.  */
705
                case '?':
706
                  {
707
                    s++;
708
                    switch (*s)
709
                      {
710
                      case 'f':
711
                        (*info->fprintf_func) (info->stream, "%s ",
712
                                               float_comp_names[GET_FIELD
713
                                                               (insn, 27, 31)]);
714
                        break;
715
 
716
                      /* these four conditions are for the set of instructions
717
                           which distinguish true/false conditions by opcode
718
                           rather than by the 'f' bit (sigh): comb, comib,
719
                           addb, addib */
720
                      case 't':
721
                        fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)],
722
                                        info);
723
                        break;
724
                      case 'n':
725
                        fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)
726
                                        + GET_FIELD (insn, 4, 4) * 8], info);
727
                        break;
728
                      case 'N':
729
                        fputs_filtered (compare_cond_64_names[GET_FIELD (insn, 16, 18)
730
                                        + GET_FIELD (insn, 2, 2) * 8], info);
731
                        break;
732
                      case 'Q':
733
                        fputs_filtered (cmpib_cond_64_names[GET_FIELD (insn, 16, 18)],
734
                                        info);
735
                        break;
736
                      case '@':
737
                        fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18)
738
                                        + GET_FIELD (insn, 4, 4) * 8], info);
739
                        break;
740
                      case 's':
741
                        (*info->fprintf_func) (info->stream, "%s ",
742
                                               compare_cond_names[GET_COND (insn)]);
743
                        break;
744
                      case 'S':
745
                        (*info->fprintf_func) (info->stream, "%s ",
746
                                               compare_cond_64_names[GET_COND (insn)]);
747
                        break;
748
                      case 'a':
749
                        (*info->fprintf_func) (info->stream, "%s ",
750
                                               add_cond_names[GET_COND (insn)]);
751
                        break;
752
                      case 'A':
753
                        (*info->fprintf_func) (info->stream, "%s ",
754
                                               add_cond_64_names[GET_COND (insn)]);
755
                        break;
756
                      case 'd':
757
                        (*info->fprintf_func) (info->stream, "%s",
758
                                               add_cond_names[GET_FIELD (insn, 16, 18)]);
759
                        break;
760
 
761
                      case 'W':
762
                        (*info->fprintf_func)
763
                          (info->stream, "%s",
764
                           wide_add_cond_names[GET_FIELD (insn, 16, 18) +
765
                                              GET_FIELD (insn, 4, 4) * 8]);
766
                        break;
767
 
768
                      case 'l':
769
                        (*info->fprintf_func) (info->stream, "%s ",
770
                                               logical_cond_names[GET_COND (insn)]);
771
                        break;
772
                      case 'L':
773
                        (*info->fprintf_func) (info->stream, "%s ",
774
                                               logical_cond_64_names[GET_COND (insn)]);
775
                        break;
776
                      case 'u':
777
                        (*info->fprintf_func) (info->stream, "%s ",
778
                                               unit_cond_names[GET_COND (insn)]);
779
                        break;
780
                      case 'U':
781
                        (*info->fprintf_func) (info->stream, "%s ",
782
                                               unit_cond_64_names[GET_COND (insn)]);
783
                        break;
784
                      case 'y':
785
                      case 'x':
786
                      case 'b':
787
                        (*info->fprintf_func)
788
                          (info->stream, "%s",
789
                           shift_cond_names[GET_FIELD (insn, 16, 18)]);
790
 
791
                        /* If the next character in args is 'n', it will handle
792
                           putting out the space.  */
793
                        if (s[1] != 'n')
794
                          (*info->fprintf_func) (info->stream, " ");
795
                        break;
796
                      case 'X':
797
                        (*info->fprintf_func) (info->stream, "%s ",
798
                                               shift_cond_64_names[GET_FIELD (insn, 16, 18)]);
799
                        break;
800
                      case 'B':
801
                        (*info->fprintf_func)
802
                          (info->stream, "%s",
803
                           bb_cond_64_names[GET_FIELD (insn, 16, 16)]);
804
 
805
                        /* If the next character in args is 'n', it will handle
806
                           putting out the space.  */
807
                        if (s[1] != 'n')
808
                          (*info->fprintf_func) (info->stream, " ");
809
                        break;
810
                      }
811
                    break;
812
                  }
813
 
814
                case 'V':
815
                  fput_const (extract_5_store (insn), info);
816
                  break;
817
                case 'r':
818
                  fput_const (extract_5r_store (insn), info);
819
                  break;
820
                case 'R':
821
                  fput_const (extract_5R_store (insn), info);
822
                  break;
823
                case 'U':
824
                  fput_const (extract_10U_store (insn), info);
825
                  break;
826
                case 'B':
827
                case 'Q':
828
                  fput_const (extract_5Q_store (insn), info);
829
                  break;
830
                case 'i':
831
                  fput_const (extract_11 (insn), info);
832
                  break;
833
                case 'j':
834
                  fput_const (extract_14 (insn), info);
835
                  break;
836
                case 'k':
837
                  fput_const (extract_21 (insn), info);
838
                  break;
839
                case 'n':
840
                  if (insn & 0x2)
841
                    (*info->fprintf_func) (info->stream, ",n ");
842
                  else
843
                    (*info->fprintf_func) (info->stream, " ");
844
                  break;
845
                case 'N':
846
                  if ((insn & 0x20) && s[1])
847
                    (*info->fprintf_func) (info->stream, ",n ");
848
                  else if (insn & 0x20)
849
                    (*info->fprintf_func) (info->stream, ",n");
850
                  else if (s[1])
851
                    (*info->fprintf_func) (info->stream, " ");
852
                  break;
853
                case 'w':
854
                  (*info->print_address_func) (memaddr + 8 + extract_12 (insn),
855
                                               info);
856
                  break;
857
                case 'W':
858
                  /* 17 bit PC-relative branch.  */
859
                  (*info->print_address_func) ((memaddr + 8
860
                                                + extract_17 (insn)),
861
                                               info);
862
                  break;
863
                case 'z':
864
                  /* 17 bit displacement.  This is an offset from a register
865
                     so it gets disasssembled as just a number, not any sort
866
                     of address.  */
867
                  fput_const (extract_17 (insn), info);
868
                  break;
869
 
870
                case 'Z':
871
                  /* addil %r1 implicit output.  */
872
                  (*info->fprintf_func) (info->stream, "%%r1");
873
                  break;
874
 
875
                case 'Y':
876
                  /* be,l %sr0,%r31 implicit output.  */
877
                  (*info->fprintf_func) (info->stream, "%%sr0,%%r31");
878
                  break;
879
 
880
                case '@':
881
                  (*info->fprintf_func) (info->stream, "0");
882
                  break;
883
 
884
                case '.':
885
                  (*info->fprintf_func) (info->stream, "%d",
886
                                    GET_FIELD (insn, 24, 25));
887
                  break;
888
                case '*':
889
                  (*info->fprintf_func) (info->stream, "%d",
890
                                    GET_FIELD (insn, 22, 25));
891
                  break;
892
                case '!':
893
                  (*info->fprintf_func) (info->stream, "%%sar");
894
                  break;
895
                case 'p':
896
                  (*info->fprintf_func) (info->stream, "%d",
897
                                    31 - GET_FIELD (insn, 22, 26));
898
                  break;
899
                case '~':
900
                  {
901
                    int num;
902
                    num = GET_FIELD (insn, 20, 20) << 5;
903
                    num |= GET_FIELD (insn, 22, 26);
904
                    (*info->fprintf_func) (info->stream, "%d", 63 - num);
905
                    break;
906
                  }
907
                case 'P':
908
                  (*info->fprintf_func) (info->stream, "%d",
909
                                    GET_FIELD (insn, 22, 26));
910
                  break;
911
                case 'q':
912
                  {
913
                    int num;
914
                    num = GET_FIELD (insn, 20, 20) << 5;
915
                    num |= GET_FIELD (insn, 22, 26);
916
                    (*info->fprintf_func) (info->stream, "%d", num);
917
                    break;
918
                  }
919
                case 'T':
920
                  (*info->fprintf_func) (info->stream, "%d",
921
                                    32 - GET_FIELD (insn, 27, 31));
922
                  break;
923
                case '%':
924
                  {
925
                    int num;
926
                    num = (GET_FIELD (insn, 23, 23) + 1) * 32;
927
                    num -= GET_FIELD (insn, 27, 31);
928
                    (*info->fprintf_func) (info->stream, "%d", num);
929
                    break;
930
                  }
931
                case '|':
932
                  {
933
                    int num;
934
                    num = (GET_FIELD (insn, 19, 19) + 1) * 32;
935
                    num -= GET_FIELD (insn, 27, 31);
936
                    (*info->fprintf_func) (info->stream, "%d", num);
937
                    break;
938
                  }
939
                case '$':
940
                  fput_const (GET_FIELD (insn, 20, 28), info);
941
                  break;
942
                case 'A':
943
                  fput_const (GET_FIELD (insn, 6, 18), info);
944
                  break;
945
                case 'D':
946
                  fput_const (GET_FIELD (insn, 6, 31), info);
947
                  break;
948
                case 'v':
949
                  (*info->fprintf_func) (info->stream, ",%d", GET_FIELD (insn, 23, 25));
950
                  break;
951
                case 'O':
952
                  fput_const ((GET_FIELD (insn, 6,20) << 5 |
953
                               GET_FIELD (insn, 27, 31)), info);
954
                  break;
955
                case 'o':
956
                  fput_const (GET_FIELD (insn, 6, 20), info);
957
                  break;
958
                case '2':
959
                  fput_const ((GET_FIELD (insn, 6, 22) << 5 |
960
                               GET_FIELD (insn, 27, 31)), info);
961
                  break;
962
                case '1':
963
                  fput_const ((GET_FIELD (insn, 11, 20) << 5 |
964
                               GET_FIELD (insn, 27, 31)), info);
965
                  break;
966
                case '0':
967
                  fput_const ((GET_FIELD (insn, 16, 20) << 5 |
968
                               GET_FIELD (insn, 27, 31)), info);
969
                  break;
970
                case 'u':
971
                  (*info->fprintf_func) (info->stream, ",%d", GET_FIELD (insn, 23, 25));
972
                  break;
973
                case 'F':
974
                  /* if no destination completer and not before a completer
975
                     for fcmp, need a space here */
976
                  if (s[1] == 'G' || s[1] == '?')
977
                    fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)],
978
                                    info);
979
                  else
980
                    (*info->fprintf_func) (info->stream, "%s ",
981
                                           float_format_names[GET_FIELD
982
                                                              (insn, 19, 20)]);
983
                  break;
984
                case 'G':
985
                  (*info->fprintf_func) (info->stream, "%s ",
986
                                    float_format_names[GET_FIELD (insn,
987
                                                                  17, 18)]);
988
                  break;
989
                case 'H':
990
                  if (GET_FIELD (insn, 26, 26) == 1)
991
                    (*info->fprintf_func) (info->stream, "%s ",
992
                                    float_format_names[0]);
993
                  else
994
                    (*info->fprintf_func) (info->stream, "%s ",
995
                                    float_format_names[1]);
996
                  break;
997
                case 'I':
998
                  /* if no destination completer and not before a completer
999
                     for fcmp, need a space here */
1000
                  if (s[1] == '?')
1001
                    fputs_filtered (float_format_names[GET_FIELD (insn, 20, 20)],
1002
                                    info);
1003
                  else
1004
                    (*info->fprintf_func) (info->stream, "%s ",
1005
                                           float_format_names[GET_FIELD
1006
                                                              (insn, 20, 20)]);
1007
                  break;
1008
 
1009
                case 'J':
1010
                  fput_const (extract_14 (insn), info);
1011
                  break;
1012
 
1013
                case '#':
1014
                  {
1015
                    int sign = GET_FIELD (insn, 31, 31);
1016
                    int imm10 = GET_FIELD (insn, 18, 27);
1017
                    int disp;
1018
 
1019
                    if (sign)
1020
                      disp = (-1 << 10) | imm10;
1021
                    else
1022
                      disp = imm10;
1023
 
1024
                    disp <<= 3;
1025
                    fput_const (disp, info);
1026
                    break;
1027
                  }
1028
                case 'K':
1029
                case 'd':
1030
                  {
1031
                    int sign = GET_FIELD (insn, 31, 31);
1032
                    int imm11 = GET_FIELD (insn, 18, 28);
1033
                    int disp;
1034
 
1035
                    if (sign)
1036
                      disp = (-1 << 11) | imm11;
1037
                    else
1038
                      disp = imm11;
1039
 
1040
                    disp <<= 2;
1041
                    fput_const (disp, info);
1042
                    break;
1043
                  }
1044
 
1045
                /* ?!? FIXME */
1046
                case '_':
1047
                case '{':
1048
                  fputs_filtered ("Disassembler botch.\n", info);
1049
                  break;
1050
 
1051
                case 'm':
1052
                  {
1053
                    int y = GET_FIELD (insn, 16, 18);
1054
 
1055
                    if (y != 1)
1056
                      fput_const ((y ^ 1) - 1, info);
1057
                  }
1058
                  break;
1059
 
1060
                case 'h':
1061
                  {
1062
                    int cbit;
1063
 
1064
                    cbit = GET_FIELD (insn, 16, 18);
1065
 
1066
                    if (cbit > 0)
1067
                      (*info->fprintf_func) (info->stream, ",%d", cbit - 1);
1068
                    break;
1069
                  }
1070
 
1071
                case '=':
1072
                  {
1073
                    int cond = GET_FIELD (insn, 27, 31);
1074
 
1075
                    if (cond == 0)
1076
                      fputs_filtered (" ", info);
1077
                    else if (cond == 1)
1078
                      fputs_filtered ("acc ", info);
1079
                    else if (cond == 2)
1080
                      fputs_filtered ("rej ", info);
1081
                    else if (cond == 5)
1082
                      fputs_filtered ("acc8 ", info);
1083
                    else if (cond == 6)
1084
                      fputs_filtered ("rej8 ", info);
1085
                    else if (cond == 9)
1086
                      fputs_filtered ("acc6 ", info);
1087
                    else if (cond == 13)
1088
                      fputs_filtered ("acc4 ", info);
1089
                    else if (cond == 17)
1090
                      fputs_filtered ("acc2 ", info);
1091
                    break;
1092
                  }
1093
 
1094
                case 'X':
1095
                  (*info->print_address_func) ((memaddr + 8
1096
                                                + extract_22 (insn)),
1097
                                               info);
1098
                  break;
1099
                case 'L':
1100
                  fputs_filtered (",%r2", info);
1101
                  break;
1102
                default:
1103
                  (*info->fprintf_func) (info->stream, "%c", *s);
1104
                  break;
1105
                }
1106
            }
1107
          return sizeof(insn);
1108
        }
1109
    }
1110
  (*info->fprintf_func) (info->stream, "#%8x", insn);
1111
  return sizeof(insn);
1112
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.