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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [s390-dis.c] - Blame information for rev 856

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

Line No. Rev Author Line
1 38 julius
/* s390-dis.c -- Disassemble S390 instructions
2
   Copyright 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
3
   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4
 
5
   This file is part of the GNU opcodes library.
6
 
7
   This library 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 3, or (at your option)
10
   any later version.
11
 
12
   It is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this file; see the file COPYING.  If not, write to the
19
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include <stdio.h>
23
#include "ansidecl.h"
24
#include "sysdep.h"
25
#include "dis-asm.h"
26
#include "opintl.h"
27
#include "opcode/s390.h"
28
 
29
static int init_flag = 0;
30
static int opc_index[256];
31
static int current_arch_mask = 0;
32
 
33
/* Set up index table for first opcode byte.  */
34
 
35
static void
36
init_disasm (struct disassemble_info *info)
37
{
38
  const struct s390_opcode *opcode;
39
  const struct s390_opcode *opcode_end;
40
  const char *p;
41
 
42
  memset (opc_index, 0, sizeof (opc_index));
43
  opcode_end = s390_opcodes + s390_num_opcodes;
44
  for (opcode = s390_opcodes; opcode < opcode_end; opcode++)
45
    {
46
      opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes;
47
      while ((opcode < opcode_end) &&
48
             (opcode[1].opcode[0] == opcode->opcode[0]))
49
        opcode++;
50
    }
51
 
52
  for (p = info->disassembler_options; p != NULL; )
53
    {
54
      if (CONST_STRNEQ (p, "esa"))
55
        current_arch_mask = 1 << S390_OPCODE_ESA;
56
      else if (CONST_STRNEQ (p, "zarch"))
57
        current_arch_mask = 1 << S390_OPCODE_ZARCH;
58
      else
59
        fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
60
 
61
      p = strchr (p, ',');
62
      if (p != NULL)
63
        p++;
64
    }
65
 
66
  if (!current_arch_mask)
67
    switch (info->mach)
68
      {
69
      case bfd_mach_s390_31:
70
        current_arch_mask = 1 << S390_OPCODE_ESA;
71
        break;
72
      case bfd_mach_s390_64:
73
        current_arch_mask = 1 << S390_OPCODE_ZARCH;
74
        break;
75
      default:
76
        abort ();
77
      }
78
 
79
  init_flag = 1;
80
}
81
 
82
/* Extracts an operand value from an instruction.  */
83
 
84
static inline unsigned int
85
s390_extract_operand (unsigned char *insn, const struct s390_operand *operand)
86
{
87
  unsigned int val;
88
  int bits;
89
 
90
  /* Extract fragments of the operand byte for byte.  */
91
  insn += operand->shift / 8;
92
  bits = (operand->shift & 7) + operand->bits;
93
  val = 0;
94
  do
95
    {
96
      val <<= 8;
97
      val |= (unsigned int) *insn++;
98
      bits -= 8;
99
    }
100
  while (bits > 0);
101
  val >>= -bits;
102
  val &= ((1U << (operand->bits - 1)) << 1) - 1;
103
 
104
  /* Check for special long displacement case.  */
105
  if (operand->bits == 20 && operand->shift == 20)
106
    val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
107
 
108
  /* Sign extend value if the operand is signed or pc relative.  */
109
  if ((operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
110
      && (val & (1U << (operand->bits - 1))))
111
    val |= (-1U << (operand->bits - 1)) << 1;
112
 
113
  /* Double value if the operand is pc relative.  */
114
  if (operand->flags & S390_OPERAND_PCREL)
115
    val <<= 1;
116
 
117
  /* Length x in an instructions has real length x + 1.  */
118
  if (operand->flags & S390_OPERAND_LENGTH)
119
    val++;
120
  return val;
121
}
122
 
123
/* Print a S390 instruction.  */
124
 
125
int
126
print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
127
{
128
  bfd_byte buffer[6];
129
  const struct s390_opcode *opcode;
130
  const struct s390_opcode *opcode_end;
131
  unsigned int value;
132
  int status, opsize, bufsize;
133
  char separator;
134
 
135
  if (init_flag == 0)
136
    init_disasm (info);
137
 
138
  /* The output looks better if we put 6 bytes on a line.  */
139
  info->bytes_per_line = 6;
140
 
141
  /* Every S390 instruction is max 6 bytes long.  */
142
  memset (buffer, 0, 6);
143
  status = (*info->read_memory_func) (memaddr, buffer, 6, info);
144
  if (status != 0)
145
    {
146
      for (bufsize = 0; bufsize < 6; bufsize++)
147
        if ((*info->read_memory_func) (memaddr, buffer, bufsize + 1, info) != 0)
148
          break;
149
      if (bufsize <= 0)
150
        {
151
          (*info->memory_error_func) (status, memaddr, info);
152
          return -1;
153
        }
154
      /* Opsize calculation looks strange but it works
155
         00xxxxxx -> 2 bytes, 01xxxxxx/10xxxxxx -> 4 bytes,
156
         11xxxxxx -> 6 bytes.  */
157
      opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
158
      status = opsize > bufsize;
159
    }
160
  else
161
    {
162
      bufsize = 6;
163
      opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
164
    }
165
 
166
  if (status == 0)
167
    {
168
      /* Find the first match in the opcode table.  */
169
      opcode_end = s390_opcodes + s390_num_opcodes;
170
      for (opcode = s390_opcodes + opc_index[(int) buffer[0]];
171
           (opcode < opcode_end) && (buffer[0] == opcode->opcode[0]);
172
           opcode++)
173
        {
174
          const struct s390_operand *operand;
175
          const unsigned char *opindex;
176
 
177
          /* Check architecture.  */
178
          if (!(opcode->modes & current_arch_mask))
179
            continue;
180
          /* Check signature of the opcode.  */
181
          if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
182
              || (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
183
              || (buffer[3] & opcode->mask[3]) != opcode->opcode[3]
184
              || (buffer[4] & opcode->mask[4]) != opcode->opcode[4]
185
              || (buffer[5] & opcode->mask[5]) != opcode->opcode[5])
186
            continue;
187
 
188
          /* The instruction is valid.  */
189
          if (opcode->operands[0] != 0)
190
            (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
191
          else
192
            (*info->fprintf_func) (info->stream, "%s", opcode->name);
193
 
194
          /* Extract the operands.  */
195
          separator = 0;
196
          for (opindex = opcode->operands; *opindex != 0; opindex++)
197
            {
198
              unsigned int value;
199
 
200
              operand = s390_operands + *opindex;
201
              value = s390_extract_operand (buffer, operand);
202
 
203
              if ((operand->flags & S390_OPERAND_INDEX) && value == 0)
204
                continue;
205
              if ((operand->flags & S390_OPERAND_BASE) &&
206
                  value == 0 && separator == '(')
207
                {
208
                  separator = ',';
209
                  continue;
210
                }
211
 
212
              if (separator)
213
                (*info->fprintf_func) (info->stream, "%c", separator);
214
 
215
              if (operand->flags & S390_OPERAND_GPR)
216
                (*info->fprintf_func) (info->stream, "%%r%i", value);
217
              else if (operand->flags & S390_OPERAND_FPR)
218
                (*info->fprintf_func) (info->stream, "%%f%i", value);
219
              else if (operand->flags & S390_OPERAND_AR)
220
                (*info->fprintf_func) (info->stream, "%%a%i", value);
221
              else if (operand->flags & S390_OPERAND_CR)
222
                (*info->fprintf_func) (info->stream, "%%c%i", value);
223
              else if (operand->flags & S390_OPERAND_PCREL)
224
                (*info->print_address_func) (memaddr + (int) value, info);
225
              else if (operand->flags & S390_OPERAND_SIGNED)
226
                (*info->fprintf_func) (info->stream, "%i", (int) value);
227
              else
228
                (*info->fprintf_func) (info->stream, "%u", value);
229
 
230
              if (operand->flags & S390_OPERAND_DISP)
231
                {
232
                  separator = '(';
233
                }
234
              else if (operand->flags & S390_OPERAND_BASE)
235
                {
236
                  (*info->fprintf_func) (info->stream, ")");
237
                  separator = ',';
238
                }
239
              else
240
                separator = ',';
241
            }
242
 
243
          /* Found instruction, printed it, return its size.  */
244
          return opsize;
245
        }
246
      /* No matching instruction found, fall through to hex print.  */
247
    }
248
 
249
  if (bufsize >= 4)
250
    {
251
      value = (unsigned int) buffer[0];
252
      value = (value << 8) + (unsigned int) buffer[1];
253
      value = (value << 8) + (unsigned int) buffer[2];
254
      value = (value << 8) + (unsigned int) buffer[3];
255
      (*info->fprintf_func) (info->stream, ".long\t0x%08x", value);
256
      return 4;
257
    }
258
  else if (bufsize >= 2)
259
    {
260
      value = (unsigned int) buffer[0];
261
      value = (value << 8) + (unsigned int) buffer[1];
262
      (*info->fprintf_func) (info->stream, ".short\t0x%04x", value);
263
      return 2;
264
    }
265
  else
266
    {
267
      value = (unsigned int) buffer[0];
268
      (*info->fprintf_func) (info->stream, ".byte\t0x%02x", value);
269
      return 1;
270
    }
271
}
272
 
273
void
274
print_s390_disassembler_options (FILE *stream)
275
{
276
  fprintf (stream, _("\n\
277
The following S/390 specific disassembler options are supported for use\n\
278
with the -M switch (multiple options should be separated by commas):\n"));
279
 
280
  fprintf (stream, _("  esa         Disassemble in ESA architecture mode\n"));
281
  fprintf (stream, _("  zarch       Disassemble in z/Architecture mode\n"));
282
}

powered by: WebSVN 2.1.0

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