* emultempl/aix.em (gld${EMULATION_NAME}_before_parse): Set
[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
4This file is used to generate m32r-asm.c.
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
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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
DE
32
33/* ??? The layout of this stuff is still work in progress.
34 For speed in assembly/disassembly, we use inline functions. That of course
35 will only work for GCC. When this stuff is finished, we can decide whether
36 to keep the inline functions (and only get the performance increase when
37 compiled with GCC), or switch to macros, or use something else.
38*/
39
1294c286
DE
40static const char * insert_normal
41 PARAMS ((long, unsigned int, int, int, int, char *));
23cf992f
NC
42static const char * parse_insn_normal
43 PARAMS ((const CGEN_INSN *, const char **, CGEN_FIELDS *));
0bf55db8 44static const char * insert_insn_normal
23cf992f 45 PARAMS ((const CGEN_INSN *, CGEN_FIELDS *, cgen_insn_t *));
9c03036a 46\f
1294c286
DE
47/* -- assembler routines inserted here */
48/* -- asm.c */
9c03036a 49
1294c286 50/* Handle '#' prefixes (i.e. skip over them). */
9c03036a 51
0bf55db8 52static const char *
1294c286
DE
53parse_hash (strp, opindex, valuep)
54 const char **strp;
55 int opindex;
56 unsigned long *valuep;
9c03036a 57{
1294c286
DE
58 if (**strp == '#')
59 ++*strp;
0bf55db8 60 return NULL;
9c03036a 61}
853713a7
DE
62
63/* Handle shigh(), high(). */
64
65static const char *
1294c286 66parse_hi16 (strp, opindex, valuep)
853713a7
DE
67 const char **strp;
68 int opindex;
853713a7
DE
69 unsigned long *valuep;
70{
71 const char *errmsg;
72 enum cgen_parse_operand_result result_type;
73
853713a7
DE
74 if (**strp == '#')
75 ++*strp;
76
cbc6c9b2 77 if (strncasecmp (*strp, "high(", 5) == 0)
853713a7
DE
78 {
79 *strp += 5;
80 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_ULO,
81 &result_type, valuep);
82 if (**strp != ')')
83 return "missing `)'";
84 ++*strp;
85 if (errmsg == NULL
86 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
87 *valuep >>= 16;
88 return errmsg;
89 }
cbc6c9b2 90 else if (strncasecmp (*strp, "shigh(", 6) == 0)
853713a7
DE
91 {
92 *strp += 6;
93 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_SLO,
94 &result_type, valuep);
95 if (**strp != ')')
96 return "missing `)'";
97 ++*strp;
98 if (errmsg == NULL
99 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
100 *valuep = (*valuep >> 16) + ((*valuep) & 0x8000 ? 1 : 0);
101 return errmsg;
102 }
103
0bf55db8 104 return cgen_parse_unsigned_integer (strp, opindex, valuep);
853713a7
DE
105}
106
107/* Handle low() in a signed context. Also handle sda().
108 The signedness of the value doesn't matter to low(), but this also
109 handles the case where low() isn't present. */
110
111static const char *
1294c286 112parse_slo16 (strp, opindex, valuep)
853713a7
DE
113 const char **strp;
114 int opindex;
853713a7
DE
115 long *valuep;
116{
117 const char *errmsg;
118 enum cgen_parse_operand_result result_type;
119
853713a7
DE
120 if (**strp == '#')
121 ++*strp;
122
cbc6c9b2 123 if (strncasecmp (*strp, "low(", 4) == 0)
853713a7
DE
124 {
125 *strp += 4;
126 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16,
127 &result_type, valuep);
128 if (**strp != ')')
129 return "missing `)'";
130 ++*strp;
0bf55db8
DE
131 if (errmsg == NULL
132 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
133 *valuep &= 0xffff;
853713a7
DE
134 return errmsg;
135 }
136
cbc6c9b2 137 if (strncasecmp (*strp, "sda(", 4) == 0)
853713a7
DE
138 {
139 *strp += 4;
140 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_SDA16, NULL, valuep);
141 if (**strp != ')')
142 return "missing `)'";
143 ++*strp;
144 return errmsg;
145 }
146
0bf55db8 147 return cgen_parse_signed_integer (strp, opindex, valuep);
853713a7
DE
148}
149
150/* Handle low() in an unsigned context.
151 The signedness of the value doesn't matter to low(), but this also
152 handles the case where low() isn't present. */
153
154static const char *
1294c286 155parse_ulo16 (strp, opindex, valuep)
853713a7
DE
156 const char **strp;
157 int opindex;
853713a7
DE
158 unsigned long *valuep;
159{
160 const char *errmsg;
161 enum cgen_parse_operand_result result_type;
162
853713a7
DE
163 if (**strp == '#')
164 ++*strp;
165
cbc6c9b2 166 if (strncasecmp (*strp, "low(", 4) == 0)
853713a7
DE
167 {
168 *strp += 4;
169 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16,
170 &result_type, valuep);
171 if (**strp != ')')
172 return "missing `)'";
173 ++*strp;
0bf55db8
DE
174 if (errmsg == NULL
175 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
176 *valuep &= 0xffff;
853713a7
DE
177 return errmsg;
178 }
179
0bf55db8 180 return cgen_parse_unsigned_integer (strp, opindex, valuep);
853713a7
DE
181}
182
183/* -- */
184
185/* Main entry point for operand parsing.
186
187 This function is basically just a big switch statement. Earlier versions
188 used tables to look up the function to use, but
189 - if the table contains both assembler and disassembler functions then
190 the disassembler contains much of the assembler and vice-versa,
191 - there's a lot of inlining possibilities as things grow,
192 - using a switch statement avoids the function call overhead.
193
194 This function could be moved into `parse_insn_normal', but keeping it
195 separate makes clear the interface between `parse_insn_normal' and each of
196 the handlers.
197*/
198
0bf55db8 199const char *
853713a7
DE
200m32r_cgen_parse_operand (opindex, strp, fields)
201 int opindex;
202 const char ** strp;
203 CGEN_FIELDS * fields;
204{
205 const char * errmsg;
206
207 switch (opindex)
208 {
209 case M32R_OPERAND_SR :
210 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r2);
211 break;
212 case M32R_OPERAND_DR :
213 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r1);
214 break;
215 case M32R_OPERAND_SRC1 :
216 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r1);
217 break;
218 case M32R_OPERAND_SRC2 :
219 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r2);
220 break;
221 case M32R_OPERAND_SCR :
222 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, & fields->f_r2);
223 break;
224 case M32R_OPERAND_DCR :
225 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, & fields->f_r1);
226 break;
227 case M32R_OPERAND_SIMM8 :
0bf55db8 228 errmsg = cgen_parse_signed_integer (strp, M32R_OPERAND_SIMM8, &fields->f_simm8);
853713a7
DE
229 break;
230 case M32R_OPERAND_SIMM16 :
0bf55db8 231 errmsg = cgen_parse_signed_integer (strp, M32R_OPERAND_SIMM16, &fields->f_simm16);
853713a7
DE
232 break;
233 case M32R_OPERAND_UIMM4 :
0bf55db8 234 errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_UIMM4, &fields->f_uimm4);
853713a7
DE
235 break;
236 case M32R_OPERAND_UIMM5 :
0bf55db8 237 errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_UIMM5, &fields->f_uimm5);
853713a7
DE
238 break;
239 case M32R_OPERAND_UIMM16 :
0bf55db8 240 errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_UIMM16, &fields->f_uimm16);
853713a7 241 break;
ab0bd049
DE
242/* start-sanitize-m32rx */
243 case M32R_OPERAND_IMM1 :
0bf55db8 244 errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_IMM1, &fields->f_imm1);
ab0bd049
DE
245 break;
246/* end-sanitize-m32rx */
247/* start-sanitize-m32rx */
248 case M32R_OPERAND_ACCD :
249 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
250 break;
251/* end-sanitize-m32rx */
252/* start-sanitize-m32rx */
253 case M32R_OPERAND_ACCS :
254 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
255 break;
256/* end-sanitize-m32rx */
257/* start-sanitize-m32rx */
258 case M32R_OPERAND_ACC :
259 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
260 break;
261/* end-sanitize-m32rx */
1294c286
DE
262 case M32R_OPERAND_HASH :
263 errmsg = parse_hash (strp, M32R_OPERAND_HASH, &fields->f_nil);
264 break;
853713a7 265 case M32R_OPERAND_HI16 :
1294c286 266 errmsg = parse_hi16 (strp, M32R_OPERAND_HI16, &fields->f_hi16);
853713a7
DE
267 break;
268 case M32R_OPERAND_SLO16 :
1294c286 269 errmsg = parse_slo16 (strp, M32R_OPERAND_SLO16, &fields->f_simm16);
853713a7
DE
270 break;
271 case M32R_OPERAND_ULO16 :
1294c286 272 errmsg = parse_ulo16 (strp, M32R_OPERAND_ULO16, &fields->f_uimm16);
853713a7
DE
273 break;
274 case M32R_OPERAND_UIMM24 :
0bf55db8 275 errmsg = cgen_parse_address (strp, M32R_OPERAND_UIMM24, 0, NULL, & fields->f_uimm24);
853713a7
DE
276 break;
277 case M32R_OPERAND_DISP8 :
0bf55db8 278 errmsg = cgen_parse_address (strp, M32R_OPERAND_DISP8, 0, NULL, & fields->f_disp8);
853713a7
DE
279 break;
280 case M32R_OPERAND_DISP16 :
0bf55db8 281 errmsg = cgen_parse_address (strp, M32R_OPERAND_DISP16, 0, NULL, & fields->f_disp16);
853713a7
DE
282 break;
283 case M32R_OPERAND_DISP24 :
0bf55db8 284 errmsg = cgen_parse_address (strp, M32R_OPERAND_DISP24, 0, NULL, & fields->f_disp24);
853713a7
DE
285 break;
286
287 default :
cbc6c9b2
DE
288 /* xgettext:c-format */
289 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
853713a7
DE
290 abort ();
291 }
292
293 return errmsg;
294}
295
296/* Main entry point for operand insertion.
297
298 This function is basically just a big switch statement. Earlier versions
299 used tables to look up the function to use, but
300 - if the table contains both assembler and disassembler functions then
301 the disassembler contains much of the assembler and vice-versa,
302 - there's a lot of inlining possibilities as things grow,
303 - using a switch statement avoids the function call overhead.
304
305 This function could be moved into `parse_insn_normal', but keeping it
306 separate makes clear the interface between `parse_insn_normal' and each of
307 the handlers. It's also needed by GAS to insert operands that couldn't be
308 resolved during parsing.
309*/
310
0bf55db8 311const char *
853713a7 312m32r_cgen_insert_operand (opindex, fields, buffer)
5d07b6cf 313 int opindex;
853713a7 314 CGEN_FIELDS * fields;
0bf55db8 315 char * buffer;
853713a7 316{
0bf55db8 317 const char * errmsg;
853713a7
DE
318
319 switch (opindex)
320 {
321 case M32R_OPERAND_SR :
1294c286 322 errmsg = insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
323 break;
324 case M32R_OPERAND_DR :
1294c286 325 errmsg = insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
326 break;
327 case M32R_OPERAND_SRC1 :
1294c286 328 errmsg = insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
329 break;
330 case M32R_OPERAND_SRC2 :
1294c286 331 errmsg = insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
332 break;
333 case M32R_OPERAND_SCR :
1294c286 334 errmsg = insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
335 break;
336 case M32R_OPERAND_DCR :
1294c286 337 errmsg = insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
338 break;
339 case M32R_OPERAND_SIMM8 :
1294c286 340 errmsg = insert_normal (fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
341 break;
342 case M32R_OPERAND_SIMM16 :
1294c286 343 errmsg = insert_normal (fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
344 break;
345 case M32R_OPERAND_UIMM4 :
1294c286 346 errmsg = insert_normal (fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
347 break;
348 case M32R_OPERAND_UIMM5 :
1294c286 349 errmsg = insert_normal (fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
350 break;
351 case M32R_OPERAND_UIMM16 :
1294c286 352 errmsg = insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7 353 break;
ab0bd049
DE
354/* start-sanitize-m32rx */
355 case M32R_OPERAND_IMM1 :
0bf55db8
DE
356 {
357 long value = ((fields->f_imm1) - (1));
1294c286 358 errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 359 }
ab0bd049
DE
360 break;
361/* end-sanitize-m32rx */
362/* start-sanitize-m32rx */
363 case M32R_OPERAND_ACCD :
1294c286 364 errmsg = insert_normal (fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
ab0bd049
DE
365 break;
366/* end-sanitize-m32rx */
367/* start-sanitize-m32rx */
368 case M32R_OPERAND_ACCS :
1294c286 369 errmsg = insert_normal (fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
ab0bd049
DE
370 break;
371/* end-sanitize-m32rx */
372/* start-sanitize-m32rx */
373 case M32R_OPERAND_ACC :
1294c286 374 errmsg = insert_normal (fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, CGEN_FIELDS_BITSIZE (fields), buffer);
ab0bd049
DE
375 break;
376/* end-sanitize-m32rx */
1294c286
DE
377 case M32R_OPERAND_HASH :
378 errmsg = insert_normal (fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
379 break;
853713a7 380 case M32R_OPERAND_HI16 :
1294c286 381 errmsg = insert_normal (fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
382 break;
383 case M32R_OPERAND_SLO16 :
1294c286 384 errmsg = insert_normal (fields->f_simm16, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
385 break;
386 case M32R_OPERAND_ULO16 :
1294c286 387 errmsg = insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
853713a7
DE
388 break;
389 case M32R_OPERAND_UIMM24 :
1294c286 390 errmsg = insert_normal (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
391 break;
392 case M32R_OPERAND_DISP8 :
0bf55db8
DE
393 {
394 long value = ((fields->f_disp8) >> (2));
1294c286 395 errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 396 }
853713a7
DE
397 break;
398 case M32R_OPERAND_DISP16 :
0bf55db8
DE
399 {
400 long value = ((fields->f_disp16) >> (2));
1294c286 401 errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 402 }
853713a7
DE
403 break;
404 case M32R_OPERAND_DISP24 :
0bf55db8
DE
405 {
406 long value = ((fields->f_disp24) >> (2));
1294c286 407 errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, CGEN_FIELDS_BITSIZE (fields), buffer);
0bf55db8 408 }
853713a7
DE
409 break;
410
411 default :
cbc6c9b2
DE
412 /* xgettext:c-format */
413 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
853713a7
DE
414 opindex);
415 abort ();
416 }
417
418 return errmsg;
419}
420
421cgen_parse_fn * m32r_cgen_parse_handlers[] =
5d07b6cf
DE
422{
423 0, /* default */
853713a7
DE
424 parse_insn_normal,
425};
426
427cgen_insert_fn * m32r_cgen_insert_handlers[] =
5d07b6cf
DE
428{
429 0, /* default */
853713a7
DE
430 insert_insn_normal,
431};
432
433void
434m32r_cgen_init_asm (mach, endian)
435 int mach;
436 enum cgen_endian endian;
437{
438 m32r_cgen_init_tables (mach);
1294c286 439 cgen_set_cpu (& m32r_cgen_opcode_table, mach, endian);
853713a7
DE
440 cgen_asm_init ();
441}
442
1294c286
DE
443\f
444/* Default insertion routine.
445
446 ATTRS is a mask of the boolean attributes.
447 LENGTH is the length of VALUE in bits.
448 TOTAL_LENGTH is the total length of the insn (currently 8,16,32).
449
450 The result is an error message or NULL if success. */
451
452/* ??? This duplicates functionality with bfd's howto table and
453 bfd_install_relocation. */
454/* ??? For architectures where insns can be representable as ints,
455 store insn in `field' struct and add registers, etc. while parsing? */
456
457static const char *
458insert_normal (value, attrs, start, length, total_length, buffer)
459 long value;
460 unsigned int attrs;
461 int start;
462 int length;
463 int total_length;
464 char * buffer;
465{
466 bfd_vma x;
467 static char buf[100];
cbc6c9b2
DE
468 /* Written this way to avoid undefined behaviour.
469 Yes, `long' will be bfd_vma but not yet. */
470 long mask = (((1L << (length - 1)) - 1) << 1) | 1;
471
472 /* If LENGTH is zero, this operand doesn't contribute to the value. */
473 if (length == 0)
474 return NULL;
1294c286
DE
475
476 /* Ensure VALUE will fit. */
cbc6c9b2 477 if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
1294c286 478 {
cbc6c9b2 479 unsigned long max = mask;
1294c286
DE
480 if ((unsigned long) value > max)
481 {
cbc6c9b2
DE
482 /* xgettext:c-format */
483 sprintf (buf, _("operand out of range (%lu not between 0 and %lu)"),
484 value, max);
1294c286
DE
485 return buf;
486 }
487 }
488 else
489 {
cbc6c9b2
DE
490 long min = - (1L << (length - 1));
491 long max = (1L << (length - 1)) - 1;
1294c286
DE
492 if (value < min || value > max)
493 {
cbc6c9b2
DE
494 sprintf
495 /* xgettext:c-format */
496 (buf, _("operand out of range (%ld not between %ld and %ld)"),
497 value, min, max);
1294c286
DE
498 return buf;
499 }
500 }
501
502#if 0 /*def CGEN_INT_INSN*/
cbc6c9b2 503 *buffer |= (value & mask) << (total_length - (start + length));
1294c286
DE
504#else
505 switch (total_length)
506 {
507 case 8:
508 x = * (unsigned char *) buffer;
509 break;
510 case 16:
511 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
512 x = bfd_getb16 (buffer);
513 else
514 x = bfd_getl16 (buffer);
515 break;
516 case 32:
517 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
518 x = bfd_getb32 (buffer);
519 else
520 x = bfd_getl32 (buffer);
521 break;
522 default :
523 abort ();
524 }
525
cbc6c9b2 526 x |= (value & mask) << (total_length - (start + length));
1294c286
DE
527
528 switch (total_length)
529 {
530 case 8:
531 * buffer = value;
532 break;
533 case 16:
534 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
535 bfd_putb16 (x, buffer);
536 else
537 bfd_putl16 (x, buffer);
538 break;
539 case 32:
540 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
541 bfd_putb32 (x, buffer);
542 else
543 bfd_putl32 (x, buffer);
544 break;
545 default :
546 abort ();
547 }
548#endif
549
550 return NULL;
551}
9c03036a
DE
552\f
553/* Default insn parser.
554
555 The syntax string is scanned and operands are parsed and stored in FIELDS.
556 Relocs are queued as we go via other callbacks.
557
558 ??? Note that this is currently an all-or-nothing parser. If we fail to
559 parse the instruction, we return 0 and the caller will start over from
560 the beginning. Backtracking will be necessary in parsing subexpressions,
561 but that can be handled there. Not handling backtracking here may get
562 expensive in the case of the m68k. Deal with later.
563
564 Returns NULL for success, an error message for failure.
565*/
566
567static const char *
568parse_insn_normal (insn, strp, fields)
0bf55db8
DE
569 const CGEN_INSN * insn;
570 const char ** strp;
571 CGEN_FIELDS * fields;
9c03036a 572{
0bf55db8
DE
573 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
574 const char * str = *strp;
575 const char * errmsg;
576 const char * p;
853713a7 577 const unsigned char * syn;
9c03036a 578#ifdef CGEN_MNEMONIC_OPERANDS
0bf55db8 579 int past_opcode_p;
9c03036a
DE
580#endif
581
23cf992f
NC
582 /* For now we assume the mnemonic is first (there are no leading operands).
583 We can parse it without needing to set up operand parsing. */
584 p = CGEN_INSN_MNEMONIC (insn);
853713a7
DE
585 while (* p && * p == * str)
586 ++ p, ++ str;
cbc6c9b2 587
853713a7 588 if (* p || (* str && !isspace (* str)))
cbc6c9b2 589 return _("unrecognized instruction");
9c03036a
DE
590
591 CGEN_INIT_PARSE ();
a394e326 592 cgen_init_parse_operand ();
9c03036a
DE
593#ifdef CGEN_MNEMONIC_OPERANDS
594 past_opcode_p = 0;
595#endif
596
597 /* We don't check for (*str != '\0') here because we want to parse
598 any trailing fake arguments in the syntax string. */
23cf992f 599 syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn));
0bf55db8 600
23cf992f 601 /* Mnemonics come first for now, ensure valid string. */
853713a7 602 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
23cf992f 603 abort ();
0bf55db8 604
23cf992f 605 ++syn;
0bf55db8 606
853713a7 607 while (* syn != 0)
9c03036a
DE
608 {
609 /* Non operand chars must match exactly. */
610 /* FIXME: Need to better handle whitespace. */
853713a7 611 if (CGEN_SYNTAX_CHAR_P (* syn))
9c03036a 612 {
853713a7 613 if (*str == CGEN_SYNTAX_CHAR (* syn))
9c03036a
DE
614 {
615#ifdef CGEN_MNEMONIC_OPERANDS
853713a7 616 if (* syn == ' ')
9c03036a
DE
617 past_opcode_p = 1;
618#endif
853713a7
DE
619 ++ syn;
620 ++ str;
9c03036a
DE
621 }
622 else
623 {
624 /* Syntax char didn't match. Can't be this insn. */
0bf55db8
DE
625 /* FIXME: would like to return something like
626 "expected char `c'" */
cbc6c9b2 627 return _("syntax error");
9c03036a
DE
628 }
629 continue;
630 }
631
632 /* We have an operand of some sort. */
633 errmsg = m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn),
634 &str, fields);
635 if (errmsg)
636 return errmsg;
637
638 /* Done with this operand, continue with next one. */
853713a7 639 ++ syn;
9c03036a
DE
640 }
641
642 /* If we're at the end of the syntax string, we're done. */
853713a7 643 if (* syn == '\0')
9c03036a
DE
644 {
645 /* FIXME: For the moment we assume a valid `str' can only contain
646 blanks now. IE: We needn't try again with a longer version of
647 the insn and it is assumed that longer versions of insns appear
648 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
853713a7
DE
649 while (isspace (* str))
650 ++ str;
9c03036a 651
853713a7 652 if (* str != '\0')
cbc6c9b2 653 return _("junk at end of line"); /* FIXME: would like to include `str' */
9c03036a
DE
654
655 return NULL;
656 }
657
658 /* We couldn't parse it. */
659 return "unrecognized instruction";
660}
661
662/* Default insn builder (insert handler).
0bf55db8
DE
663 The instruction is recorded in target byte order.
664 The result is an error message or NULL if success. */
665/* FIXME: change buffer to char *? */
9c03036a 666
0bf55db8 667static const char *
9c03036a 668insert_insn_normal (insn, fields, buffer)
0bf55db8
DE
669 const CGEN_INSN * insn;
670 CGEN_FIELDS * fields;
671 cgen_insn_t * buffer;
9c03036a 672{
0bf55db8
DE
673 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
674 bfd_vma value;
853713a7 675 const unsigned char * syn;
9c03036a
DE
676
677 CGEN_INIT_INSERT ();
23cf992f 678 value = CGEN_INSN_VALUE (insn);
9c03036a
DE
679
680 /* If we're recording insns as numbers (rather than a string of bytes),
681 target byte order handling is deferred until later. */
682#undef min
683#define min(a,b) ((a) < (b) ? (a) : (b))
684#if 0 /*def CGEN_INT_INSN*/
685 *buffer = value;
686#else
687 switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)))
688 {
689 case 8:
853713a7 690 * buffer = value;
9c03036a
DE
691 break;
692 case 16:
693 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
694 bfd_putb16 (value, (char *) buffer);
695 else
696 bfd_putl16 (value, (char *) buffer);
697 break;
698 case 32:
699 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
700 bfd_putb32 (value, (char *) buffer);
701 else
702 bfd_putl32 (value, (char *) buffer);
703 break;
704 default:
705 abort ();
706 }
707#endif
708
709 /* ??? Rather than scanning the syntax string again, we could store
710 in `fields' a null terminated list of the fields that are present. */
711
853713a7 712 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
9c03036a 713 {
0bf55db8
DE
714 const char *errmsg;
715
853713a7 716 if (CGEN_SYNTAX_CHAR_P (* syn))
9c03036a
DE
717 continue;
718
0bf55db8
DE
719 errmsg = m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields,
720 (char *) buffer);
721 if (errmsg)
722 return errmsg;
9c03036a 723 }
0bf55db8
DE
724
725 return NULL;
9c03036a
DE
726}
727\f
728/* Main entry point.
729 This routine is called for each instruction to be assembled.
730 STR points to the insn to be assembled.
731 We assume all necessary tables have been initialized.
1294c286
DE
732 The assembled instruction, less any fixups, is stored in buf.
733 [??? What byte order?]
9c03036a
DE
734 The result is a pointer to the insn's entry in the opcode table,
735 or NULL if an error occured (an error message will have already been
1294c286
DE
736 printed).
737
738 Note that when processing (non-alias) macro-insns,
739 this function recurses. */
9c03036a 740
23cf992f 741const CGEN_INSN *
5b3b8cb0 742m32r_cgen_assemble_insn (str, fields, buf, errmsg)
0bf55db8 743 const char * str;
853713a7
DE
744 CGEN_FIELDS * fields;
745 cgen_insn_t * buf;
0bf55db8 746 char ** errmsg;
9c03036a 747{
0bf55db8 748 const char * start;
853713a7 749 CGEN_INSN_LIST * ilist;
9c03036a
DE
750
751 /* Skip leading white space. */
853713a7
DE
752 while (isspace (* str))
753 ++ str;
9c03036a
DE
754
755 /* The instructions are stored in hashed lists.
756 Get the first in the list. */
757 ilist = CGEN_ASM_LOOKUP_INSN (str);
758
759 /* Keep looking until we find a match. */
760
761 start = str;
762 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
763 {
23cf992f 764 const CGEN_INSN *insn = ilist->insn;
9c03036a
DE
765
766#if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
767 /* Is this insn supported by the selected cpu? */
768 if (! m32r_cgen_insn_supported (insn))
769 continue;
770#endif
771
772#if 1 /* FIXME: wip */
773 /* If the RELAX attribute is set, this is an insn that shouldn't be
774 chosen immediately. Instead, it is used during assembler/linker
775 relaxation if possible. */
776 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
777 continue;
778#endif
779
780 str = start;
781
782 /* Record a default length for the insn. This will get set to the
783 correct value while parsing. */
784 /* FIXME: wip */
785 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
786
853713a7 787 if (! CGEN_PARSE_FN (insn) (insn, & str, fields))
9c03036a 788 {
0bf55db8
DE
789 if (CGEN_INSERT_FN (insn) (insn, fields, buf) != NULL)
790 continue;
9c03036a
DE
791 /* It is up to the caller to actually output the insn and any
792 queued relocs. */
793 return insn;
794 }
795
796 /* Try the next entry. */
797 }
798
5b3b8cb0
DE
799 /* FIXME: We can return a better error message than this.
800 Need to track why it failed and pick the right one. */
801 {
802 static char errbuf[100];
cbc6c9b2
DE
803 if (strlen (start) > 50)
804 /* xgettext:c-format */
805 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
806 else
807 /* xgettext:c-format */
808 sprintf (errbuf, _("bad instruction `%.50s'"), start);
809
5b3b8cb0
DE
810 *errmsg = errbuf;
811 return NULL;
812 }
9c03036a
DE
813}
814\f
5b3b8cb0
DE
815#if 0 /* This calls back to GAS which we can't do without care. */
816
9c03036a 817/* Record each member of OPVALS in the assembler's symbol table.
5b3b8cb0
DE
818 This lets GAS parse registers for us.
819 ??? Interesting idea but not currently used. */
9c03036a 820
23cf992f
NC
821/* Record each member of OPVALS in the assembler's symbol table.
822 FIXME: Not currently used. */
823
9c03036a
DE
824void
825m32r_cgen_asm_hash_keywords (opvals)
853713a7 826 CGEN_KEYWORD * opvals;
9c03036a 827{
23cf992f 828 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
853713a7 829 const CGEN_KEYWORD_ENTRY * ke;
9c03036a 830
853713a7 831 while ((ke = cgen_keyword_search_next (& search)) != NULL)
9c03036a
DE
832 {
833#if 0 /* Unnecessary, should be done in the search routine. */
834 if (! m32r_cgen_opval_supported (ke))
835 continue;
836#endif
837 cgen_asm_record_register (ke->name, ke->value);
838 }
839}
5b3b8cb0
DE
840
841#endif /* 0 */
This page took 0.100663 seconds and 4 git commands to generate.