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