1 /* Instruction printing code for the TXVU
2 Copyright (C) 1998 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #include "opcode/txvu.h"
23 static void print_insn
PARAMS ((bfd_vma
, disassemble_info
*, TXVU_INSN
, int));
25 /* Print one instruction from PC on INFO->STREAM.
26 Return the size of the instruction. */
29 print_insn_txvu (pc
, info
)
31 disassemble_info
*info
;
34 void *stream
= info
->stream
;
35 fprintf_ftype func
= info
->fprintf_func
;
37 /* First element is upper, second is lower. */
38 TXVU_INSN upper
,lower
;
39 static int initialized
= 0;
44 txvu_opcode_init_tables (0);
47 status
= (*info
->read_memory_func
) (pc
, buffer
, 8, info
);
50 (*info
->memory_error_func
) (status
, pc
, info
);
53 /* The lower instruction has the lower address. */
54 upper
= bfd_getl32 (buffer
+ 4);
55 lower
= bfd_getl32 (buffer
);
57 /* FIXME: This will need revisiting. */
58 print_insn (pc
, info
, upper
, 0);
59 #ifdef VERTICAL_BAR_SEPARATOR
60 (*func
) (stream
, " | ");
62 /* Not sure how much whitespace to print here.
63 At least two spaces, not more than 9, and having columns line up somewhat
65 (*func
) (stream
, " \t");
67 print_insn (pc
, info
, lower
, 1);
72 /* Print one instruction.
73 LOWER_P is non-zero if disassembling a lower slot insn. */
76 print_insn (pc
, info
, insn
, lower_p
)
78 disassemble_info
*info
;
82 const txvu_opcode
*opcode
;
83 void *stream
= info
->stream
;
84 fprintf_ftype func
= info
->fprintf_func
;
86 /* The instructions are stored in lists hashed by the insn code
87 (though we needn't care how they're hashed). */
90 opcode
= txvu_lower_opcode_lookup_dis (insn
);
92 opcode
= txvu_upper_opcode_lookup_dis (insn
);
93 for ( ; opcode
!= NULL
; opcode
= TXVU_OPCODE_NEXT_DIS (opcode
))
95 const unsigned char *syn
;
96 int mods
,invalid
,num_operands
;
98 const txvu_operand
*operand
;
100 /* Basic bit mask must be correct. */
101 if ((insn
& opcode
->mask
) != opcode
->value
)
104 /* Make two passes over the operands. First see if any of them
105 have extraction functions, and, if they do, make sure the
106 instruction is valid. */
108 txvu_opcode_init_print ();
111 for (syn
= opcode
->syntax
; *syn
; ++syn
)
119 index
= TXVU_OPERAND_INDEX (*syn
);
120 while (TXVU_MOD_P (txvu_operands
[index
].flags
))
122 mods
|= txvu_operands
[index
].flags
& TXVU_MOD_BITS
;
124 index
= TXVU_OPERAND_INDEX (*syn
);
126 operand
= txvu_operands
+ index
;
127 if (operand
->extract
)
128 (*operand
->extract
) (opcode
, operand
, mods
, &insn
, &invalid
);
133 /* The instruction is valid. */
135 (*func
) (stream
, "%s", opcode
->mnemonic
);
137 for (syn
= opcode
->syntax
; *syn
; ++syn
)
143 (*func
) (stream
, "%c", *syn
);
147 /* We have an operand. Fetch any special modifiers. */
149 index
= TXVU_OPERAND_INDEX (*syn
);
150 while (TXVU_MOD_P (txvu_operands
[index
].flags
))
152 mods
|= txvu_operands
[index
].flags
& TXVU_MOD_BITS
;
154 index
= TXVU_OPERAND_INDEX (*syn
);
156 operand
= txvu_operands
+ index
;
158 /* Extract the value from the instruction. */
159 if (operand
->extract
)
161 value
= (*operand
->extract
) (opcode
, operand
, mods
,
162 &insn
, (int *) NULL
);
166 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
167 if ((operand
->flags
& TXVU_OPERAND_SIGNED
) != 0
168 && (value
& (1 << (operand
->bits
- 1))))
169 value
-= 1 << operand
->bits
;
172 #if 0 /* commas are part of the syntax string now */
173 /* If second or later operand, print a comma. */
174 if (num_operands
> 0)
175 (*func
) (stream
, ",");
178 /* Print the operand as directed by the flags. */
180 (*operand
->print
) (opcode
, operand
, mods
, &insn
, info
, value
);
181 else if (operand
->flags
& TXVU_OPERAND_FAKE
)
182 ; /* nothing to do (??? at least not yet) */
183 else if (operand
->flags
& TXVU_OPERAND_RELATIVE_BRANCH
)
184 (*info
->print_address_func
) (pc
+ (value
<< 3), info
);
185 /* ??? Not all cases of this are currently caught. */
186 else if (operand
->flags
& TXVU_OPERAND_ABSOLUTE_BRANCH
)
187 (*info
->print_address_func
) ((bfd_vma
) value
& 0xffffffff, info
);
188 else if (operand
->flags
& TXVU_OPERAND_ADDRESS
)
189 (*info
->print_address_func
) ((bfd_vma
) value
& 0xffffffff, info
);
191 (*func
) (stream
, "%ld", value
);
193 if (! (operand
->flags
& TXVU_OPERAND_SUFFIX
))
197 /* We have found and printed an instruction; return. */
201 (*func
) (stream
, "*unknown*");