+
+/* Returns number of bytes "eaten" by the operand, or return -1 if an
+ invalid operand was found, or -2 if an opcode tabel error was
+ found. */
+
+static int
+print_insn_arg (const char *d,
+ unsigned char *p0,
+ bfd_vma addr, /* PC for this arg to be relative to. */
+ disassemble_info *info)
+{
+ int arg_len;
+
+ /* Check validity of addressing length. */
+ switch (d[1])
+ {
+ case 'b' : arg_len = 1; break;
+ case 'd' : arg_len = 8; break;
+ case 'f' : arg_len = 4; break;
+ case 'g' : arg_len = 8; break;
+ case 'h' : arg_len = 16; break;
+ case 'l' : arg_len = 4; break;
+ case 'o' : arg_len = 16; break;
+ case 'w' : arg_len = 2; break;
+ case 'q' : arg_len = 8; break;
+ default : abort ();
+ }
+
+ /* Branches have no mode byte. */
+ if (d[0] == 'b')
+ {
+ unsigned char *p = p0;
+
+ if (arg_len == 1)
+ (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
+ else
+ (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
+
+ return p - p0;
+ }
+
+ return print_insn_mode (d, arg_len, p0, addr, info);
+}
+
+/* Print the vax instruction at address MEMADDR in debugged memory,
+ on INFO->STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn_vax (bfd_vma memaddr, disassemble_info *info)
+{
+ static bfd_boolean parsed_disassembler_options = FALSE;
+ const struct vot *votp;
+ const char *argp;
+ unsigned char *arg;
+ struct private priv;
+ bfd_byte *buffer = priv.the_buffer;
+
+ info->private_data = & priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = memaddr;
+
+ if (! parsed_disassembler_options
+ && info->disassembler_options != NULL)
+ {
+ parse_disassembler_options (info->disassembler_options);
+
+ /* To avoid repeated parsing of these options. */
+ parsed_disassembler_options = TRUE;
+ }
+
+ if (OPCODES_SIGSETJMP (priv.bailout) != 0)
+ /* Error return. */
+ return -1;
+
+ argp = NULL;
+ /* Check if the info buffer has more than one byte left since
+ the last opcode might be a single byte with no argument data. */
+ if (info->buffer_length - (memaddr - info->buffer_vma) > 1
+ && (info->stop_vma == 0 || memaddr < (info->stop_vma - 1)))
+ {
+ FETCH_DATA (info, buffer + 2);
+ }
+ else
+ {
+ FETCH_DATA (info, buffer + 1);
+ buffer[1] = 0;
+ }
+
+ /* Decode function entry mask. */
+ if (is_function_entry (info, memaddr))
+ {
+ int i = 0;
+ int register_mask = buffer[1] << 8 | buffer[0];
+
+ (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
+ register_mask);
+
+ for (i = 15; i >= 0; i--)
+ if (register_mask & (1 << i))
+ (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
+
+ (*info->fprintf_func) (info->stream, " >");
+
+ return 2;
+ }
+
+ /* Decode PLT entry offset longword. */
+ if (is_plt_tail (info, memaddr))
+ {
+ int offset;
+
+ FETCH_DATA (info, buffer + 4);
+ offset = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
+ (*info->fprintf_func) (info->stream, ".long 0x%08x", offset);
+
+ return 4;
+ }
+
+ for (votp = &votstrs[0]; votp->name[0]; votp++)
+ {
+ vax_opcodeT opcode = votp->detail.code;
+
+ /* 2 byte codes match 2 buffer pos. */
+ if ((bfd_byte) opcode == buffer[0]
+ && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
+ {
+ argp = votp->detail.args;
+ break;
+ }
+ }
+ if (argp == NULL)
+ {
+ /* Handle undefined instructions. */
+ (*info->fprintf_func) (info->stream, ".word 0x%x",
+ (buffer[0] << 8) + buffer[1]);
+ return 2;
+ }
+
+ /* Point at first byte of argument data, and at descriptor for first
+ argument. */
+ arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
+
+ /* Make sure we have it in mem */
+ FETCH_DATA (info, arg);
+
+ (*info->fprintf_func) (info->stream, "%s", votp->name);
+ if (*argp)
+ (*info->fprintf_func) (info->stream, " ");
+
+ while (*argp)
+ {
+ arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
+ argp += 2;
+ if (*argp)
+ (*info->fprintf_func) (info->stream, ",");
+ }
+
+ return arg - buffer;
+}
+