Thu Nov 12 19:21:57 1998 Dave Brolley <brolley@cygnus.com>
[deliverable/binutils-gdb.git] / opcodes / m32r-asm.c
CommitLineData
9c03036a
DE
1/* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
fbc8134d 4THIS FILE IS USED TO GENERATE m32r-asm.c.
9c03036a 5
0bf55db8 6Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
9c03036a
DE
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
fbc8134d
DE
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
9c03036a 23
23cf992f 24#include "sysdep.h"
9c03036a
DE
25#include <ctype.h>
26#include <stdio.h>
27#include "ansidecl.h"
28#include "bfd.h"
0bf55db8 29#include "symcat.h"
9c03036a 30#include "m32r-opc.h"
cbc6c9b2 31#include "opintl.h"
9c03036a 32
617e3d09
DE
33#undef min
34#define min(a,b) ((a) < (b) ? (a) : (b))
35#undef max
36#define max(a,b) ((a) > (b) ? (a) : (b))
37
38#undef INLINE
39#ifdef __GNUC__
40#define INLINE __inline__
41#else
42#define INLINE
43#endif
9c03036a 44
1294c286 45static const char * insert_normal
617e3d09
DE
46 PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, int, int, int,
47 CGEN_INSN_BYTES_PTR));
23cf992f 48static const char * parse_insn_normal
617e3d09
DE
49 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
50 const char **, CGEN_FIELDS *));
0bf55db8 51static const char * insert_insn_normal
617e3d09
DE
52 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
53 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
9c03036a 54\f
1294c286
DE
55/* -- assembler routines inserted here */
56/* -- asm.c */
9c03036a 57
1294c286 58/* Handle '#' prefixes (i.e. skip over them). */
9c03036a 59
0bf55db8 60static const char *
617e3d09
DE
61parse_hash (od, strp, opindex, valuep)
62 CGEN_OPCODE_DESC od;
1294c286
DE
63 const char **strp;
64 int opindex;
65 unsigned long *valuep;
9c03036a 66{
1294c286
DE
67 if (**strp == '#')
68 ++*strp;
0bf55db8 69 return NULL;
9c03036a 70}
853713a7
DE
71
72/* Handle shigh(), high(). */
73
74static const char *
617e3d09
DE
75parse_hi16 (od, strp, opindex, valuep)
76 CGEN_OPCODE_DESC od;
853713a7
DE
77 const char **strp;
78 int opindex;
853713a7
DE
79 unsigned long *valuep;
80{
81 const char *errmsg;
82 enum cgen_parse_operand_result result_type;
617e3d09 83 bfd_vma value;
853713a7 84
853713a7
DE
85 if (**strp == '#')
86 ++*strp;
87
cbc6c9b2 88 if (strncasecmp (*strp, "high(", 5) == 0)
853713a7
DE
89 {
90 *strp += 5;
617e3d09
DE
91 errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
92 &result_type, &value);
853713a7
DE
93 if (**strp != ')')
94 return "missing `)'";
95 ++*strp;
96 if (errmsg == NULL
97 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
617e3d09
DE
98 value >>= 16;
99 *valuep = value;
853713a7
DE
100 return errmsg;
101 }
cbc6c9b2 102 else if (strncasecmp (*strp, "shigh(", 6) == 0)
853713a7
DE
103 {
104 *strp += 6;
617e3d09
DE
105 errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
106 &result_type, &value);
853713a7
DE
107 if (**strp != ')')
108 return "missing `)'";
109 ++*strp;
110 if (errmsg == NULL
111 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
617e3d09
DE
112 value = (value >> 16) + (value & 0x8000 ? 1 : 0);
113 *valuep = value;
853713a7
DE
114 return errmsg;
115 }
116
617e3d09 117 return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
853713a7
DE
118}
119
120/* Handle low() in a signed context. Also handle sda().
121 The signedness of the value doesn't matter to low(), but this also
122 handles the case where low() isn't present. */
123
124static const char *
617e3d09
DE
125parse_slo16 (od, strp, opindex, valuep)
126 CGEN_OPCODE_DESC od;
853713a7
DE
127 const char **strp;
128 int opindex;
853713a7
DE
129 long *valuep;
130{
131 const char *errmsg;
132 enum cgen_parse_operand_result result_type;
617e3d09 133 bfd_vma value;
853713a7 134
853713a7
DE
135 if (**strp == '#')
136 ++*strp;
137
cbc6c9b2 138 if (strncasecmp (*strp, "low(", 4) == 0)
853713a7
DE
139 {
140 *strp += 4;
617e3d09
DE
141 errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_M32R_LO16,
142 &result_type, &value);
853713a7
DE
143 if (**strp != ')')
144 return "missing `)'";
145 ++*strp;
0bf55db8
DE
146 if (errmsg == NULL
147 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
617e3d09
DE
148 value &= 0xffff;
149 *valuep = value;
853713a7
DE
150 return errmsg;
151 }
152
cbc6c9b2 153 if (strncasecmp (*strp, "sda(", 4) == 0)
853713a7
DE
154 {
155 *strp += 4;
617e3d09
DE
156 errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_M32R_SDA16,
157 NULL, &value);
853713a7
DE
158 if (**strp != ')')
159 return "missing `)'";
160 ++*strp;
617e3d09 161 *valuep = value;
853713a7
DE
162 return errmsg;
163 }
164
617e3d09 165 return cgen_parse_signed_integer (od, strp, opindex, valuep);
853713a7
DE
166}
167
168/* Handle low() in an unsigned context.
169 The signedness of the value doesn't matter to low(), but this also
170 handles the case where low() isn't present. */
171
172static const char *
617e3d09
DE
173parse_ulo16 (od, strp, opindex, valuep)
174 CGEN_OPCODE_DESC od;
853713a7
DE
175 const char **strp;
176 int opindex;
853713a7
DE
177 unsigned long *valuep;
178{
179 const char *errmsg;
180 enum cgen_parse_operand_result result_type;
617e3d09 181 bfd_vma value;
853713a7 182
853713a7
DE
183 if (**strp == '#')
184 ++*strp;
185
cbc6c9b2 186 if (strncasecmp (*strp, "low(", 4) == 0)
853713a7
DE
187 {
188 *strp += 4;
617e3d09
DE
189 errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_M32R_LO16,
190 &result_type, &value);
853713a7
DE
191 if (**strp != ')')
192 return "missing `)'";
193 ++*strp;
0bf55db8
DE
194 if (errmsg == NULL
195 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
617e3d09
DE
196 value &= 0xffff;
197 *valuep = value;
853713a7
DE
198 return errmsg;
199 }
200
617e3d09 201 return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
853713a7
DE
202}
203
204/* -- */
205
206/* Main entry point for operand parsing.
207
208 This function is basically just a big switch statement. Earlier versions
209 used tables to look up the function to use, but
210 - if the table contains both assembler and disassembler functions then
211 the disassembler contains much of the assembler and vice-versa,
212 - there's a lot of inlining possibilities as things grow,
213 - using a switch statement avoids the function call overhead.
214
215 This function could be moved into `parse_insn_normal', but keeping it
216 separate makes clear the interface between `parse_insn_normal' and each of
217 the handlers.
218*/
219
0bf55db8 220const char *
617e3d09
DE
221m32r_cgen_parse_operand (od, opindex, strp, fields)
222 CGEN_OPCODE_DESC od;
853713a7
DE
223 int opindex;
224 const char ** strp;
225 CGEN_FIELDS * fields;
226{
227 const char * errmsg;
228
229 switch (opindex)
230 {
231 case M32R_OPERAND_SR :
617e3d09 232 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_gr, & fields->f_r2);
853713a7
DE
233 break;
234 case M32R_OPERAND_DR :
617e3d09 235 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_gr, & fields->f_r1);
853713a7
DE
236 break;
237 case M32R_OPERAND_SRC1 :
617e3d09 238 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_gr, & fields->f_r1);
853713a7
DE
239 break;
240 case M32R_OPERAND_SRC2 :
617e3d09 241 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_gr, & fields->f_r2);
853713a7
DE
242 break;
243 case M32R_OPERAND_SCR :
617e3d09 244 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_cr, & fields->f_r2);
853713a7
DE
245 break;
246 case M32R_OPERAND_DCR :
617e3d09 247 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_cr, & fields->f_r1);
853713a7
DE
248 break;
249 case M32R_OPERAND_SIMM8 :
617e3d09 250 errmsg = cgen_parse_signed_integer (od, strp, M32R_OPERAND_SIMM8, &fields->f_simm8);
853713a7
DE
251 break;
252 case M32R_OPERAND_SIMM16 :
617e3d09 253 errmsg = cgen_parse_signed_integer (od, strp, M32R_OPERAND_SIMM16, &fields->f_simm16);
853713a7
DE
254 break;
255 case M32R_OPERAND_UIMM4 :
617e3d09 256 errmsg = cgen_parse_unsigned_integer (od, strp, M32R_OPERAND_UIMM4, &fields->f_uimm4);
853713a7
DE
257 break;
258 case M32R_OPERAND_UIMM5 :
617e3d09 259 errmsg = cgen_parse_unsigned_integer (od, strp, M32R_OPERAND_UIMM5, &fields->f_uimm5);
853713a7
DE
260 break;
261 case M32R_OPERAND_UIMM16 :
617e3d09 262 errmsg = cgen_parse_unsigned_integer (od, strp, M32R_OPERAND_UIMM16, &fields->f_uimm16);
853713a7 263 break;
ab0bd049
DE
264/* start-sanitize-m32rx */
265 case M32R_OPERAND_IMM1 :
617e3d09 266 errmsg = cgen_parse_unsigned_integer (od, strp, M32R_OPERAND_IMM1, &fields->f_imm1);
ab0bd049
DE
267 break;
268/* end-sanitize-m32rx */
269/* start-sanitize-m32rx */
270 case M32R_OPERAND_ACCD :
617e3d09 271 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
ab0bd049
DE
272 break;
273/* end-sanitize-m32rx */
274/* start-sanitize-m32rx */
275 case M32R_OPERAND_ACCS :
617e3d09 276 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
ab0bd049
DE
277 break;
278/* end-sanitize-m32rx */
279/* start-sanitize-m32rx */
280 case M32R_OPERAND_ACC :
617e3d09 281 errmsg = cgen_parse_keyword (od, strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
ab0bd049
DE
282 break;
283/* end-sanitize-m32rx */
1294c286 284 case M32R_OPERAND_HASH :
617e3d09 285 errmsg = parse_hash (od, strp, M32R_OPERAND_HASH, &fields->f_nil);
1294c286 286 break;
853713a7 287 case M32R_OPERAND_HI16 :
617e3d09 288 errmsg = parse_hi16 (od, strp, M32R_OPERAND_HI16, &fields->f_hi16);
853713a7
DE
289 break;
290 case M32R_OPERAND_SLO16 :
617e3d09 291 errmsg = parse_slo16 (od, strp, M32R_OPERAND_SLO16, &fields->f_simm16);
853713a7
DE
292 break;
293 case M32R_OPERAND_ULO16 :
617e3d09 294 errmsg = parse_ulo16 (od, strp, M32R_OPERAND_ULO16, &fields->f_uimm16);
853713a7
DE
295 break;
296 case M32R_OPERAND_UIMM24 :
617e3d09
DE
297 {
298 bfd_vma value;
299 errmsg = cgen_parse_address (od, strp, M32R_OPERAND_UIMM24, 0, NULL, & value);
300 fields->f_uimm24 = value;
301 }
853713a7
DE
302 break;
303 case M32R_OPERAND_DISP8 :
617e3d09
DE
304 {
305 bfd_vma value;
306 errmsg = cgen_parse_address (od, strp, M32R_OPERAND_DISP8, 0, NULL, & value);
307 fields->f_disp8 = value;
308 }
853713a7
DE
309 break;
310 case M32R_OPERAND_DISP16 :
617e3d09
DE
311 {
312 bfd_vma value;
313 errmsg = cgen_parse_address (od, strp, M32R_OPERAND_DISP16, 0, NULL, & value);
314 fields->f_disp16 = value;
315 }
853713a7
DE
316 break;
317 case M32R_OPERAND_DISP24 :
617e3d09
DE
318 {
319 bfd_vma value;
320 errmsg = cgen_parse_address (od, strp, M32R_OPERAND_DISP24, 0, NULL, & value);
321 fields->f_disp24 = value;
322 }
853713a7
DE
323 break;
324
325 default :
cbc6c9b2
DE
326 /* xgettext:c-format */
327 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
853713a7
DE
328 abort ();
329 }
330
331 return errmsg;
332}
333
334/* Main entry point for operand insertion.
335
336 This function is basically just a big switch statement. Earlier versions
337 used tables to look up the function to use, but
338 - if the table contains both assembler and disassembler functions then
339 the disassembler contains much of the assembler and vice-versa,
340 - there's a lot of inlining possibilities as things grow,
341 - using a switch statement avoids the function call overhead.
342
343 This function could be moved into `parse_insn_normal', but keeping it
344 separate makes clear the interface between `parse_insn_normal' and each of
345 the handlers. It's also needed by GAS to insert operands that couldn't be
346 resolved during parsing.
347*/
348
0bf55db8 349const char *
617e3d09
DE
350m32r_cgen_insert_operand (od, opindex, fields, buffer, pc)
351 CGEN_OPCODE_DESC od;
5d07b6cf 352 int opindex;
853713a7 353 CGEN_FIELDS * fields;
617e3d09 354 CGEN_INSN_BYTES_PTR buffer;
fbc8134d 355 bfd_vma pc;
853713a7 356{
0bf55db8 357 const char * errmsg;
853713a7
DE
358
359 switch (opindex)
360 {
361 case M32R_OPERAND_SR :
617e3d09 362 errmsg = insert_normal (od, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
363 break;
364 case M32R_OPERAND_DR :
617e3d09 365 errmsg = insert_normal (od, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
366 break;
367 case M32R_OPERAND_SRC1 :
617e3d09 368 errmsg = insert_normal (od, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
369 break;
370 case M32R_OPERAND_SRC2 :
617e3d09 371 errmsg = insert_normal (od, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
372 break;
373 case M32R_OPERAND_SCR :
617e3d09 374 errmsg = insert_normal (od, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
375 break;
376 case M32R_OPERAND_DCR :
617e3d09 377 errmsg = insert_normal (od, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
378 break;
379 case M32R_OPERAND_SIMM8 :
617e3d09 380 errmsg = insert_normal (od, fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
381 break;
382 case M32R_OPERAND_SIMM16 :
617e3d09 383 errmsg = insert_normal (od, fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
384 break;
385 case M32R_OPERAND_UIMM4 :
617e3d09 386 errmsg = insert_normal (od, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
387 break;
388 case M32R_OPERAND_UIMM5 :
617e3d09 389 errmsg = insert_normal (od, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
390 break;
391 case M32R_OPERAND_UIMM16 :
617e3d09 392 errmsg = insert_normal (od, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7 393 break;
ab0bd049
DE
394/* start-sanitize-m32rx */
395 case M32R_OPERAND_IMM1 :
0bf55db8 396 {
fbc8134d
DE
397 long value = fields->f_imm1;
398 value = ((value) - (1));
617e3d09 399 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 400 }
ab0bd049
DE
401 break;
402/* end-sanitize-m32rx */
403/* start-sanitize-m32rx */
404 case M32R_OPERAND_ACCD :
617e3d09 405 errmsg = insert_normal (od, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
ab0bd049
DE
406 break;
407/* end-sanitize-m32rx */
408/* start-sanitize-m32rx */
409 case M32R_OPERAND_ACCS :
617e3d09 410 errmsg = insert_normal (od, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
ab0bd049
DE
411 break;
412/* end-sanitize-m32rx */
413/* start-sanitize-m32rx */
414 case M32R_OPERAND_ACC :
617e3d09 415 errmsg = insert_normal (od, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, CGEN_FIELDS_BITSIZE (fields), buffer);
ab0bd049
DE
416 break;
417/* end-sanitize-m32rx */
1294c286 418 case M32R_OPERAND_HASH :
617e3d09 419 errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
1294c286 420 break;
853713a7 421 case M32R_OPERAND_HI16 :
617e3d09 422 errmsg = insert_normal (od, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
423 break;
424 case M32R_OPERAND_SLO16 :
617e3d09 425 errmsg = insert_normal (od, fields->f_simm16, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
426 break;
427 case M32R_OPERAND_ULO16 :
617e3d09 428 errmsg = insert_normal (od, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
429 break;
430 case M32R_OPERAND_UIMM24 :
617e3d09 431 errmsg = insert_normal (od, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
432 break;
433 case M32R_OPERAND_DISP8 :
0bf55db8 434 {
fbc8134d 435 long value = fields->f_disp8;
b00ea55c 436 value = ((int) (((value) - (((pc) & (-4))))) >> (2));
617e3d09 437 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 438 }
853713a7
DE
439 break;
440 case M32R_OPERAND_DISP16 :
0bf55db8 441 {
fbc8134d 442 long value = fields->f_disp16;
b00ea55c 443 value = ((int) (((value) - (pc))) >> (2));
617e3d09 444 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 445 }
853713a7
DE
446 break;
447 case M32R_OPERAND_DISP24 :
0bf55db8 448 {
fbc8134d 449 long value = fields->f_disp24;
b00ea55c 450 value = ((int) (((value) - (pc))) >> (2));
617e3d09 451 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 452 }
853713a7
DE
453 break;
454
455 default :
cbc6c9b2
DE
456 /* xgettext:c-format */
457 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
853713a7
DE
458 opindex);
459 abort ();
460 }
461
462 return errmsg;
463}
464
617e3d09 465cgen_parse_fn * const m32r_cgen_parse_handlers[] =
5d07b6cf
DE
466{
467 0, /* default */
853713a7
DE
468 parse_insn_normal,
469};
470
617e3d09 471cgen_insert_fn * const m32r_cgen_insert_handlers[] =
5d07b6cf
DE
472{
473 0, /* default */
853713a7
DE
474 insert_insn_normal,
475};
476
477void
617e3d09
DE
478m32r_cgen_init_asm (od)
479 CGEN_OPCODE_DESC od;
853713a7 480{
853713a7
DE
481}
482
1294c286 483\f
617e3d09
DE
484#if ! CGEN_INT_INSN_P
485
486/* Subroutine of insert_normal. */
487
488static INLINE void
489insert_1 (od, value, start, length, word_length, bufp)
490 CGEN_OPCODE_DESC od;
491 unsigned long value;
492 int start,length,word_length;
493 unsigned char *bufp;
494{
495 unsigned long x,mask;
496 int shift;
497 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
498
499 switch (word_length)
500 {
501 case 8:
502 x = *bufp;
503 break;
504 case 16:
505 if (big_p)
506 x = bfd_getb16 (bufp);
507 else
508 x = bfd_getl16 (bufp);
509 break;
510 case 24:
511 /* ??? This may need reworking as these cases don't necessarily
512 want the first byte and the last two bytes handled like this. */
513 if (big_p)
514 x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
515 else
516 x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
517 break;
518 case 32:
519 if (big_p)
520 x = bfd_getb32 (bufp);
521 else
522 x = bfd_getl32 (bufp);
523 break;
524 default :
525 abort ();
526 }
527
528 /* Written this way to avoid undefined behaviour. */
529 mask = (((1L << (length - 1)) - 1) << 1) | 1;
530 if (CGEN_INSN_LSB0_P)
531 shift = start;
532 else
533 shift = (word_length - (start + length));
534 x = (x & ~(mask << shift)) | ((value & mask) << shift);
535
536 switch (word_length)
537 {
538 case 8:
539 *bufp = x;
540 break;
541 case 16:
542 if (big_p)
543 bfd_putb16 (x, bufp);
544 else
545 bfd_putl16 (x, bufp);
546 break;
547 case 24:
548 /* ??? This may need reworking as these cases don't necessarily
549 want the first byte and the last two bytes handled like this. */
550 if (big_p)
551 {
552 bfd_putb8 (x >> 16, bufp);
553 bfd_putb16 (x, bufp + 1);
554 }
555 else
556 {
557 bfd_putl16 (x, bufp);
558 bfd_putb8 (x >> 16, bufp + 2);
559 }
560 break;
561 case 32:
562 if (big_p)
563 bfd_putb32 (x, bufp);
564 else
565 bfd_putl32 (x, bufp);
566 break;
567 default :
568 abort ();
569 }
570}
571
572#endif /* ! CGEN_INT_INSN_P */
573
1294c286
DE
574/* Default insertion routine.
575
576 ATTRS is a mask of the boolean attributes.
617e3d09 577 START is the starting bit number, architecture origin.
1294c286 578 LENGTH is the length of VALUE in bits.
617e3d09 579 TOTAL_LENGTH is the total length of the insn.
1294c286
DE
580
581 The result is an error message or NULL if success. */
582
617e3d09
DE
583/* ??? May need to know word length in order to properly place values as
584 an insn may be made of multiple words and the current bit number handling
585 may be insufficient. Word length is an architectural attribute and thus
586 methinks the way to go [if needed] is to fetch this value from OD or
587 define a macro in <arch>-opc.h rather than adding an extra argument -
588 after all that's how endianness is handled. */
1294c286
DE
589/* ??? This duplicates functionality with bfd's howto table and
590 bfd_install_relocation. */
591/* ??? For architectures where insns can be representable as ints,
592 store insn in `field' struct and add registers, etc. while parsing? */
617e3d09
DE
593/* ??? This doesn't handle bfd_vma's. Create another function when
594 necessary. */
1294c286
DE
595
596static const char *
617e3d09
DE
597insert_normal (od, value, attrs, start, length, total_length, buffer)
598 CGEN_OPCODE_DESC od;
1294c286
DE
599 long value;
600 unsigned int attrs;
601 int start;
602 int length;
603 int total_length;
617e3d09 604 CGEN_INSN_BYTES_PTR buffer;
1294c286 605{
617e3d09
DE
606 static char errbuf[100];
607 /* Written this way to avoid undefined behaviour. */
608 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
cbc6c9b2
DE
609
610 /* If LENGTH is zero, this operand doesn't contribute to the value. */
611 if (length == 0)
612 return NULL;
1294c286
DE
613
614 /* Ensure VALUE will fit. */
cbc6c9b2 615 if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
1294c286 616 {
617e3d09
DE
617 unsigned long maxval = mask;
618 if ((unsigned long) value > maxval)
1294c286 619 {
cbc6c9b2 620 /* xgettext:c-format */
617e3d09
DE
621 sprintf (errbuf,
622 _("operand out of range (%lu not between 0 and %lu)"),
623 value, maxval);
624 return errbuf;
1294c286
DE
625 }
626 }
627 else
628 {
617e3d09
DE
629 long minval = - (1L << (length - 1));
630 long maxval = (1L << (length - 1)) - 1;
631 if (value < minval || value > maxval)
1294c286 632 {
cbc6c9b2
DE
633 sprintf
634 /* xgettext:c-format */
617e3d09
DE
635 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
636 value, minval, maxval);
637 return errbuf;
1294c286
DE
638 }
639 }
640
617e3d09
DE
641#if CGEN_INT_INSN_P
642
643 if (total_length > 32)
644 abort ();
645 {
646 int shift;
647
648 if (CGEN_INSN_LSB0_P)
649 shift = start;
650 else
651 shift = total_length - (start + length);
652 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
653 }
654
1294c286 655#else
617e3d09
DE
656
657 /* FIXME: unfinished and untested */
658
659/* ??? To be defined in <arch>-opc.h as necessary. */
660#ifndef CGEN_WORD_ENDIAN
661#define CGEN_WORD_ENDIAN(od) CGEN_OPCODE_ENDIAN (od)
662#endif
663#ifndef CGEN_INSN_WORD_ENDIAN
664#define CGEN_INSN_WORD_ENDIAN(od) CGEN_WORD_ENDIAN (od)
665#endif
666
667 /* The hard case is probably too slow for the normal cases.
668 It's certainly more difficult to understand than the normal case.
669 Thus this is split into two. Keep it that way. The hard case is defined
670 to be when a field straddles a (loosely defined) word boundary
671 (??? which may require target specific help to determine). */
672
673#if 0 /*wip*/
674
675#define HARD_CASE_P 0 /* FIXME:wip */
676
677 if (HARD_CASE_P)
1294c286 678 {
617e3d09
DE
679 unsigned char *bufp = (unsigned char *) buffer;
680 int insn_length_left = total_length;
681
682 if (CGEN_INSN_LSB0_P)
683 {
684 int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
685 ? ...
686 : start / CGEN_BASE_INSN_BITSIZE);
687 bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
688 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
689 else
690 start -= word_offset * CGEN_BASE_INSN_BITSIZE;
691 }
1294c286 692 else
617e3d09
DE
693 {
694 int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
695 ? start / CGEN_BASE_INSN_BITSIZE
696 : ...);
697 bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
698 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
699 start -= word_offset * CGEN_BASE_INSN_BITSIZE;
700 else
701 }
1294c286 702
617e3d09
DE
703 /* Loop so we handle a field straddling an insn word boundary
704 (remember, "insn word boundary" is loosely defined here). */
1294c286 705
617e3d09
DE
706 while (length > 0)
707 {
708 int this_pass_length = length;
709 int this_pass_start = start;
710 int this_pass_word_length = min (insn_length_left,
711 (CGEN_BASE_INSN_BITSIZE == 8
712 ? 32
713 : CGEN_BASE_INSN_BITSIZE));
714
715 insert_1 (od, value, attrs,
716 this_pass_start, this_pass_length, this_pass_word_length,
717 bufp);
718
719 length -= this_pass_length;
720 insn_length_left -= this_pass_word_length;
721 if (???)
722 {
723 value >>= ???;
724 start += ???;
725 }
726 else
727 {
728 value >>= ???;
729 start += ???;
730 }
731 bufp += this_pass_word_length / 8;
732 }
733 }
734 else
735#endif /* 0 */
1294c286 736 {
617e3d09
DE
737 unsigned char *bufp = (unsigned char *) buffer;
738
739 if (length > 32)
740 abort ();
741
742 /* Adjust start,total_length,bufp to point to the pseudo-word that holds
743 the value. For example in a 48 bit insn where the value to insert
744 (say an immediate value) is the last 16 bits then word_length here
745 would be 16. To handle a 24 bit insn with an 18 bit immediate,
746 insert_1 handles 24 bits (using a combination of bfd_get8,16). */
747
748 if (total_length > 32)
749 {
750 int needed_width = start % 8 + length;
751 int fetch_length = (needed_width <= 8 ? 8
752 : needed_width <= 16 ? 16
753 : 32);
754
755 if (CGEN_INSN_LSB0_P)
756 {
757 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
758 {
759 abort (); /* wip */
760 }
761 else
762 {
763 int offset = start & ~7;
764
765 bufp += offset / 8;
766 start -= offset;
767 total_length -= offset;
768 }
769 }
770 else
771 {
772 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
773 {
774 int offset = start & ~7;
775
776 bufp += offset / 8;
777 start -= offset;
778 total_length -= offset;
779 }
780 else
781 {
782 abort (); /* wip */
783 }
784 }
785 }
786
787 insert_1 (od, value, start, length, total_length, bufp);
1294c286 788 }
617e3d09
DE
789
790#endif /* ! CGEN_INT_INSN_P */
1294c286
DE
791
792 return NULL;
793}
9c03036a
DE
794\f
795/* Default insn parser.
796
797 The syntax string is scanned and operands are parsed and stored in FIELDS.
798 Relocs are queued as we go via other callbacks.
799
800 ??? Note that this is currently an all-or-nothing parser. If we fail to
801 parse the instruction, we return 0 and the caller will start over from
802 the beginning. Backtracking will be necessary in parsing subexpressions,
803 but that can be handled there. Not handling backtracking here may get
804 expensive in the case of the m68k. Deal with later.
805
806 Returns NULL for success, an error message for failure.
807*/
808
809static const char *
617e3d09
DE
810parse_insn_normal (od, insn, strp, fields)
811 CGEN_OPCODE_DESC od;
0bf55db8
DE
812 const CGEN_INSN * insn;
813 const char ** strp;
814 CGEN_FIELDS * fields;
9c03036a 815{
0bf55db8
DE
816 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
817 const char * str = *strp;
818 const char * errmsg;
819 const char * p;
853713a7 820 const unsigned char * syn;
9c03036a 821#ifdef CGEN_MNEMONIC_OPERANDS
fbc8134d 822 /* FIXME: wip */
0bf55db8 823 int past_opcode_p;
9c03036a
DE
824#endif
825
23cf992f 826 /* For now we assume the mnemonic is first (there are no leading operands).
617e3d09
DE
827 We can parse it without needing to set up operand parsing.
828 GAS's input scrubber will ensure mnemonics are lowercase, but we may
829 not be called from GAS. */
23cf992f 830 p = CGEN_INSN_MNEMONIC (insn);
617e3d09
DE
831 while (*p && tolower (*p) == tolower (*str))
832 ++p, ++str;
cbc6c9b2 833
853713a7 834 if (* p || (* str && !isspace (* str)))
cbc6c9b2 835 return _("unrecognized instruction");
9c03036a 836
617e3d09
DE
837 CGEN_INIT_PARSE (od);
838 cgen_init_parse_operand (od);
9c03036a
DE
839#ifdef CGEN_MNEMONIC_OPERANDS
840 past_opcode_p = 0;
841#endif
842
843 /* We don't check for (*str != '\0') here because we want to parse
844 any trailing fake arguments in the syntax string. */
617e3d09 845 syn = CGEN_SYNTAX_STRING (syntax);
0bf55db8 846
23cf992f 847 /* Mnemonics come first for now, ensure valid string. */
853713a7 848 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
23cf992f 849 abort ();
0bf55db8 850
23cf992f 851 ++syn;
0bf55db8 852
853713a7 853 while (* syn != 0)
9c03036a
DE
854 {
855 /* Non operand chars must match exactly. */
853713a7 856 if (CGEN_SYNTAX_CHAR_P (* syn))
9c03036a 857 {
853713a7 858 if (*str == CGEN_SYNTAX_CHAR (* syn))
9c03036a
DE
859 {
860#ifdef CGEN_MNEMONIC_OPERANDS
853713a7 861 if (* syn == ' ')
9c03036a
DE
862 past_opcode_p = 1;
863#endif
853713a7
DE
864 ++ syn;
865 ++ str;
9c03036a
DE
866 }
867 else
868 {
869 /* Syntax char didn't match. Can't be this insn. */
0bf55db8
DE
870 /* FIXME: would like to return something like
871 "expected char `c'" */
cbc6c9b2 872 return _("syntax error");
9c03036a
DE
873 }
874 continue;
875 }
876
877 /* We have an operand of some sort. */
617e3d09
DE
878 errmsg = m32r_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
879 &str, fields);
9c03036a
DE
880 if (errmsg)
881 return errmsg;
882
883 /* Done with this operand, continue with next one. */
853713a7 884 ++ syn;
9c03036a
DE
885 }
886
887 /* If we're at the end of the syntax string, we're done. */
853713a7 888 if (* syn == '\0')
9c03036a
DE
889 {
890 /* FIXME: For the moment we assume a valid `str' can only contain
891 blanks now. IE: We needn't try again with a longer version of
892 the insn and it is assumed that longer versions of insns appear
893 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
853713a7
DE
894 while (isspace (* str))
895 ++ str;
9c03036a 896
853713a7 897 if (* str != '\0')
cbc6c9b2 898 return _("junk at end of line"); /* FIXME: would like to include `str' */
9c03036a
DE
899
900 return NULL;
901 }
902
903 /* We couldn't parse it. */
617e3d09 904 return _("unrecognized instruction");
9c03036a
DE
905}
906
907/* Default insn builder (insert handler).
617e3d09
DE
908 The instruction is recorded in CGEN_INT_INSN_P byte order
909 (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
910 recorded in host byte order, otherwise BUFFER is an array of bytes and the
911 value is recorded in target byte order).
0bf55db8 912 The result is an error message or NULL if success. */
9c03036a 913
0bf55db8 914static const char *
617e3d09
DE
915insert_insn_normal (od, insn, fields, buffer, pc)
916 CGEN_OPCODE_DESC od;
0bf55db8
DE
917 const CGEN_INSN * insn;
918 CGEN_FIELDS * fields;
617e3d09 919 CGEN_INSN_BYTES_PTR buffer;
fbc8134d 920 bfd_vma pc;
9c03036a 921{
0bf55db8 922 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
617e3d09 923 unsigned long value;
853713a7 924 const unsigned char * syn;
9c03036a 925
617e3d09 926 CGEN_INIT_INSERT (od);
23cf992f 927 value = CGEN_INSN_VALUE (insn);
9c03036a
DE
928
929 /* If we're recording insns as numbers (rather than a string of bytes),
930 target byte order handling is deferred until later. */
617e3d09
DE
931
932#if CGEN_INT_INSN_P
933
9c03036a 934 *buffer = value;
617e3d09 935
9c03036a 936#else
617e3d09
DE
937
938 cgen_insn_put_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
939 CGEN_FIELDS_BITSIZE (fields)),
940 value);
941
942#endif /* ! CGEN_INT_INSN_P */
9c03036a
DE
943
944 /* ??? Rather than scanning the syntax string again, we could store
945 in `fields' a null terminated list of the fields that are present. */
946
853713a7 947 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
9c03036a 948 {
0bf55db8
DE
949 const char *errmsg;
950
853713a7 951 if (CGEN_SYNTAX_CHAR_P (* syn))
9c03036a
DE
952 continue;
953
617e3d09
DE
954 errmsg = m32r_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
955 fields, buffer, pc);
0bf55db8
DE
956 if (errmsg)
957 return errmsg;
9c03036a 958 }
0bf55db8
DE
959
960 return NULL;
9c03036a
DE
961}
962\f
963/* Main entry point.
964 This routine is called for each instruction to be assembled.
965 STR points to the insn to be assembled.
966 We assume all necessary tables have been initialized.
617e3d09
DE
967 The assembled instruction, less any fixups, is stored in BUF.
968 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
969 still needs to be converted to target byte order, otherwise BUF is an array
970 of bytes in target byte order.
9c03036a
DE
971 The result is a pointer to the insn's entry in the opcode table,
972 or NULL if an error occured (an error message will have already been
1294c286
DE
973 printed).
974
975 Note that when processing (non-alias) macro-insns,
976 this function recurses. */
9c03036a 977
23cf992f 978const CGEN_INSN *
617e3d09
DE
979m32r_cgen_assemble_insn (od, str, fields, buf, errmsg)
980 CGEN_OPCODE_DESC od;
0bf55db8 981 const char * str;
853713a7 982 CGEN_FIELDS * fields;
617e3d09 983 CGEN_INSN_BYTES_PTR buf;
0bf55db8 984 char ** errmsg;
9c03036a 985{
0bf55db8 986 const char * start;
853713a7 987 CGEN_INSN_LIST * ilist;
9c03036a
DE
988
989 /* Skip leading white space. */
853713a7
DE
990 while (isspace (* str))
991 ++ str;
9c03036a
DE
992
993 /* The instructions are stored in hashed lists.
994 Get the first in the list. */
617e3d09 995 ilist = CGEN_ASM_LOOKUP_INSN (od, str);
9c03036a
DE
996
997 /* Keep looking until we find a match. */
998
999 start = str;
1000 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1001 {
23cf992f 1002 const CGEN_INSN *insn = ilist->insn;
9c03036a
DE
1003
1004#if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
1005 /* Is this insn supported by the selected cpu? */
617e3d09 1006 if (! m32r_cgen_insn_supported (od, insn))
9c03036a
DE
1007 continue;
1008#endif
1009
9c03036a
DE
1010 /* If the RELAX attribute is set, this is an insn that shouldn't be
1011 chosen immediately. Instead, it is used during assembler/linker
1012 relaxation if possible. */
1013 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
1014 continue;
9c03036a
DE
1015
1016 str = start;
1017
1018 /* Record a default length for the insn. This will get set to the
1019 correct value while parsing. */
1020 /* FIXME: wip */
1021 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1022
617e3d09 1023 if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
9c03036a 1024 {
fbc8134d 1025 /* ??? 0 is passed for `pc' */
617e3d09 1026 if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
0bf55db8 1027 continue;
9c03036a
DE
1028 /* It is up to the caller to actually output the insn and any
1029 queued relocs. */
1030 return insn;
1031 }
1032
1033 /* Try the next entry. */
1034 }
1035
5b3b8cb0
DE
1036 /* FIXME: We can return a better error message than this.
1037 Need to track why it failed and pick the right one. */
1038 {
1039 static char errbuf[100];
cbc6c9b2
DE
1040 if (strlen (start) > 50)
1041 /* xgettext:c-format */
1042 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1043 else
1044 /* xgettext:c-format */
1045 sprintf (errbuf, _("bad instruction `%.50s'"), start);
1046
5b3b8cb0
DE
1047 *errmsg = errbuf;
1048 return NULL;
1049 }
9c03036a
DE
1050}
1051\f
5b3b8cb0
DE
1052#if 0 /* This calls back to GAS which we can't do without care. */
1053
9c03036a 1054/* Record each member of OPVALS in the assembler's symbol table.
5b3b8cb0
DE
1055 This lets GAS parse registers for us.
1056 ??? Interesting idea but not currently used. */
9c03036a 1057
23cf992f
NC
1058/* Record each member of OPVALS in the assembler's symbol table.
1059 FIXME: Not currently used. */
1060
9c03036a 1061void
617e3d09
DE
1062m32r_cgen_asm_hash_keywords (od, opvals)
1063 CGEN_OPCODE_DESC od;
853713a7 1064 CGEN_KEYWORD * opvals;
9c03036a 1065{
23cf992f 1066 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
853713a7 1067 const CGEN_KEYWORD_ENTRY * ke;
9c03036a 1068
853713a7 1069 while ((ke = cgen_keyword_search_next (& search)) != NULL)
9c03036a
DE
1070 {
1071#if 0 /* Unnecessary, should be done in the search routine. */
1072 if (! m32r_cgen_opval_supported (ke))
1073 continue;
1074#endif
617e3d09 1075 cgen_asm_record_register (od, ke->name, ke->value);
9c03036a
DE
1076 }
1077}
5b3b8cb0
DE
1078
1079#endif /* 0 */
This page took 0.122454 seconds and 4 git commands to generate.