00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "sysdep.h"
00023 #include "dis-asm.h"
00024 #include "opcode/pdp11.h"
00025
00026 #define AFTER_INSTRUCTION "\t"
00027 #define OPERAND_SEPARATOR ", "
00028
00029 #define JUMP 0x1000
00030
00031 #define FPRINTF (*info->fprintf_func)
00032 #define F info->stream
00033
00034
00035 #define SIGN_BITS (8 * sizeof (int) - 16)
00036 #define sign_extend(x) (((x) << SIGN_BITS) >> SIGN_BITS)
00037
00038 static int read_word PARAMS ((bfd_vma memaddr, int *word,
00039 disassemble_info *info));
00040 static void print_signed_octal PARAMS ((int n, disassemble_info *info));
00041 static void print_reg PARAMS ((int reg, disassemble_info *info));
00042 static void print_freg PARAMS ((int freg, disassemble_info *info));
00043 static int print_operand PARAMS ((bfd_vma *memaddr, int code,
00044 disassemble_info *info));
00045 static int print_foperand PARAMS ((bfd_vma *memaddr, int code,
00046 disassemble_info *info));
00047 int print_insn_pdp11 PARAMS ((bfd_vma memaddr, disassemble_info *info));
00048
00049 static int
00050 read_word (memaddr, word, info)
00051 bfd_vma memaddr;
00052 int *word;
00053 disassemble_info *info;
00054 {
00055 int status;
00056 bfd_byte x[2];
00057
00058 status = (*info->read_memory_func) (memaddr, x, 2, info);
00059 if (status != 0)
00060 return -1;
00061
00062 *word = x[1] << 8 | x[0];
00063 return 0;
00064 }
00065
00066 static void
00067 print_signed_octal (n, info)
00068 int n;
00069 disassemble_info *info;
00070 {
00071 if (n < 0)
00072 FPRINTF (F, "-%o", -n);
00073 else
00074 FPRINTF (F, "%o", n);
00075 }
00076
00077 static void
00078 print_reg (reg, info)
00079 int reg;
00080 disassemble_info *info;
00081 {
00082
00083 reg &= 7;
00084
00085 switch (reg)
00086 {
00087 case 0: case 1: case 2: case 3: case 4: case 5:
00088 FPRINTF (F, "r%d", reg); break;
00089 case 6: FPRINTF (F, "sp"); break;
00090 case 7: FPRINTF (F, "pc"); break;
00091 default: ;
00092 }
00093 }
00094
00095 static void
00096 print_freg (freg, info)
00097 int freg;
00098 disassemble_info *info;
00099 {
00100 FPRINTF (F, "fr%d", freg);
00101 }
00102
00103 static int
00104 print_operand (memaddr, code, info)
00105 bfd_vma *memaddr;
00106 int code;
00107 disassemble_info *info;
00108 {
00109 int mode = (code >> 3) & 7;
00110 int reg = code & 7;
00111 int disp;
00112
00113 switch (mode)
00114 {
00115 case 0:
00116 print_reg (reg, info);
00117 break;
00118 case 1:
00119 FPRINTF (F, "(");
00120 print_reg (reg, info);
00121 FPRINTF (F, ")");
00122 break;
00123 case 2:
00124 if (reg == 7)
00125 {
00126 int data;
00127 if (read_word (*memaddr, &data, info) < 0)
00128 return -1;
00129 FPRINTF (F, "$");
00130 print_signed_octal (sign_extend (data), info);
00131 *memaddr += 2;
00132 }
00133 else
00134 {
00135 FPRINTF (F, "(");
00136 print_reg (reg, info);
00137 FPRINTF (F, ")+");
00138 }
00139 break;
00140 case 3:
00141 if (reg == 7)
00142 {
00143 int address;
00144 if (read_word (*memaddr, &address, info) < 0)
00145 return -1;
00146 FPRINTF (F, "*$%o", address);
00147 *memaddr += 2;
00148 }
00149 else
00150 {
00151 FPRINTF (F, "*(");
00152 print_reg (reg, info);
00153 FPRINTF (F, ")+");
00154 }
00155 break;
00156 case 4:
00157 FPRINTF (F, "-(");
00158 print_reg (reg, info);
00159 FPRINTF (F, ")");
00160 break;
00161 case 5:
00162 FPRINTF (F, "*-(");
00163 print_reg (reg, info);
00164 FPRINTF (F, ")");
00165 break;
00166 case 6:
00167 case 7:
00168 if (read_word (*memaddr, &disp, info) < 0)
00169 return -1;
00170 *memaddr += 2;
00171 if (reg == 7)
00172 {
00173 bfd_vma address = *memaddr + sign_extend (disp);
00174 if (mode == 7)
00175 FPRINTF (F, "*");
00176 if (!(code & JUMP))
00177 FPRINTF (F, "$");
00178 (*info->print_address_func) (address, info);
00179 }
00180 else
00181 {
00182 if (mode == 7)
00183 FPRINTF (F, "*");
00184 print_signed_octal (sign_extend (disp), info);
00185 FPRINTF (F, "(");
00186 print_reg (reg, info);
00187 FPRINTF (F, ")");
00188 }
00189 break;
00190 }
00191
00192 return 0;
00193 }
00194
00195 static int
00196 print_foperand (memaddr, code, info)
00197 bfd_vma *memaddr;
00198 int code;
00199 disassemble_info *info;
00200 {
00201 int mode = (code >> 3) & 7;
00202 int reg = code & 7;
00203
00204 if (mode == 0)
00205 print_freg (reg, info);
00206 else
00207 return print_operand (memaddr, code, info);
00208
00209 return 0;
00210 }
00211
00212
00213
00214
00215 int
00216 print_insn_pdp11 (memaddr, info)
00217 bfd_vma memaddr;
00218 disassemble_info *info;
00219 {
00220 bfd_vma start_memaddr = memaddr;
00221 int opcode;
00222 int src, dst;
00223 int i;
00224
00225 info->bytes_per_line = 6;
00226 info->bytes_per_chunk = 2;
00227 info->display_endian = BFD_ENDIAN_LITTLE;
00228
00229 if (read_word (memaddr, &opcode, info) != 0)
00230 return -1;
00231 memaddr += 2;
00232
00233 src = (opcode >> 6) & 0x3f;
00234 dst = opcode & 0x3f;
00235
00236 for (i = 0; i < pdp11_num_opcodes; i++)
00237 {
00238 #define OP pdp11_opcodes[i]
00239 if ((opcode & OP.mask) == OP.opcode)
00240 switch (OP.type)
00241 {
00242 case PDP11_OPCODE_NO_OPS:
00243 FPRINTF (F, OP.name);
00244 goto done;
00245 case PDP11_OPCODE_REG:
00246 FPRINTF (F, OP.name);
00247 FPRINTF (F, AFTER_INSTRUCTION);
00248 print_reg (dst, info);
00249 goto done;
00250 case PDP11_OPCODE_OP:
00251 FPRINTF (F, OP.name);
00252 FPRINTF (F, AFTER_INSTRUCTION);
00253 if (strcmp (OP.name, "jmp") == 0)
00254 dst |= JUMP;
00255 if (print_operand (&memaddr, dst, info) < 0)
00256 return -1;
00257 goto done;
00258 case PDP11_OPCODE_FOP:
00259 FPRINTF (F, OP.name);
00260 FPRINTF (F, AFTER_INSTRUCTION);
00261 if (strcmp (OP.name, "jmp") == 0)
00262 dst |= JUMP;
00263 if (print_foperand (&memaddr, dst, info) < 0)
00264 return -1;
00265 goto done;
00266 case PDP11_OPCODE_REG_OP:
00267 FPRINTF (F, OP.name);
00268 FPRINTF (F, AFTER_INSTRUCTION);
00269 print_reg (src, info);
00270 FPRINTF (F, OPERAND_SEPARATOR);
00271 if (strcmp (OP.name, "jsr") == 0)
00272 dst |= JUMP;
00273 if (print_operand (&memaddr, dst, info) < 0)
00274 return -1;
00275 goto done;
00276 case PDP11_OPCODE_REG_OP_REV:
00277 FPRINTF (F, OP.name);
00278 FPRINTF (F, AFTER_INSTRUCTION);
00279 if (print_operand (&memaddr, dst, info) < 0)
00280 return -1;
00281 FPRINTF (F, OPERAND_SEPARATOR);
00282 print_reg (src, info);
00283 goto done;
00284 case PDP11_OPCODE_AC_FOP:
00285 {
00286 int ac = (opcode & 0xe0) >> 6;
00287 FPRINTF (F, OP.name);
00288 FPRINTF (F, AFTER_INSTRUCTION);
00289 print_freg (ac, info);
00290 FPRINTF (F, OPERAND_SEPARATOR);
00291 if (print_foperand (&memaddr, dst, info) < 0)
00292 return -1;
00293 goto done;
00294 }
00295 case PDP11_OPCODE_FOP_AC:
00296 {
00297 int ac = (opcode & 0xe0) >> 6;
00298 FPRINTF (F, OP.name);
00299 FPRINTF (F, AFTER_INSTRUCTION);
00300 if (print_foperand (&memaddr, dst, info) < 0)
00301 return -1;
00302 FPRINTF (F, OPERAND_SEPARATOR);
00303 print_freg (ac, info);
00304 goto done;
00305 }
00306 case PDP11_OPCODE_AC_OP:
00307 {
00308 int ac = (opcode & 0xe0) >> 6;
00309 FPRINTF (F, OP.name);
00310 FPRINTF (F, AFTER_INSTRUCTION);
00311 print_freg (ac, info);
00312 FPRINTF (F, OPERAND_SEPARATOR);
00313 if (print_operand (&memaddr, dst, info) < 0)
00314 return -1;
00315 goto done;
00316 }
00317 case PDP11_OPCODE_OP_AC:
00318 {
00319 int ac = (opcode & 0xe0) >> 6;
00320 FPRINTF (F, OP.name);
00321 FPRINTF (F, AFTER_INSTRUCTION);
00322 if (print_operand (&memaddr, dst, info) < 0)
00323 return -1;
00324 FPRINTF (F, OPERAND_SEPARATOR);
00325 print_freg (ac, info);
00326 goto done;
00327 }
00328 case PDP11_OPCODE_OP_OP:
00329 FPRINTF (F, OP.name);
00330 FPRINTF (F, AFTER_INSTRUCTION);
00331 if (print_operand (&memaddr, src, info) < 0)
00332 return -1;
00333 FPRINTF (F, OPERAND_SEPARATOR);
00334 if (print_operand (&memaddr, dst, info) < 0)
00335 return -1;
00336 goto done;
00337 case PDP11_OPCODE_DISPL:
00338 {
00339 int displ = (opcode & 0xff) << 8;
00340 bfd_vma address = memaddr + (sign_extend (displ) >> 7);
00341 FPRINTF (F, OP.name);
00342 FPRINTF (F, AFTER_INSTRUCTION);
00343 (*info->print_address_func) (address, info);
00344 goto done;
00345 }
00346 case PDP11_OPCODE_REG_DISPL:
00347 {
00348 int displ = (opcode & 0x3f) << 10;
00349 bfd_vma address = memaddr - (displ >> 9);
00350
00351 FPRINTF (F, OP.name);
00352 FPRINTF (F, AFTER_INSTRUCTION);
00353 print_reg (src, info);
00354 FPRINTF (F, OPERAND_SEPARATOR);
00355 (*info->print_address_func) (address, info);
00356 goto done;
00357 }
00358 case PDP11_OPCODE_IMM8:
00359 {
00360 int code = opcode & 0xff;
00361 FPRINTF (F, OP.name);
00362 FPRINTF (F, AFTER_INSTRUCTION);
00363 FPRINTF (F, "%o", code);
00364 goto done;
00365 }
00366 case PDP11_OPCODE_IMM6:
00367 {
00368 int code = opcode & 0x3f;
00369 FPRINTF (F, OP.name);
00370 FPRINTF (F, AFTER_INSTRUCTION);
00371 FPRINTF (F, "%o", code);
00372 goto done;
00373 }
00374 case PDP11_OPCODE_IMM3:
00375 {
00376 int code = opcode & 7;
00377 FPRINTF (F, OP.name);
00378 FPRINTF (F, AFTER_INSTRUCTION);
00379 FPRINTF (F, "%o", code);
00380 goto done;
00381 }
00382 case PDP11_OPCODE_ILLEGAL:
00383 {
00384 FPRINTF (F, ".word");
00385 FPRINTF (F, AFTER_INSTRUCTION);
00386 FPRINTF (F, "%o", opcode);
00387 goto done;
00388 }
00389 default:
00390
00391 FPRINTF (F, "<internal error: unrecognized instruction type>");
00392 return -1;
00393 }
00394 #undef OP
00395 }
00396 done:
00397
00398 return memaddr - start_memaddr;
00399 }