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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [opcodes/] [s390-dis.c] - Blame information for rev 308

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

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