tc-cr16.c revision 1.1.1.6 1 1.1 christos /* tc-cr16.c -- Assembler code for the CR16 CPU core.
2 1.1.1.6 christos Copyright (C) 2007-2022 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Contributed by M R Swami Reddy <MR.Swami.Reddy (at) nsc.com>
5 1.1 christos
6 1.1 christos This file is part of GAS, the GNU Assembler.
7 1.1 christos
8 1.1 christos GAS is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3, or (at your option)
11 1.1 christos any later version.
12 1.1 christos
13 1.1 christos GAS is distributed in the hope that it will be useful,
14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 christos GNU General Public License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with GAS; see the file COPYING. If not, write to the
20 1.1 christos Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21 1.1 christos MA 02110-1301, USA. */
22 1.1 christos
23 1.1 christos #include "as.h"
24 1.1 christos #include "safe-ctype.h"
25 1.1 christos #include "dwarf2dbg.h"
26 1.1 christos #include "opcode/cr16.h"
27 1.1 christos #include "elf/cr16.h"
28 1.1 christos
29 1.1.1.6 christos #include <limits.h>
30 1.1.1.6 christos #ifndef CHAR_BIT
31 1.1.1.6 christos #define CHAR_BIT 8
32 1.1.1.6 christos #endif
33 1.1 christos
34 1.1 christos /* Word is considered here as a 16-bit unsigned short int. */
35 1.1 christos #define WORD_SHIFT 16
36 1.1 christos
37 1.1 christos /* Register is 2-byte size. */
38 1.1 christos #define REG_SIZE 2
39 1.1 christos
40 1.1 christos /* Maximum size of a single instruction (in words). */
41 1.1 christos #define INSN_MAX_SIZE 3
42 1.1 christos
43 1.1 christos /* Maximum bits which may be set in a `mask16' operand. */
44 1.1 christos #define MAX_REGS_IN_MASK16 8
45 1.1 christos
46 1.1 christos /* Assign a number NUM, shifted by SHIFT bytes, into a location
47 1.1 christos pointed by index BYTE of array 'output_opcode'. */
48 1.1.1.6 christos #define CR16_PRINT(BYTE, NUM, SHIFT) output_opcode[BYTE] |= (NUM) << (SHIFT)
49 1.1 christos
50 1.1 christos /* Operand errors. */
51 1.1 christos typedef enum
52 1.1 christos {
53 1.1 christos OP_LEGAL = 0, /* Legal operand. */
54 1.1 christos OP_OUT_OF_RANGE, /* Operand not within permitted range. */
55 1.1 christos OP_NOT_EVEN /* Operand is Odd number, should be even. */
56 1.1 christos }
57 1.1 christos op_err;
58 1.1 christos
59 1.1 christos /* Opcode mnemonics hash table. */
60 1.1.1.6 christos static htab_t cr16_inst_hash;
61 1.1 christos /* CR16 registers hash table. */
62 1.1.1.6 christos static htab_t reg_hash;
63 1.1 christos /* CR16 register pair hash table. */
64 1.1.1.6 christos static htab_t regp_hash;
65 1.1 christos /* CR16 processor registers hash table. */
66 1.1.1.6 christos static htab_t preg_hash;
67 1.1 christos /* CR16 processor registers 32 bit hash table. */
68 1.1.1.6 christos static htab_t pregp_hash;
69 1.1 christos /* Current instruction we're assembling. */
70 1.1 christos const inst *instruction;
71 1.1 christos
72 1.1 christos
73 1.1 christos static int code_label = 0;
74 1.1 christos
75 1.1 christos /* Global variables. */
76 1.1 christos
77 1.1 christos /* Array to hold an instruction encoding. */
78 1.1 christos long output_opcode[2];
79 1.1 christos
80 1.1 christos /* Nonzero means a relocatable symbol. */
81 1.1 christos int relocatable;
82 1.1 christos
83 1.1 christos /* A copy of the original instruction (used in error messages). */
84 1.1 christos char ins_parse[MAX_INST_LEN];
85 1.1 christos
86 1.1 christos /* The current processed argument number. */
87 1.1 christos int cur_arg_num;
88 1.1 christos
89 1.1 christos /* Generic assembler global variables which must be defined by all targets. */
90 1.1 christos
91 1.1 christos /* Characters which always start a comment. */
92 1.1 christos const char comment_chars[] = "#";
93 1.1 christos
94 1.1 christos /* Characters which start a comment at the beginning of a line. */
95 1.1 christos const char line_comment_chars[] = "#";
96 1.1 christos
97 1.1 christos /* This array holds machine specific line separator characters. */
98 1.1 christos const char line_separator_chars[] = ";";
99 1.1 christos
100 1.1 christos /* Chars that can be used to separate mant from exp in floating point nums. */
101 1.1 christos const char EXP_CHARS[] = "eE";
102 1.1 christos
103 1.1 christos /* Chars that mean this number is a floating point constant as in 0f12.456 */
104 1.1 christos const char FLT_CHARS[] = "f'";
105 1.1 christos
106 1.1 christos #ifdef OBJ_ELF
107 1.1 christos /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
108 1.1 christos symbolS * GOT_symbol;
109 1.1 christos #endif
110 1.1 christos
111 1.1 christos /* Target-specific multicharacter options, not const-declared at usage. */
112 1.1 christos const char *md_shortopts = "";
113 1.1 christos struct option md_longopts[] =
114 1.1 christos {
115 1.1 christos {NULL, no_argument, NULL, 0}
116 1.1 christos };
117 1.1 christos size_t md_longopts_size = sizeof (md_longopts);
118 1.1 christos
119 1.1 christos static void
120 1.1 christos l_cons (int nbytes)
121 1.1 christos {
122 1.1 christos int c;
123 1.1 christos expressionS exp;
124 1.1 christos
125 1.1 christos #ifdef md_flush_pending_output
126 1.1.1.6 christos md_flush_pending_output ();
127 1.1 christos #endif
128 1.1 christos
129 1.1 christos if (is_it_end_of_statement ())
130 1.1 christos {
131 1.1 christos demand_empty_rest_of_line ();
132 1.1 christos return;
133 1.1 christos }
134 1.1 christos
135 1.1 christos #ifdef TC_ADDRESS_BYTES
136 1.1 christos if (nbytes == 0)
137 1.1 christos nbytes = TC_ADDRESS_BYTES ();
138 1.1 christos #endif
139 1.1 christos
140 1.1 christos #ifdef md_cons_align
141 1.1 christos md_cons_align (nbytes);
142 1.1 christos #endif
143 1.1 christos
144 1.1 christos c = 0;
145 1.1 christos do
146 1.1 christos {
147 1.1 christos unsigned int bits_available = BITS_PER_CHAR * nbytes;
148 1.1 christos char *hold = input_line_pointer;
149 1.1 christos
150 1.1 christos expression (&exp);
151 1.1 christos
152 1.1 christos if (*input_line_pointer == ':')
153 1.1.1.6 christos {
154 1.1.1.6 christos /* Bitfields. */
155 1.1.1.6 christos long value = 0;
156 1.1.1.6 christos
157 1.1.1.6 christos for (;;)
158 1.1.1.6 christos {
159 1.1.1.6 christos unsigned long width;
160 1.1.1.6 christos
161 1.1.1.6 christos if (*input_line_pointer != ':')
162 1.1.1.6 christos {
163 1.1.1.6 christos input_line_pointer = hold;
164 1.1.1.6 christos break;
165 1.1.1.6 christos }
166 1.1.1.6 christos if (exp.X_op == O_absent)
167 1.1.1.6 christos {
168 1.1.1.6 christos as_warn (_("using a bit field width of zero"));
169 1.1.1.6 christos exp.X_add_number = 0;
170 1.1.1.6 christos exp.X_op = O_constant;
171 1.1.1.6 christos }
172 1.1.1.6 christos
173 1.1.1.6 christos if (exp.X_op != O_constant)
174 1.1.1.6 christos {
175 1.1.1.6 christos *input_line_pointer = '\0';
176 1.1.1.6 christos as_bad (_("field width \"%s\" too complex for a bitfield"),
177 1.1.1.6 christos hold);
178 1.1.1.6 christos *input_line_pointer = ':';
179 1.1.1.6 christos demand_empty_rest_of_line ();
180 1.1.1.6 christos return;
181 1.1.1.6 christos }
182 1.1.1.6 christos
183 1.1.1.6 christos if ((width = exp.X_add_number) >
184 1.1.1.6 christos (unsigned int)(BITS_PER_CHAR * nbytes))
185 1.1.1.6 christos {
186 1.1.1.4 christos as_warn (ngettext ("field width %lu too big to fit in %d"
187 1.1.1.4 christos " byte: truncated to %d bits",
188 1.1.1.4 christos "field width %lu too big to fit in %d"
189 1.1.1.4 christos " bytes: truncated to %d bits",
190 1.1.1.4 christos nbytes),
191 1.1.1.4 christos width, nbytes, (BITS_PER_CHAR * nbytes));
192 1.1.1.6 christos width = BITS_PER_CHAR * nbytes;
193 1.1.1.6 christos }
194 1.1.1.6 christos
195 1.1.1.6 christos if (width > bits_available)
196 1.1.1.6 christos {
197 1.1.1.6 christos /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */
198 1.1.1.6 christos input_line_pointer = hold;
199 1.1.1.6 christos exp.X_add_number = value;
200 1.1.1.6 christos break;
201 1.1.1.6 christos }
202 1.1.1.6 christos
203 1.1.1.6 christos /* Skip ':'. */
204 1.1.1.6 christos hold = ++input_line_pointer;
205 1.1.1.6 christos
206 1.1.1.6 christos expression (&exp);
207 1.1.1.6 christos if (exp.X_op != O_constant)
208 1.1.1.6 christos {
209 1.1.1.6 christos char cache = *input_line_pointer;
210 1.1.1.6 christos
211 1.1.1.6 christos *input_line_pointer = '\0';
212 1.1.1.6 christos as_bad (_("field value \"%s\" too complex for a bitfield"),
213 1.1.1.6 christos hold);
214 1.1.1.6 christos *input_line_pointer = cache;
215 1.1.1.6 christos demand_empty_rest_of_line ();
216 1.1.1.6 christos return;
217 1.1.1.6 christos }
218 1.1.1.6 christos
219 1.1.1.6 christos value |= ((~(-(1 << width)) & exp.X_add_number)
220 1.1.1.6 christos << ((BITS_PER_CHAR * nbytes) - bits_available));
221 1.1.1.6 christos
222 1.1.1.6 christos if ((bits_available -= width) == 0
223 1.1.1.6 christos || is_it_end_of_statement ()
224 1.1.1.6 christos || *input_line_pointer != ',')
225 1.1.1.6 christos break;
226 1.1 christos
227 1.1.1.6 christos hold = ++input_line_pointer;
228 1.1.1.6 christos expression (&exp);
229 1.1.1.6 christos }
230 1.1 christos
231 1.1.1.6 christos exp.X_add_number = value;
232 1.1.1.6 christos exp.X_op = O_constant;
233 1.1.1.6 christos exp.X_unsigned = 1;
234 1.1.1.6 christos }
235 1.1 christos
236 1.1 christos if ((*(input_line_pointer) == '@') && (*(input_line_pointer +1) == 'c'))
237 1.1.1.6 christos code_label = 1;
238 1.1 christos emit_expr (&exp, (unsigned int) nbytes);
239 1.1 christos ++c;
240 1.1 christos if ((*(input_line_pointer) == '@') && (*(input_line_pointer +1) == 'c'))
241 1.1.1.6 christos {
242 1.1.1.6 christos input_line_pointer +=3;
243 1.1.1.6 christos break;
244 1.1.1.6 christos }
245 1.1 christos }
246 1.1 christos while ((*input_line_pointer++ == ','));
247 1.1 christos
248 1.1 christos /* Put terminator back into stream. */
249 1.1 christos input_line_pointer--;
250 1.1 christos
251 1.1 christos demand_empty_rest_of_line ();
252 1.1 christos }
253 1.1 christos
254 1.1 christos /* This table describes all the machine specific pseudo-ops
255 1.1 christos the assembler has to support. The fields are:
256 1.1 christos *** Pseudo-op name without dot.
257 1.1 christos *** Function to call to execute this pseudo-op.
258 1.1 christos *** Integer arg to pass to the function. */
259 1.1 christos
260 1.1 christos const pseudo_typeS md_pseudo_table[] =
261 1.1 christos {
262 1.1 christos /* In CR16 machine, align is in bytes (not a ptwo boundary). */
263 1.1 christos {"align", s_align_bytes, 0},
264 1.1 christos {"long", l_cons, 4 },
265 1.1 christos {"4byte", l_cons, 4 },
266 1.1 christos {0, 0, 0}
267 1.1 christos };
268 1.1 christos
269 1.1 christos /* CR16 relaxation table. */
270 1.1 christos const relax_typeS md_relax_table[] =
271 1.1 christos {
272 1.1 christos /* bCC */
273 1.1 christos {0x7f, -0x80, 2, 1}, /* 8 */
274 1.1 christos {0xfffe, -0x10000, 4, 2}, /* 16 */
275 1.1 christos {0xfffffe, -0x1000000, 6, 0}, /* 24 */
276 1.1 christos };
277 1.1 christos
278 1.1 christos /* Return the bit size for a given operand. */
279 1.1 christos
280 1.1 christos static int
281 1.1 christos get_opbits (operand_type op)
282 1.1 christos {
283 1.1 christos if (op < MAX_OPRD)
284 1.1 christos return cr16_optab[op].bit_size;
285 1.1 christos
286 1.1 christos return 0;
287 1.1 christos }
288 1.1 christos
289 1.1 christos /* Return the argument type of a given operand. */
290 1.1 christos
291 1.1 christos static argtype
292 1.1 christos get_optype (operand_type op)
293 1.1 christos {
294 1.1 christos if (op < MAX_OPRD)
295 1.1 christos return cr16_optab[op].arg_type;
296 1.1 christos else
297 1.1 christos return nullargs;
298 1.1 christos }
299 1.1 christos
300 1.1 christos /* Return the flags of a given operand. */
301 1.1 christos
302 1.1 christos static int
303 1.1 christos get_opflags (operand_type op)
304 1.1 christos {
305 1.1 christos if (op < MAX_OPRD)
306 1.1 christos return cr16_optab[op].flags;
307 1.1 christos
308 1.1 christos return 0;
309 1.1 christos }
310 1.1 christos
311 1.1 christos /* Get the cc code. */
312 1.1 christos
313 1.1 christos static int
314 1.1 christos get_cc (char *cc_name)
315 1.1 christos {
316 1.1 christos unsigned int i;
317 1.1 christos
318 1.1 christos for (i = 0; i < cr16_num_cc; i++)
319 1.1 christos if (strcmp (cc_name, cr16_b_cond_tab[i]) == 0)
320 1.1 christos return i;
321 1.1 christos
322 1.1 christos return -1;
323 1.1 christos }
324 1.1 christos
325 1.1 christos /* Get the core processor register 'reg_name'. */
326 1.1 christos
327 1.1 christos static reg
328 1.1 christos get_register (char *reg_name)
329 1.1 christos {
330 1.1 christos const reg_entry *rreg;
331 1.1 christos
332 1.1.1.6 christos rreg = (const reg_entry *) str_hash_find (reg_hash, reg_name);
333 1.1 christos
334 1.1 christos if (rreg != NULL)
335 1.1 christos return rreg->value.reg_val;
336 1.1 christos
337 1.1 christos return nullregister;
338 1.1 christos }
339 1.1 christos /* Get the core processor register-pair 'reg_name'. */
340 1.1 christos
341 1.1 christos static reg
342 1.1 christos get_register_pair (char *reg_name)
343 1.1 christos {
344 1.1 christos const reg_entry *rreg;
345 1.1 christos char tmp_rp[16]="\0";
346 1.1 christos
347 1.1.1.4 christos /* Add '(' and ')' to the reg pair, if it's not present. */
348 1.1.1.2 christos if (reg_name[0] != '(')
349 1.1 christos {
350 1.1 christos tmp_rp[0] = '(';
351 1.1 christos strcat (tmp_rp, reg_name);
352 1.1 christos strcat (tmp_rp,")");
353 1.1.1.6 christos rreg = (const reg_entry *) str_hash_find (regp_hash, tmp_rp);
354 1.1 christos }
355 1.1 christos else
356 1.1.1.6 christos rreg = (const reg_entry *) str_hash_find (regp_hash, reg_name);
357 1.1 christos
358 1.1 christos if (rreg != NULL)
359 1.1 christos return rreg->value.reg_val;
360 1.1 christos
361 1.1 christos return nullregister;
362 1.1.1.2 christos }
363 1.1 christos
364 1.1 christos /* Get the index register 'reg_name'. */
365 1.1 christos
366 1.1 christos static reg
367 1.1 christos get_index_register (char *reg_name)
368 1.1 christos {
369 1.1 christos const reg_entry *rreg;
370 1.1 christos
371 1.1.1.6 christos rreg = (const reg_entry *) str_hash_find (reg_hash, reg_name);
372 1.1 christos
373 1.1 christos if ((rreg != NULL)
374 1.1 christos && ((rreg->value.reg_val == 12) || (rreg->value.reg_val == 13)))
375 1.1 christos return rreg->value.reg_val;
376 1.1 christos
377 1.1 christos return nullregister;
378 1.1 christos }
379 1.1 christos /* Get the core processor index register-pair 'reg_name'. */
380 1.1 christos
381 1.1 christos static reg
382 1.1 christos get_index_register_pair (char *reg_name)
383 1.1 christos {
384 1.1 christos const reg_entry *rreg;
385 1.1 christos
386 1.1.1.6 christos rreg = (const reg_entry *) str_hash_find (regp_hash, reg_name);
387 1.1 christos
388 1.1 christos if (rreg != NULL)
389 1.1 christos {
390 1.1 christos if ((rreg->value.reg_val != 1) || (rreg->value.reg_val != 7)
391 1.1.1.6 christos || (rreg->value.reg_val != 9) || (rreg->value.reg_val > 10))
392 1.1.1.6 christos return rreg->value.reg_val;
393 1.1 christos
394 1.1 christos as_bad (_("Unknown register pair - index relative mode: `%d'"), rreg->value.reg_val);
395 1.1 christos }
396 1.1 christos
397 1.1 christos return nullregister;
398 1.1 christos }
399 1.1 christos
400 1.1 christos /* Get the processor register 'preg_name'. */
401 1.1 christos
402 1.1 christos static preg
403 1.1 christos get_pregister (char *preg_name)
404 1.1 christos {
405 1.1 christos const reg_entry *prreg;
406 1.1 christos
407 1.1.1.6 christos prreg = (const reg_entry *) str_hash_find (preg_hash, preg_name);
408 1.1 christos
409 1.1 christos if (prreg != NULL)
410 1.1 christos return prreg->value.preg_val;
411 1.1 christos
412 1.1 christos return nullpregister;
413 1.1 christos }
414 1.1 christos
415 1.1 christos /* Get the processor register 'preg_name 32 bit'. */
416 1.1 christos
417 1.1 christos static preg
418 1.1 christos get_pregisterp (char *preg_name)
419 1.1 christos {
420 1.1 christos const reg_entry *prreg;
421 1.1 christos
422 1.1.1.6 christos prreg = (const reg_entry *) str_hash_find (pregp_hash, preg_name);
423 1.1 christos
424 1.1 christos if (prreg != NULL)
425 1.1 christos return prreg->value.preg_val;
426 1.1 christos
427 1.1 christos return nullpregister;
428 1.1 christos }
429 1.1 christos
430 1.1 christos
431 1.1 christos /* Round up a section size to the appropriate boundary. */
432 1.1 christos
433 1.1 christos valueT
434 1.1 christos md_section_align (segT seg, valueT val)
435 1.1 christos {
436 1.1 christos /* Round .text section to a multiple of 2. */
437 1.1 christos if (seg == text_section)
438 1.1 christos return (val + 1) & ~1;
439 1.1 christos return val;
440 1.1 christos }
441 1.1 christos
442 1.1 christos /* Parse an operand that is machine-specific (remove '*'). */
443 1.1 christos
444 1.1 christos void
445 1.1 christos md_operand (expressionS * exp)
446 1.1 christos {
447 1.1 christos char c = *input_line_pointer;
448 1.1 christos
449 1.1 christos switch (c)
450 1.1 christos {
451 1.1 christos case '*':
452 1.1 christos input_line_pointer++;
453 1.1 christos expression (exp);
454 1.1 christos break;
455 1.1 christos default:
456 1.1 christos break;
457 1.1 christos }
458 1.1 christos }
459 1.1 christos
460 1.1 christos /* Reset global variables before parsing a new instruction. */
461 1.1 christos
462 1.1 christos static void
463 1.1 christos reset_vars (char *op)
464 1.1 christos {
465 1.1 christos cur_arg_num = relocatable = 0;
466 1.1 christos memset (& output_opcode, '\0', sizeof (output_opcode));
467 1.1 christos
468 1.1 christos /* Save a copy of the original OP (used in error messages). */
469 1.1 christos strncpy (ins_parse, op, sizeof ins_parse - 1);
470 1.1 christos ins_parse [sizeof ins_parse - 1] = 0;
471 1.1 christos }
472 1.1 christos
473 1.1 christos /* This macro decides whether a particular reloc is an entry in a
474 1.1 christos switch table. It is used when relaxing, because the linker needs
475 1.1 christos to know about all such entries so that it can adjust them if
476 1.1 christos necessary. */
477 1.1 christos
478 1.1.1.6 christos #define SWITCH_TABLE(fix) \
479 1.1.1.6 christos ((fix)->fx_addsy != NULL \
480 1.1.1.6 christos && (fix)->fx_subsy != NULL \
481 1.1.1.6 christos && ((fix)->fx_r_type == BFD_RELOC_CR16_NUM8 \
482 1.1.1.6 christos || (fix)->fx_r_type == BFD_RELOC_CR16_NUM16 \
483 1.1.1.6 christos || (fix)->fx_r_type == BFD_RELOC_CR16_NUM32 \
484 1.1.1.6 christos || (fix)->fx_r_type == BFD_RELOC_CR16_NUM32a) \
485 1.1.1.6 christos && S_GET_SEGMENT ((fix)->fx_addsy) != undefined_section \
486 1.1.1.6 christos && S_GET_SEGMENT ((fix)->fx_addsy) == S_GET_SEGMENT ((fix)->fx_subsy))
487 1.1 christos
488 1.1 christos /* See whether we need to force a relocation into the output file.
489 1.1 christos This is used to force out switch and PC relative relocations when
490 1.1 christos relaxing. */
491 1.1 christos
492 1.1 christos int
493 1.1 christos cr16_force_relocation (fixS *fix)
494 1.1 christos {
495 1.1 christos if (generic_force_reloc (fix) || SWITCH_TABLE (fix))
496 1.1 christos return 1;
497 1.1 christos
498 1.1 christos return 0;
499 1.1 christos }
500 1.1 christos
501 1.1 christos /* Record a fixup for a cons expression. */
502 1.1 christos
503 1.1 christos void
504 1.1.1.2 christos cr16_cons_fix_new (fragS *frag, int offset, int len, expressionS *exp,
505 1.1.1.2 christos bfd_reloc_code_real_type rtype)
506 1.1 christos {
507 1.1 christos switch (len)
508 1.1 christos {
509 1.1 christos default: rtype = BFD_RELOC_NONE; break;
510 1.1 christos case 1: rtype = BFD_RELOC_CR16_NUM8 ; break;
511 1.1 christos case 2: rtype = BFD_RELOC_CR16_NUM16; break;
512 1.1 christos case 4:
513 1.1 christos if (code_label)
514 1.1.1.6 christos {
515 1.1.1.6 christos rtype = BFD_RELOC_CR16_NUM32a;
516 1.1.1.6 christos code_label = 0;
517 1.1.1.6 christos }
518 1.1 christos else
519 1.1.1.6 christos rtype = BFD_RELOC_CR16_NUM32;
520 1.1 christos break;
521 1.1 christos }
522 1.1 christos
523 1.1 christos fix_new_exp (frag, offset, len, exp, 0, rtype);
524 1.1 christos }
525 1.1 christos
526 1.1 christos /* Generate a relocation entry for a fixup. */
527 1.1 christos
528 1.1 christos arelent *
529 1.1 christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
530 1.1 christos {
531 1.1 christos arelent * reloc;
532 1.1 christos
533 1.1 christos /* If symbols are local and resolved, then no relocation needed. */
534 1.1.1.2 christos if ( ((fixP->fx_addsy)
535 1.1.1.6 christos && (S_GET_SEGMENT (fixP->fx_addsy) == absolute_section))
536 1.1.1.2 christos || ((fixP->fx_subsy)
537 1.1 christos && (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)))
538 1.1.1.6 christos return NULL;
539 1.1 christos
540 1.1.1.3 christos reloc = XNEW (arelent);
541 1.1.1.3 christos reloc->sym_ptr_ptr = XNEW (asymbol *);
542 1.1 christos *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
543 1.1 christos reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
544 1.1 christos reloc->addend = fixP->fx_offset;
545 1.1 christos
546 1.1 christos if (fixP->fx_subsy != NULL)
547 1.1 christos {
548 1.1 christos if (SWITCH_TABLE (fixP))
549 1.1 christos {
550 1.1.1.6 christos /* Keep the current difference in the addend. */
551 1.1.1.6 christos reloc->addend = (S_GET_VALUE (fixP->fx_addsy)
552 1.1.1.6 christos - S_GET_VALUE (fixP->fx_subsy) + fixP->fx_offset);
553 1.1.1.6 christos
554 1.1.1.6 christos switch (fixP->fx_r_type)
555 1.1.1.6 christos {
556 1.1.1.6 christos case BFD_RELOC_CR16_NUM8:
557 1.1.1.6 christos fixP->fx_r_type = BFD_RELOC_CR16_SWITCH8;
558 1.1.1.6 christos break;
559 1.1.1.6 christos case BFD_RELOC_CR16_NUM16:
560 1.1.1.6 christos fixP->fx_r_type = BFD_RELOC_CR16_SWITCH16;
561 1.1.1.6 christos break;
562 1.1.1.6 christos case BFD_RELOC_CR16_NUM32:
563 1.1.1.6 christos fixP->fx_r_type = BFD_RELOC_CR16_SWITCH32;
564 1.1.1.6 christos break;
565 1.1.1.6 christos case BFD_RELOC_CR16_NUM32a:
566 1.1.1.6 christos fixP->fx_r_type = BFD_RELOC_CR16_NUM32a;
567 1.1.1.6 christos break;
568 1.1.1.6 christos default:
569 1.1.1.6 christos abort ();
570 1.1.1.6 christos break;
571 1.1.1.6 christos }
572 1.1 christos }
573 1.1.1.6 christos else
574 1.1 christos {
575 1.1.1.6 christos /* We only resolve difference expressions in the same section. */
576 1.1.1.6 christos as_bad_subtract (fixP);
577 1.1.1.6 christos free (reloc->sym_ptr_ptr);
578 1.1.1.6 christos free (reloc);
579 1.1.1.6 christos return NULL;
580 1.1 christos }
581 1.1.1.6 christos }
582 1.1.1.6 christos #ifdef OBJ_ELF
583 1.1.1.6 christos if ((fixP->fx_r_type == BFD_RELOC_CR16_GOT_REGREL20)
584 1.1.1.6 christos && GOT_symbol
585 1.1.1.6 christos && fixP->fx_addsy == GOT_symbol)
586 1.1.1.6 christos {
587 1.1.1.6 christos reloc->addend = fixP->fx_offset = reloc->address;
588 1.1.1.6 christos }
589 1.1.1.6 christos else if ((fixP->fx_r_type == BFD_RELOC_CR16_GOTC_REGREL20)
590 1.1.1.6 christos && GOT_symbol
591 1.1.1.6 christos && fixP->fx_addsy == GOT_symbol)
592 1.1.1.6 christos {
593 1.1.1.6 christos reloc->addend = fixP->fx_offset = reloc->address;
594 1.1.1.6 christos }
595 1.1 christos #endif
596 1.1 christos
597 1.1 christos gas_assert ((int) fixP->fx_r_type > 0);
598 1.1 christos reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
599 1.1 christos
600 1.1 christos if (reloc->howto == NULL)
601 1.1 christos {
602 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
603 1.1.1.6 christos _("internal error: reloc %d (`%s') not supported by object file format"),
604 1.1.1.6 christos fixP->fx_r_type,
605 1.1.1.6 christos bfd_get_reloc_code_name (fixP->fx_r_type));
606 1.1 christos return NULL;
607 1.1 christos }
608 1.1 christos gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
609 1.1 christos
610 1.1 christos return reloc;
611 1.1 christos }
612 1.1 christos
613 1.1 christos /* Prepare machine-dependent frags for relaxation. */
614 1.1 christos
615 1.1 christos int
616 1.1 christos md_estimate_size_before_relax (fragS *fragp, asection *seg)
617 1.1 christos {
618 1.1 christos /* If symbol is undefined or located in a different section,
619 1.1 christos select the largest supported relocation. */
620 1.1 christos relax_substateT subtype;
621 1.1 christos relax_substateT rlx_state[] = {0, 2};
622 1.1 christos
623 1.1 christos for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
624 1.1 christos {
625 1.1 christos if (fragp->fr_subtype == rlx_state[subtype]
626 1.1.1.6 christos && (!S_IS_DEFINED (fragp->fr_symbol)
627 1.1.1.6 christos || seg != S_GET_SEGMENT (fragp->fr_symbol)))
628 1.1.1.6 christos {
629 1.1.1.6 christos fragp->fr_subtype = rlx_state[subtype + 1];
630 1.1.1.6 christos break;
631 1.1.1.6 christos }
632 1.1 christos }
633 1.1 christos
634 1.1 christos if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
635 1.1 christos abort ();
636 1.1 christos
637 1.1 christos return md_relax_table[fragp->fr_subtype].rlx_length;
638 1.1 christos }
639 1.1 christos
640 1.1 christos void
641 1.1 christos md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
642 1.1 christos {
643 1.1 christos /* 'opcode' points to the start of the instruction, whether
644 1.1 christos we need to change the instruction's fixed encoding. */
645 1.1.1.6 christos char *opcode = &fragP->fr_literal[0] + fragP->fr_fix;
646 1.1 christos bfd_reloc_code_real_type reloc;
647 1.1 christos
648 1.1 christos subseg_change (sec, 0);
649 1.1 christos
650 1.1 christos switch (fragP->fr_subtype)
651 1.1 christos {
652 1.1 christos case 0:
653 1.1 christos reloc = BFD_RELOC_CR16_DISP8;
654 1.1 christos break;
655 1.1 christos case 1:
656 1.1 christos /* If the subtype is not changed due to :m operand qualifier,
657 1.1.1.6 christos then no need to update the opcode value. */
658 1.1 christos if ((int)opcode[1] != 0x18)
659 1.1.1.6 christos {
660 1.1.1.6 christos opcode[0] = (opcode[0] & 0xf0);
661 1.1.1.6 christos opcode[1] = 0x18;
662 1.1.1.6 christos }
663 1.1 christos reloc = BFD_RELOC_CR16_DISP16;
664 1.1 christos break;
665 1.1 christos case 2:
666 1.1 christos /* If the subtype is not changed due to :l operand qualifier,
667 1.1.1.6 christos then no need to update the opcode value. */
668 1.1 christos if ((int)opcode[1] != 0)
669 1.1.1.6 christos {
670 1.1.1.6 christos opcode[2] = opcode[0];
671 1.1.1.6 christos opcode[0] = opcode[1];
672 1.1.1.6 christos opcode[1] = 0x0;
673 1.1.1.6 christos }
674 1.1 christos reloc = BFD_RELOC_CR16_DISP24;
675 1.1 christos break;
676 1.1 christos default:
677 1.1 christos abort();
678 1.1 christos }
679 1.1 christos
680 1.1 christos fix_new (fragP, fragP->fr_fix,
681 1.1.1.6 christos bfd_get_reloc_size (bfd_reloc_type_lookup (stdoutput, reloc)),
682 1.1.1.6 christos fragP->fr_symbol, fragP->fr_offset, 1, reloc);
683 1.1 christos fragP->fr_var = 0;
684 1.1 christos fragP->fr_fix += md_relax_table[fragP->fr_subtype].rlx_length;
685 1.1 christos }
686 1.1 christos
687 1.1 christos symbolS *
688 1.1 christos md_undefined_symbol (char *name)
689 1.1 christos {
690 1.1 christos if (*name == '_' && *(name + 1) == 'G'
691 1.1 christos && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
692 1.1.1.6 christos {
693 1.1.1.6 christos if (!GOT_symbol)
694 1.1.1.6 christos {
695 1.1.1.6 christos if (symbol_find (name))
696 1.1.1.6 christos as_bad (_("GOT already in symbol table"));
697 1.1.1.6 christos GOT_symbol = symbol_new (name, undefined_section,
698 1.1.1.6 christos &zero_address_frag, 0);
699 1.1.1.6 christos }
700 1.1.1.6 christos return GOT_symbol;
701 1.1.1.6 christos }
702 1.1 christos return 0;
703 1.1 christos }
704 1.1 christos
705 1.1 christos /* Process machine-dependent command line options. Called once for
706 1.1 christos each option on the command line that the machine-independent part of
707 1.1 christos GAS does not understand. */
708 1.1 christos
709 1.1 christos int
710 1.1.1.3 christos md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
711 1.1 christos {
712 1.1 christos return 0;
713 1.1 christos }
714 1.1 christos
715 1.1 christos /* Machine-dependent usage-output. */
716 1.1 christos
717 1.1 christos void
718 1.1 christos md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
719 1.1 christos {
720 1.1 christos return;
721 1.1 christos }
722 1.1 christos
723 1.1.1.3 christos const char *
724 1.1 christos md_atof (int type, char *litP, int *sizeP)
725 1.1 christos {
726 1.1 christos return ieee_md_atof (type, litP, sizeP, target_big_endian);
727 1.1 christos }
728 1.1 christos
729 1.1 christos /* Apply a fixS (fixup of an instruction or data that we didn't have
730 1.1 christos enough info to complete immediately) to the data in a frag.
731 1.1 christos Since linkrelax is nonzero and TC_LINKRELAX_FIXUP is defined to disable
732 1.1 christos relaxation of debug sections, this function is called only when
733 1.1 christos fixuping relocations of debug sections. */
734 1.1 christos
735 1.1 christos void
736 1.1 christos md_apply_fix (fixS *fixP, valueT *valP, segT seg)
737 1.1 christos {
738 1.1 christos valueT val = * valP;
739 1.1 christos
740 1.1 christos if (fixP->fx_addsy == NULL
741 1.1 christos && fixP->fx_pcrel == 0)
742 1.1 christos fixP->fx_done = 1;
743 1.1 christos else if (fixP->fx_pcrel == 1
744 1.1 christos && fixP->fx_addsy != NULL
745 1.1 christos && S_GET_SEGMENT (fixP->fx_addsy) == seg)
746 1.1 christos fixP->fx_done = 1;
747 1.1 christos else
748 1.1 christos fixP->fx_done = 0;
749 1.1 christos
750 1.1 christos if (fixP->fx_addsy != NULL && !fixP->fx_pcrel)
751 1.1 christos {
752 1.1 christos val = fixP->fx_offset;
753 1.1 christos fixP->fx_done = 1;
754 1.1 christos }
755 1.1 christos
756 1.1 christos if (fixP->fx_done)
757 1.1 christos {
758 1.1 christos char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
759 1.1 christos
760 1.1 christos fixP->fx_offset = 0;
761 1.1 christos
762 1.1 christos switch (fixP->fx_r_type)
763 1.1 christos {
764 1.1 christos case BFD_RELOC_CR16_NUM8:
765 1.1 christos bfd_put_8 (stdoutput, (unsigned char) val, buf);
766 1.1 christos break;
767 1.1 christos case BFD_RELOC_CR16_NUM16:
768 1.1 christos bfd_put_16 (stdoutput, val, buf);
769 1.1 christos break;
770 1.1 christos case BFD_RELOC_CR16_NUM32:
771 1.1 christos bfd_put_32 (stdoutput, val, buf);
772 1.1 christos break;
773 1.1 christos case BFD_RELOC_CR16_NUM32a:
774 1.1 christos bfd_put_32 (stdoutput, val, buf);
775 1.1 christos break;
776 1.1 christos default:
777 1.1 christos /* We shouldn't ever get here because linkrelax is nonzero. */
778 1.1 christos abort ();
779 1.1 christos break;
780 1.1 christos }
781 1.1 christos fixP->fx_done = 0;
782 1.1 christos }
783 1.1 christos else
784 1.1 christos fixP->fx_offset = * valP;
785 1.1 christos }
786 1.1 christos
787 1.1 christos /* The location from which a PC relative jump should be calculated,
788 1.1 christos given a PC relative reloc. */
789 1.1 christos
790 1.1 christos long
791 1.1 christos md_pcrel_from (fixS *fixp)
792 1.1 christos {
793 1.1 christos return fixp->fx_frag->fr_address + fixp->fx_where;
794 1.1 christos }
795 1.1 christos
796 1.1 christos static void
797 1.1.1.6 christos initialise_reg_hash_table (htab_t *hash_table,
798 1.1.1.6 christos const reg_entry *register_table,
799 1.1.1.6 christos const unsigned int num_entries)
800 1.1 christos {
801 1.1.1.6 christos const reg_entry *rreg;
802 1.1 christos
803 1.1.1.6 christos *hash_table = str_htab_create ();
804 1.1 christos
805 1.1 christos for (rreg = register_table;
806 1.1 christos rreg < (register_table + num_entries);
807 1.1 christos rreg++)
808 1.1.1.6 christos if (str_hash_insert (*hash_table, rreg->name, rreg, 0) != NULL)
809 1.1.1.6 christos as_fatal (_("duplicate %s"), rreg->name);
810 1.1 christos }
811 1.1 christos
812 1.1 christos /* This function is called once, at assembler startup time. This should
813 1.1 christos set up all the tables, etc that the MD part of the assembler needs. */
814 1.1 christos
815 1.1 christos void
816 1.1 christos md_begin (void)
817 1.1 christos {
818 1.1 christos int i = 0;
819 1.1 christos
820 1.1 christos /* Set up a hash table for the instructions. */
821 1.1.1.6 christos cr16_inst_hash = str_htab_create ();
822 1.1 christos
823 1.1 christos while (cr16_instruction[i].mnemonic != NULL)
824 1.1 christos {
825 1.1 christos const char *mnemonic = cr16_instruction[i].mnemonic;
826 1.1 christos
827 1.1.1.6 christos if (str_hash_insert (cr16_inst_hash, mnemonic, cr16_instruction + i, 0))
828 1.1.1.6 christos as_fatal (_("duplicate %s"), mnemonic);
829 1.1 christos
830 1.1 christos /* Insert unique names into hash table. The CR16 instruction set
831 1.1.1.6 christos has many identical opcode names that have different opcodes based
832 1.1.1.6 christos on the operands. This hash table then provides a quick index to
833 1.1.1.6 christos the first opcode with a particular name in the opcode table. */
834 1.1 christos do
835 1.1.1.6 christos {
836 1.1.1.6 christos ++i;
837 1.1.1.6 christos }
838 1.1 christos while (cr16_instruction[i].mnemonic != NULL
839 1.1.1.6 christos && streq (cr16_instruction[i].mnemonic, mnemonic));
840 1.1 christos }
841 1.1 christos
842 1.1 christos /* Initialize reg_hash hash table. */
843 1.1 christos initialise_reg_hash_table (& reg_hash, cr16_regtab, NUMREGS);
844 1.1 christos /* Initialize regp_hash hash table. */
845 1.1 christos initialise_reg_hash_table (& regp_hash, cr16_regptab, NUMREGPS);
846 1.1 christos /* Initialize preg_hash hash table. */
847 1.1 christos initialise_reg_hash_table (& preg_hash, cr16_pregtab, NUMPREGS);
848 1.1 christos /* Initialize pregp_hash hash table. */
849 1.1 christos initialise_reg_hash_table (& pregp_hash, cr16_pregptab, NUMPREGPS);
850 1.1 christos
851 1.1 christos /* Set linkrelax here to avoid fixups in most sections. */
852 1.1 christos linkrelax = 1;
853 1.1 christos }
854 1.1 christos
855 1.1 christos /* Process constants (immediate/absolute)
856 1.1 christos and labels (jump targets/Memory locations). */
857 1.1 christos
858 1.1 christos static void
859 1.1 christos process_label_constant (char *str, ins * cr16_ins)
860 1.1 christos {
861 1.1 christos char *saved_input_line_pointer;
862 1.1 christos int symbol_with_at = 0;
863 1.1 christos int symbol_with_s = 0;
864 1.1 christos int symbol_with_m = 0;
865 1.1 christos int symbol_with_l = 0;
866 1.1 christos int symbol_with_at_got = 0;
867 1.1 christos int symbol_with_at_gotc = 0;
868 1.1 christos argument *cur_arg = cr16_ins->arg + cur_arg_num; /* Current argument. */
869 1.1 christos
870 1.1 christos saved_input_line_pointer = input_line_pointer;
871 1.1 christos input_line_pointer = str;
872 1.1 christos
873 1.1 christos expression (&cr16_ins->exp);
874 1.1 christos
875 1.1 christos switch (cr16_ins->exp.X_op)
876 1.1 christos {
877 1.1 christos case O_big:
878 1.1 christos case O_absent:
879 1.1 christos /* Missing or bad expr becomes absolute 0. */
880 1.1 christos as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
881 1.1.1.6 christos str);
882 1.1 christos cr16_ins->exp.X_op = O_constant;
883 1.1 christos cr16_ins->exp.X_add_number = 0;
884 1.1 christos cr16_ins->exp.X_add_symbol = NULL;
885 1.1 christos cr16_ins->exp.X_op_symbol = NULL;
886 1.1 christos /* Fall through. */
887 1.1 christos
888 1.1 christos case O_constant:
889 1.1 christos cur_arg->X_op = O_constant;
890 1.1 christos cur_arg->constant = cr16_ins->exp.X_add_number;
891 1.1 christos break;
892 1.1 christos
893 1.1 christos case O_symbol:
894 1.1 christos case O_subtract:
895 1.1 christos case O_add:
896 1.1 christos cur_arg->X_op = O_symbol;
897 1.1 christos cur_arg->constant = cr16_ins->exp.X_add_number;
898 1.1 christos cr16_ins->exp.X_add_number = 0;
899 1.1 christos cr16_ins->rtype = BFD_RELOC_NONE;
900 1.1 christos relocatable = 1;
901 1.1 christos
902 1.1.1.6 christos if (startswith (input_line_pointer, "@c"))
903 1.1.1.6 christos symbol_with_at = 1;
904 1.1 christos
905 1.1.1.6 christos if (startswith (input_line_pointer, "@l")
906 1.1.1.6 christos || startswith (input_line_pointer, ":l"))
907 1.1.1.6 christos symbol_with_l = 1;
908 1.1.1.6 christos
909 1.1.1.6 christos if (startswith (input_line_pointer, "@m")
910 1.1.1.6 christos || startswith (input_line_pointer, ":m"))
911 1.1.1.6 christos symbol_with_m = 1;
912 1.1.1.6 christos
913 1.1.1.6 christos if (startswith (input_line_pointer, "@s")
914 1.1.1.6 christos || startswith (input_line_pointer, ":s"))
915 1.1.1.6 christos symbol_with_s = 1;
916 1.1 christos
917 1.1.1.6 christos if (startswith (input_line_pointer, "@cGOT")
918 1.1.1.6 christos || startswith (input_line_pointer, "@cgot"))
919 1.1 christos {
920 1.1 christos if (GOT_symbol == NULL)
921 1.1.1.6 christos GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
922 1.1 christos
923 1.1.1.6 christos symbol_with_at_gotc = 1;
924 1.1 christos }
925 1.1.1.6 christos else if (startswith (input_line_pointer, "@GOT")
926 1.1.1.6 christos || startswith (input_line_pointer, "@got"))
927 1.1 christos {
928 1.1.1.6 christos if ((startswith (input_line_pointer, "+"))
929 1.1.1.6 christos || (startswith (input_line_pointer, "-")))
930 1.1.1.6 christos as_warn (_("GOT bad expression with %s."), input_line_pointer);
931 1.1 christos
932 1.1 christos if (GOT_symbol == NULL)
933 1.1.1.6 christos GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
934 1.1 christos
935 1.1.1.6 christos symbol_with_at_got = 1;
936 1.1 christos }
937 1.1 christos
938 1.1 christos switch (cur_arg->type)
939 1.1.1.6 christos {
940 1.1.1.6 christos case arg_cr:
941 1.1.1.6 christos if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
942 1.1.1.6 christos {
943 1.1 christos if (symbol_with_at_got)
944 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
945 1.1 christos else if (symbol_with_at_gotc)
946 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
947 1.1 christos else if (cur_arg->size == 20)
948 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
949 1.1.1.6 christos else
950 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
951 1.1 christos }
952 1.1.1.6 christos break;
953 1.1.1.6 christos
954 1.1.1.6 christos case arg_crp:
955 1.1.1.6 christos if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
956 1.1.1.6 christos {
957 1.1.1.6 christos if (symbol_with_at_got)
958 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
959 1.1.1.6 christos else if (symbol_with_at_gotc)
960 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
961 1.1.1.6 christos } else {
962 1.1.1.6 christos switch (instruction->size)
963 1.1.1.6 christos {
964 1.1.1.6 christos case 1:
965 1.1.1.6 christos switch (cur_arg->size)
966 1.1.1.6 christos {
967 1.1.1.6 christos case 0:
968 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL0;
969 1.1.1.6 christos break;
970 1.1.1.6 christos case 4:
971 1.1.1.6 christos if (IS_INSN_MNEMONIC ("loadb") || IS_INSN_MNEMONIC ("storb"))
972 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL4;
973 1.1.1.6 christos else
974 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL4a;
975 1.1.1.6 christos break;
976 1.1.1.6 christos default: break;
977 1.1.1.6 christos }
978 1.1.1.6 christos break;
979 1.1.1.6 christos case 2:
980 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL16;
981 1.1.1.6 christos break;
982 1.1.1.6 christos case 3:
983 1.1.1.6 christos if (cur_arg->size == 20)
984 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
985 1.1.1.6 christos else
986 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
987 1.1.1.6 christos break;
988 1.1.1.6 christos default:
989 1.1.1.6 christos break;
990 1.1.1.6 christos }
991 1.1.1.6 christos }
992 1.1.1.6 christos break;
993 1.1 christos
994 1.1.1.6 christos case arg_idxr:
995 1.1.1.6 christos if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
996 1.1 christos {
997 1.1 christos if (symbol_with_at_got)
998 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
999 1.1 christos else if (symbol_with_at_gotc)
1000 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
1001 1.1 christos else
1002 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
1003 1.1 christos }
1004 1.1.1.6 christos break;
1005 1.1 christos
1006 1.1.1.6 christos case arg_idxrp:
1007 1.1.1.6 christos if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
1008 1.1 christos {
1009 1.1.1.6 christos if (symbol_with_at_got)
1010 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
1011 1.1.1.6 christos else if (symbol_with_at_gotc)
1012 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
1013 1.1.1.6 christos else {
1014 1.1.1.6 christos switch (instruction->size)
1015 1.1.1.6 christos {
1016 1.1.1.6 christos case 1: cr16_ins->rtype = BFD_RELOC_CR16_REGREL0; break;
1017 1.1.1.6 christos case 2: cr16_ins->rtype = BFD_RELOC_CR16_REGREL14; break;
1018 1.1.1.6 christos case 3: cr16_ins->rtype = BFD_RELOC_CR16_REGREL20; break;
1019 1.1.1.6 christos default: break;
1020 1.1.1.6 christos }
1021 1.1.1.6 christos }
1022 1.1 christos }
1023 1.1.1.6 christos break;
1024 1.1 christos
1025 1.1.1.6 christos case arg_c:
1026 1.1.1.6 christos if (IS_INSN_MNEMONIC ("bal"))
1027 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
1028 1.1.1.6 christos else if (IS_INSN_TYPE (BRANCH_INS))
1029 1.1.1.6 christos {
1030 1.1.1.6 christos if (symbol_with_l)
1031 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
1032 1.1.1.6 christos else if (symbol_with_m)
1033 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_DISP16;
1034 1.1.1.6 christos else
1035 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_DISP8;
1036 1.1.1.6 christos }
1037 1.1.1.6 christos else if (IS_INSN_TYPE (STOR_IMM_INS) || IS_INSN_TYPE (LD_STOR_INS)
1038 1.1.1.6 christos || IS_INSN_TYPE (CSTBIT_INS))
1039 1.1.1.6 christos {
1040 1.1 christos if (symbol_with_s)
1041 1.1.1.6 christos as_bad (_("operand %d: illegal use expression: `%s`"), cur_arg_num + 1, str);
1042 1.1 christos if (symbol_with_at_got)
1043 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
1044 1.1 christos else if (symbol_with_at_gotc)
1045 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
1046 1.1 christos else if (symbol_with_m)
1047 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_ABS20;
1048 1.1.1.6 christos else /* Default to (symbol_with_l) */
1049 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_ABS24;
1050 1.1.1.6 christos }
1051 1.1.1.6 christos else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
1052 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_DISP4;
1053 1.1.1.6 christos break;
1054 1.1.1.6 christos
1055 1.1.1.6 christos case arg_ic:
1056 1.1.1.6 christos if (IS_INSN_TYPE (ARITH_INS))
1057 1.1.1.6 christos {
1058 1.1 christos if (symbol_with_at_got)
1059 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOT_REGREL20;
1060 1.1 christos else if (symbol_with_at_gotc)
1061 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_GOTC_REGREL20;
1062 1.1 christos else if (symbol_with_s)
1063 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_IMM4;
1064 1.1.1.6 christos else if (symbol_with_m)
1065 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_IMM20;
1066 1.1.1.6 christos else if (symbol_with_at)
1067 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_IMM32a;
1068 1.1.1.6 christos else /* Default to (symbol_with_l) */
1069 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_IMM32;
1070 1.1.1.6 christos }
1071 1.1.1.6 christos else if (IS_INSN_TYPE (ARITH_BYTE_INS))
1072 1.1.1.6 christos {
1073 1.1.1.6 christos cr16_ins->rtype = BFD_RELOC_CR16_IMM16;
1074 1.1.1.6 christos }
1075 1.1.1.6 christos break;
1076 1.1.1.6 christos default:
1077 1.1.1.6 christos break;
1078 1.1.1.6 christos }
1079 1.1 christos break;
1080 1.1 christos
1081 1.1 christos default:
1082 1.1 christos cur_arg->X_op = cr16_ins->exp.X_op;
1083 1.1 christos break;
1084 1.1 christos }
1085 1.1 christos
1086 1.1 christos input_line_pointer = saved_input_line_pointer;
1087 1.1 christos return;
1088 1.1 christos }
1089 1.1 christos
1090 1.1 christos /* Retrieve the opcode image of a given register.
1091 1.1 christos If the register is illegal for the current instruction,
1092 1.1 christos issue an error. */
1093 1.1 christos
1094 1.1 christos static int
1095 1.1 christos getreg_image (reg r)
1096 1.1 christos {
1097 1.1 christos const reg_entry *rreg;
1098 1.1 christos char *reg_name;
1099 1.1 christos int is_procreg = 0; /* Nonzero means argument should be processor reg. */
1100 1.1 christos
1101 1.1 christos /* Check whether the register is in registers table. */
1102 1.1 christos if (r < MAX_REG)
1103 1.1 christos rreg = cr16_regtab + r;
1104 1.1 christos else /* Register not found. */
1105 1.1 christos {
1106 1.1 christos as_bad (_("Unknown register: `%d'"), r);
1107 1.1 christos return 0;
1108 1.1 christos }
1109 1.1 christos
1110 1.1 christos reg_name = rreg->name;
1111 1.1 christos
1112 1.1.1.6 christos /* Issue a error message when register is illegal. */
1113 1.1.1.6 christos #define IMAGE_ERR \
1114 1.1.1.6 christos as_bad (_("Illegal register (`%s') in Instruction: `%s'"), \
1115 1.1.1.4 christos reg_name, ins_parse);
1116 1.1 christos
1117 1.1 christos switch (rreg->type)
1118 1.1 christos {
1119 1.1 christos case CR16_R_REGTYPE:
1120 1.1 christos if (! is_procreg)
1121 1.1.1.6 christos return rreg->image;
1122 1.1 christos else
1123 1.1.1.6 christos IMAGE_ERR;
1124 1.1.1.4 christos break;
1125 1.1 christos
1126 1.1 christos case CR16_P_REGTYPE:
1127 1.1 christos return rreg->image;
1128 1.1 christos break;
1129 1.1 christos
1130 1.1 christos default:
1131 1.1 christos IMAGE_ERR;
1132 1.1.1.4 christos break;
1133 1.1 christos }
1134 1.1 christos
1135 1.1 christos return 0;
1136 1.1 christos }
1137 1.1 christos
1138 1.1 christos /* Parsing different types of operands
1139 1.1 christos -> constants Immediate/Absolute/Relative numbers
1140 1.1 christos -> Labels Relocatable symbols
1141 1.1 christos -> (reg pair base) Register pair base
1142 1.1 christos -> (rbase) Register base
1143 1.1 christos -> disp(rbase) Register relative
1144 1.1 christos -> [rinx]disp(reg pair) Register index with reg pair mode
1145 1.1 christos -> disp(rbase,ridx,scl) Register index mode. */
1146 1.1 christos
1147 1.1 christos static void
1148 1.1 christos set_operand (char *operand, ins * cr16_ins)
1149 1.1 christos {
1150 1.1.1.4 christos char *operandS; /* Pointer to start of sub-operand. */
1151 1.1.1.4 christos char *operandE; /* Pointer to end of sub-operand. */
1152 1.1 christos
1153 1.1 christos argument *cur_arg = &cr16_ins->arg[cur_arg_num]; /* Current argument. */
1154 1.1 christos
1155 1.1 christos /* Initialize pointers. */
1156 1.1 christos operandS = operandE = operand;
1157 1.1 christos
1158 1.1 christos switch (cur_arg->type)
1159 1.1 christos {
1160 1.1 christos case arg_ic: /* Case $0x18. */
1161 1.1 christos operandS++;
1162 1.1.1.4 christos /* Fall through. */
1163 1.1 christos case arg_c: /* Case 0x18. */
1164 1.1 christos /* Set constant. */
1165 1.1 christos process_label_constant (operandS, cr16_ins);
1166 1.1 christos
1167 1.1 christos if (cur_arg->type != arg_ic)
1168 1.1.1.6 christos cur_arg->type = arg_c;
1169 1.1 christos break;
1170 1.1 christos
1171 1.1 christos case arg_icr: /* Case $0x18(r1). */
1172 1.1 christos operandS++;
1173 1.1 christos case arg_cr: /* Case 0x18(r1). */
1174 1.1 christos /* Set displacement constant. */
1175 1.1 christos while (*operandE != '(')
1176 1.1.1.6 christos operandE++;
1177 1.1 christos *operandE = '\0';
1178 1.1 christos process_label_constant (operandS, cr16_ins);
1179 1.1 christos operandS = operandE;
1180 1.1.1.4 christos /* Fall through. */
1181 1.1 christos case arg_rbase: /* Case (r1) or (r1,r0). */
1182 1.1 christos operandS++;
1183 1.1 christos /* Set register base. */
1184 1.1 christos while (*operandE != ')')
1185 1.1.1.6 christos operandE++;
1186 1.1 christos *operandE = '\0';
1187 1.1 christos if ((cur_arg->r = get_register (operandS)) == nullregister)
1188 1.1.1.6 christos as_bad (_("Illegal register `%s' in Instruction `%s'"),
1189 1.1.1.6 christos operandS, ins_parse);
1190 1.1 christos
1191 1.1 christos /* set the arg->rp, if reg is "r12" or "r13" or "14" or "15" */
1192 1.1 christos if ((cur_arg->type != arg_rbase)
1193 1.1.1.6 christos && ((getreg_image (cur_arg->r) == 12)
1194 1.1.1.6 christos || (getreg_image (cur_arg->r) == 13)
1195 1.1.1.6 christos || (getreg_image (cur_arg->r) == 14)
1196 1.1.1.6 christos || (getreg_image (cur_arg->r) == 15)))
1197 1.1.1.6 christos {
1198 1.1.1.6 christos cur_arg->type = arg_crp;
1199 1.1.1.6 christos cur_arg->rp = cur_arg->r;
1200 1.1.1.6 christos }
1201 1.1 christos break;
1202 1.1 christos
1203 1.1 christos case arg_crp: /* Case 0x18(r1,r0). */
1204 1.1 christos /* Set displacement constant. */
1205 1.1 christos while (*operandE != '(')
1206 1.1.1.6 christos operandE++;
1207 1.1 christos *operandE = '\0';
1208 1.1 christos process_label_constant (operandS, cr16_ins);
1209 1.1 christos operandS = operandE;
1210 1.1 christos operandS++;
1211 1.1 christos /* Set register pair base. */
1212 1.1 christos while (*operandE != ')')
1213 1.1.1.6 christos operandE++;
1214 1.1 christos *operandE = '\0';
1215 1.1 christos if ((cur_arg->rp = get_register_pair (operandS)) == nullregister)
1216 1.1.1.6 christos as_bad (_("Illegal register pair `%s' in Instruction `%s'"),
1217 1.1.1.6 christos operandS, ins_parse);
1218 1.1 christos break;
1219 1.1 christos
1220 1.1 christos case arg_idxr:
1221 1.1 christos /* Set register pair base. */
1222 1.1 christos if ((strchr (operandS,'(') != NULL))
1223 1.1.1.6 christos {
1224 1.1.1.6 christos while ((*operandE != '(') && (! ISSPACE (*operandE)))
1225 1.1.1.6 christos operandE++;
1226 1.1.1.6 christos if ((cur_arg->rp = get_index_register_pair (operandE)) == nullregister)
1227 1.1.1.6 christos as_bad (_("Illegal register pair `%s' in Instruction `%s'"),
1228 1.1.1.6 christos operandS, ins_parse);
1229 1.1.1.6 christos *operandE++ = '\0';
1230 1.1.1.6 christos cur_arg->type = arg_idxrp;
1231 1.1.1.6 christos }
1232 1.1 christos else
1233 1.1.1.6 christos cur_arg->rp = -1;
1234 1.1 christos
1235 1.1.1.6 christos operandE = operandS;
1236 1.1 christos /* Set displacement constant. */
1237 1.1 christos while (*operandE != ']')
1238 1.1.1.6 christos operandE++;
1239 1.1 christos process_label_constant (++operandE, cr16_ins);
1240 1.1 christos *operandE++ = '\0';
1241 1.1 christos operandE = operandS;
1242 1.1 christos
1243 1.1 christos /* Set index register . */
1244 1.1 christos operandS = strchr (operandE,'[');
1245 1.1 christos if (operandS != NULL)
1246 1.1.1.6 christos { /* Eliminate '[', detach from rest of operand. */
1247 1.1.1.6 christos *operandS++ = '\0';
1248 1.1 christos
1249 1.1.1.6 christos operandE = strchr (operandS, ']');
1250 1.1 christos
1251 1.1.1.6 christos if (operandE == NULL)
1252 1.1.1.6 christos as_bad (_("unmatched '['"));
1253 1.1.1.6 christos else
1254 1.1.1.6 christos { /* Eliminate ']' and make sure it was the last thing
1255 1.1.1.6 christos in the string. */
1256 1.1.1.6 christos *operandE = '\0';
1257 1.1.1.6 christos if (*(operandE + 1) != '\0')
1258 1.1.1.6 christos as_bad (_("garbage after index spec ignored"));
1259 1.1.1.6 christos }
1260 1.1.1.6 christos }
1261 1.1 christos
1262 1.1 christos if ((cur_arg->i_r = get_index_register (operandS)) == nullregister)
1263 1.1.1.6 christos as_bad (_("Illegal register `%s' in Instruction `%s'"),
1264 1.1.1.6 christos operandS, ins_parse);
1265 1.1 christos *operandE = '\0';
1266 1.1 christos *operandS = '\0';
1267 1.1 christos break;
1268 1.1 christos
1269 1.1 christos default:
1270 1.1 christos break;
1271 1.1 christos }
1272 1.1 christos }
1273 1.1 christos
1274 1.1 christos /* Parse a single operand.
1275 1.1 christos operand - Current operand to parse.
1276 1.1 christos cr16_ins - Current assembled instruction. */
1277 1.1 christos
1278 1.1 christos static void
1279 1.1 christos parse_operand (char *operand, ins * cr16_ins)
1280 1.1 christos {
1281 1.1 christos int ret_val;
1282 1.1 christos argument *cur_arg = cr16_ins->arg + cur_arg_num; /* Current argument. */
1283 1.1 christos
1284 1.1 christos /* Initialize the type to NULL before parsing. */
1285 1.1 christos cur_arg->type = nullargs;
1286 1.1 christos
1287 1.1 christos /* Check whether this is a condition code . */
1288 1.1 christos if ((IS_INSN_MNEMONIC ("b")) && ((ret_val = get_cc (operand)) != -1))
1289 1.1 christos {
1290 1.1 christos cur_arg->type = arg_cc;
1291 1.1 christos cur_arg->cc = ret_val;
1292 1.1 christos cur_arg->X_op = O_register;
1293 1.1 christos return;
1294 1.1 christos }
1295 1.1 christos
1296 1.1 christos /* Check whether this is a general processor register. */
1297 1.1 christos if ((ret_val = get_register (operand)) != nullregister)
1298 1.1 christos {
1299 1.1 christos cur_arg->type = arg_r;
1300 1.1 christos cur_arg->r = ret_val;
1301 1.1 christos cur_arg->X_op = 0;
1302 1.1 christos return;
1303 1.1 christos }
1304 1.1 christos
1305 1.1 christos /* Check whether this is a general processor register pair. */
1306 1.1 christos if ((operand[0] == '(')
1307 1.1 christos && ((ret_val = get_register_pair (operand)) != nullregister))
1308 1.1 christos {
1309 1.1 christos cur_arg->type = arg_rp;
1310 1.1 christos cur_arg->rp = ret_val;
1311 1.1 christos cur_arg->X_op = O_register;
1312 1.1 christos return;
1313 1.1 christos }
1314 1.1 christos
1315 1.1 christos /* Check whether the operand is a processor register.
1316 1.1 christos For "lprd" and "sprd" instruction, only 32 bit
1317 1.1 christos processor registers used. */
1318 1.1 christos if (!(IS_INSN_MNEMONIC ("lprd") || (IS_INSN_MNEMONIC ("sprd")))
1319 1.1 christos && ((ret_val = get_pregister (operand)) != nullpregister))
1320 1.1 christos {
1321 1.1 christos cur_arg->type = arg_pr;
1322 1.1 christos cur_arg->pr = ret_val;
1323 1.1 christos cur_arg->X_op = O_register;
1324 1.1 christos return;
1325 1.1 christos }
1326 1.1 christos
1327 1.1 christos /* Check whether this is a processor register - 32 bit. */
1328 1.1 christos if ((ret_val = get_pregisterp (operand)) != nullpregister)
1329 1.1 christos {
1330 1.1 christos cur_arg->type = arg_prp;
1331 1.1 christos cur_arg->prp = ret_val;
1332 1.1 christos cur_arg->X_op = O_register;
1333 1.1 christos return;
1334 1.1 christos }
1335 1.1 christos
1336 1.1 christos /* Deal with special characters. */
1337 1.1 christos switch (operand[0])
1338 1.1 christos {
1339 1.1 christos case '$':
1340 1.1 christos if (strchr (operand, '(') != NULL)
1341 1.1.1.6 christos cur_arg->type = arg_icr;
1342 1.1 christos else
1343 1.1.1.6 christos cur_arg->type = arg_ic;
1344 1.1 christos goto set_params;
1345 1.1 christos break;
1346 1.1 christos
1347 1.1 christos case '(':
1348 1.1 christos cur_arg->type = arg_rbase;
1349 1.1 christos goto set_params;
1350 1.1 christos break;
1351 1.1 christos
1352 1.1 christos case '[':
1353 1.1 christos cur_arg->type = arg_idxr;
1354 1.1 christos goto set_params;
1355 1.1 christos break;
1356 1.1 christos
1357 1.1 christos default:
1358 1.1 christos break;
1359 1.1 christos }
1360 1.1 christos
1361 1.1 christos if (strchr (operand, '(') != NULL)
1362 1.1 christos {
1363 1.1 christos if (strchr (operand, ',') != NULL
1364 1.1.1.6 christos && (strchr (operand, ',') > strchr (operand, '(')))
1365 1.1.1.6 christos cur_arg->type = arg_crp;
1366 1.1 christos else
1367 1.1.1.6 christos cur_arg->type = arg_cr;
1368 1.1 christos }
1369 1.1 christos else
1370 1.1 christos cur_arg->type = arg_c;
1371 1.1 christos
1372 1.1.1.6 christos /* Parse an operand according to its type. */
1373 1.1 christos set_params:
1374 1.1 christos cur_arg->constant = 0;
1375 1.1 christos set_operand (operand, cr16_ins);
1376 1.1 christos }
1377 1.1 christos
1378 1.1 christos /* Parse the various operands. Each operand is then analyzed to fillup
1379 1.1 christos the fields in the cr16_ins data structure. */
1380 1.1 christos
1381 1.1 christos static void
1382 1.1 christos parse_operands (ins * cr16_ins, char *operands)
1383 1.1 christos {
1384 1.1 christos char *operandS; /* Operands string. */
1385 1.1 christos char *operandH, *operandT; /* Single operand head/tail pointers. */
1386 1.1 christos int allocated = 0; /* Indicates a new operands string was allocated.*/
1387 1.1 christos char *operand[MAX_OPERANDS];/* Separating the operands. */
1388 1.1 christos int op_num = 0; /* Current operand number we are parsing. */
1389 1.1 christos int bracket_flag = 0; /* Indicates a bracket '(' was found. */
1390 1.1 christos int sq_bracket_flag = 0; /* Indicates a square bracket '[' was found. */
1391 1.1 christos
1392 1.1 christos /* Preprocess the list of registers, if necessary. */
1393 1.1 christos operandS = operandH = operandT = operands;
1394 1.1 christos
1395 1.1 christos while (*operandT != '\0')
1396 1.1 christos {
1397 1.1 christos if (*operandT == ',' && bracket_flag != 1 && sq_bracket_flag != 1)
1398 1.1.1.6 christos {
1399 1.1.1.6 christos *operandT++ = '\0';
1400 1.1.1.6 christos operand[op_num++] = strdup (operandH);
1401 1.1.1.6 christos operandH = operandT;
1402 1.1.1.6 christos continue;
1403 1.1.1.6 christos }
1404 1.1 christos
1405 1.1 christos if (*operandT == ' ')
1406 1.1.1.6 christos as_bad (_("Illegal operands (whitespace): `%s'"), ins_parse);
1407 1.1 christos
1408 1.1 christos if (*operandT == '(')
1409 1.1.1.6 christos bracket_flag = 1;
1410 1.1 christos else if (*operandT == '[')
1411 1.1.1.6 christos sq_bracket_flag = 1;
1412 1.1 christos
1413 1.1 christos if (*operandT == ')')
1414 1.1.1.6 christos {
1415 1.1.1.6 christos if (bracket_flag)
1416 1.1.1.6 christos bracket_flag = 0;
1417 1.1.1.6 christos else
1418 1.1.1.6 christos as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
1419 1.1.1.6 christos }
1420 1.1 christos else if (*operandT == ']')
1421 1.1.1.6 christos {
1422 1.1.1.6 christos if (sq_bracket_flag)
1423 1.1.1.6 christos sq_bracket_flag = 0;
1424 1.1.1.6 christos else
1425 1.1.1.6 christos as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
1426 1.1.1.6 christos }
1427 1.1 christos
1428 1.1 christos if (bracket_flag == 1 && *operandT == ')')
1429 1.1.1.6 christos bracket_flag = 0;
1430 1.1 christos else if (sq_bracket_flag == 1 && *operandT == ']')
1431 1.1.1.6 christos sq_bracket_flag = 0;
1432 1.1 christos
1433 1.1 christos operandT++;
1434 1.1 christos }
1435 1.1 christos
1436 1.1 christos /* Adding the last operand. */
1437 1.1 christos operand[op_num++] = strdup (operandH);
1438 1.1 christos cr16_ins->nargs = op_num;
1439 1.1 christos
1440 1.1 christos /* Verifying correct syntax of operands (all brackets should be closed). */
1441 1.1 christos if (bracket_flag || sq_bracket_flag)
1442 1.1 christos as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
1443 1.1 christos
1444 1.1 christos /* Now we parse each operand separately. */
1445 1.1 christos for (op_num = 0; op_num < cr16_ins->nargs; op_num++)
1446 1.1 christos {
1447 1.1 christos cur_arg_num = op_num;
1448 1.1 christos parse_operand (operand[op_num], cr16_ins);
1449 1.1 christos free (operand[op_num]);
1450 1.1 christos }
1451 1.1 christos
1452 1.1 christos if (allocated)
1453 1.1 christos free (operandS);
1454 1.1 christos }
1455 1.1 christos
1456 1.1 christos /* Get the trap index in dispatch table, given its name.
1457 1.1 christos This routine is used by assembling the 'excp' instruction. */
1458 1.1 christos
1459 1.1 christos static int
1460 1.1 christos gettrap (char *s)
1461 1.1 christos {
1462 1.1 christos const trap_entry *trap;
1463 1.1 christos
1464 1.1 christos for (trap = cr16_traps; trap < (cr16_traps + NUMTRAPS); trap++)
1465 1.1 christos if (strcasecmp (trap->name, s) == 0)
1466 1.1 christos return trap->entry;
1467 1.1 christos
1468 1.1.1.4 christos /* To make compatible with CR16 4.1 tools, the below 3-lines of
1469 1.1 christos * code added. Refer: Development Tracker item #123 */
1470 1.1 christos for (trap = cr16_traps; trap < (cr16_traps + NUMTRAPS); trap++)
1471 1.1 christos if (trap->entry == (unsigned int) atoi (s))
1472 1.1 christos return trap->entry;
1473 1.1 christos
1474 1.1 christos as_bad (_("Unknown exception: `%s'"), s);
1475 1.1 christos return 0;
1476 1.1 christos }
1477 1.1 christos
1478 1.1 christos /* Top level module where instruction parsing starts.
1479 1.1 christos cr16_ins - data structure holds some information.
1480 1.1 christos operands - holds the operands part of the whole instruction. */
1481 1.1 christos
1482 1.1 christos static void
1483 1.1 christos parse_insn (ins *insn, char *operands)
1484 1.1 christos {
1485 1.1 christos int i;
1486 1.1 christos
1487 1.1 christos /* Handle instructions with no operands. */
1488 1.1 christos for (i = 0; cr16_no_op_insn[i] != NULL; i++)
1489 1.1 christos {
1490 1.1 christos if (streq (cr16_no_op_insn[i], instruction->mnemonic))
1491 1.1 christos {
1492 1.1 christos insn->nargs = 0;
1493 1.1 christos return;
1494 1.1 christos }
1495 1.1 christos }
1496 1.1 christos
1497 1.1 christos /* Handle 'excp' instructions. */
1498 1.1 christos if (IS_INSN_MNEMONIC ("excp"))
1499 1.1 christos {
1500 1.1 christos insn->nargs = 1;
1501 1.1 christos insn->arg[0].type = arg_ic;
1502 1.1 christos insn->arg[0].constant = gettrap (operands);
1503 1.1 christos insn->arg[0].X_op = O_constant;
1504 1.1 christos return;
1505 1.1 christos }
1506 1.1 christos
1507 1.1 christos if (operands != NULL)
1508 1.1 christos parse_operands (insn, operands);
1509 1.1 christos }
1510 1.1 christos
1511 1.1 christos /* bCC instruction requires special handling. */
1512 1.1 christos static char *
1513 1.1 christos get_b_cc (char * op)
1514 1.1 christos {
1515 1.1 christos unsigned int i;
1516 1.1 christos
1517 1.1.1.6 christos if (op[1] == 0 || (op[2] != 0 && op[3] != 0))
1518 1.1.1.6 christos return NULL;
1519 1.1 christos
1520 1.1 christos for (i = 0; i < cr16_num_cc ; i++)
1521 1.1.1.6 christos if (streq (op + 1, cr16_b_cond_tab[i]))
1522 1.1 christos return (char *) cr16_b_cond_tab[i];
1523 1.1 christos
1524 1.1 christos return NULL;
1525 1.1 christos }
1526 1.1 christos
1527 1.1 christos /* bCC instruction requires special handling. */
1528 1.1 christos static int
1529 1.1 christos is_bcc_insn (char * op)
1530 1.1 christos {
1531 1.1 christos if (!(streq (op, "bal") || streq (op, "beq0b") || streq (op, "bnq0b")
1532 1.1.1.6 christos || streq (op, "beq0w") || streq (op, "bnq0w")))
1533 1.1 christos if ((op[0] == 'b') && (get_b_cc (op) != NULL))
1534 1.1 christos return 1;
1535 1.1 christos return 0;
1536 1.1 christos }
1537 1.1 christos
1538 1.1 christos /* Cinv instruction requires special handling. */
1539 1.1 christos
1540 1.1 christos static void
1541 1.1 christos check_cinv_options (char * operand)
1542 1.1 christos {
1543 1.1 christos char *p = operand;
1544 1.1 christos
1545 1.1 christos while (*++p != ']')
1546 1.1 christos {
1547 1.1 christos switch (*p)
1548 1.1 christos {
1549 1.1 christos case ',':
1550 1.1 christos case ' ':
1551 1.1 christos case 'i':
1552 1.1 christos case 'u':
1553 1.1 christos case 'd':
1554 1.1 christos break;
1555 1.1 christos default:
1556 1.1 christos as_bad (_("Illegal `cinv' parameter: `%c'"), *p);
1557 1.1 christos }
1558 1.1 christos }
1559 1.1 christos }
1560 1.1 christos
1561 1.1 christos /* Retrieve the opcode image of a given register pair.
1562 1.1 christos If the register is illegal for the current instruction,
1563 1.1 christos issue an error. */
1564 1.1 christos
1565 1.1 christos static int
1566 1.1 christos getregp_image (reg r)
1567 1.1 christos {
1568 1.1 christos const reg_entry *rreg;
1569 1.1 christos char *reg_name;
1570 1.1 christos
1571 1.1 christos /* Check whether the register is in registers table. */
1572 1.1 christos if (r < MAX_REG)
1573 1.1 christos rreg = cr16_regptab + r;
1574 1.1 christos /* Register not found. */
1575 1.1 christos else
1576 1.1 christos {
1577 1.1 christos as_bad (_("Unknown register pair: `%d'"), r);
1578 1.1 christos return 0;
1579 1.1 christos }
1580 1.1 christos
1581 1.1 christos reg_name = rreg->name;
1582 1.1 christos
1583 1.1.1.6 christos /* Issue a error message when register pair is illegal. */
1584 1.1.1.6 christos #define RPAIR_IMAGE_ERR \
1585 1.1.1.6 christos as_bad (_("Illegal register pair (`%s') in Instruction: `%s'"), \
1586 1.1.1.6 christos reg_name, ins_parse); \
1587 1.1 christos break;
1588 1.1 christos
1589 1.1 christos switch (rreg->type)
1590 1.1 christos {
1591 1.1 christos case CR16_RP_REGTYPE:
1592 1.1 christos return rreg->image;
1593 1.1 christos default:
1594 1.1 christos RPAIR_IMAGE_ERR;
1595 1.1 christos }
1596 1.1 christos
1597 1.1 christos return 0;
1598 1.1 christos }
1599 1.1 christos
1600 1.1 christos /* Retrieve the opcode image of a given index register pair.
1601 1.1 christos If the register is illegal for the current instruction,
1602 1.1 christos issue an error. */
1603 1.1 christos
1604 1.1 christos static int
1605 1.1 christos getidxregp_image (reg r)
1606 1.1 christos {
1607 1.1 christos const reg_entry *rreg;
1608 1.1 christos char *reg_name;
1609 1.1 christos
1610 1.1 christos /* Check whether the register is in registers table. */
1611 1.1 christos if (r < MAX_REG)
1612 1.1 christos rreg = cr16_regptab + r;
1613 1.1 christos /* Register not found. */
1614 1.1 christos else
1615 1.1 christos {
1616 1.1 christos as_bad (_("Unknown register pair: `%d'"), r);
1617 1.1 christos return 0;
1618 1.1 christos }
1619 1.1 christos
1620 1.1 christos reg_name = rreg->name;
1621 1.1 christos
1622 1.1.1.6 christos /* Issue a error message when register pair is illegal. */
1623 1.1.1.6 christos #define IDX_RPAIR_IMAGE_ERR \
1624 1.1 christos as_bad (_("Illegal index register pair (`%s') in Instruction: `%s'"), \
1625 1.1.1.6 christos reg_name, ins_parse); \
1626 1.1 christos
1627 1.1 christos if (rreg->type == CR16_RP_REGTYPE)
1628 1.1 christos {
1629 1.1 christos switch (rreg->image)
1630 1.1.1.6 christos {
1631 1.1.1.6 christos case 0: return 0; break;
1632 1.1.1.6 christos case 2: return 1; break;
1633 1.1.1.6 christos case 4: return 2; break;
1634 1.1.1.6 christos case 6: return 3; break;
1635 1.1.1.6 christos case 8: return 4; break;
1636 1.1.1.6 christos case 10: return 5; break;
1637 1.1.1.6 christos case 3: return 6; break;
1638 1.1.1.6 christos case 5: return 7; break;
1639 1.1.1.6 christos default:
1640 1.1.1.6 christos break;
1641 1.1.1.6 christos }
1642 1.1 christos }
1643 1.1 christos
1644 1.1 christos IDX_RPAIR_IMAGE_ERR;
1645 1.1 christos return 0;
1646 1.1 christos }
1647 1.1 christos
1648 1.1.1.4 christos /* Retrieve the opcode image of a given processor register.
1649 1.1 christos If the register is illegal for the current instruction,
1650 1.1 christos issue an error. */
1651 1.1 christos static int
1652 1.1 christos getprocreg_image (int r)
1653 1.1 christos {
1654 1.1 christos const reg_entry *rreg;
1655 1.1 christos char *reg_name;
1656 1.1 christos
1657 1.1 christos /* Check whether the register is in registers table. */
1658 1.1 christos if (r >= MAX_REG && r < MAX_PREG)
1659 1.1 christos rreg = &cr16_pregtab[r - MAX_REG];
1660 1.1 christos /* Register not found. */
1661 1.1 christos else
1662 1.1 christos {
1663 1.1 christos as_bad (_("Unknown processor register : `%d'"), r);
1664 1.1 christos return 0;
1665 1.1 christos }
1666 1.1 christos
1667 1.1 christos reg_name = rreg->name;
1668 1.1 christos
1669 1.1.1.6 christos /* Issue a error message when register pair is illegal. */
1670 1.1.1.6 christos #define PROCREG_IMAGE_ERR \
1671 1.1.1.6 christos as_bad (_("Illegal processor register (`%s') in Instruction: `%s'"), \
1672 1.1.1.6 christos reg_name, ins_parse); \
1673 1.1 christos break;
1674 1.1 christos
1675 1.1 christos switch (rreg->type)
1676 1.1 christos {
1677 1.1 christos case CR16_P_REGTYPE:
1678 1.1 christos return rreg->image;
1679 1.1 christos default:
1680 1.1 christos PROCREG_IMAGE_ERR;
1681 1.1 christos }
1682 1.1 christos
1683 1.1 christos return 0;
1684 1.1 christos }
1685 1.1 christos
1686 1.1.1.4 christos /* Retrieve the opcode image of a given processor register.
1687 1.1 christos If the register is illegal for the current instruction,
1688 1.1 christos issue an error. */
1689 1.1 christos static int
1690 1.1 christos getprocregp_image (int r)
1691 1.1 christos {
1692 1.1 christos const reg_entry *rreg;
1693 1.1 christos char *reg_name;
1694 1.1 christos int pregptab_disp = 0;
1695 1.1 christos
1696 1.1 christos /* Check whether the register is in registers table. */
1697 1.1 christos if (r >= MAX_REG && r < MAX_PREG)
1698 1.1 christos {
1699 1.1 christos r = r - MAX_REG;
1700 1.1 christos switch (r)
1701 1.1.1.6 christos {
1702 1.1.1.6 christos case 4: pregptab_disp = 1; break;
1703 1.1.1.6 christos case 6: pregptab_disp = 2; break;
1704 1.1.1.6 christos case 8:
1705 1.1.1.6 christos case 9:
1706 1.1.1.6 christos case 10:
1707 1.1.1.6 christos pregptab_disp = 3; break;
1708 1.1.1.6 christos case 12:
1709 1.1.1.6 christos pregptab_disp = 4; break;
1710 1.1.1.6 christos case 14:
1711 1.1.1.6 christos pregptab_disp = 5; break;
1712 1.1.1.6 christos default: break;
1713 1.1.1.6 christos }
1714 1.1 christos rreg = &cr16_pregptab[r - pregptab_disp];
1715 1.1 christos }
1716 1.1 christos /* Register not found. */
1717 1.1 christos else
1718 1.1 christos {
1719 1.1 christos as_bad (_("Unknown processor register (32 bit) : `%d'"), r);
1720 1.1 christos return 0;
1721 1.1 christos }
1722 1.1 christos
1723 1.1 christos reg_name = rreg->name;
1724 1.1 christos
1725 1.1.1.6 christos /* Issue a error message when register pair is illegal. */
1726 1.1.1.6 christos #define PROCREGP_IMAGE_ERR \
1727 1.1.1.6 christos as_bad (_("Illegal 32 bit - processor register (`%s') in Instruction: `%s'"), \
1728 1.1.1.6 christos reg_name, ins_parse); \
1729 1.1 christos break;
1730 1.1 christos
1731 1.1 christos switch (rreg->type)
1732 1.1 christos {
1733 1.1 christos case CR16_P_REGTYPE:
1734 1.1 christos return rreg->image;
1735 1.1 christos default:
1736 1.1 christos PROCREGP_IMAGE_ERR;
1737 1.1 christos }
1738 1.1 christos
1739 1.1 christos return 0;
1740 1.1 christos }
1741 1.1 christos
1742 1.1 christos /* Routine used to represent integer X using NBITS bits. */
1743 1.1 christos
1744 1.1 christos static long
1745 1.1 christos getconstant (long x, int nbits)
1746 1.1 christos {
1747 1.1.1.6 christos if ((unsigned) nbits >= sizeof (x) * CHAR_BIT)
1748 1.1.1.6 christos return x;
1749 1.1.1.6 christos return x & ((1UL << nbits) - 1);
1750 1.1 christos }
1751 1.1 christos
1752 1.1 christos /* Print a constant value to 'output_opcode':
1753 1.1 christos ARG holds the operand's type and value.
1754 1.1 christos SHIFT represents the location of the operand to be print into.
1755 1.1 christos NBITS determines the size (in bits) of the constant. */
1756 1.1 christos
1757 1.1 christos static void
1758 1.1 christos print_constant (int nbits, int shift, argument *arg)
1759 1.1 christos {
1760 1.1 christos unsigned long mask = 0;
1761 1.1.1.6 christos unsigned long constant = getconstant (arg->constant, nbits);
1762 1.1 christos
1763 1.1 christos switch (nbits)
1764 1.1 christos {
1765 1.1 christos case 32:
1766 1.1 christos case 28:
1767 1.1 christos /* mask the upper part of the constant, that is, the bits
1768 1.1.1.6 christos going to the lowest byte of output_opcode[0].
1769 1.1.1.6 christos The upper part of output_opcode[1] is always filled,
1770 1.1.1.6 christos therefore it is always masked with 0xFFFF. */
1771 1.1 christos mask = (1 << (nbits - 16)) - 1;
1772 1.1 christos /* Divide the constant between two consecutive words :
1773 1.1.1.6 christos 0 1 2 3
1774 1.1.1.6 christos +---------+---------+---------+---------+
1775 1.1.1.6 christos | | X X X X | x X x X | |
1776 1.1.1.6 christos +---------+---------+---------+---------+
1777 1.1.1.6 christos output_opcode[0] output_opcode[1] */
1778 1.1 christos
1779 1.1 christos CR16_PRINT (0, (constant >> WORD_SHIFT) & mask, 0);
1780 1.1.1.6 christos CR16_PRINT (1, constant & 0xFFFF, WORD_SHIFT);
1781 1.1 christos break;
1782 1.1 christos
1783 1.1 christos case 21:
1784 1.1.1.4 christos if ((nbits == 21) && (IS_INSN_TYPE (LD_STOR_INS)))
1785 1.1.1.4 christos nbits = 20;
1786 1.1.1.4 christos /* Fall through. */
1787 1.1 christos case 24:
1788 1.1 christos case 22:
1789 1.1 christos case 20:
1790 1.1 christos /* mask the upper part of the constant, that is, the bits
1791 1.1.1.6 christos going to the lowest byte of output_opcode[0].
1792 1.1.1.6 christos The upper part of output_opcode[1] is always filled,
1793 1.1.1.6 christos therefore it is always masked with 0xFFFF. */
1794 1.1 christos mask = (1 << (nbits - 16)) - 1;
1795 1.1 christos /* Divide the constant between two consecutive words :
1796 1.1.1.6 christos 0 1 2 3
1797 1.1.1.6 christos +---------+---------+---------+---------+
1798 1.1.1.6 christos | | X X X X | - X - X | |
1799 1.1.1.6 christos +---------+---------+---------+---------+
1800 1.1.1.6 christos output_opcode[0] output_opcode[1] */
1801 1.1.1.6 christos
1802 1.1.1.6 christos if (instruction->size > 2 && shift == WORD_SHIFT)
1803 1.1.1.6 christos {
1804 1.1.1.6 christos if (arg->type == arg_idxrp)
1805 1.1.1.6 christos {
1806 1.1.1.6 christos CR16_PRINT (0, ((constant >> WORD_SHIFT) & mask) << 8, 0);
1807 1.1.1.6 christos CR16_PRINT (1, constant & 0xFFFF, WORD_SHIFT);
1808 1.1.1.6 christos }
1809 1.1.1.6 christos else
1810 1.1.1.6 christos {
1811 1.1.1.6 christos CR16_PRINT (0,
1812 1.1.1.6 christos ((((constant >> WORD_SHIFT) & mask & 0xf) << 8)
1813 1.1.1.6 christos | (((constant >> WORD_SHIFT) & mask & 0xf0) >> 4)),
1814 1.1.1.6 christos 0);
1815 1.1.1.6 christos CR16_PRINT (1, constant & 0xFFFF, WORD_SHIFT);
1816 1.1.1.6 christos }
1817 1.1.1.6 christos }
1818 1.1 christos else
1819 1.1.1.6 christos CR16_PRINT (0, constant, shift);
1820 1.1 christos break;
1821 1.1 christos
1822 1.1 christos case 14:
1823 1.1 christos if (arg->type == arg_idxrp)
1824 1.1.1.6 christos {
1825 1.1.1.6 christos if (instruction->size == 2)
1826 1.1.1.6 christos {
1827 1.1.1.6 christos CR16_PRINT (0, (constant) & 0xf, shift); /* 0-3 bits. */
1828 1.1.1.6 christos CR16_PRINT (0, (constant >> 4) & 0x3, shift + 20); /* 4-5 bits. */
1829 1.1.1.6 christos CR16_PRINT (0, (constant >> 6) & 0x3, shift + 14); /* 6-7 bits. */
1830 1.1.1.6 christos CR16_PRINT (0, (constant >> 8) & 0x3f, shift + 8); /* 8-13 bits. */
1831 1.1.1.6 christos }
1832 1.1.1.6 christos else
1833 1.1.1.6 christos CR16_PRINT (0, constant, shift);
1834 1.1.1.6 christos }
1835 1.1 christos break;
1836 1.1 christos
1837 1.1 christos case 16:
1838 1.1 christos case 12:
1839 1.1 christos /* When instruction size is 3 and 'shift' is 16, a 16-bit constant is
1840 1.1.1.6 christos always filling the upper part of output_opcode[1]. If we mistakenly
1841 1.1.1.6 christos write it to output_opcode[0], the constant prefix (that is, 'match')
1842 1.1.1.6 christos will be overridden.
1843 1.1.1.6 christos 0 1 2 3
1844 1.1.1.6 christos +---------+---------+---------+---------+
1845 1.1.1.6 christos | 'match' | | X X X X | |
1846 1.1.1.6 christos +---------+---------+---------+---------+
1847 1.1.1.6 christos output_opcode[0] output_opcode[1] */
1848 1.1 christos
1849 1.1.1.6 christos if (instruction->size > 2 && shift == WORD_SHIFT)
1850 1.1.1.6 christos CR16_PRINT (1, constant, WORD_SHIFT);
1851 1.1 christos else
1852 1.1.1.6 christos CR16_PRINT (0, constant, shift);
1853 1.1 christos break;
1854 1.1 christos
1855 1.1 christos case 8:
1856 1.1.1.6 christos CR16_PRINT (0, (constant / 2) & 0xf, shift);
1857 1.1.1.6 christos CR16_PRINT (0, (constant / 2) >> 4, shift + 8);
1858 1.1 christos break;
1859 1.1 christos
1860 1.1 christos default:
1861 1.1.1.6 christos CR16_PRINT (0, constant, shift);
1862 1.1 christos break;
1863 1.1 christos }
1864 1.1 christos }
1865 1.1 christos
1866 1.1 christos /* Print an operand to 'output_opcode', which later on will be
1867 1.1 christos printed to the object file:
1868 1.1 christos ARG holds the operand's type, size and value.
1869 1.1 christos SHIFT represents the printing location of operand.
1870 1.1 christos NBITS determines the size (in bits) of a constant operand. */
1871 1.1 christos
1872 1.1 christos static void
1873 1.1 christos print_operand (int nbits, int shift, argument *arg)
1874 1.1 christos {
1875 1.1 christos switch (arg->type)
1876 1.1 christos {
1877 1.1 christos case arg_cc:
1878 1.1 christos CR16_PRINT (0, arg->cc, shift);
1879 1.1 christos break;
1880 1.1 christos
1881 1.1 christos case arg_r:
1882 1.1 christos CR16_PRINT (0, getreg_image (arg->r), shift);
1883 1.1 christos break;
1884 1.1 christos
1885 1.1 christos case arg_rp:
1886 1.1 christos CR16_PRINT (0, getregp_image (arg->rp), shift);
1887 1.1 christos break;
1888 1.1 christos
1889 1.1 christos case arg_pr:
1890 1.1 christos CR16_PRINT (0, getprocreg_image (arg->pr), shift);
1891 1.1 christos break;
1892 1.1 christos
1893 1.1 christos case arg_prp:
1894 1.1 christos CR16_PRINT (0, getprocregp_image (arg->prp), shift);
1895 1.1 christos break;
1896 1.1 christos
1897 1.1 christos case arg_idxrp:
1898 1.1 christos /* 16 12 8 6 0
1899 1.1.1.6 christos +-----------------------------+
1900 1.1.1.6 christos | r_index | disp | rp_base |
1901 1.1.1.6 christos +-----------------------------+ */
1902 1.1 christos
1903 1.1 christos if (instruction->size == 3)
1904 1.1.1.6 christos {
1905 1.1.1.6 christos CR16_PRINT (0, getidxregp_image (arg->rp), 0);
1906 1.1.1.6 christos CR16_PRINT (0, getreg_image (arg->i_r) & 1, 3);
1907 1.1.1.6 christos }
1908 1.1 christos else
1909 1.1.1.6 christos {
1910 1.1.1.6 christos CR16_PRINT (0, getidxregp_image (arg->rp), 16);
1911 1.1.1.6 christos CR16_PRINT (0, getreg_image (arg->i_r) & 1, 19);
1912 1.1.1.6 christos }
1913 1.1 christos print_constant (nbits, shift, arg);
1914 1.1 christos break;
1915 1.1 christos
1916 1.1 christos case arg_idxr:
1917 1.1.1.6 christos CR16_PRINT (0, getreg_image (arg->i_r) & 1,
1918 1.1.1.6 christos (IS_INSN_TYPE (CSTBIT_INS)
1919 1.1.1.6 christos && instruction->mnemonic[4] == 'b') ? 23 : 24);
1920 1.1 christos print_constant (nbits, shift, arg);
1921 1.1 christos break;
1922 1.1 christos
1923 1.1 christos case arg_ic:
1924 1.1 christos case arg_c:
1925 1.1 christos print_constant (nbits, shift, arg);
1926 1.1 christos break;
1927 1.1 christos
1928 1.1 christos case arg_rbase:
1929 1.1 christos CR16_PRINT (0, getreg_image (arg->r), shift);
1930 1.1 christos break;
1931 1.1 christos
1932 1.1 christos case arg_cr:
1933 1.1.1.6 christos print_constant (nbits, shift, arg);
1934 1.1 christos /* Add the register argument to the output_opcode. */
1935 1.1.1.6 christos CR16_PRINT (0, getreg_image (arg->r), shift - 16);
1936 1.1 christos break;
1937 1.1 christos
1938 1.1 christos case arg_crp:
1939 1.1.1.6 christos print_constant (nbits, shift, arg);
1940 1.1.1.6 christos if ((IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
1941 1.1.1.6 christos && instruction->size == 1)
1942 1.1.1.6 christos CR16_PRINT (0, getregp_image (arg->rp), 16);
1943 1.1.1.6 christos else if (instruction->size > 1)
1944 1.1.1.6 christos CR16_PRINT (0, getregp_image (arg->rp), (shift + 16) & 31);
1945 1.1 christos else
1946 1.1.1.6 christos CR16_PRINT (0, getregp_image (arg->rp), shift);
1947 1.1 christos break;
1948 1.1 christos
1949 1.1 christos default:
1950 1.1 christos break;
1951 1.1 christos }
1952 1.1 christos }
1953 1.1 christos
1954 1.1 christos /* Retrieve the number of operands for the current assembled instruction. */
1955 1.1 christos
1956 1.1 christos static int
1957 1.1 christos get_number_of_operands (void)
1958 1.1 christos {
1959 1.1 christos int i;
1960 1.1 christos
1961 1.1 christos for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
1962 1.1 christos ;
1963 1.1 christos return i;
1964 1.1 christos }
1965 1.1 christos
1966 1.1 christos /* Verify that the number NUM can be represented in BITS bits (that is,
1967 1.1 christos within its permitted range), based on the instruction's FLAGS.
1968 1.1 christos If UPDATE is nonzero, update the value of NUM if necessary.
1969 1.1 christos Return OP_LEGAL upon success, actual error type upon failure. */
1970 1.1 christos
1971 1.1 christos static op_err
1972 1.1 christos check_range (long *num, int bits, int unsigned flags, int update)
1973 1.1 christos {
1974 1.1.1.6 christos int32_t min, max;
1975 1.1.1.3 christos op_err retval = OP_LEGAL;
1976 1.1.1.6 christos int32_t value = *num;
1977 1.1 christos
1978 1.1 christos /* Verify operand value is even. */
1979 1.1 christos if (flags & OP_EVEN)
1980 1.1 christos {
1981 1.1 christos if (value % 2)
1982 1.1.1.6 christos return OP_NOT_EVEN;
1983 1.1 christos }
1984 1.1 christos
1985 1.1 christos if (flags & OP_DEC)
1986 1.1 christos {
1987 1.1 christos value -= 1;
1988 1.1 christos if (update)
1989 1.1.1.6 christos *num = value;
1990 1.1 christos }
1991 1.1 christos
1992 1.1 christos if (flags & OP_SHIFT)
1993 1.1 christos {
1994 1.1 christos value >>= 1;
1995 1.1 christos if (update)
1996 1.1.1.6 christos *num = value;
1997 1.1 christos }
1998 1.1 christos else if (flags & OP_SHIFT_DEC)
1999 1.1 christos {
2000 1.1 christos value = (value >> 1) - 1;
2001 1.1 christos if (update)
2002 1.1.1.6 christos *num = value;
2003 1.1 christos }
2004 1.1 christos
2005 1.1 christos if (flags & OP_ABS20)
2006 1.1 christos {
2007 1.1 christos if (value > 0xEFFFF)
2008 1.1.1.6 christos return OP_OUT_OF_RANGE;
2009 1.1 christos }
2010 1.1 christos
2011 1.1 christos if (flags & OP_ESC)
2012 1.1 christos {
2013 1.1 christos if (value == 0xB || value == 0x9)
2014 1.1.1.6 christos return OP_OUT_OF_RANGE;
2015 1.1 christos else if (value == -1)
2016 1.1.1.6 christos {
2017 1.1.1.6 christos if (update)
2018 1.1.1.6 christos *num = 9;
2019 1.1.1.6 christos return retval;
2020 1.1.1.6 christos }
2021 1.1 christos }
2022 1.1 christos
2023 1.1 christos if (flags & OP_ESC1)
2024 1.1 christos {
2025 1.1 christos if (value > 13)
2026 1.1.1.6 christos return OP_OUT_OF_RANGE;
2027 1.1 christos }
2028 1.1 christos
2029 1.1.1.6 christos if (bits == 0)
2030 1.1.1.6 christos {
2031 1.1.1.6 christos if (value != 0)
2032 1.1.1.6 christos retval = OP_OUT_OF_RANGE;
2033 1.1.1.6 christos return retval;
2034 1.1.1.6 christos }
2035 1.1.1.6 christos
2036 1.1.1.6 christos if (flags & OP_SIGNED)
2037 1.1.1.6 christos {
2038 1.1.1.6 christos max = (1U << (bits - 1)) - 1;
2039 1.1.1.6 christos min = - (1U << (bits - 1));
2040 1.1.1.6 christos if (value > max || value < min)
2041 1.1.1.6 christos retval = OP_OUT_OF_RANGE;
2042 1.1.1.6 christos }
2043 1.1.1.6 christos else if (flags & OP_UNSIGNED)
2044 1.1.1.6 christos {
2045 1.1.1.6 christos max = (1U << (bits - 1) << 1) - 1;
2046 1.1.1.6 christos if ((uint32_t) value > (uint32_t) max)
2047 1.1.1.6 christos retval = OP_OUT_OF_RANGE;
2048 1.1.1.6 christos }
2049 1.1.1.6 christos else if (flags & OP_NEG)
2050 1.1.1.6 christos {
2051 1.1.1.6 christos min = - ((1U << (bits - 1)) - 1);
2052 1.1.1.6 christos if (value < min)
2053 1.1.1.6 christos retval = OP_OUT_OF_RANGE;
2054 1.1.1.6 christos }
2055 1.1.1.6 christos return retval;
2056 1.1 christos }
2057 1.1 christos
2058 1.1.1.4 christos /* Bunch of error checking.
2059 1.1 christos The checks are made after a matching instruction was found. */
2060 1.1 christos
2061 1.1 christos static void
2062 1.1 christos warn_if_needed (ins *insn)
2063 1.1 christos {
2064 1.1 christos /* If the post-increment address mode is used and the load/store
2065 1.1 christos source register is the same as rbase, the result of the
2066 1.1 christos instruction is undefined. */
2067 1.1 christos if (IS_INSN_TYPE (LD_STOR_INS_INC))
2068 1.1 christos {
2069 1.1 christos /* Enough to verify that one of the arguments is a simple reg. */
2070 1.1 christos if ((insn->arg[0].type == arg_r) || (insn->arg[1].type == arg_r))
2071 1.1.1.6 christos if (insn->arg[0].r == insn->arg[1].r)
2072 1.1.1.6 christos as_bad (_("Same src/dest register is used (`r%d'), "
2073 1.1.1.6 christos "result is undefined"), insn->arg[0].r);
2074 1.1 christos }
2075 1.1 christos
2076 1.1 christos if (IS_INSN_MNEMONIC ("pop")
2077 1.1 christos || IS_INSN_MNEMONIC ("push")
2078 1.1 christos || IS_INSN_MNEMONIC ("popret"))
2079 1.1 christos {
2080 1.1 christos unsigned int count = insn->arg[0].constant, reg_val;
2081 1.1 christos
2082 1.1.1.4 christos /* Check if count operand caused to save/retrieve the RA twice
2083 1.1.1.6 christos to generate warning message. */
2084 1.1.1.6 christos if (insn->nargs > 2)
2085 1.1.1.6 christos {
2086 1.1.1.6 christos reg_val = getreg_image (insn->arg[1].r);
2087 1.1.1.6 christos
2088 1.1.1.6 christos if ( ((reg_val == 9) && (count > 7))
2089 1.1.1.6 christos || ((reg_val == 10) && (count > 6))
2090 1.1.1.6 christos || ((reg_val == 11) && (count > 5))
2091 1.1.1.6 christos || ((reg_val == 12) && (count > 4))
2092 1.1.1.6 christos || ((reg_val == 13) && (count > 2))
2093 1.1.1.6 christos || ((reg_val == 14) && (count > 0)))
2094 1.1.1.6 christos as_warn (_("RA register is saved twice."));
2095 1.1.1.6 christos
2096 1.1.1.6 christos /* Check if the third operand is "RA" or "ra" */
2097 1.1.1.6 christos if (!(((insn->arg[2].r) == ra) || ((insn->arg[2].r) == RA)))
2098 1.1.1.6 christos as_bad (_("`%s' Illegal use of registers."), ins_parse);
2099 1.1.1.6 christos }
2100 1.1 christos
2101 1.1 christos if (insn->nargs > 1)
2102 1.1.1.6 christos {
2103 1.1.1.6 christos reg_val = getreg_image (insn->arg[1].r);
2104 1.1 christos
2105 1.1.1.6 christos /* If register is a register pair ie r12/r13/r14 in operand1, then
2106 1.1.1.6 christos the count constant should be validated. */
2107 1.1.1.6 christos if (((reg_val == 11) && (count > 7))
2108 1.1.1.6 christos || ((reg_val == 12) && (count > 6))
2109 1.1.1.6 christos || ((reg_val == 13) && (count > 4))
2110 1.1.1.6 christos || ((reg_val == 14) && (count > 2))
2111 1.1.1.6 christos || ((reg_val == 15) && (count > 0)))
2112 1.1.1.6 christos as_bad (_("`%s' Illegal count-register combination."), ins_parse);
2113 1.1.1.6 christos }
2114 1.1.1.6 christos else
2115 1.1.1.6 christos {
2116 1.1.1.6 christos /* Check if the operand is "RA" or "ra" */
2117 1.1.1.6 christos if (!(((insn->arg[0].r) == ra) || ((insn->arg[0].r) == RA)))
2118 1.1.1.6 christos as_bad (_("`%s' Illegal use of register."), ins_parse);
2119 1.1.1.6 christos }
2120 1.1 christos }
2121 1.1 christos
2122 1.1 christos /* Some instruction assume the stack pointer as rptr operand.
2123 1.1 christos Issue an error when the register to be loaded is also SP. */
2124 1.1 christos if (instruction->flags & NO_SP)
2125 1.1 christos {
2126 1.1 christos if (getreg_image (insn->arg[1].r) == getreg_image (sp))
2127 1.1.1.6 christos as_bad (_("`%s' has undefined result"), ins_parse);
2128 1.1 christos }
2129 1.1 christos
2130 1.1 christos /* If the rptr register is specified as one of the registers to be loaded,
2131 1.1 christos the final contents of rptr are undefined. Thus, we issue an error. */
2132 1.1 christos if (instruction->flags & NO_RPTR)
2133 1.1 christos {
2134 1.1 christos if ((1 << getreg_image (insn->arg[0].r)) & insn->arg[1].constant)
2135 1.1.1.6 christos as_bad (_("Same src/dest register is used (`r%d'),result is undefined"),
2136 1.1.1.6 christos getreg_image (insn->arg[0].r));
2137 1.1 christos }
2138 1.1 christos }
2139 1.1 christos
2140 1.1 christos /* In some cases, we need to adjust the instruction pointer although a
2141 1.1 christos match was already found. Here, we gather all these cases.
2142 1.1 christos Returns 1 if instruction pointer was adjusted, otherwise 0. */
2143 1.1 christos
2144 1.1 christos static int
2145 1.1 christos adjust_if_needed (ins *insn ATTRIBUTE_UNUSED)
2146 1.1 christos {
2147 1.1 christos int ret_value = 0;
2148 1.1 christos
2149 1.1 christos if ((IS_INSN_TYPE (CSTBIT_INS)) || (IS_INSN_TYPE (LD_STOR_INS)))
2150 1.1 christos {
2151 1.1 christos if ((instruction->operands[0].op_type == abs24)
2152 1.1.1.6 christos && ((insn->arg[0].constant) > 0xF00000))
2153 1.1.1.6 christos {
2154 1.1.1.6 christos insn->arg[0].constant &= 0xFFFFF;
2155 1.1.1.6 christos instruction--;
2156 1.1.1.6 christos ret_value = 1;
2157 1.1.1.6 christos }
2158 1.1 christos }
2159 1.1 christos
2160 1.1 christos return ret_value;
2161 1.1 christos }
2162 1.1 christos
2163 1.1 christos /* Assemble a single instruction:
2164 1.1 christos INSN is already parsed (that is, all operand values and types are set).
2165 1.1 christos For instruction to be assembled, we need to find an appropriate template in
2166 1.1 christos the instruction table, meeting the following conditions:
2167 1.1 christos 1: Has the same number of operands.
2168 1.1 christos 2: Has the same operand types.
2169 1.1 christos 3: Each operand size is sufficient to represent the instruction's values.
2170 1.1 christos Returns 1 upon success, 0 upon failure. */
2171 1.1 christos
2172 1.1 christos static int
2173 1.1.1.3 christos assemble_insn (const char *mnemonic, ins *insn)
2174 1.1 christos {
2175 1.1 christos /* Type of each operand in the current template. */
2176 1.1 christos argtype cur_type[MAX_OPERANDS];
2177 1.1 christos /* Size (in bits) of each operand in the current template. */
2178 1.1 christos unsigned int cur_size[MAX_OPERANDS];
2179 1.1 christos /* Flags of each operand in the current template. */
2180 1.1 christos unsigned int cur_flags[MAX_OPERANDS];
2181 1.1 christos /* Instruction type to match. */
2182 1.1 christos unsigned int ins_type;
2183 1.1 christos /* Boolean flag to mark whether a match was found. */
2184 1.1 christos int match = 0;
2185 1.1 christos int i;
2186 1.1 christos /* Nonzero if an instruction with same number of operands was found. */
2187 1.1 christos int found_same_number_of_operands = 0;
2188 1.1 christos /* Nonzero if an instruction with same argument types was found. */
2189 1.1 christos int found_same_argument_types = 0;
2190 1.1 christos /* Nonzero if a constant was found within the required range. */
2191 1.1 christos int found_const_within_range = 0;
2192 1.1 christos /* Argument number of an operand with invalid type. */
2193 1.1 christos int invalid_optype = -1;
2194 1.1 christos /* Argument number of an operand with invalid constant value. */
2195 1.1 christos int invalid_const = -1;
2196 1.1 christos /* Operand error (used for issuing various constant error messages). */
2197 1.1 christos op_err op_error, const_err = OP_LEGAL;
2198 1.1 christos
2199 1.1.1.6 christos /* Retrieve data (based on FUNC) for each operand of a given instruction. */
2200 1.1.1.6 christos #define GET_CURRENT_DATA(FUNC, ARRAY) \
2201 1.1.1.6 christos for (i = 0; i < insn->nargs; i++) \
2202 1.1 christos ARRAY[i] = FUNC (instruction->operands[i].op_type)
2203 1.1 christos
2204 1.1 christos #define GET_CURRENT_TYPE GET_CURRENT_DATA (get_optype, cur_type)
2205 1.1 christos #define GET_CURRENT_SIZE GET_CURRENT_DATA (get_opbits, cur_size)
2206 1.1 christos #define GET_CURRENT_FLAGS GET_CURRENT_DATA (get_opflags, cur_flags)
2207 1.1 christos
2208 1.1 christos /* Instruction has no operands -> only copy the constant opcode. */
2209 1.1 christos if (insn->nargs == 0)
2210 1.1 christos {
2211 1.1 christos output_opcode[0] = BIN (instruction->match, instruction->match_bits);
2212 1.1 christos return 1;
2213 1.1 christos }
2214 1.1 christos
2215 1.1 christos /* In some case, same mnemonic can appear with different instruction types.
2216 1.1 christos For example, 'storb' is supported with 3 different types :
2217 1.1 christos LD_STOR_INS, LD_STOR_INS_INC, STOR_IMM_INS.
2218 1.1 christos We assume that when reaching this point, the instruction type was
2219 1.1 christos pre-determined. We need to make sure that the type stays the same
2220 1.1 christos during a search for matching instruction. */
2221 1.1 christos ins_type = CR16_INS_TYPE (instruction->flags);
2222 1.1 christos
2223 1.1 christos while (/* Check that match is still not found. */
2224 1.1.1.6 christos match != 1
2225 1.1.1.6 christos /* Check we didn't get to end of table. */
2226 1.1.1.6 christos && instruction->mnemonic != NULL
2227 1.1.1.6 christos /* Check that the actual mnemonic is still available. */
2228 1.1.1.6 christos && IS_INSN_MNEMONIC (mnemonic)
2229 1.1.1.6 christos /* Check that the instruction type wasn't changed. */
2230 1.1.1.6 christos && IS_INSN_TYPE (ins_type))
2231 1.1 christos {
2232 1.1 christos /* Check whether number of arguments is legal. */
2233 1.1 christos if (get_number_of_operands () != insn->nargs)
2234 1.1.1.6 christos goto next_insn;
2235 1.1 christos found_same_number_of_operands = 1;
2236 1.1 christos
2237 1.1 christos /* Initialize arrays with data of each operand in current template. */
2238 1.1 christos GET_CURRENT_TYPE;
2239 1.1 christos GET_CURRENT_SIZE;
2240 1.1 christos GET_CURRENT_FLAGS;
2241 1.1 christos
2242 1.1 christos /* Check for type compatibility. */
2243 1.1 christos for (i = 0; i < insn->nargs; i++)
2244 1.1.1.6 christos {
2245 1.1.1.6 christos if (cur_type[i] != insn->arg[i].type)
2246 1.1.1.6 christos {
2247 1.1.1.6 christos if (invalid_optype == -1)
2248 1.1.1.6 christos invalid_optype = i + 1;
2249 1.1.1.6 christos goto next_insn;
2250 1.1.1.6 christos }
2251 1.1.1.6 christos }
2252 1.1 christos found_same_argument_types = 1;
2253 1.1 christos
2254 1.1 christos for (i = 0; i < insn->nargs; i++)
2255 1.1.1.6 christos {
2256 1.1.1.6 christos /* If 'bal' instruction size is '2' and reg operand is not 'ra'
2257 1.1.1.6 christos then goto next instruction. */
2258 1.1.1.6 christos if (IS_INSN_MNEMONIC ("bal") && (i == 0)
2259 1.1.1.6 christos && (instruction->size == 2) && (insn->arg[i].rp != 14))
2260 1.1.1.6 christos goto next_insn;
2261 1.1.1.6 christos
2262 1.1.1.6 christos /* If 'storb' instruction with 'sp' reg and 16-bit disp of
2263 1.1.1.6 christos * reg-pair, leads to undefined trap, so this should use
2264 1.1.1.6 christos * 20-bit disp of reg-pair. */
2265 1.1.1.6 christos if (IS_INSN_MNEMONIC ("storb") && (instruction->size == 2)
2266 1.1.1.6 christos && (insn->arg[i].r == 15) && (insn->arg[i + 1].type == arg_crp))
2267 1.1.1.6 christos goto next_insn;
2268 1.1.1.6 christos
2269 1.1.1.6 christos /* Only check range - don't update the constant's value, since the
2270 1.1.1.6 christos current instruction may not be the last we try to match.
2271 1.1.1.6 christos The constant's value will be updated later, right before printing
2272 1.1.1.6 christos it to the object file. */
2273 1.1.1.6 christos if ((insn->arg[i].X_op == O_constant)
2274 1.1.1.6 christos && (op_error = check_range (&insn->arg[i].constant, cur_size[i],
2275 1.1.1.6 christos cur_flags[i], 0)))
2276 1.1.1.6 christos {
2277 1.1.1.6 christos if (invalid_const == -1)
2278 1.1.1.6 christos {
2279 1.1.1.6 christos invalid_const = i + 1;
2280 1.1.1.6 christos const_err = op_error;
2281 1.1.1.6 christos }
2282 1.1.1.6 christos goto next_insn;
2283 1.1.1.6 christos }
2284 1.1.1.6 christos /* For symbols, we make sure the relocation size (which was already
2285 1.1.1.6 christos determined) is sufficient. */
2286 1.1.1.6 christos else if ((insn->arg[i].X_op == O_symbol)
2287 1.1.1.6 christos && ((bfd_reloc_type_lookup (stdoutput, insn->rtype))->bitsize
2288 1.1.1.6 christos > cur_size[i]))
2289 1.1.1.6 christos goto next_insn;
2290 1.1.1.6 christos }
2291 1.1 christos found_const_within_range = 1;
2292 1.1 christos
2293 1.1 christos /* If we got till here -> Full match is found. */
2294 1.1 christos match = 1;
2295 1.1 christos break;
2296 1.1 christos
2297 1.1.1.6 christos /* Try again with next instruction. */
2298 1.1.1.6 christos next_insn:
2299 1.1 christos instruction++;
2300 1.1 christos }
2301 1.1 christos
2302 1.1 christos if (!match)
2303 1.1 christos {
2304 1.1 christos /* We haven't found a match - instruction can't be assembled. */
2305 1.1 christos if (!found_same_number_of_operands)
2306 1.1.1.6 christos as_bad (_("Incorrect number of operands"));
2307 1.1 christos else if (!found_same_argument_types)
2308 1.1.1.6 christos as_bad (_("Illegal type of operand (arg %d)"), invalid_optype);
2309 1.1 christos else if (!found_const_within_range)
2310 1.1.1.6 christos {
2311 1.1.1.6 christos switch (const_err)
2312 1.1.1.6 christos {
2313 1.1.1.6 christos case OP_OUT_OF_RANGE:
2314 1.1.1.6 christos as_bad (_("Operand out of range (arg %d)"), invalid_const);
2315 1.1.1.6 christos break;
2316 1.1.1.6 christos case OP_NOT_EVEN:
2317 1.1.1.6 christos as_bad (_("Operand has odd displacement (arg %d)"), invalid_const);
2318 1.1.1.6 christos break;
2319 1.1.1.6 christos default:
2320 1.1.1.6 christos as_bad (_("Illegal operand (arg %d)"), invalid_const);
2321 1.1.1.6 christos break;
2322 1.1.1.6 christos }
2323 1.1.1.6 christos }
2324 1.1 christos
2325 1.1.1.6 christos return 0;
2326 1.1 christos }
2327 1.1 christos else
2328 1.1 christos /* Full match - print the encoding to output file. */
2329 1.1 christos {
2330 1.1.1.4 christos /* Make further checking (such that couldn't be made earlier).
2331 1.1.1.6 christos Warn the user if necessary. */
2332 1.1 christos warn_if_needed (insn);
2333 1.1 christos
2334 1.1 christos /* Check whether we need to adjust the instruction pointer. */
2335 1.1 christos if (adjust_if_needed (insn))
2336 1.1.1.6 christos /* If instruction pointer was adjusted, we need to update
2337 1.1.1.6 christos the size of the current template operands. */
2338 1.1.1.6 christos GET_CURRENT_SIZE;
2339 1.1 christos
2340 1.1 christos for (i = 0; i < insn->nargs; i++)
2341 1.1.1.6 christos {
2342 1.1.1.6 christos int j = instruction->flags & REVERSE_MATCH ?
2343 1.1.1.6 christos i == 0 ? 1 :
2344 1.1.1.6 christos i == 1 ? 0 : i :
2345 1.1.1.6 christos i;
2346 1.1.1.6 christos
2347 1.1.1.6 christos /* This time, update constant value before printing it. */
2348 1.1.1.6 christos if ((insn->arg[j].X_op == O_constant)
2349 1.1.1.6 christos && (check_range (&insn->arg[j].constant, cur_size[j],
2350 1.1.1.6 christos cur_flags[j], 1) != OP_LEGAL))
2351 1.1.1.6 christos as_fatal (_("Illegal operand (arg %d)"), j+1);
2352 1.1.1.6 christos }
2353 1.1 christos
2354 1.1 christos /* First, copy the instruction's opcode. */
2355 1.1 christos output_opcode[0] = BIN (instruction->match, instruction->match_bits);
2356 1.1 christos
2357 1.1 christos for (i = 0; i < insn->nargs; i++)
2358 1.1.1.6 christos {
2359 1.1.1.6 christos /* For BAL (ra),disp17 instruction only. And also set the
2360 1.1.1.6 christos DISP24a relocation type. */
2361 1.1.1.6 christos if (IS_INSN_MNEMONIC ("bal") && (instruction->size == 2) && i == 0)
2362 1.1.1.6 christos {
2363 1.1.1.6 christos insn->rtype = BFD_RELOC_CR16_DISP24a;
2364 1.1.1.6 christos continue;
2365 1.1.1.6 christos }
2366 1.1.1.6 christos cur_arg_num = i;
2367 1.1.1.6 christos print_operand (cur_size[i], instruction->operands[i].shift,
2368 1.1.1.6 christos &insn->arg[i]);
2369 1.1.1.6 christos }
2370 1.1 christos }
2371 1.1 christos
2372 1.1 christos return 1;
2373 1.1 christos }
2374 1.1 christos
2375 1.1 christos /* Print the instruction.
2376 1.1 christos Handle also cases where the instruction is relaxable/relocatable. */
2377 1.1 christos
2378 1.1 christos static void
2379 1.1 christos print_insn (ins *insn)
2380 1.1 christos {
2381 1.1 christos unsigned int i, j, insn_size;
2382 1.1 christos char *this_frag;
2383 1.1 christos unsigned short words[4];
2384 1.1 christos int addr_mod;
2385 1.1 christos
2386 1.1 christos /* Arrange the insn encodings in a WORD size array. */
2387 1.1 christos for (i = 0, j = 0; i < 2; i++)
2388 1.1 christos {
2389 1.1 christos words[j++] = (output_opcode[i] >> 16) & 0xFFFF;
2390 1.1 christos words[j++] = output_opcode[i] & 0xFFFF;
2391 1.1 christos }
2392 1.1 christos
2393 1.1.1.6 christos /* Handle relocation. */
2394 1.1.1.6 christos if ((instruction->flags & RELAXABLE) && relocatable)
2395 1.1.1.6 christos {
2396 1.1.1.6 christos int relax_subtype;
2397 1.1.1.6 christos /* Write the maximal instruction size supported. */
2398 1.1.1.6 christos insn_size = INSN_MAX_SIZE;
2399 1.1.1.6 christos
2400 1.1.1.6 christos if (IS_INSN_TYPE (BRANCH_INS))
2401 1.1.1.6 christos {
2402 1.1.1.6 christos switch (insn->rtype)
2403 1.1.1.6 christos {
2404 1.1.1.6 christos case BFD_RELOC_CR16_DISP24:
2405 1.1.1.6 christos relax_subtype = 2;
2406 1.1.1.6 christos break;
2407 1.1.1.6 christos case BFD_RELOC_CR16_DISP16:
2408 1.1.1.6 christos relax_subtype = 1;
2409 1.1.1.6 christos break;
2410 1.1.1.6 christos default:
2411 1.1.1.6 christos relax_subtype = 0;
2412 1.1.1.6 christos break;
2413 1.1.1.6 christos }
2414 1.1.1.6 christos }
2415 1.1.1.6 christos else
2416 1.1.1.6 christos abort ();
2417 1.1.1.6 christos
2418 1.1.1.6 christos this_frag = frag_var (rs_machine_dependent, insn_size *2,
2419 1.1.1.6 christos 4, relax_subtype,
2420 1.1.1.6 christos insn->exp.X_add_symbol,
2421 1.1.1.6 christos 0,
2422 1.1.1.6 christos 0);
2423 1.1.1.6 christos }
2424 1.1.1.6 christos else
2425 1.1.1.6 christos {
2426 1.1.1.6 christos insn_size = instruction->size;
2427 1.1.1.6 christos this_frag = frag_more (insn_size * 2);
2428 1.1.1.6 christos
2429 1.1.1.6 christos if ((relocatable) && (insn->rtype != BFD_RELOC_NONE))
2430 1.1.1.6 christos {
2431 1.1.1.6 christos reloc_howto_type *reloc_howto;
2432 1.1.1.6 christos int size;
2433 1.1.1.6 christos
2434 1.1.1.6 christos reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
2435 1.1.1.6 christos
2436 1.1.1.6 christos if (!reloc_howto)
2437 1.1.1.6 christos abort ();
2438 1.1.1.6 christos
2439 1.1.1.6 christos size = bfd_get_reloc_size (reloc_howto);
2440 1.1.1.6 christos
2441 1.1.1.6 christos if (size < 1 || size > 4)
2442 1.1.1.6 christos abort ();
2443 1.1.1.6 christos
2444 1.1.1.6 christos fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
2445 1.1.1.6 christos size, &insn->exp, reloc_howto->pc_relative,
2446 1.1.1.6 christos insn->rtype);
2447 1.1.1.6 christos }
2448 1.1.1.6 christos }
2449 1.1 christos
2450 1.1 christos /* Verify a 2-byte code alignment. */
2451 1.1 christos addr_mod = frag_now_fix () & 1;
2452 1.1 christos if (frag_now->has_code && frag_now->insn_addr != addr_mod)
2453 1.1 christos as_bad (_("instruction address is not a multiple of 2"));
2454 1.1 christos frag_now->insn_addr = addr_mod;
2455 1.1 christos frag_now->has_code = 1;
2456 1.1 christos
2457 1.1 christos /* Write the instruction encoding to frag. */
2458 1.1 christos for (i = 0; i < insn_size; i++)
2459 1.1 christos {
2460 1.1 christos md_number_to_chars (this_frag, (valueT) words[i], 2);
2461 1.1 christos this_frag += 2;
2462 1.1 christos }
2463 1.1 christos }
2464 1.1 christos
2465 1.1.1.3 christos /* Actually assemble an instruction. */
2466 1.1.1.3 christos
2467 1.1.1.3 christos static void
2468 1.1.1.3 christos cr16_assemble (const char *op, char *param)
2469 1.1.1.3 christos {
2470 1.1.1.3 christos ins cr16_ins;
2471 1.1.1.3 christos
2472 1.1.1.3 christos /* Find the instruction. */
2473 1.1.1.6 christos instruction = (const inst *) str_hash_find (cr16_inst_hash, op);
2474 1.1.1.3 christos if (instruction == NULL)
2475 1.1.1.3 christos {
2476 1.1.1.3 christos as_bad (_("Unknown opcode: `%s'"), op);
2477 1.1.1.3 christos return;
2478 1.1.1.3 christos }
2479 1.1.1.3 christos
2480 1.1.1.3 christos /* Tie dwarf2 debug info to the address at the start of the insn. */
2481 1.1.1.3 christos dwarf2_emit_insn (0);
2482 1.1.1.3 christos
2483 1.1.1.3 christos /* Parse the instruction's operands. */
2484 1.1.1.3 christos parse_insn (&cr16_ins, param);
2485 1.1.1.3 christos
2486 1.1.1.3 christos /* Assemble the instruction - return upon failure. */
2487 1.1.1.3 christos if (assemble_insn (op, &cr16_ins) == 0)
2488 1.1.1.3 christos return;
2489 1.1.1.3 christos
2490 1.1.1.3 christos /* Print the instruction. */
2491 1.1.1.3 christos print_insn (&cr16_ins);
2492 1.1.1.3 christos }
2493 1.1.1.3 christos
2494 1.1 christos /* This is the guts of the machine-dependent assembler. OP points to a
2495 1.1 christos machine dependent instruction. This function is supposed to emit
2496 1.1 christos the frags/bytes it assembles to. */
2497 1.1 christos
2498 1.1 christos void
2499 1.1 christos md_assemble (char *op)
2500 1.1 christos {
2501 1.1 christos ins cr16_ins;
2502 1.1 christos char *param, param1[32];
2503 1.1 christos
2504 1.1 christos /* Reset global variables for a new instruction. */
2505 1.1 christos reset_vars (op);
2506 1.1 christos
2507 1.1 christos /* Strip the mnemonic. */
2508 1.1 christos for (param = op; *param != 0 && !ISSPACE (*param); param++)
2509 1.1 christos ;
2510 1.1 christos *param++ = '\0';
2511 1.1 christos
2512 1.1.1.4 christos /* bCC instructions and adjust the mnemonic by adding extra white spaces. */
2513 1.1 christos if (is_bcc_insn (op))
2514 1.1 christos {
2515 1.1 christos strcpy (param1, get_b_cc (op));
2516 1.1 christos strcat (param1,",");
2517 1.1 christos strcat (param1, param);
2518 1.1 christos param = (char *) ¶m1;
2519 1.1.1.3 christos cr16_assemble ("b", param);
2520 1.1.1.3 christos return;
2521 1.1 christos }
2522 1.1 christos
2523 1.1 christos /* Checking the cinv options and adjust the mnemonic by removing the
2524 1.1 christos extra white spaces. */
2525 1.1 christos if (streq ("cinv", op))
2526 1.1 christos {
2527 1.1.1.6 christos /* Validate the cinv options. */
2528 1.1.1.6 christos unsigned int op_len, param_len;
2529 1.1 christos check_cinv_options (param);
2530 1.1.1.6 christos op_len = strlen (op);
2531 1.1.1.6 christos param_len = strlen (param) + 1;
2532 1.1.1.6 christos memmove (op + op_len, param, param_len);
2533 1.1 christos }
2534 1.1 christos
2535 1.1 christos /* MAPPING - SHIFT INSN, if imm4/imm16 positive values
2536 1.1 christos lsh[b/w] imm4/imm6, reg ==> ashu[b/w] imm4/imm16, reg
2537 1.1.1.4 christos as CR16 core doesn't support lsh[b/w] right shift operations. */
2538 1.1 christos if ((streq ("lshb", op) || streq ("lshw", op) || streq ("lshd", op))
2539 1.1 christos && (param [0] == '$'))
2540 1.1 christos {
2541 1.1 christos strcpy (param1, param);
2542 1.1 christos /* Find the instruction. */
2543 1.1.1.6 christos instruction = (const inst *) str_hash_find (cr16_inst_hash, op);
2544 1.1.1.6 christos parse_operands (&cr16_ins, param1);
2545 1.1 christos if (((&cr16_ins)->arg[0].type == arg_ic)
2546 1.1.1.6 christos && ((&cr16_ins)->arg[0].constant >= 0))
2547 1.1.1.6 christos {
2548 1.1.1.6 christos if (streq ("lshb", op))
2549 1.1.1.6 christos cr16_assemble ("ashub", param);
2550 1.1.1.6 christos else if (streq ("lshd", op))
2551 1.1.1.6 christos cr16_assemble ("ashud", param);
2552 1.1.1.6 christos else
2553 1.1.1.6 christos cr16_assemble ("ashuw", param);
2554 1.1.1.6 christos return;
2555 1.1.1.6 christos }
2556 1.1 christos }
2557 1.1 christos
2558 1.1.1.3 christos cr16_assemble (op, param);
2559 1.1 christos }
2560