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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [s390-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* s390-dis.c -- Disassemble S390 instructions
2
   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
3
   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4
 
5
   This file is part of GDB, GAS and the GNU binutils.
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
20
   02111-1307, USA.  */
21
 
22
#include <stdio.h>
23
#include "ansidecl.h"
24
#include "sysdep.h"
25
#include "dis-asm.h"
26
#include "opcode/s390.h"
27
 
28
static int init_flag = 0;
29
static int opc_index[256];
30
static int current_arch_mask = 0;
31
 
32
static void init_disasm PARAMS ((struct disassemble_info *));
33
static unsigned int s390_extract_operand
34
  PARAMS ((unsigned char *, const struct s390_operand *));
35
 
36
/* Set up index table for first opcode byte.  */
37
 
38
static void
39
init_disasm (info)
40
     struct disassemble_info *info;
41
{
42
  const struct s390_opcode *opcode;
43
  const struct s390_opcode *opcode_end;
44
 
45
  memset (opc_index, 0, sizeof (opc_index));
46
  opcode_end = s390_opcodes + s390_num_opcodes;
47
  for (opcode = s390_opcodes; opcode < opcode_end; opcode++)
48
    {
49
      opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes;
50
      while ((opcode < opcode_end) &&
51
             (opcode[1].opcode[0] == opcode->opcode[0]))
52
        opcode++;
53
    }
54
  switch (info->mach)
55
    {
56
    case bfd_mach_s390_31:
57
      current_arch_mask = 1 << S390_OPCODE_ESA;
58
      break;
59
    case bfd_mach_s390_64:
60
      current_arch_mask = 1 << S390_OPCODE_ESAME;
61
      break;
62
    default:
63
      abort ();
64
    }
65
  init_flag = 1;
66
}
67
 
68
/* Extracts an operand value from an instruction.  */
69
 
70
static inline unsigned int
71
s390_extract_operand (insn, operand)
72
     unsigned char *insn;
73
     const struct s390_operand *operand;
74
{
75
  unsigned int val;
76
  int bits;
77
 
78
  /* Extract fragments of the operand byte for byte.  */
79
  insn += operand->shift / 8;
80
  bits = (operand->shift & 7) + operand->bits;
81
  val = 0;
82
  do
83
    {
84
      val <<= 8;
85
      val |= (unsigned int) *insn++;
86
      bits -= 8;
87
    }
88
  while (bits > 0);
89
  val >>= -bits;
90
  val &= ((1U << (operand->bits - 1)) << 1) - 1;
91
 
92
  /* Sign extend value if the operand is signed or pc relative.  */
93
  if ((operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
94
      && (val & (1U << (operand->bits - 1))))
95
    val |= (-1U << (operand->bits - 1)) << 1;
96
 
97
  /* Double value if the operand is pc relative.  */
98
  if (operand->flags & S390_OPERAND_PCREL)
99
    val <<= 1;
100
 
101
  /* Length x in an instructions has real length x+1.  */
102
  if (operand->flags & S390_OPERAND_LENGTH)
103
    val++;
104
  return val;
105
}
106
 
107
/* Print a S390 instruction.  */
108
 
109
int
110
print_insn_s390 (memaddr, info)
111
     bfd_vma memaddr;
112
     struct disassemble_info *info;
113
{
114
  bfd_byte buffer[6];
115
  const struct s390_opcode *opcode;
116
  const struct s390_opcode *opcode_end;
117
  unsigned int value;
118
  int status, opsize, bufsize;
119
  char separator;
120
 
121
  if (init_flag == 0)
122
    init_disasm (info);
123
 
124
  /* The output looks better if we put 6 bytes on a line.  */
125
  info->bytes_per_line = 6;
126
 
127
  /* Every S390 instruction is max 6 bytes long.  */
128
  memset (buffer, 0, 6);
129
  status = (*info->read_memory_func) (memaddr, buffer, 6, info);
130
  if (status != 0)
131
    {
132
      for (bufsize = 0; bufsize < 6; bufsize++)
133
        if ((*info->read_memory_func) (memaddr, buffer, bufsize + 1, info) != 0)
134
          break;
135
      if (bufsize <= 0)
136
        {
137
          (*info->memory_error_func) (status, memaddr, info);
138
          return -1;
139
        }
140
      /* Opsize calculation looks strange but it works
141
         00xxxxxx -> 2 bytes, 01xxxxxx/10xxxxxx -> 4 bytes,
142
         11xxxxxx -> 6 bytes.  */
143
      opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
144
      status = opsize > bufsize;
145
    }
146
  else
147
    {
148
      bufsize = 6;
149
      opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
150
    }
151
 
152
  if (status == 0)
153
    {
154
      /* Find the first match in the opcode table.  */
155
      opcode_end = s390_opcodes + s390_num_opcodes;
156
      for (opcode = s390_opcodes + opc_index[(int) buffer[0]];
157
           (opcode < opcode_end) && (buffer[0] == opcode->opcode[0]);
158
           opcode++)
159
        {
160
          const struct s390_operand *operand;
161
          const unsigned char *opindex;
162
 
163
          /* Check architecture.  */
164
          if (!(opcode->architecture & current_arch_mask))
165
            continue;
166
          /* Check signature of the opcode.  */
167
          if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
168
              || (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
169
              || (buffer[3] & opcode->mask[3]) != opcode->opcode[3]
170
              || (buffer[4] & opcode->mask[4]) != opcode->opcode[4]
171
              || (buffer[5] & opcode->mask[5]) != opcode->opcode[5])
172
            continue;
173
 
174
          /* The instruction is valid.  */
175
          if (opcode->operands[0] != 0)
176
            (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
177
          else
178
            (*info->fprintf_func) (info->stream, "%s", opcode->name);
179
 
180
          /* Extract the operands.  */
181
          separator = 0;
182
          for (opindex = opcode->operands; *opindex != 0; opindex++)
183
            {
184
              unsigned int value;
185
 
186
              operand = s390_operands + *opindex;
187
              value = s390_extract_operand (buffer, operand);
188
 
189
              if ((operand->flags & S390_OPERAND_INDEX) && value == 0)
190
                continue;
191
              if ((operand->flags & S390_OPERAND_BASE) &&
192
                  value == 0 && separator == '(')
193
                {
194
                  separator = ',';
195
                  continue;
196
                }
197
 
198
              if (separator)
199
                (*info->fprintf_func) (info->stream, "%c", separator);
200
 
201
              if (operand->flags & S390_OPERAND_GPR)
202
                (*info->fprintf_func) (info->stream, "%%r%i", value);
203
              else if (operand->flags & S390_OPERAND_FPR)
204
                (*info->fprintf_func) (info->stream, "%%f%i", value);
205
              else if (operand->flags & S390_OPERAND_AR)
206
                (*info->fprintf_func) (info->stream, "%%a%i", value);
207
              else if (operand->flags & S390_OPERAND_CR)
208
                (*info->fprintf_func) (info->stream, "%%c%i", value);
209
              else if (operand->flags & S390_OPERAND_PCREL)
210
                (*info->print_address_func) (memaddr + (int) value, info);
211
              else if (operand->flags & S390_OPERAND_SIGNED)
212
                (*info->fprintf_func) (info->stream, "%i", (int) value);
213
              else
214
                (*info->fprintf_func) (info->stream, "%i", value);
215
 
216
              if (operand->flags & S390_OPERAND_DISP)
217
                {
218
                  separator = '(';
219
                }
220
              else if (operand->flags & S390_OPERAND_BASE)
221
                {
222
                  (*info->fprintf_func) (info->stream, ")");
223
                  separator = ',';
224
                }
225
              else
226
                separator = ',';
227
            }
228
 
229
          /* Found instruction, printed it, return its size.  */
230
          return opsize;
231
        }
232
      /* No matching instruction found, fall through to hex print.  */
233
    }
234
 
235
  if (bufsize >= 4)
236
    {
237
      value = (unsigned int) buffer[0];
238
      value = (value << 8) + (unsigned int) buffer[1];
239
      value = (value << 8) + (unsigned int) buffer[2];
240
      value = (value << 8) + (unsigned int) buffer[3];
241
      (*info->fprintf_func) (info->stream, ".long\t0x%08x", value);
242
      return 4;
243
    }
244
  else if (bufsize >= 2)
245
    {
246
      value = (unsigned int) buffer[0];
247
      value = (value << 8) + (unsigned int) buffer[1];
248
      (*info->fprintf_func) (info->stream, ".short\t0x%04x", value);
249
      return 2;
250
    }
251
  else
252
    {
253
      value = (unsigned int) buffer[0];
254
      (*info->fprintf_func) (info->stream, ".byte\t0x%02x", value);
255
      return 1;
256
    }
257
}

powered by: WebSVN 2.1.0

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