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