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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [s390-dis.c] - Blame information for rev 1778

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

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

powered by: WebSVN 2.1.0

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