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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [hppa-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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