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