* txvu-dis.c (print_insn): Extract/print fns take pointer to
[deliverable/binutils-gdb.git] / opcodes / txvu-dis.c
1 /* Instruction printing code for the TXVU
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
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.
8
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.
13
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. */
17
18 #include "dis-asm.h"
19 #include "opcode/txvu.h"
20 #include "elf-bfd.h"
21 #include "elf/txvu.h"
22
23 static void print_insn PARAMS ((bfd_vma, disassemble_info *, TXVU_INSN, int));
24
25 /* Print one instruction from PC on INFO->STREAM.
26 Return the size of the instruction. */
27
28 int
29 print_insn_txvu (pc, info)
30 bfd_vma pc;
31 disassemble_info *info;
32 {
33 bfd_byte buffer[8];
34 void *stream = info->stream;
35 fprintf_ftype func = info->fprintf_func;
36 int status;
37 /* First element is upper, second is lower. */
38 TXVU_INSN upper,lower;
39 static int initialized = 0;
40
41 if (!initialized)
42 {
43 initialized = 1;
44 txvu_opcode_init_tables (0);
45 }
46
47 status = (*info->read_memory_func) (pc, buffer, 8, info);
48 if (status != 0)
49 {
50 (*info->memory_error_func) (status, pc, info);
51 return -1;
52 }
53 /* The lower instruction has the lower address. */
54 upper = bfd_getl32 (buffer + 4);
55 lower = bfd_getl32 (buffer);
56
57 /* FIXME: This will need revisiting. */
58 print_insn (pc, info, upper, 0);
59 #ifdef VERTICAL_BAR_SEPARATOR
60 (*func) (stream, " | ");
61 #else
62 /* Not sure how much whitespace to print here.
63 At least two spaces, not more than 9, and having columns line up somewhat
64 seems reasonable. */
65 (*func) (stream, " \t");
66 #endif
67 print_insn (pc, info, lower, 1);
68
69 return 8;
70 }
71
72 /* Print one instruction.
73 LOWER_P is non-zero if disassembling a lower slot insn. */
74
75 static void
76 print_insn (pc, info, insn, lower_p)
77 bfd_vma pc;
78 disassemble_info *info;
79 TXVU_INSN insn;
80 int lower_p;
81 {
82 const struct txvu_opcode *opcode;
83 void *stream = info->stream;
84 fprintf_ftype func = info->fprintf_func;
85
86 /* The instructions are stored in lists hashed by the insn code
87 (though we needn't care how they're hashed). */
88
89 if (lower_p)
90 opcode = txvu_lower_opcode_lookup_dis (insn);
91 else
92 opcode = txvu_upper_opcode_lookup_dis (insn);
93 for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_DIS (opcode))
94 {
95 const unsigned char *syn;
96 int mods,invalid,num_operands;
97 long value;
98 const struct txvu_operand *operand;
99
100 /* Basic bit mask must be correct. */
101 if ((insn & opcode->mask) != opcode->value)
102 continue;
103
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. */
107
108 txvu_opcode_init_print ();
109 invalid = 0;
110
111 for (syn = opcode->syntax; *syn; ++syn)
112 {
113 int index;
114
115 if (*syn < 128)
116 continue;
117
118 mods = 0;
119 index = TXVU_OPERAND_INDEX (*syn);
120 while (TXVU_MOD_P (txvu_operands[index].flags))
121 {
122 mods |= txvu_operands[index].flags & TXVU_MOD_BITS;
123 ++syn;
124 index = TXVU_OPERAND_INDEX (*syn);
125 }
126 operand = txvu_operands + index;
127 if (operand->extract)
128 (*operand->extract) (&insn, operand, mods, &invalid);
129 }
130 if (invalid)
131 continue;
132
133 /* The instruction is valid. */
134
135 (*func) (stream, "%s", opcode->mnemonic);
136 num_operands = 0;
137 for (syn = opcode->syntax; *syn; ++syn)
138 {
139 int index;
140
141 if (*syn < 128)
142 {
143 (*func) (stream, "%c", *syn);
144 continue;
145 }
146
147 /* We have an operand. Fetch any special modifiers. */
148 mods = 0;
149 index = TXVU_OPERAND_INDEX (*syn);
150 while (TXVU_MOD_P (txvu_operands[index].flags))
151 {
152 mods |= txvu_operands[index].flags & TXVU_MOD_BITS;
153 ++syn;
154 index = TXVU_OPERAND_INDEX (*syn);
155 }
156 operand = txvu_operands + index;
157
158 /* Extract the value from the instruction. */
159 if (operand->extract)
160 {
161 value = (*operand->extract) (&insn, operand, mods, (int *) NULL);
162 }
163 else
164 {
165 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
166 if ((operand->flags & TXVU_OPERAND_SIGNED) != 0
167 && (value & (1 << (operand->bits - 1))))
168 value -= 1 << operand->bits;
169 }
170
171 #if 0 /* commas are part of the syntax string now */
172 /* If second or later operand, print a comma. */
173 if (num_operands > 0)
174 (*func) (stream, ",");
175 #endif
176
177 /* Print the operand as directed by the flags. */
178 if (operand->print)
179 (*operand->print) (info, &insn, value);
180 else if (operand->flags & TXVU_OPERAND_FAKE)
181 ; /* nothing to do (??? at least not yet) */
182 else if (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH)
183 (*info->print_address_func) (pc + (value << 3), info);
184 /* ??? Not all cases of this are currently caught. */
185 else if (operand->flags & TXVU_OPERAND_ABSOLUTE_BRANCH)
186 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
187 else if (operand->flags & TXVU_OPERAND_ADDRESS)
188 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
189 else
190 (*func) (stream, "%ld", value);
191
192 if (! (operand->flags & TXVU_OPERAND_SUFFIX))
193 ++num_operands;
194 }
195
196 /* We have found and printed an instruction; return. */
197 return;
198 }
199
200 (*func) (stream, "*unknown*");
201 }
This page took 0.03494 seconds and 5 git commands to generate.