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