00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include "ansidecl.h"
00028 #include "sysdep.h"
00029 #include "dis-asm.h"
00030 #include "opcode/s390.h"
00031
00032 static int init_flag = 0;
00033 static int opc_index[256];
00034 static int current_arch_mask = 0;
00035
00036 static void init_disasm PARAMS ((struct disassemble_info *));
00037 static unsigned int s390_extract_operand
00038 PARAMS ((unsigned char *, const struct s390_operand *));
00039
00040
00041
00042 static void
00043 init_disasm (info)
00044 struct disassemble_info *info;
00045 {
00046 const struct s390_opcode *opcode;
00047 const struct s390_opcode *opcode_end;
00048
00049 memset (opc_index, 0, sizeof (opc_index));
00050 opcode_end = s390_opcodes + s390_num_opcodes;
00051 for (opcode = s390_opcodes; opcode < opcode_end; opcode++)
00052 {
00053 opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes;
00054 while ((opcode < opcode_end) &&
00055 (opcode[1].opcode[0] == opcode->opcode[0]))
00056 opcode++;
00057 }
00058 switch (info->mach)
00059 {
00060 case bfd_mach_s390_31:
00061 current_arch_mask = 1 << S390_OPCODE_ESA;
00062 break;
00063 case bfd_mach_s390_64:
00064 current_arch_mask = 1 << S390_OPCODE_ZARCH;
00065 break;
00066 default:
00067 abort ();
00068 }
00069 init_flag = 1;
00070 }
00071
00072
00073
00074 static inline unsigned int
00075 s390_extract_operand (insn, operand)
00076 unsigned char *insn;
00077 const struct s390_operand *operand;
00078 {
00079 unsigned int val;
00080 int bits;
00081
00082
00083 insn += operand->shift / 8;
00084 bits = (operand->shift & 7) + operand->bits;
00085 val = 0;
00086 do
00087 {
00088 val <<= 8;
00089 val |= (unsigned int) *insn++;
00090 bits -= 8;
00091 }
00092 while (bits > 0);
00093 val >>= -bits;
00094 val &= ((1U << (operand->bits - 1)) << 1) - 1;
00095
00096
00097 if (operand->bits == 20 && operand->shift == 20)
00098 val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
00099
00100
00101 if ((operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
00102 && (val & (1U << (operand->bits - 1))))
00103 val |= (-1U << (operand->bits - 1)) << 1;
00104
00105
00106 if (operand->flags & S390_OPERAND_PCREL)
00107 val <<= 1;
00108
00109
00110 if (operand->flags & S390_OPERAND_LENGTH)
00111 val++;
00112 return val;
00113 }
00114
00115
00116
00117 int
00118 print_insn_s390 (memaddr, info)
00119 bfd_vma memaddr;
00120 struct disassemble_info *info;
00121 {
00122 bfd_byte buffer[6];
00123 const struct s390_opcode *opcode;
00124 const struct s390_opcode *opcode_end;
00125 unsigned int value;
00126 int status, opsize, bufsize;
00127 char separator;
00128
00129 if (init_flag == 0)
00130 init_disasm (info);
00131
00132
00133 info->bytes_per_line = 6;
00134
00135
00136 memset (buffer, 0, 6);
00137 status = (*info->read_memory_func) (memaddr, buffer, 6, info);
00138 if (status != 0)
00139 {
00140 for (bufsize = 0; bufsize < 6; bufsize++)
00141 if ((*info->read_memory_func) (memaddr, buffer, bufsize + 1, info) != 0)
00142 break;
00143 if (bufsize <= 0)
00144 {
00145 (*info->memory_error_func) (status, memaddr, info);
00146 return -1;
00147 }
00148
00149
00150
00151 opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
00152 status = opsize > bufsize;
00153 }
00154 else
00155 {
00156 bufsize = 6;
00157 opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
00158 }
00159
00160 if (status == 0)
00161 {
00162
00163 opcode_end = s390_opcodes + s390_num_opcodes;
00164 for (opcode = s390_opcodes + opc_index[(int) buffer[0]];
00165 (opcode < opcode_end) && (buffer[0] == opcode->opcode[0]);
00166 opcode++)
00167 {
00168 const struct s390_operand *operand;
00169 const unsigned char *opindex;
00170
00171
00172 if (!(opcode->modes & current_arch_mask))
00173 continue;
00174
00175 if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
00176 || (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
00177 || (buffer[3] & opcode->mask[3]) != opcode->opcode[3]
00178 || (buffer[4] & opcode->mask[4]) != opcode->opcode[4]
00179 || (buffer[5] & opcode->mask[5]) != opcode->opcode[5])
00180 continue;
00181
00182
00183 if (opcode->operands[0] != 0)
00184 (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
00185 else
00186 (*info->fprintf_func) (info->stream, "%s", opcode->name);
00187
00188
00189 separator = 0;
00190 for (opindex = opcode->operands; *opindex != 0; opindex++)
00191 {
00192 unsigned int value;
00193
00194 operand = s390_operands + *opindex;
00195 value = s390_extract_operand (buffer, operand);
00196
00197 if ((operand->flags & S390_OPERAND_INDEX) && value == 0)
00198 continue;
00199 if ((operand->flags & S390_OPERAND_BASE) &&
00200 value == 0 && separator == '(')
00201 {
00202 separator = ',';
00203 continue;
00204 }
00205
00206 if (separator)
00207 (*info->fprintf_func) (info->stream, "%c", separator);
00208
00209 if (operand->flags & S390_OPERAND_GPR)
00210 (*info->fprintf_func) (info->stream, "%%r%i", value);
00211 else if (operand->flags & S390_OPERAND_FPR)
00212 (*info->fprintf_func) (info->stream, "%%f%i", value);
00213 else if (operand->flags & S390_OPERAND_AR)
00214 (*info->fprintf_func) (info->stream, "%%a%i", value);
00215 else if (operand->flags & S390_OPERAND_CR)
00216 (*info->fprintf_func) (info->stream, "%%c%i", value);
00217 else if (operand->flags & S390_OPERAND_PCREL)
00218 (*info->print_address_func) (memaddr + (int) value, info);
00219 else if (operand->flags & S390_OPERAND_SIGNED)
00220 (*info->fprintf_func) (info->stream, "%i", (int) value);
00221 else
00222 (*info->fprintf_func) (info->stream, "%i", value);
00223
00224 if (operand->flags & S390_OPERAND_DISP)
00225 {
00226 separator = '(';
00227 }
00228 else if (operand->flags & S390_OPERAND_BASE)
00229 {
00230 (*info->fprintf_func) (info->stream, ")");
00231 separator = ',';
00232 }
00233 else
00234 separator = ',';
00235 }
00236
00237
00238 return opsize;
00239 }
00240
00241 }
00242
00243 if (bufsize >= 4)
00244 {
00245 value = (unsigned int) buffer[0];
00246 value = (value << 8) + (unsigned int) buffer[1];
00247 value = (value << 8) + (unsigned int) buffer[2];
00248 value = (value << 8) + (unsigned int) buffer[3];
00249 (*info->fprintf_func) (info->stream, ".long\t0x%08x", value);
00250 return 4;
00251 }
00252 else if (bufsize >= 2)
00253 {
00254 value = (unsigned int) buffer[0];
00255 value = (value << 8) + (unsigned int) buffer[1];
00256 (*info->fprintf_func) (info->stream, ".short\t0x%04x", value);
00257 return 2;
00258 }
00259 else
00260 {
00261 value = (unsigned int) buffer[0];
00262 (*info->fprintf_func) (info->stream, ".byte\t0x%02x", value);
00263 return 1;
00264 }
00265 }