00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define DEBUG 0
00023
00024 #include "dis-asm.h"
00025 #include "opcode/or32.h"
00026 #include "safe-ctype.h"
00027 #include <string.h>
00028 #include <stdlib.h>
00029
00030 #define EXTEND29(x) ((x) & (unsigned long) 0x10000000 ? ((x) | (unsigned long) 0xf0000000) : ((x)))
00031
00032 static void find_bytes_big PARAMS ((unsigned char *, unsigned long *));
00033 static void find_bytes_little PARAMS ((unsigned char *, unsigned long *));
00034 static unsigned long or32_extract PARAMS ((char, char *, unsigned long));
00035 static int or32_opcode_match PARAMS ((unsigned long, char *));
00036 static void or32_print_register PARAMS ((char, char *, unsigned long, struct disassemble_info *));
00037 static void or32_print_immediate PARAMS ((char, char *, unsigned long, struct disassemble_info *));
00038 static int print_insn PARAMS ((bfd_vma, struct disassemble_info *));
00039
00040
00041
00042 static void
00043 find_bytes_big (insn_ch, insn)
00044 unsigned char *insn_ch;
00045 unsigned long *insn;
00046 {
00047 *insn =
00048 ((unsigned long) insn_ch[0] << 24) +
00049 ((unsigned long) insn_ch[1] << 16) +
00050 ((unsigned long) insn_ch[2] << 8) +
00051 ((unsigned long) insn_ch[3]);
00052 #if DEBUG
00053 printf ("find_bytes_big3: %x\n", *insn);
00054 #endif
00055 }
00056
00057 static void
00058 find_bytes_little (insn_ch, insn)
00059 unsigned char *insn_ch;
00060 unsigned long *insn;
00061 {
00062 *insn =
00063 ((unsigned long) insn_ch[3] << 24) +
00064 ((unsigned long) insn_ch[2] << 16) +
00065 ((unsigned long) insn_ch[1] << 8) +
00066 ((unsigned long) insn_ch[0]);
00067 }
00068
00069 typedef void (*find_byte_func_type)
00070 PARAMS ((unsigned char *, unsigned long *));
00071
00072 static unsigned long
00073 or32_extract (param_ch, enc_initial, insn)
00074 char param_ch;
00075 char *enc_initial;
00076 unsigned long insn;
00077 {
00078 char *enc;
00079 unsigned long ret = 0;
00080 int opc_pos = 0;
00081 int param_pos = 0;
00082
00083 for (enc = enc_initial; *enc != '\0'; enc++)
00084 if (*enc == param_ch)
00085 {
00086 if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
00087 continue;
00088 else
00089 param_pos++;
00090 }
00091
00092 #if DEBUG
00093 printf ("or32_extract: %c %x ", param_ch, param_pos);
00094 #endif
00095 opc_pos = 32;
00096
00097 for (enc = enc_initial; *enc != '\0'; )
00098 if ((*enc == '0') && (*(enc + 1) == 'x'))
00099 {
00100 opc_pos -= 4;
00101
00102 if ((param_ch == '0') || (param_ch == '1'))
00103 {
00104 unsigned long tmp = strtoul (enc, NULL, 16);
00105 #if DEBUG
00106 printf (" enc=%s, tmp=%x ", enc, tmp);
00107 #endif
00108 if (param_ch == '0')
00109 tmp = 15 - tmp;
00110 ret |= tmp << opc_pos;
00111 }
00112 enc += 3;
00113 }
00114 else if ((*enc == '0') || (*enc == '1'))
00115 {
00116 opc_pos--;
00117 if (param_ch == *enc)
00118 ret |= 1 << opc_pos;
00119 enc++;
00120 }
00121 else if (*enc == param_ch)
00122 {
00123 opc_pos--;
00124 param_pos--;
00125 #if DEBUG
00126 printf ("\n ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
00127 #endif
00128 ret += ((insn >> opc_pos) & 0x1) << param_pos;
00129
00130 if (!param_pos
00131 && letter_signed (param_ch)
00132 && ret >> (letter_range (param_ch) - 1))
00133 {
00134 #if DEBUG
00135 printf ("\n ret=%x opc_pos=%x, param_pos=%x\n",
00136 ret, opc_pos, param_pos);
00137 #endif
00138 ret |= 0xffffffff << letter_range(param_ch);
00139 #if DEBUG
00140 printf ("\n after conversion to signed: ret=%x\n", ret);
00141 #endif
00142 }
00143 enc++;
00144 }
00145 else if (ISALPHA (*enc))
00146 {
00147 opc_pos--;
00148 enc++;
00149 }
00150 else if (*enc == '-')
00151 {
00152 opc_pos--;
00153 enc++;
00154 }
00155 else
00156 enc++;
00157
00158 #if DEBUG
00159 printf ("ret=%x\n", ret);
00160 #endif
00161 return ret;
00162 }
00163
00164 static int
00165 or32_opcode_match (insn, encoding)
00166 unsigned long insn;
00167 char *encoding;
00168 {
00169 unsigned long ones, zeros;
00170
00171 #if DEBUG
00172 printf ("or32_opcode_match: %.8lx\n", insn);
00173 #endif
00174 ones = or32_extract ('1', encoding, insn);
00175 zeros = or32_extract ('0', encoding, insn);
00176
00177 #if DEBUG
00178 printf ("ones: %x \n", ones);
00179 printf ("zeros: %x \n", zeros);
00180 #endif
00181 if ((insn & ones) != ones)
00182 {
00183 #if DEBUG
00184 printf ("ret1\n");
00185 #endif
00186 return 0;
00187 }
00188
00189 if ((~insn & zeros) != zeros)
00190 {
00191 #if DEBUG
00192 printf ("ret2\n");
00193 #endif
00194 return 0;
00195 }
00196
00197 #if DEBUG
00198 printf ("ret3\n");
00199 #endif
00200 return 1;
00201 }
00202
00203
00204
00205 static void
00206 or32_print_register (param_ch, encoding, insn, info)
00207 char param_ch;
00208 char *encoding;
00209 unsigned long insn;
00210 struct disassemble_info *info;
00211 {
00212 int regnum = or32_extract (param_ch, encoding, insn);
00213
00214 #if DEBUG
00215 printf ("or32_print_register: %c, %s, %x\n", param_ch, encoding, insn);
00216 #endif
00217 if (param_ch == 'A')
00218 (*info->fprintf_func) (info->stream, "r%d", regnum);
00219 else if (param_ch == 'B')
00220 (*info->fprintf_func) (info->stream, "r%d", regnum);
00221 else if (param_ch == 'D')
00222 (*info->fprintf_func) (info->stream, "r%d", regnum);
00223 else if (regnum < 16)
00224 (*info->fprintf_func) (info->stream, "r%d", regnum);
00225 else if (regnum < 32)
00226 (*info->fprintf_func) (info->stream, "r%d", regnum-16);
00227 else
00228 (*info->fprintf_func) (info->stream, "X%d", regnum);
00229 }
00230
00231
00232
00233 static void
00234 or32_print_immediate (param_ch, encoding, insn, info)
00235 char param_ch;
00236 char *encoding;
00237 unsigned long insn;
00238 struct disassemble_info *info;
00239 {
00240 int imm = or32_extract(param_ch, encoding, insn);
00241
00242 if (letter_signed(param_ch))
00243 (*info->fprintf_func) (info->stream, "0x%x", imm);
00244
00245 else
00246 (*info->fprintf_func) (info->stream, "0x%x", imm);
00247 }
00248
00249
00250
00251
00252 static int
00253 print_insn (memaddr, info)
00254 bfd_vma memaddr;
00255 struct disassemble_info *info;
00256 {
00257
00258 unsigned char insn_ch[4];
00259
00260 unsigned long addr;
00261
00262 unsigned long insn;
00263 find_byte_func_type find_byte_func = (find_byte_func_type)info->private_data;
00264 struct or32_opcode const * opcode;
00265
00266 {
00267 int status =
00268 (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
00269
00270 if (status != 0)
00271 {
00272 (*info->memory_error_func) (status, memaddr, info);
00273 return -1;
00274 }
00275 }
00276
00277 (*find_byte_func) (&insn_ch[0], &insn);
00278
00279 for (opcode = &or32_opcodes[0];
00280 opcode < &or32_opcodes[or32_num_opcodes];
00281 ++opcode)
00282 {
00283 if (or32_opcode_match (insn, opcode->encoding))
00284 {
00285 char *s;
00286
00287 (*info->fprintf_func) (info->stream, "%s ", opcode->name);
00288
00289 for (s = opcode->args; *s != '\0'; ++s)
00290 {
00291 switch (*s)
00292 {
00293 case '\0':
00294 return 4;
00295
00296 case 'r':
00297 or32_print_register (*++s, opcode->encoding, insn, info);
00298 break;
00299
00300 case 'X':
00301 addr = or32_extract ('X', opcode->encoding, insn) << 2;
00302
00303
00304 addr = memaddr + EXTEND29 (addr);
00305
00306 (*info->print_address_func)
00307 (addr, info);
00308 break;
00309
00310 default:
00311 if (strchr (opcode->encoding, *s))
00312 or32_print_immediate (*s, opcode->encoding, insn, info);
00313 else
00314 (*info->fprintf_func) (info->stream, "%c", *s);
00315 }
00316 }
00317
00318 return 4;
00319 }
00320 }
00321
00322
00323 (*info->fprintf_func)
00324 (info->stream, ".word 0x%08x", insn);
00325 return 4;
00326 }
00327
00328
00329
00330 int
00331 print_insn_big_or32 (memaddr, info)
00332 bfd_vma memaddr;
00333 struct disassemble_info *info;
00334 {
00335 info->private_data = (PTR) find_bytes_big;
00336 return print_insn (memaddr, info);
00337 }
00338
00339
00340
00341 int
00342 print_insn_little_or32 (memaddr, info)
00343 bfd_vma memaddr;
00344 struct disassemble_info *info;
00345 {
00346 info->private_data = (PTR) find_bytes_little;
00347 return print_insn (memaddr, info);
00348 }