]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/fr30-dis.c
Fri Dec 4 17:08:08 1998 Dave Brolley <brolley@cygnus.com>
[thirdparty/binutils-gdb.git] / opcodes / fr30-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-dis.c.
5
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24 #include "sysdep.h"
25 #include <stdio.h>
26 #include "ansidecl.h"
27 #include "dis-asm.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "fr30-opc.h"
31 #include "opintl.h"
32
33 #undef INLINE
34 #ifdef __GNUC__
35 #define INLINE __inline__
36 #else
37 #define INLINE
38 #endif
39
40 /* Default text to print if an instruction isn't recognized. */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 /* Used by the ifield rtx function. */
44 #define FLD(f) (fields->f)
45
46 static int extract_normal
47 PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
48 unsigned int, unsigned int, unsigned int, unsigned int,
49 unsigned int, unsigned int, bfd_vma, long *));
50 static void print_normal
51 PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
52 static void print_address
53 PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
54 static void print_keyword
55 PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
56 static int extract_insn_normal
57 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
59 static void print_insn_normal
60 PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
61 bfd_vma, int));
62 static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
63 disassemble_info *, char *, int));
64 static int default_print_insn
65 PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
66 \f
67 /* -- disassembler routines inserted here */
68 /* -- dis.c */
69
70 static void
71 print_register_list (dis_info, value, offset)
72 PTR dis_info;
73 long value;
74 long offset;
75 {
76 disassemble_info *info = dis_info;
77 int mask = 1;
78 int index;
79
80 if (value & mask)
81 (*info->fprintf_func) (info->stream, "r%i", index + offset);
82
83 for (index = 1; index <= 7; ++index)
84 {
85 mask <<= 1;
86 if (value & mask)
87 (*info->fprintf_func) (info->stream, ",r%i", index + offset);
88 }
89 }
90
91 static void
92 print_hi_register_list (od, dis_info, value, attrs, pc, length)
93 CGEN_OPCODE_DESC od;
94 PTR dis_info;
95 long value;
96 unsigned int attrs;
97 bfd_vma pc;
98 int length;
99 {
100 print_register_list (dis_info, value, 8);
101 }
102
103 static void
104 print_low_register_list (od, dis_info, value, attrs, pc, length)
105 CGEN_OPCODE_DESC od;
106 PTR dis_info;
107 long value;
108 unsigned int attrs;
109 bfd_vma pc;
110 int length;
111 {
112 print_register_list (dis_info, value, 0);
113 }
114
115 static void
116 print_m4 (od, dis_info, value, attrs, pc, length)
117 CGEN_OPCODE_DESC od;
118 PTR dis_info;
119 long value;
120 unsigned int attrs;
121 bfd_vma pc;
122 int length;
123 {
124 disassemble_info *info = (disassemble_info *) dis_info;
125 (*info->fprintf_func) (info->stream, "%ld", value);
126 }
127 /* -- */
128
129 /* Main entry point for operand extraction.
130
131 This function is basically just a big switch statement. Earlier versions
132 used tables to look up the function to use, but
133 - if the table contains both assembler and disassembler functions then
134 the disassembler contains much of the assembler and vice-versa,
135 - there's a lot of inlining possibilities as things grow,
136 - using a switch statement avoids the function call overhead.
137
138 This function could be moved into `print_insn_normal', but keeping it
139 separate makes clear the interface between `print_insn_normal' and each of
140 the handlers.
141 */
142
143 int
144 fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
145 CGEN_OPCODE_DESC od;
146 int opindex;
147 CGEN_EXTRACT_INFO *ex_info;
148 CGEN_INSN_INT insn_value;
149 CGEN_FIELDS * fields;
150 bfd_vma pc;
151 {
152 int length;
153 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
154
155 switch (opindex)
156 {
157 case FR30_OPERAND_RI :
158 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, pc, & fields->f_Ri);
159 break;
160 case FR30_OPERAND_RJ :
161 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, pc, & fields->f_Rj);
162 break;
163 case FR30_OPERAND_RIC :
164 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 12, 4, 16, total_length, pc, & fields->f_Ric);
165 break;
166 case FR30_OPERAND_RJC :
167 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, 4, 16, total_length, pc, & fields->f_Rjc);
168 break;
169 case FR30_OPERAND_CRI :
170 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 12, 4, 16, total_length, pc, & fields->f_CRi);
171 break;
172 case FR30_OPERAND_CRJ :
173 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, 4, 16, total_length, pc, & fields->f_CRj);
174 break;
175 case FR30_OPERAND_RS1 :
176 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, pc, & fields->f_Rs1);
177 break;
178 case FR30_OPERAND_RS2 :
179 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, pc, & fields->f_Rs2);
180 break;
181 case FR30_OPERAND_R13 :
182 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil);
183 break;
184 case FR30_OPERAND_R14 :
185 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil);
186 break;
187 case FR30_OPERAND_R15 :
188 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil);
189 break;
190 case FR30_OPERAND_PS :
191 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil);
192 break;
193 case FR30_OPERAND_U4 :
194 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, pc, & fields->f_u4);
195 break;
196 case FR30_OPERAND_U4C :
197 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, pc, & fields->f_u4c);
198 break;
199 case FR30_OPERAND_U8 :
200 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & fields->f_u8);
201 break;
202 case FR30_OPERAND_I8 :
203 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 8, 16, total_length, pc, & fields->f_i8);
204 break;
205 case FR30_OPERAND_UDISP6 :
206 {
207 long value;
208 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, pc, & value);
209 value = ((value) << (2));
210 fields->f_udisp6 = value;
211 }
212 break;
213 case FR30_OPERAND_DISP8 :
214 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, pc, & fields->f_disp8);
215 break;
216 case FR30_OPERAND_DISP9 :
217 {
218 long value;
219 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, pc, & value);
220 value = ((value) << (1));
221 fields->f_disp9 = value;
222 }
223 break;
224 case FR30_OPERAND_DISP10 :
225 {
226 long value;
227 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 4, 8, 16, total_length, pc, & value);
228 value = ((value) << (2));
229 fields->f_disp10 = value;
230 }
231 break;
232 case FR30_OPERAND_S10 :
233 {
234 long value;
235 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 0, 8, 8, 16, total_length, pc, & value);
236 value = ((value) << (2));
237 fields->f_s10 = value;
238 }
239 break;
240 case FR30_OPERAND_U10 :
241 {
242 long value;
243 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & value);
244 value = ((value) << (2));
245 fields->f_u10 = value;
246 }
247 break;
248 case FR30_OPERAND_I32 :
249 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 0, 32, 32, total_length, pc, & fields->f_i32);
250 break;
251 case FR30_OPERAND_M4 :
252 {
253 long value;
254 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, pc, & value);
255 value = ((value) | (((-1) << (4))));
256 fields->f_m4 = value;
257 }
258 break;
259 case FR30_OPERAND_I20 :
260 {
261 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED)|(1<<CGEN_OPERAND_VIRTUAL), 0, 8, 4, 16, total_length, pc, & fields->f_i20_4);
262 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED)|(1<<CGEN_OPERAND_VIRTUAL), 16, 0, 16, 16, total_length, pc, & fields->f_i20_16);
263 do {
264 FLD (f_i20) = ((((FLD (f_i20_4)) << (16))) | (FLD (f_i20_16)));
265 } while (0);
266 }
267 break;
268 case FR30_OPERAND_DIR8 :
269 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & fields->f_dir8);
270 break;
271 case FR30_OPERAND_DIR9 :
272 {
273 long value;
274 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & value);
275 value = ((value) << (1));
276 fields->f_dir9 = value;
277 }
278 break;
279 case FR30_OPERAND_DIR10 :
280 {
281 long value;
282 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & value);
283 value = ((value) << (2));
284 fields->f_dir10 = value;
285 }
286 break;
287 case FR30_OPERAND_LABEL9 :
288 {
289 long value;
290 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 0, 8, 8, 16, total_length, pc, & value);
291 value = ((((value) << (1))) + (((pc) + (2))));
292 fields->f_rel9 = value;
293 }
294 break;
295 case FR30_OPERAND_LABEL12 :
296 {
297 long value;
298 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 0, 5, 11, 16, total_length, pc, & value);
299 value = ((((value) << (1))) + (((pc) + (2))));
300 fields->f_rel12 = value;
301 }
302 break;
303 case FR30_OPERAND_REGLIST_LOW :
304 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & fields->f_reglist_low);
305 break;
306 case FR30_OPERAND_REGLIST_HI :
307 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, pc, & fields->f_reglist_hi);
308 break;
309 case FR30_OPERAND_CC :
310 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 16, total_length, pc, & fields->f_cc);
311 break;
312 case FR30_OPERAND_CCC :
313 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 0, 8, 16, total_length, pc, & fields->f_ccc);
314 break;
315
316 default :
317 /* xgettext:c-format */
318 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
319 opindex);
320 abort ();
321 }
322
323 return length;
324 }
325
326 /* Main entry point for printing operands.
327
328 This function is basically just a big switch statement. Earlier versions
329 used tables to look up the function to use, but
330 - if the table contains both assembler and disassembler functions then
331 the disassembler contains much of the assembler and vice-versa,
332 - there's a lot of inlining possibilities as things grow,
333 - using a switch statement avoids the function call overhead.
334
335 This function could be moved into `print_insn_normal', but keeping it
336 separate makes clear the interface between `print_insn_normal' and each of
337 the handlers.
338 */
339
340 void
341 fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
342 CGEN_OPCODE_DESC od;
343 int opindex;
344 disassemble_info * info;
345 CGEN_FIELDS * fields;
346 void const * attrs;
347 bfd_vma pc;
348 int length;
349 {
350 switch (opindex)
351 {
352 case FR30_OPERAND_RI :
353 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED));
354 break;
355 case FR30_OPERAND_RJ :
356 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED));
357 break;
358 case FR30_OPERAND_RIC :
359 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ric, 0|(1<<CGEN_OPERAND_UNSIGNED));
360 break;
361 case FR30_OPERAND_RJC :
362 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rjc, 0|(1<<CGEN_OPERAND_UNSIGNED));
363 break;
364 case FR30_OPERAND_CRI :
365 print_keyword (od, info, & fr30_cgen_opval_h_cr, fields->f_CRi, 0|(1<<CGEN_OPERAND_UNSIGNED));
366 break;
367 case FR30_OPERAND_CRJ :
368 print_keyword (od, info, & fr30_cgen_opval_h_cr, fields->f_CRj, 0|(1<<CGEN_OPERAND_UNSIGNED));
369 break;
370 case FR30_OPERAND_RS1 :
371 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED));
372 break;
373 case FR30_OPERAND_RS2 :
374 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED));
375 break;
376 case FR30_OPERAND_R13 :
377 print_keyword (od, info, & fr30_cgen_opval_h_r13, fields->f_nil, 0);
378 break;
379 case FR30_OPERAND_R14 :
380 print_keyword (od, info, & fr30_cgen_opval_h_r14, fields->f_nil, 0);
381 break;
382 case FR30_OPERAND_R15 :
383 print_keyword (od, info, & fr30_cgen_opval_h_r15, fields->f_nil, 0);
384 break;
385 case FR30_OPERAND_PS :
386 print_keyword (od, info, & fr30_cgen_opval_h_ps, fields->f_nil, 0);
387 break;
388 case FR30_OPERAND_U4 :
389 print_normal (od, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
390 break;
391 case FR30_OPERAND_U4C :
392 print_normal (od, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
393 break;
394 case FR30_OPERAND_U8 :
395 print_normal (od, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
396 break;
397 case FR30_OPERAND_I8 :
398 print_normal (od, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
399 break;
400 case FR30_OPERAND_UDISP6 :
401 print_normal (od, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
402 break;
403 case FR30_OPERAND_DISP8 :
404 print_normal (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
405 break;
406 case FR30_OPERAND_DISP9 :
407 print_normal (od, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
408 break;
409 case FR30_OPERAND_DISP10 :
410 print_normal (od, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
411 break;
412 case FR30_OPERAND_S10 :
413 print_normal (od, info, fields->f_s10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
414 break;
415 case FR30_OPERAND_U10 :
416 print_normal (od, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
417 break;
418 case FR30_OPERAND_I32 :
419 print_normal (od, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
420 break;
421 case FR30_OPERAND_M4 :
422 print_m4 (od, info, fields->f_m4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
423 break;
424 case FR30_OPERAND_I20 :
425 print_normal (od, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
426 break;
427 case FR30_OPERAND_DIR8 :
428 print_normal (od, info, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
429 break;
430 case FR30_OPERAND_DIR9 :
431 print_normal (od, info, fields->f_dir9, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
432 break;
433 case FR30_OPERAND_DIR10 :
434 print_normal (od, info, fields->f_dir10, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
435 break;
436 case FR30_OPERAND_LABEL9 :
437 print_address (od, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), pc, length);
438 break;
439 case FR30_OPERAND_LABEL12 :
440 print_address (od, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), pc, length);
441 break;
442 case FR30_OPERAND_REGLIST_LOW :
443 print_low_register_list (od, info, fields->f_reglist_low, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
444 break;
445 case FR30_OPERAND_REGLIST_HI :
446 print_hi_register_list (od, info, fields->f_reglist_hi, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
447 break;
448 case FR30_OPERAND_CC :
449 print_normal (od, info, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
450 break;
451 case FR30_OPERAND_CCC :
452 print_normal (od, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
453 break;
454
455 default :
456 /* xgettext:c-format */
457 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
458 opindex);
459 abort ();
460 }
461 }
462
463 cgen_extract_fn * const fr30_cgen_extract_handlers[] =
464 {
465 0, /* default */
466 extract_insn_normal,
467 };
468
469 cgen_print_fn * const fr30_cgen_print_handlers[] =
470 {
471 0, /* default */
472 print_insn_normal,
473 };
474
475
476 void
477 fr30_cgen_init_dis (od)
478 CGEN_OPCODE_DESC od;
479 {
480 }
481
482 \f
483 #if ! CGEN_INT_INSN_P
484
485 /* Subroutine of extract_normal.
486 Ensure sufficient bytes are cached in EX_INFO.
487 OFFSET is the offset in bytes from the start of the insn of the value.
488 BYTES is the length of the needed value.
489 Returns 1 for success, 0 for failure. */
490
491 static INLINE int
492 fill_cache (od, ex_info, offset, bytes, pc)
493 CGEN_OPCODE_DESC od;
494 CGEN_EXTRACT_INFO *ex_info;
495 int offset, bytes;
496 bfd_vma pc;
497 {
498 /* It's doubtful that the middle part has already been fetched so
499 we don't optimize that case. kiss. */
500 int mask;
501 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
502
503 /* First do a quick check. */
504 mask = (1 << bytes) - 1;
505 if (((ex_info->valid >> offset) & mask) == mask)
506 return 1;
507
508 /* Search for the first byte we need to read. */
509 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
510 if (! (mask & ex_info->valid))
511 break;
512
513 if (bytes)
514 {
515 int status;
516
517 pc += offset;
518 status = (*info->read_memory_func)
519 (pc, ex_info->insn_bytes + offset, bytes, info);
520
521 if (status != 0)
522 {
523 (*info->memory_error_func) (status, pc, info);
524 return 0;
525 }
526
527 ex_info->valid |= ((1 << bytes) - 1) << offset;
528 }
529
530 return 1;
531 }
532
533 /* Subroutine of extract_normal. */
534
535 static INLINE long
536 extract_1 (od, ex_info, start, length, word_length, bufp, pc)
537 CGEN_OPCODE_DESC od;
538 CGEN_EXTRACT_INFO *ex_info;
539 int start,length,word_length;
540 unsigned char *bufp;
541 bfd_vma pc;
542 {
543 unsigned long x,mask;
544 int shift;
545 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
546
547 switch (word_length)
548 {
549 case 8:
550 x = *bufp;
551 break;
552 case 16:
553 if (big_p)
554 x = bfd_getb16 (bufp);
555 else
556 x = bfd_getl16 (bufp);
557 break;
558 case 24:
559 /* ??? This may need reworking as these cases don't necessarily
560 want the first byte and the last two bytes handled like this. */
561 if (big_p)
562 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
563 else
564 x = bfd_getl16 (bufp) | (bufp[2] << 16);
565 break;
566 case 32:
567 if (big_p)
568 x = bfd_getb32 (bufp);
569 else
570 x = bfd_getl32 (bufp);
571 break;
572 default :
573 abort ();
574 }
575
576 /* Written this way to avoid undefined behaviour. */
577 mask = (((1L << (length - 1)) - 1) << 1) | 1;
578 if (CGEN_INSN_LSB0_P)
579 shift = (start + 1) - length;
580 else
581 shift = (word_length - (start + length));
582 return (x >> shift) & mask;
583 }
584
585 #endif /* ! CGEN_INT_INSN_P */
586
587 /* Default extraction routine.
588
589 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
590 or sometimes less for cases like the m32r where the base insn size is 32
591 but some insns are 16 bits.
592 ATTRS is a mask of the boolean attributes. We only need `UNSIGNED',
593 but for generality we take a bitmask of all of them.
594 WORD_OFFSET is the offset in bits from the start of the insn of the value.
595 WORD_LENGTH is the length of the word in bits in which the value resides.
596 START is the starting bit number in the word, architecture origin.
597 LENGTH is the length of VALUE in bits.
598 TOTAL_LENGTH is the total length of the insn in bits.
599
600 Returns 1 for success, 0 for failure. */
601
602 /* ??? The return code isn't properly used. wip. */
603
604 /* ??? This doesn't handle bfd_vma's. Create another function when
605 necessary. */
606
607 static int
608 extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length,
609 word_length, total_length, pc, valuep)
610 CGEN_OPCODE_DESC od;
611 CGEN_EXTRACT_INFO *ex_info;
612 CGEN_INSN_INT insn_value;
613 unsigned int attrs;
614 unsigned int word_offset, start, length, word_length, total_length;
615 bfd_vma pc;
616 long *valuep;
617 {
618 CGEN_INSN_INT value;
619
620 /* If LENGTH is zero, this operand doesn't contribute to the value
621 so give it a standard value of zero. */
622 if (length == 0)
623 {
624 *valuep = 0;
625 return 1;
626 }
627
628 if (CGEN_INT_INSN_P
629 && word_offset != 0)
630 abort ();
631
632 if (word_length > 32)
633 abort ();
634
635 /* For architectures with insns smaller than the insn-base-bitsize,
636 word_length may be too big. */
637 #if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
638 if (word_offset == 0
639 && word_length > total_length)
640 word_length = total_length;
641 #endif
642
643 /* Does the value reside in INSN_VALUE? */
644
645 if (word_offset == 0)
646 {
647 /* Written this way to avoid undefined behaviour. */
648 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
649
650 if (CGEN_INSN_LSB0_P)
651 value = insn_value >> ((start + 1) - length);
652 else
653 value = insn_value >> (word_length - (start + length));
654 value &= mask;
655 /* sign extend? */
656 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
657 && (value & (1L << (length - 1))))
658 value |= ~mask;
659 }
660
661 #if ! CGEN_INT_INSN_P
662
663 else
664 {
665 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
666
667 if (word_length > 32)
668 abort ();
669
670 if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0)
671 return 0;
672
673 value = extract_1 (od, ex_info, start, length, word_length, bufp, pc);
674 }
675
676 #endif /* ! CGEN_INT_INSN_P */
677
678 *valuep = value;
679
680 return 1;
681 }
682
683 /* Default print handler. */
684
685 static void
686 print_normal (od, dis_info, value, attrs, pc, length)
687 CGEN_OPCODE_DESC od;
688 PTR dis_info;
689 long value;
690 unsigned int attrs;
691 bfd_vma pc;
692 int length;
693 {
694 disassemble_info *info = (disassemble_info *) dis_info;
695
696 #ifdef CGEN_PRINT_NORMAL
697 CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
698 #endif
699
700 /* Print the operand as directed by the attributes. */
701 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
702 ; /* nothing to do */
703 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
704 (*info->fprintf_func) (info->stream, "0x%lx", value);
705 else
706 (*info->fprintf_func) (info->stream, "%ld", value);
707 }
708
709 /* Default address handler. */
710
711 static void
712 print_address (od, dis_info, value, attrs, pc, length)
713 CGEN_OPCODE_DESC od;
714 PTR dis_info;
715 bfd_vma value;
716 unsigned int attrs;
717 bfd_vma pc;
718 int length;
719 {
720 disassemble_info *info = (disassemble_info *) dis_info;
721
722 #ifdef CGEN_PRINT_ADDRESS
723 CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
724 #endif
725
726 /* Print the operand as directed by the attributes. */
727 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
728 ; /* nothing to do */
729 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
730 (*info->print_address_func) (value, info);
731 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
732 (*info->print_address_func) (value, info);
733 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
734 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
735 else
736 (*info->fprintf_func) (info->stream, "%ld", (long) value);
737 }
738
739 /* Keyword print handler. */
740
741 static void
742 print_keyword (od, dis_info, keyword_table, value, attrs)
743 CGEN_OPCODE_DESC od;
744 PTR dis_info;
745 CGEN_KEYWORD *keyword_table;
746 long value;
747 unsigned int attrs;
748 {
749 disassemble_info *info = (disassemble_info *) dis_info;
750 const CGEN_KEYWORD_ENTRY *ke;
751
752 ke = cgen_keyword_lookup_value (keyword_table, value);
753 if (ke != NULL)
754 (*info->fprintf_func) (info->stream, "%s", ke->name);
755 else
756 (*info->fprintf_func) (info->stream, "???");
757 }
758 \f
759 /* Default insn extractor.
760
761 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
762 The extracted fields are stored in FIELDS.
763 EX_INFO is used to handle reading variable length insns.
764 Return the length of the insn in bits, or 0 if no match,
765 or -1 if an error occurs fetching data (memory_error_func will have
766 been called). */
767
768 static int
769 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
770 CGEN_OPCODE_DESC od;
771 const CGEN_INSN *insn;
772 CGEN_EXTRACT_INFO *ex_info;
773 CGEN_INSN_INT insn_value;
774 CGEN_FIELDS *fields;
775 bfd_vma pc;
776 {
777 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
778 const unsigned char *syn;
779
780 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
781
782 CGEN_INIT_EXTRACT (od);
783
784 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
785 {
786 int length;
787
788 if (CGEN_SYNTAX_CHAR_P (*syn))
789 continue;
790
791 length = fr30_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
792 ex_info, insn_value, fields, pc);
793 if (length <= 0)
794 return length;
795 }
796
797 /* We recognized and successfully extracted this insn. */
798 return CGEN_INSN_BITSIZE (insn);
799 }
800
801 /* Default insn printer.
802
803 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
804 about disassemble_info. */
805
806 static void
807 print_insn_normal (od, dis_info, insn, fields, pc, length)
808 CGEN_OPCODE_DESC od;
809 PTR dis_info;
810 const CGEN_INSN *insn;
811 CGEN_FIELDS *fields;
812 bfd_vma pc;
813 int length;
814 {
815 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
816 disassemble_info *info = (disassemble_info *) dis_info;
817 const unsigned char *syn;
818
819 CGEN_INIT_PRINT (od);
820
821 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
822 {
823 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
824 {
825 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
826 continue;
827 }
828 if (CGEN_SYNTAX_CHAR_P (*syn))
829 {
830 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
831 continue;
832 }
833
834 /* We have an operand. */
835 fr30_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
836 fields, CGEN_INSN_ATTRS (insn), pc, length);
837 }
838 }
839 \f
840 /* Utility to print an insn.
841 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
842 The result is the size of the insn in bytes or zero for an unknown insn
843 or -1 if an error occurs fetching data (memory_error_func will have
844 been called). */
845
846 static int
847 print_insn (od, pc, info, buf, buflen)
848 CGEN_OPCODE_DESC od;
849 bfd_vma pc;
850 disassemble_info *info;
851 char *buf;
852 int buflen;
853 {
854 unsigned long insn_value;
855 const CGEN_INSN_LIST *insn_list;
856 CGEN_EXTRACT_INFO ex_info;
857
858 ex_info.dis_info = info;
859 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
860 ex_info.insn_bytes = buf;
861
862 switch (buflen)
863 {
864 case 1:
865 insn_value = buf[0];
866 break;
867 case 2:
868 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
869 break;
870 case 4:
871 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
872 break;
873 default:
874 abort ();
875 }
876
877 /* The instructions are stored in hash lists.
878 Pick the first one and keep trying until we find the right one. */
879
880 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
881 while (insn_list != NULL)
882 {
883 const CGEN_INSN *insn = insn_list->insn;
884 CGEN_FIELDS fields;
885 int length;
886
887 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
888 /* Supported by this cpu? */
889 if (! fr30_cgen_insn_supported (od, insn))
890 continue;
891 #endif
892
893 /* Basic bit mask must be correct. */
894 /* ??? May wish to allow target to defer this check until the extract
895 handler. */
896 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
897 == CGEN_INSN_BASE_VALUE (insn))
898 {
899 /* Printing is handled in two passes. The first pass parses the
900 machine insn and extracts the fields. The second pass prints
901 them. */
902
903 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
904 &fields, pc);
905 /* length < 0 -> error */
906 if (length < 0)
907 return length;
908 if (length > 0)
909 {
910 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
911 /* length is in bits, result is in bytes */
912 return length / 8;
913 }
914 }
915
916 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
917 }
918
919 return 0;
920 }
921
922 /* Default value for CGEN_PRINT_INSN.
923 The result is the size of the insn in bytes or zero for an unknown insn
924 or -1 if an error occured fetching bytes. */
925
926 #ifndef CGEN_PRINT_INSN
927 #define CGEN_PRINT_INSN default_print_insn
928 #endif
929
930 static int
931 default_print_insn (od, pc, info)
932 CGEN_OPCODE_DESC od;
933 bfd_vma pc;
934 disassemble_info *info;
935 {
936 char buf[CGEN_MAX_INSN_SIZE];
937 int status;
938
939 /* Read the base part of the insn. */
940
941 status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
942 if (status != 0)
943 {
944 (*info->memory_error_func) (status, pc, info);
945 return -1;
946 }
947
948 return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
949 }
950
951 /* Main entry point.
952 Print one instruction from PC on INFO->STREAM.
953 Return the size of the instruction (in bytes). */
954
955 int
956 print_insn_fr30 (pc, info)
957 bfd_vma pc;
958 disassemble_info *info;
959 {
960 int length;
961 static CGEN_OPCODE_DESC od = 0;
962 int mach = info->mach;
963 int big_p = info->endian == BFD_ENDIAN_BIG;
964
965 /* If we haven't initialized yet, initialize the opcode table. */
966 if (! od)
967 {
968 od = fr30_cgen_opcode_open (mach,
969 big_p ?
970 CGEN_ENDIAN_BIG
971 : CGEN_ENDIAN_LITTLE);
972 fr30_cgen_init_dis (od);
973 }
974 /* If we've switched cpu's, re-initialize. */
975 /* ??? Perhaps we should use BFD_ENDIAN. */
976 else if (mach != CGEN_OPCODE_MACH (od)
977 || (CGEN_OPCODE_ENDIAN (od)
978 != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
979 {
980 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
981 }
982
983 /* We try to have as much common code as possible.
984 But at this point some targets need to take over. */
985 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
986 but if not possible try to move this hook elsewhere rather than
987 have two hooks. */
988 length = CGEN_PRINT_INSN (od, pc, info);
989 if (length > 0)
990 return length;
991 if (length < 0)
992 return -1;
993
994 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
995 return CGEN_DEFAULT_INSN_SIZE;
996 }