]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-crx.c
Fix spelling mistakes and typos in the GAS sources.
[thirdparty/binutils-gdb.git] / gas / config / tc-crx.c
CommitLineData
1fe1f39c 1/* tc-crx.c -- Assembler code for the CRX CPU core.
2571583a 2 Copyright (C) 2004-2017 Free Software Foundation, Inc.
1fe1f39c
NC
3
4 Contributed by Tomer Levi, NSC, Israel.
5 Originally written for GAS 2.12 by Tomer Levi, NSC, Israel.
6 Updates, BFDizing, GNUifying and ELF support by Tomer Levi.
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
ec2655a6 12 the Free Software Foundation; either version 3, or (at your option)
1fe1f39c
NC
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the
4b4da160
NC
22 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
1fe1f39c
NC
24
25#include "as.h"
1f42f8b3 26#include "bfd_stdint.h"
1fe1f39c
NC
27#include "safe-ctype.h"
28#include "dwarf2dbg.h"
29#include "opcode/crx.h"
30#include "elf/crx.h"
31
1fe1f39c 32/* Word is considered here as a 16-bit unsigned short int. */
1fe1f39c
NC
33#define WORD_SHIFT 16
34
35/* Register is 4-bit size. */
36#define REG_SIZE 4
37
38/* Maximum size of a single instruction (in words). */
39#define INSN_MAX_SIZE 3
40
41/* Maximum bits which may be set in a `mask16' operand. */
42#define MAX_REGS_IN_MASK16 8
43
1fe1f39c
NC
44/* Utility macros for string comparison. */
45#define streq(a, b) (strcmp (a, b) == 0)
46#define strneq(a, b, c) (strncmp (a, b, c) == 0)
47
023d1155 48/* Assign a number NUM, shifted by SHIFT bytes, into a location
1fe1f39c
NC
49 pointed by index BYTE of array 'output_opcode'. */
50#define CRX_PRINT(BYTE, NUM, SHIFT) output_opcode[BYTE] |= (NUM << SHIFT)
51
023d1155
TL
52/* Operand errors. */
53typedef enum
54 {
55 OP_LEGAL = 0, /* Legal operand. */
56 OP_OUT_OF_RANGE, /* Operand not within permitted range. */
57 OP_NOT_EVEN, /* Operand is Odd number, should be even. */
58 OP_ILLEGAL_DISPU4, /* Operand is not within DISPU4 range. */
59 OP_ILLEGAL_CST4, /* Operand is not within CST4 range. */
3739860c 60 OP_NOT_UPPER_64KB /* Operand is not within the upper 64KB
023d1155
TL
61 (0xFFFF0000-0xFFFFFFFF). */
62 }
63op_err;
64
1fe1f39c
NC
65/* Opcode mnemonics hash table. */
66static struct hash_control *crx_inst_hash;
67/* CRX registers hash table. */
68static struct hash_control *reg_hash;
69/* CRX coprocessor registers hash table. */
70static struct hash_control *copreg_hash;
71/* Current instruction we're assembling. */
72const inst *instruction;
73
023d1155
TL
74/* Global variables. */
75
76/* Array to hold an instruction encoding. */
1fe1f39c 77long output_opcode[2];
023d1155 78
1fe1f39c
NC
79/* Nonzero means a relocatable symbol. */
80int relocatable;
023d1155 81
1fe1f39c
NC
82/* A copy of the original instruction (used in error messages). */
83char ins_parse[MAX_INST_LEN];
023d1155
TL
84
85/* The current processed argument number. */
82d6ee2a 86int cur_arg_num;
1fe1f39c
NC
87
88/* Generic assembler global variables which must be defined by all targets. */
89
90/* Characters which always start a comment. */
91const char comment_chars[] = "#";
92
93/* Characters which start a comment at the beginning of a line. */
94const char line_comment_chars[] = "#";
95
96/* This array holds machine specific line separator characters. */
97const char line_separator_chars[] = ";";
98
99/* Chars that can be used to separate mant from exp in floating point nums. */
100const char EXP_CHARS[] = "eE";
101
102/* Chars that mean this number is a floating point constant as in 0f12.456 */
103const char FLT_CHARS[] = "f'";
104
105/* Target-specific multicharacter options, not const-declared at usage. */
106const char *md_shortopts = "";
42851540
NC
107struct option md_longopts[] =
108{
1fe1f39c
NC
109 {NULL, no_argument, NULL, 0}
110};
111size_t md_longopts_size = sizeof (md_longopts);
112
113/* This table describes all the machine specific pseudo-ops
114 the assembler has to support. The fields are:
115 *** Pseudo-op name without dot.
116 *** Function to call to execute this pseudo-op.
117 *** Integer arg to pass to the function. */
118
119const pseudo_typeS md_pseudo_table[] =
120{
121 /* In CRX machine, align is in bytes (not a ptwo boundary). */
122 {"align", s_align_bytes, 0},
123 {0, 0, 0}
124};
125
023d1155 126/* CRX relaxation table. */
1fe1f39c
NC
127const relax_typeS md_relax_table[] =
128{
129 /* bCC */
130 {0xfa, -0x100, 2, 1}, /* 8 */
131 {0xfffe, -0x10000, 4, 2}, /* 16 */
132 {0xfffffffe, -0xfffffffe, 6, 0}, /* 32 */
133
134 /* bal */
135 {0xfffe, -0x10000, 4, 4}, /* 16 */
136 {0xfffffffe, -0xfffffffe, 6, 0}, /* 32 */
137
30c62922 138 /* cmpbr/bcop */
1fe1f39c
NC
139 {0xfe, -0x100, 4, 6}, /* 8 */
140 {0xfffffe, -0x1000000, 6, 0} /* 24 */
141};
142
023d1155 143static void reset_vars (char *);
1fe1f39c
NC
144static reg get_register (char *);
145static copreg get_copregister (char *);
023d1155
TL
146static argtype get_optype (operand_type);
147static int get_opbits (operand_type);
148static int get_opflags (operand_type);
1fe1f39c 149static int get_number_of_operands (void);
82d6ee2a 150static void parse_operand (char *, ins *);
87975d2a
AM
151static int gettrap (const char *);
152static void handle_LoadStor (const char *);
153static int get_cinv_parameters (const char *);
023d1155
TL
154static long getconstant (long, int);
155static op_err check_range (long *, int, unsigned int, int);
1fe1f39c
NC
156static int getreg_image (reg);
157static void parse_operands (ins *, char *);
158static void parse_insn (ins *, char *);
159static void print_operand (int, int, argument *);
160static void print_constant (int, int, argument *);
161static int exponent2scale (int);
1fe1f39c 162static void mask_reg (int, unsigned short *);
023d1155 163static void process_label_constant (char *, ins *);
82d6ee2a 164static void set_operand (char *, ins *);
1fe1f39c
NC
165static char * preprocess_reglist (char *, int *);
166static int assemble_insn (char *, ins *);
167static void print_insn (ins *);
023d1155
TL
168static void warn_if_needed (ins *);
169static int adjust_if_needed (ins *);
1fe1f39c
NC
170
171/* Return the bit size for a given operand. */
172
173static int
023d1155 174get_opbits (operand_type op)
1fe1f39c
NC
175{
176 if (op < MAX_OPRD)
177 return crx_optab[op].bit_size;
178 else
179 return 0;
180}
181
182/* Return the argument type of a given operand. */
183
184static argtype
023d1155 185get_optype (operand_type op)
1fe1f39c
NC
186{
187 if (op < MAX_OPRD)
188 return crx_optab[op].arg_type;
189 else
190 return nullargs;
191}
192
9bb1ebc2
TL
193/* Return the flags of a given operand. */
194
195static int
023d1155 196get_opflags (operand_type op)
9bb1ebc2
TL
197{
198 if (op < MAX_OPRD)
199 return crx_optab[op].flags;
200 else
201 return 0;
202}
203
1fe1f39c
NC
204/* Get the core processor register 'reg_name'. */
205
206static reg
207get_register (char *reg_name)
208{
91d6fa6a 209 const reg_entry *rreg;
1fe1f39c 210
91d6fa6a 211 rreg = (const reg_entry *) hash_find (reg_hash, reg_name);
1fe1f39c 212
91d6fa6a
NC
213 if (rreg != NULL)
214 return rreg->value.reg_val;
1fe1f39c
NC
215 else
216 return nullregister;
217}
218
219/* Get the coprocessor register 'copreg_name'. */
220
221static copreg
222get_copregister (char *copreg_name)
223{
91d6fa6a 224 const reg_entry *coreg;
1fe1f39c 225
91d6fa6a 226 coreg = (const reg_entry *) hash_find (copreg_hash, copreg_name);
1fe1f39c 227
91d6fa6a
NC
228 if (coreg != NULL)
229 return coreg->value.copreg_val;
1fe1f39c
NC
230 else
231 return nullcopregister;
232}
233
1fe1f39c
NC
234/* Round up a section size to the appropriate boundary. */
235
236valueT
237md_section_align (segT seg, valueT val)
238{
239 /* Round .text section to a multiple of 2. */
240 if (seg == text_section)
241 return (val + 1) & ~1;
242 return val;
243}
244
245/* Parse an operand that is machine-specific (remove '*'). */
246
247void
248md_operand (expressionS * exp)
249{
250 char c = *input_line_pointer;
251
252 switch (c)
253 {
254 case '*':
255 input_line_pointer++;
256 expression (exp);
257 break;
258 default:
259 break;
260 }
261}
262
263/* Reset global variables before parsing a new instruction. */
264
265static void
023d1155 266reset_vars (char *op)
1fe1f39c 267{
023d1155 268 cur_arg_num = relocatable = 0;
42851540 269 memset (& output_opcode, '\0', sizeof (output_opcode));
1fe1f39c 270
1fe1f39c 271 /* Save a copy of the original OP (used in error messages). */
6c5cf62c
NC
272 strncpy (ins_parse, op, sizeof ins_parse - 1);
273 ins_parse [sizeof ins_parse - 1] = 0;
1fe1f39c
NC
274}
275
670ec21d
NC
276/* This macro decides whether a particular reloc is an entry in a
277 switch table. It is used when relaxing, because the linker needs
278 to know about all such entries so that it can adjust them if
279 necessary. */
280
281#define SWITCH_TABLE(fix) \
282 ( (fix)->fx_addsy != NULL \
283 && (fix)->fx_subsy != NULL \
284 && S_GET_SEGMENT ((fix)->fx_addsy) == \
285 S_GET_SEGMENT ((fix)->fx_subsy) \
286 && S_GET_SEGMENT (fix->fx_addsy) != undefined_section \
287 && ( (fix)->fx_r_type == BFD_RELOC_CRX_NUM8 \
288 || (fix)->fx_r_type == BFD_RELOC_CRX_NUM16 \
289 || (fix)->fx_r_type == BFD_RELOC_CRX_NUM32))
290
291/* See whether we need to force a relocation into the output file.
292 This is used to force out switch and PC relative relocations when
293 relaxing. */
294
295int
296crx_force_relocation (fixS *fix)
297{
298 if (generic_force_reloc (fix) || SWITCH_TABLE (fix))
299 return 1;
300
301 return 0;
302}
303
1fe1f39c
NC
304/* Generate a relocation entry for a fixup. */
305
306arelent *
307tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
308{
309 arelent * reloc;
310
325801bd
TS
311 reloc = XNEW (arelent);
312 reloc->sym_ptr_ptr = XNEW (asymbol *);
1fe1f39c
NC
313 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
314 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
315 reloc->addend = fixP->fx_offset;
316
317 if (fixP->fx_subsy != NULL)
670ec21d
NC
318 {
319 if (SWITCH_TABLE (fixP))
320 {
321 /* Keep the current difference in the addend. */
322 reloc->addend = (S_GET_VALUE (fixP->fx_addsy)
323 - S_GET_VALUE (fixP->fx_subsy) + fixP->fx_offset);
42851540 324
670ec21d
NC
325 switch (fixP->fx_r_type)
326 {
327 case BFD_RELOC_CRX_NUM8:
328 fixP->fx_r_type = BFD_RELOC_CRX_SWITCH8;
329 break;
330 case BFD_RELOC_CRX_NUM16:
331 fixP->fx_r_type = BFD_RELOC_CRX_SWITCH16;
332 break;
333 case BFD_RELOC_CRX_NUM32:
334 fixP->fx_r_type = BFD_RELOC_CRX_SWITCH32;
335 break;
336 default:
337 abort ();
338 break;
339 }
340 }
341 else
342 {
343 /* We only resolve difference expressions in the same section. */
344 as_bad_where (fixP->fx_file, fixP->fx_line,
345 _("can't resolve `%s' {%s section} - `%s' {%s section}"),
346 fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
347 segment_name (fixP->fx_addsy
348 ? S_GET_SEGMENT (fixP->fx_addsy)
349 : absolute_section),
350 S_GET_NAME (fixP->fx_subsy),
351 segment_name (S_GET_SEGMENT (fixP->fx_addsy)));
352 }
353 }
1fe1f39c 354
9c2799c2 355 gas_assert ((int) fixP->fx_r_type > 0);
1fe1f39c
NC
356 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
357
358 if (reloc->howto == (reloc_howto_type *) NULL)
359 {
360 as_bad_where (fixP->fx_file, fixP->fx_line,
361 _("internal error: reloc %d (`%s') not supported by object file format"),
362 fixP->fx_r_type,
363 bfd_get_reloc_code_name (fixP->fx_r_type));
364 return NULL;
365 }
9c2799c2 366 gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1fe1f39c
NC
367
368 return reloc;
369}
370
371/* Prepare machine-dependent frags for relaxation. */
372
373int
374md_estimate_size_before_relax (fragS *fragp, asection *seg)
375{
376 /* If symbol is undefined or located in a different section,
377 select the largest supported relocation. */
378 relax_substateT subtype;
379 relax_substateT rlx_state[] = {0, 2,
380 3, 4,
381 5, 6};
382
383 for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
384 {
385 if (fragp->fr_subtype == rlx_state[subtype]
386 && (!S_IS_DEFINED (fragp->fr_symbol)
387 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
388 {
389 fragp->fr_subtype = rlx_state[subtype + 1];
390 break;
391 }
392 }
393
394 if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
395 abort ();
396
397 return md_relax_table[fragp->fr_subtype].rlx_length;
398}
399
400void
401md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
402{
403 /* 'opcode' points to the start of the instruction, whether
404 we need to change the instruction's fixed encoding. */
405 char *opcode = fragP->fr_literal + fragP->fr_fix;
406 bfd_reloc_code_real_type reloc;
407
408 subseg_change (sec, 0);
409
410 switch (fragP->fr_subtype)
411 {
412 case 0:
413 reloc = BFD_RELOC_CRX_REL8;
414 break;
415 case 1:
416 *opcode = 0x7e;
417 reloc = BFD_RELOC_CRX_REL16;
418 break;
419 case 2:
420 *opcode = 0x7f;
421 reloc = BFD_RELOC_CRX_REL32;
422 break;
423 case 3:
424 reloc = BFD_RELOC_CRX_REL16;
425 break;
426 case 4:
427 *++opcode = 0x31;
428 reloc = BFD_RELOC_CRX_REL32;
429 break;
430 case 5:
431 reloc = BFD_RELOC_CRX_REL8_CMP;
432 break;
433 case 6:
434 *++opcode = 0x31;
435 reloc = BFD_RELOC_CRX_REL24;
436 break;
437 default:
438 abort ();
439 break;
440 }
441
442 fix_new (fragP, fragP->fr_fix,
443 bfd_get_reloc_size (bfd_reloc_type_lookup (stdoutput, reloc)),
444 fragP->fr_symbol, fragP->fr_offset, 1, reloc);
445 fragP->fr_var = 0;
446 fragP->fr_fix += md_relax_table[fragP->fr_subtype].rlx_length;
447}
448
449/* Process machine-dependent command line options. Called once for
450 each option on the command line that the machine-independent part of
451 GAS does not understand. */
452
453int
17b9d67d 454md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
1fe1f39c
NC
455{
456 return 0;
457}
458
459/* Machine-dependent usage-output. */
460
461void
462md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
463{
464 return;
465}
466
6d4af3c2 467const char *
1fe1f39c
NC
468md_atof (int type, char *litP, int *sizeP)
469{
499ac353 470 return ieee_md_atof (type, litP, sizeP, target_big_endian);
1fe1f39c
NC
471}
472
473/* Apply a fixS (fixup of an instruction or data that we didn't have
474 enough info to complete immediately) to the data in a frag.
475 Since linkrelax is nonzero and TC_LINKRELAX_FIXUP is defined to disable
476 relaxation of debug sections, this function is called only when
477 fixuping relocations of debug sections. */
478
479void
55cf6793 480md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1fe1f39c
NC
481{
482 valueT val = * valP;
483 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
484 fixP->fx_offset = 0;
485
486 switch (fixP->fx_r_type)
487 {
488 case BFD_RELOC_CRX_NUM8:
489 bfd_put_8 (stdoutput, (unsigned char) val, buf);
490 break;
491 case BFD_RELOC_CRX_NUM16:
492 bfd_put_16 (stdoutput, val, buf);
493 break;
494 case BFD_RELOC_CRX_NUM32:
495 bfd_put_32 (stdoutput, val, buf);
496 break;
497 default:
498 /* We shouldn't ever get here because linkrelax is nonzero. */
499 abort ();
500 break;
501 }
502
503 fixP->fx_done = 0;
504
505 if (fixP->fx_addsy == NULL
506 && fixP->fx_pcrel == 0)
507 fixP->fx_done = 1;
508
509 if (fixP->fx_pcrel == 1
510 && fixP->fx_addsy != NULL
511 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
512 fixP->fx_done = 1;
513}
514
515/* The location from which a PC relative jump should be calculated,
516 given a PC relative reloc. */
517
518long
519md_pcrel_from (fixS *fixp)
520{
521 return fixp->fx_frag->fr_address + fixp->fx_where;
522}
523
524/* This function is called once, at assembler startup time. This should
525 set up all the tables, etc that the MD part of the assembler needs. */
526
527void
528md_begin (void)
529{
530 const char *hashret = NULL;
531 int i = 0;
532
533 /* Set up a hash table for the instructions. */
9bb1ebc2 534 if ((crx_inst_hash = hash_new ()) == NULL)
1fe1f39c 535 as_fatal (_("Virtual memory exhausted"));
3739860c 536
1fe1f39c
NC
537 while (crx_instruction[i].mnemonic != NULL)
538 {
539 const char *mnemonic = crx_instruction[i].mnemonic;
540
541 hashret = hash_insert (crx_inst_hash, mnemonic,
5a49b8ac 542 (void *) &crx_instruction[i]);
1fe1f39c
NC
543
544 if (hashret != NULL && *hashret != '\0')
545 as_fatal (_("Can't hash `%s': %s\n"), crx_instruction[i].mnemonic,
546 *hashret == 0 ? _("(unknown reason)") : hashret);
547
548 /* Insert unique names into hash table. The CRX instruction set
549 has many identical opcode names that have different opcodes based
550 on the operands. This hash table then provides a quick index to
551 the first opcode with a particular name in the opcode table. */
552 do
553 {
554 ++i;
555 }
556 while (crx_instruction[i].mnemonic != NULL
557 && streq (crx_instruction[i].mnemonic, mnemonic));
558 }
559
560 /* Initialize reg_hash hash table. */
9bb1ebc2
TL
561 if ((reg_hash = hash_new ()) == NULL)
562 as_fatal (_("Virtual memory exhausted"));
1fe1f39c
NC
563
564 {
565 const reg_entry *regtab;
566
567 for (regtab = crx_regtab;
568 regtab < (crx_regtab + NUMREGS); regtab++)
569 {
5a49b8ac 570 hashret = hash_insert (reg_hash, regtab->name, (void *) regtab);
1fe1f39c 571 if (hashret)
33eaf5de 572 as_fatal (_("Internal error: Can't hash %s: %s"),
1fe1f39c
NC
573 regtab->name,
574 hashret);
575 }
576 }
577
578 /* Initialize copreg_hash hash table. */
9bb1ebc2
TL
579 if ((copreg_hash = hash_new ()) == NULL)
580 as_fatal (_("Virtual memory exhausted"));
1fe1f39c
NC
581
582 {
583 const reg_entry *copregtab;
584
585 for (copregtab = crx_copregtab; copregtab < (crx_copregtab + NUMCOPREGS);
586 copregtab++)
587 {
5a49b8ac
AM
588 hashret = hash_insert (copreg_hash, copregtab->name,
589 (void *) copregtab);
1fe1f39c 590 if (hashret)
33eaf5de 591 as_fatal (_("Internal error: Can't hash %s: %s"),
1fe1f39c
NC
592 copregtab->name,
593 hashret);
594 }
595 }
596 /* Set linkrelax here to avoid fixups in most sections. */
597 linkrelax = 1;
598}
599
3739860c 600/* Process constants (immediate/absolute)
023d1155 601 and labels (jump targets/Memory locations). */
1fe1f39c
NC
602
603static void
82d6ee2a 604process_label_constant (char *str, ins * crx_ins)
1fe1f39c 605{
023d1155 606 char *saved_input_line_pointer;
82d6ee2a
TL
607 argument *cur_arg = &crx_ins->arg[cur_arg_num]; /* Current argument. */
608
023d1155 609 saved_input_line_pointer = input_line_pointer;
1fe1f39c
NC
610 input_line_pointer = str;
611
612 expression (&crx_ins->exp);
3739860c 613
1fe1f39c
NC
614 switch (crx_ins->exp.X_op)
615 {
42851540
NC
616 case O_big:
617 case O_absent:
618 /* Missing or bad expr becomes absolute 0. */
619 as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
620 str);
621 crx_ins->exp.X_op = O_constant;
622 crx_ins->exp.X_add_number = 0;
623 crx_ins->exp.X_add_symbol = (symbolS *) 0;
624 crx_ins->exp.X_op_symbol = (symbolS *) 0;
023d1155 625 /* Fall through. */
42851540 626
1fe1f39c 627 case O_constant:
023d1155
TL
628 cur_arg->X_op = O_constant;
629 cur_arg->constant = crx_ins->exp.X_add_number;
1fe1f39c
NC
630 break;
631
632 case O_symbol:
633 case O_subtract:
023d1155
TL
634 case O_add:
635 cur_arg->X_op = O_symbol;
42851540 636 crx_ins->rtype = BFD_RELOC_NONE;
1fe1f39c
NC
637 relocatable = 1;
638
82d6ee2a 639 switch (cur_arg->type)
1fe1f39c
NC
640 {
641 case arg_cr:
1fe1f39c
NC
642 if (IS_INSN_TYPE (LD_STOR_INS_INC))
643 crx_ins->rtype = BFD_RELOC_CRX_REGREL12;
644 else if (IS_INSN_TYPE (CSTBIT_INS)
645 || IS_INSN_TYPE (STOR_IMM_INS))
1fe1f39c
NC
646 crx_ins->rtype = BFD_RELOC_CRX_REGREL28;
647 else
1fe1f39c 648 crx_ins->rtype = BFD_RELOC_CRX_REGREL32;
023d1155
TL
649 break;
650
82d6ee2a 651 case arg_idxr:
1fe1f39c
NC
652 crx_ins->rtype = BFD_RELOC_CRX_REGREL22;
653 break;
3739860c 654
1fe1f39c 655 case arg_c:
1fe1f39c
NC
656 if (IS_INSN_MNEMONIC ("bal") || IS_INSN_TYPE (DCR_BRANCH_INS))
657 crx_ins->rtype = BFD_RELOC_CRX_REL16;
658 else if (IS_INSN_TYPE (BRANCH_INS))
9bb1ebc2 659 crx_ins->rtype = BFD_RELOC_CRX_REL8;
1fe1f39c
NC
660 else if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (STOR_IMM_INS)
661 || IS_INSN_TYPE (CSTBIT_INS))
662 crx_ins->rtype = BFD_RELOC_CRX_ABS32;
663 else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
664 crx_ins->rtype = BFD_RELOC_CRX_REL4;
30c62922 665 else if (IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (COP_BRANCH_INS))
9bb1ebc2 666 crx_ins->rtype = BFD_RELOC_CRX_REL8_CMP;
1fe1f39c 667 break;
3739860c 668
1fe1f39c 669 case arg_ic:
1fe1f39c
NC
670 if (IS_INSN_TYPE (ARITH_INS))
671 crx_ins->rtype = BFD_RELOC_CRX_IMM32;
672 else if (IS_INSN_TYPE (ARITH_BYTE_INS))
673 crx_ins->rtype = BFD_RELOC_CRX_IMM16;
674 break;
675 default:
676 break;
677 }
1fe1f39c
NC
678 break;
679
680 default:
023d1155 681 cur_arg->X_op = crx_ins->exp.X_op;
1fe1f39c
NC
682 break;
683 }
684
023d1155
TL
685 input_line_pointer = saved_input_line_pointer;
686 return;
1fe1f39c
NC
687}
688
689/* Get the values of the scale to be encoded -
690 used for the scaled index mode of addressing. */
691
692static int
693exponent2scale (int val)
694{
695 int exponent;
696
697 /* If 'val' is 0, the following 'for' will be an endless loop. */
698 if (val == 0)
699 return 0;
700
701 for (exponent = 0; (val != 1); val >>= 1, exponent++)
702 ;
703
704 return exponent;
705}
706
82d6ee2a
TL
707/* Parsing different types of operands
708 -> constants Immediate/Absolute/Relative numbers
709 -> Labels Relocatable symbols
710 -> (rbase) Register base
711 -> disp(rbase) Register relative
712 -> disp(rbase)+ Post-increment mode
713 -> disp(rbase,ridx,scl) Register index mode */
1fe1f39c
NC
714
715static void
82d6ee2a 716set_operand (char *operand, ins * crx_ins)
1fe1f39c 717{
33eaf5de
NC
718 char *operandS; /* Pointer to start of sub-operand. */
719 char *operandE; /* Pointer to end of sub-operand. */
82d6ee2a
TL
720 expressionS scale;
721 int scale_val;
722 char *input_save, c;
723 argument *cur_arg = &crx_ins->arg[cur_arg_num]; /* Current argument. */
1fe1f39c 724
82d6ee2a
TL
725 /* Initialize pointers. */
726 operandS = operandE = operand;
727
728 switch (cur_arg->type)
1fe1f39c 729 {
82d6ee2a
TL
730 case arg_sc: /* Case *+0x18. */
731 case arg_ic: /* Case $0x18. */
732 operandS++;
1a0670f3 733 /* Fall through. */
82d6ee2a
TL
734 case arg_c: /* Case 0x18. */
735 /* Set constant. */
aea44f62 736 process_label_constant (operandS, crx_ins);
3739860c 737
82d6ee2a
TL
738 if (cur_arg->type != arg_ic)
739 cur_arg->type = arg_c;
740 break;
741
742 case arg_icr: /* Case $0x18(r1). */
743 operandS++;
744 case arg_cr: /* Case 0x18(r1). */
745 /* Set displacement constant. */
746 while (*operandE != '(')
747 operandE++;
748 *operandE = '\0';
aea44f62 749 process_label_constant (operandS, crx_ins);
3739860c 750 operandS = operandE;
1a0670f3 751 /* Fall through. */
82d6ee2a
TL
752 case arg_rbase: /* Case (r1). */
753 operandS++;
754 /* Set register base. */
755 while (*operandE != ')')
756 operandE++;
757 *operandE = '\0';
758 if ((cur_arg->r = get_register (operandS)) == nullregister)
33eaf5de 759 as_bad (_("Illegal register `%s' in instruction `%s'"),
82d6ee2a 760 operandS, ins_parse);
1fe1f39c 761
82d6ee2a
TL
762 if (cur_arg->type != arg_rbase)
763 cur_arg->type = arg_cr;
764 break;
1fe1f39c 765
82d6ee2a
TL
766 case arg_idxr:
767 /* Set displacement constant. */
768 while (*operandE != '(')
769 operandE++;
770 *operandE = '\0';
771 process_label_constant (operandS, crx_ins);
772 operandS = ++operandE;
3739860c 773
82d6ee2a
TL
774 /* Set register base. */
775 while ((*operandE != ',') && (! ISSPACE (*operandE)))
776 operandE++;
777 *operandE++ = '\0';
778 if ((cur_arg->r = get_register (operandS)) == nullregister)
33eaf5de 779 as_bad (_("Illegal register `%s' in instruction `%s'"),
82d6ee2a
TL
780 operandS, ins_parse);
781
782 /* Skip leading white space. */
783 while (ISSPACE (*operandE))
784 operandE++;
785 operandS = operandE;
1fe1f39c 786
82d6ee2a
TL
787 /* Set register index. */
788 while ((*operandE != ')') && (*operandE != ','))
789 operandE++;
790 c = *operandE;
791 *operandE++ = '\0';
1fe1f39c 792
82d6ee2a 793 if ((cur_arg->i_r = get_register (operandS)) == nullregister)
33eaf5de 794 as_bad (_("Illegal register `%s' in instruction `%s'"),
82d6ee2a
TL
795 operandS, ins_parse);
796
797 /* Skip leading white space. */
798 while (ISSPACE (*operandE))
799 operandE++;
800 operandS = operandE;
801
802 /* Set the scale. */
803 if (c == ')')
804 cur_arg->scale = 0;
1fe1f39c
NC
805 else
806 {
82d6ee2a
TL
807 while (*operandE != ')')
808 operandE++;
809 *operandE = '\0';
1fe1f39c 810
82d6ee2a
TL
811 /* Preprocess the scale string. */
812 input_save = input_line_pointer;
813 input_line_pointer = operandS;
814 expression (&scale);
815 input_line_pointer = input_save;
1fe1f39c 816
82d6ee2a 817 scale_val = scale.X_add_number;
1fe1f39c 818
82d6ee2a
TL
819 /* Check if the scale value is legal. */
820 if (scale_val != 1 && scale_val != 2
821 && scale_val != 4 && scale_val != 8)
822 as_bad (_("Illegal Scale - `%d'"), scale_val);
1fe1f39c 823
82d6ee2a 824 cur_arg->scale = exponent2scale (scale_val);
1fe1f39c
NC
825 }
826 break;
82d6ee2a 827
1fe1f39c
NC
828 default:
829 break;
830 }
831}
832
82d6ee2a
TL
833/* Parse a single operand.
834 operand - Current operand to parse.
835 crx_ins - Current assembled instruction. */
1fe1f39c
NC
836
837static void
82d6ee2a 838parse_operand (char *operand, ins * crx_ins)
1fe1f39c 839{
82d6ee2a
TL
840 int ret_val;
841 argument *cur_arg = &crx_ins->arg[cur_arg_num]; /* Current argument. */
1fe1f39c 842
82d6ee2a
TL
843 /* Initialize the type to NULL before parsing. */
844 cur_arg->type = nullargs;
1fe1f39c 845
82d6ee2a
TL
846 /* Check whether this is a general processor register. */
847 if ((ret_val = get_register (operand)) != nullregister)
1fe1f39c 848 {
82d6ee2a
TL
849 cur_arg->type = arg_r;
850 cur_arg->r = ret_val;
023d1155
TL
851 cur_arg->X_op = O_register;
852 return;
1fe1f39c 853 }
1fe1f39c 854
82d6ee2a
TL
855 /* Check whether this is a core [special] coprocessor register. */
856 if ((ret_val = get_copregister (operand)) != nullcopregister)
857 {
858 cur_arg->type = arg_copr;
859 if (ret_val >= cs0)
860 cur_arg->type = arg_copsr;
861 cur_arg->cr = ret_val;
023d1155
TL
862 cur_arg->X_op = O_register;
863 return;
82d6ee2a 864 }
1fe1f39c 865
82d6ee2a 866 /* Deal with special characters. */
1fe1f39c
NC
867 switch (operand[0])
868 {
1fe1f39c
NC
869 case '$':
870 if (strchr (operand, '(') != NULL)
82d6ee2a 871 cur_arg->type = arg_icr;
1fe1f39c 872 else
82d6ee2a
TL
873 cur_arg->type = arg_ic;
874 goto set_params;
1fe1f39c
NC
875 break;
876
1fe1f39c 877 case '*':
82d6ee2a
TL
878 cur_arg->type = arg_sc;
879 goto set_params;
1fe1f39c 880 break;
82d6ee2a
TL
881
882 case '(':
883 cur_arg->type = arg_rbase;
884 goto set_params;
1fe1f39c 885 break;
82d6ee2a 886
1fe1f39c 887 default:
82d6ee2a
TL
888 break;
889 }
3739860c 890
82d6ee2a
TL
891 if (strchr (operand, '(') != NULL)
892 {
893 if (strchr (operand, ',') != NULL
894 && (strchr (operand, ',') > strchr (operand, '(')))
895 cur_arg->type = arg_idxr;
1fe1f39c 896 else
82d6ee2a
TL
897 cur_arg->type = arg_cr;
898 }
899 else
900 cur_arg->type = arg_c;
901 goto set_params;
902
903/* Parse an operand according to its type. */
904set_params:
905 cur_arg->constant = 0;
906 set_operand (operand, crx_ins);
1fe1f39c
NC
907}
908
3739860c 909/* Parse the various operands. Each operand is then analyzed to fillup
82d6ee2a 910 the fields in the crx_ins data structure. */
1fe1f39c
NC
911
912static void
913parse_operands (ins * crx_ins, char *operands)
914{
915 char *operandS; /* Operands string. */
916 char *operandH, *operandT; /* Single operand head/tail pointers. */
917 int allocated = 0; /* Indicates a new operands string was allocated. */
918 char *operand[MAX_OPERANDS]; /* Separating the operands. */
919 int op_num = 0; /* Current operand number we are parsing. */
920 int bracket_flag = 0; /* Indicates a bracket '(' was found. */
921 int sq_bracket_flag = 0; /* Indicates a square bracket '[' was found. */
922
923 /* Preprocess the list of registers, if necessary. */
924 operandS = operandH = operandT = (INST_HAS_REG_LIST) ?
925 preprocess_reglist (operands, &allocated) : operands;
926
927 while (*operandT != '\0')
928 {
929 if (*operandT == ',' && bracket_flag != 1 && sq_bracket_flag != 1)
930 {
931 *operandT++ = '\0';
932 operand[op_num++] = strdup (operandH);
933 operandH = operandT;
934 continue;
935 }
936
937 if (*operandT == ' ')
938 as_bad (_("Illegal operands (whitespace): `%s'"), ins_parse);
939
940 if (*operandT == '(')
941 bracket_flag = 1;
942 else if (*operandT == '[')
943 sq_bracket_flag = 1;
944
945 if (*operandT == ')')
946 {
947 if (bracket_flag)
948 bracket_flag = 0;
949 else
950 as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
951 }
952 else if (*operandT == ']')
953 {
954 if (sq_bracket_flag)
955 sq_bracket_flag = 0;
956 else
957 as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
958 }
959
960 if (bracket_flag == 1 && *operandT == ')')
961 bracket_flag = 0;
962 else if (sq_bracket_flag == 1 && *operandT == ']')
963 sq_bracket_flag = 0;
964
965 operandT++;
966 }
967
968 /* Adding the last operand. */
969 operand[op_num++] = strdup (operandH);
970 crx_ins->nargs = op_num;
971
972 /* Verifying correct syntax of operands (all brackets should be closed). */
973 if (bracket_flag || sq_bracket_flag)
974 as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
975
82d6ee2a 976 /* Now we parse each operand separately. */
1fe1f39c
NC
977 for (op_num = 0; op_num < crx_ins->nargs; op_num++)
978 {
82d6ee2a
TL
979 cur_arg_num = op_num;
980 parse_operand (operand[op_num], crx_ins);
1fe1f39c
NC
981 free (operand[op_num]);
982 }
983
984 if (allocated)
985 free (operandS);
986}
987
988/* Get the trap index in dispatch table, given its name.
989 This routine is used by assembling the 'excp' instruction. */
990
991static int
87975d2a 992gettrap (const char *s)
1fe1f39c
NC
993{
994 const trap_entry *trap;
995
996 for (trap = crx_traps; trap < (crx_traps + NUMTRAPS); trap++)
42851540 997 if (strcasecmp (trap->name, s) == 0)
1fe1f39c
NC
998 return trap->entry;
999
1000 as_bad (_("Unknown exception: `%s'"), s);
1001 return 0;
1002}
1003
3739860c
L
1004/* Post-Increment instructions, as well as Store-Immediate instructions, are a
1005 sub-group within load/stor instruction groups.
1006 Therefore, when parsing a Post-Increment/Store-Immediate insn, we have to
1007 advance the instruction pointer to the start of that sub-group (that is, up
64995a6b
TL
1008 to the first instruction of that type).
1009 Otherwise, the insn will be mistakenly identified as of type LD_STOR_INS. */
1fe1f39c
NC
1010
1011static void
87975d2a 1012handle_LoadStor (const char *operands)
1fe1f39c 1013{
3739860c
L
1014 /* Post-Increment instructions precede Store-Immediate instructions in
1015 CRX instruction table, hence they are handled before.
9bb1ebc2 1016 This synchronization should be kept. */
64995a6b 1017
1fe1f39c 1018 /* Assuming Post-Increment insn has the following format :
64995a6b
TL
1019 'MNEMONIC DISP(REG)+, REG' (e.g. 'loadw 12(r5)+, r6').
1020 LD_STOR_INS_INC are the only store insns containing a plus sign (+). */
1fe1f39c 1021 if (strstr (operands, ")+") != NULL)
9bb1ebc2
TL
1022 {
1023 while (! IS_INSN_TYPE (LD_STOR_INS_INC))
1024 instruction++;
1025 return;
1026 }
1027
1028 /* Assuming Store-Immediate insn has the following format :
1029 'MNEMONIC $DISP, ...' (e.g. 'storb $1, 12(r5)').
1030 STOR_IMM_INS are the only store insns containing a dollar sign ($). */
1031 if (strstr (operands, "$") != NULL)
1032 while (! IS_INSN_TYPE (STOR_IMM_INS))
1fe1f39c
NC
1033 instruction++;
1034}
1035
1036/* Top level module where instruction parsing starts.
1037 crx_ins - data structure holds some information.
1038 operands - holds the operands part of the whole instruction. */
1039
1040static void
1041parse_insn (ins *insn, char *operands)
1042{
023d1155
TL
1043 int i;
1044
1045 /* Handle instructions with no operands. */
1046 for (i = 0; no_op_insn[i] != NULL; i++)
1047 {
1048 if (streq (no_op_insn[i], instruction->mnemonic))
1049 {
1050 insn->nargs = 0;
1051 return;
1052 }
1053 }
1054
1055 /* Handle 'excp'/'cinv' instructions. */
1fe1f39c
NC
1056 if (IS_INSN_MNEMONIC ("excp") || IS_INSN_MNEMONIC ("cinv"))
1057 {
1058 insn->nargs = 1;
1059 insn->arg[0].type = arg_ic;
1fe1f39c
NC
1060 insn->arg[0].constant = IS_INSN_MNEMONIC ("excp") ?
1061 gettrap (operands) : get_cinv_parameters (operands);
023d1155 1062 insn->arg[0].X_op = O_constant;
1fe1f39c
NC
1063 return;
1064 }
1065
e3c52c53 1066 /* Handle load/stor unique instructions before parsing. */
64995a6b
TL
1067 if (IS_INSN_TYPE (LD_STOR_INS))
1068 handle_LoadStor (operands);
1fe1f39c
NC
1069
1070 if (operands != NULL)
1071 parse_operands (insn, operands);
1072}
1073
1074/* Cinv instruction requires special handling. */
1075
1076static int
87975d2a 1077get_cinv_parameters (const char *operand)
1fe1f39c 1078{
87975d2a 1079 const char *p = operand;
48c9f030 1080 int d_used = 0, i_used = 0, u_used = 0, b_used = 0;
1fe1f39c
NC
1081
1082 while (*++p != ']')
1083 {
1084 if (*p == ',' || *p == ' ')
1085 continue;
1086
1087 if (*p == 'd')
1088 d_used = 1;
1089 else if (*p == 'i')
1090 i_used = 1;
1091 else if (*p == 'u')
1092 u_used = 1;
48c9f030
NC
1093 else if (*p == 'b')
1094 b_used = 1;
1fe1f39c
NC
1095 else
1096 as_bad (_("Illegal `cinv' parameter: `%c'"), *p);
1097 }
1098
48c9f030
NC
1099 return ((b_used ? 8 : 0)
1100 + (d_used ? 4 : 0)
1fe1f39c
NC
1101 + (i_used ? 2 : 0)
1102 + (u_used ? 1 : 0));
1103}
1104
1105/* Retrieve the opcode image of a given register.
1106 If the register is illegal for the current instruction,
1107 issue an error. */
1108
1109static int
1110getreg_image (reg r)
1111{
91d6fa6a 1112 const reg_entry *rreg;
1fe1f39c 1113 char *reg_name;
9bb1ebc2 1114 int is_procreg = 0; /* Nonzero means argument should be processor reg. */
1fe1f39c 1115
82d6ee2a
TL
1116 if (((IS_INSN_MNEMONIC ("mtpr")) && (cur_arg_num == 1))
1117 || ((IS_INSN_MNEMONIC ("mfpr")) && (cur_arg_num == 0)) )
9bb1ebc2 1118 is_procreg = 1;
1fe1f39c
NC
1119
1120 /* Check whether the register is in registers table. */
1121 if (r < MAX_REG)
91d6fa6a 1122 rreg = &crx_regtab[r];
1fe1f39c 1123 /* Check whether the register is in coprocessor registers table. */
87975d2a 1124 else if (r < (int) MAX_COPREG)
91d6fa6a 1125 rreg = &crx_copregtab[r-MAX_REG];
1fe1f39c
NC
1126 /* Register not found. */
1127 else
1128 {
1129 as_bad (_("Unknown register: `%d'"), r);
1130 return 0;
1131 }
1132
91d6fa6a 1133 reg_name = rreg->name;
1fe1f39c
NC
1134
1135/* Issue a error message when register is illegal. */
1136#define IMAGE_ERR \
33eaf5de 1137 as_bad (_("Illegal register (`%s') in instruction: `%s'"), \
1fe1f39c
NC
1138 reg_name, ins_parse); \
1139 break;
1140
91d6fa6a 1141 switch (rreg->type)
1fe1f39c
NC
1142 {
1143 case CRX_U_REGTYPE:
9bb1ebc2 1144 if (is_procreg || (instruction->flags & USER_REG))
91d6fa6a 1145 return rreg->image;
9bb1ebc2
TL
1146 else
1147 IMAGE_ERR;
1148
1fe1f39c 1149 case CRX_CFG_REGTYPE:
9bb1ebc2 1150 if (is_procreg)
91d6fa6a 1151 return rreg->image;
1fe1f39c
NC
1152 else
1153 IMAGE_ERR;
1154
1155 case CRX_R_REGTYPE:
9bb1ebc2 1156 if (! is_procreg)
91d6fa6a 1157 return rreg->image;
1fe1f39c
NC
1158 else
1159 IMAGE_ERR;
1160
9bb1ebc2
TL
1161 case CRX_C_REGTYPE:
1162 case CRX_CS_REGTYPE:
91d6fa6a 1163 return rreg->image;
9bb1ebc2
TL
1164 break;
1165
1fe1f39c
NC
1166 default:
1167 IMAGE_ERR;
1168 }
1169
1170 return 0;
1171}
1172
023d1155 1173/* Routine used to represent integer X using NBITS bits. */
1fe1f39c 1174
023d1155
TL
1175static long
1176getconstant (long x, int nbits)
1fe1f39c 1177{
1f42f8b3 1178 return x & ((((1U << (nbits - 1)) - 1) << 1) | 1);
1fe1f39c
NC
1179}
1180
1181/* Print a constant value to 'output_opcode':
1182 ARG holds the operand's type and value.
1183 SHIFT represents the location of the operand to be print into.
1184 NBITS determines the size (in bits) of the constant. */
1185
1186static void
1187print_constant (int nbits, int shift, argument *arg)
1188{
1189 unsigned long mask = 0;
1190
1191 long constant = getconstant (arg->constant, nbits);
1192
1193 switch (nbits)
1194 {
1195 case 32:
1196 case 28:
1197 case 24:
1198 case 22:
1199 /* mask the upper part of the constant, that is, the bits
1200 going to the lowest byte of output_opcode[0].
1201 The upper part of output_opcode[1] is always filled,
1202 therefore it is always masked with 0xFFFF. */
1203 mask = (1 << (nbits - 16)) - 1;
1204 /* Divide the constant between two consecutive words :
1205 0 1 2 3
1206 +---------+---------+---------+---------+
1207 | | X X X X | X X X X | |
1208 +---------+---------+---------+---------+
1209 output_opcode[0] output_opcode[1] */
1210
1211 CRX_PRINT (0, (constant >> WORD_SHIFT) & mask, 0);
1212 CRX_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
1213 break;
1214
1215 case 16:
1216 case 12:
1217 /* Special case - in arg_cr, the SHIFT represents the location
1218 of the REGISTER, not the constant, which is itself not shifted. */
1219 if (arg->type == arg_cr)
1220 {
1221 CRX_PRINT (0, constant, 0);
1222 break;
1223 }
1224
3739860c
L
1225 /* When instruction size is 3 and 'shift' is 16, a 16-bit constant is
1226 always filling the upper part of output_opcode[1]. If we mistakenly
9bb1ebc2 1227 write it to output_opcode[0], the constant prefix (that is, 'match')
708587a4 1228 will be overridden.
9bb1ebc2
TL
1229 0 1 2 3
1230 +---------+---------+---------+---------+
1231 | 'match' | | X X X X | |
1232 +---------+---------+---------+---------+
1233 output_opcode[0] output_opcode[1] */
1234
1235 if ((instruction->size > 2) && (shift == WORD_SHIFT))
1fe1f39c
NC
1236 CRX_PRINT (1, constant, WORD_SHIFT);
1237 else
1238 CRX_PRINT (0, constant, shift);
1239 break;
1240
1241 default:
1242 CRX_PRINT (0, constant, shift);
1243 break;
1244 }
1245}
1246
1247/* Print an operand to 'output_opcode', which later on will be
1248 printed to the object file:
1249 ARG holds the operand's type, size and value.
1250 SHIFT represents the printing location of operand.
1251 NBITS determines the size (in bits) of a constant operand. */
1252
1253static void
1254print_operand (int nbits, int shift, argument *arg)
1255{
1256 switch (arg->type)
1257 {
1258 case arg_r:
1259 CRX_PRINT (0, getreg_image (arg->r), shift);
1260 break;
1261
1262 case arg_copr:
1263 if (arg->cr < c0 || arg->cr > c15)
33eaf5de 1264 as_bad (_("Illegal co-processor register in instruction `%s'"),
1fe1f39c
NC
1265 ins_parse);
1266 CRX_PRINT (0, getreg_image (arg->cr), shift);
1267 break;
1268
1269 case arg_copsr:
1270 if (arg->cr < cs0 || arg->cr > cs15)
33eaf5de 1271 as_bad (_("Illegal co-processor special register in instruction `%s'"),
1fe1f39c
NC
1272 ins_parse);
1273 CRX_PRINT (0, getreg_image (arg->cr), shift);
1274 break;
1275
82d6ee2a 1276 case arg_idxr:
1fe1f39c
NC
1277 /* 16 12 8 6 0
1278 +--------------------------------+
9bb1ebc2 1279 | r_base | r_idx | scl| disp |
1fe1f39c
NC
1280 +--------------------------------+ */
1281 CRX_PRINT (0, getreg_image (arg->r), 12);
1282 CRX_PRINT (0, getreg_image (arg->i_r), 8);
1283 CRX_PRINT (0, arg->scale, 6);
1a0670f3 1284 /* Fall through. */
82d6ee2a
TL
1285 case arg_ic:
1286 case arg_c:
1fe1f39c
NC
1287 print_constant (nbits, shift, arg);
1288 break;
1289
1290 case arg_rbase:
1291 CRX_PRINT (0, getreg_image (arg->r), shift);
1292 break;
1293
1294 case arg_cr:
1295 /* case base_cst4. */
023d1155
TL
1296 if (instruction->flags & DISPU4MAP)
1297 print_constant (nbits, shift + REG_SIZE, arg);
1fe1f39c 1298 else
9bb1ebc2 1299 /* rbase_disps<NN> and other such cases. */
1fe1f39c
NC
1300 print_constant (nbits, shift, arg);
1301 /* Add the register argument to the output_opcode. */
1302 CRX_PRINT (0, getreg_image (arg->r), shift);
1303 break;
1304
1fe1f39c
NC
1305 default:
1306 break;
1307 }
1308}
1309
1310/* Retrieve the number of operands for the current assembled instruction. */
1311
1312static int
1313get_number_of_operands (void)
1314{
1315 int i;
1316
1317 for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
1318 ;
1319 return i;
1320}
1321
3739860c
L
1322/* Verify that the number NUM can be represented in BITS bits (that is,
1323 within its permitted range), based on the instruction's FLAGS.
023d1155
TL
1324 If UPDATE is nonzero, update the value of NUM if necessary.
1325 Return OP_LEGAL upon success, actual error type upon failure. */
1326
1327static op_err
1328check_range (long *num, int bits, int unsigned flags, int update)
1329{
1f42f8b3 1330 uint32_t max;
6610dc6d 1331 op_err retval = OP_LEGAL;
023d1155 1332 int bin;
1f42f8b3
AM
1333 uint32_t upper_64kb = 0xffff0000;
1334 uint32_t value = *num;
023d1155
TL
1335
1336 /* Verify operand value is even. */
1337 if (flags & OP_EVEN)
1338 {
1339 if (value % 2)
1340 return OP_NOT_EVEN;
1341 }
1342
1343 if (flags & OP_UPPER_64KB)
1344 {
1345 /* Check if value is to be mapped to upper 64 KB memory area. */
1346 if ((value & upper_64kb) == upper_64kb)
1347 {
1348 value -= upper_64kb;
1349 if (update)
1350 *num = value;
1351 }
1352 else
1353 return OP_NOT_UPPER_64KB;
1354 }
1355
1356 if (flags & OP_SHIFT)
1357 {
1f42f8b3
AM
1358 /* All OP_SHIFT args are also OP_SIGNED, so we want to keep the
1359 sign. However, right shift of a signed type with a negative
1360 value is implementation defined. See ISO C 6.5.7. So we use
1361 an unsigned type and sign extend afterwards. */
023d1155 1362 value >>= 1;
805e800d 1363 value = (value ^ 0x40000000) - 0x40000000;
023d1155
TL
1364 if (update)
1365 *num = value;
1366 }
1367 else if (flags & OP_SHIFT_DEC)
1368 {
1369 value = (value >> 1) - 1;
1370 if (update)
1371 *num = value;
1372 }
1373
1374 if (flags & OP_ESC)
1375 {
1376 /* 0x7e and 0x7f are reserved escape sequences of dispe9. */
1377 if (value == 0x7e || value == 0x7f)
1378 return OP_OUT_OF_RANGE;
1379 }
1380
1381 if (flags & OP_DISPU4)
1382 {
1383 int is_dispu4 = 0;
1384
3739860c 1385 uint32_t mul = (instruction->flags & DISPUB4 ? 1
1f42f8b3
AM
1386 : instruction->flags & DISPUW4 ? 2
1387 : instruction->flags & DISPUD4 ? 4
1388 : 0);
3739860c 1389
023d1155
TL
1390 for (bin = 0; bin < cst4_maps; bin++)
1391 {
1f42f8b3 1392 if (value == mul * bin)
023d1155
TL
1393 {
1394 is_dispu4 = 1;
1395 if (update)
1396 *num = bin;
1397 break;
1398 }
1399 }
1400 if (!is_dispu4)
1401 retval = OP_ILLEGAL_DISPU4;
1402 }
1403 else if (flags & OP_CST4)
1404 {
1405 int is_cst4 = 0;
1406
1407 for (bin = 0; bin < cst4_maps; bin++)
1408 {
805e800d 1409 if (value == (uint32_t) cst4_map[bin])
023d1155
TL
1410 {
1411 is_cst4 = 1;
1412 if (update)
1413 *num = bin;
1414 break;
1415 }
1416 }
1417 if (!is_cst4)
1418 retval = OP_ILLEGAL_CST4;
1419 }
1420 else if (flags & OP_SIGNED)
1421 {
1f42f8b3
AM
1422 max = 1;
1423 max = max << (bits - 1);
1424 value += max;
1425 max = ((max - 1) << 1) | 1;
1426 if (value > max)
023d1155
TL
1427 retval = OP_OUT_OF_RANGE;
1428 }
1429 else if (flags & OP_UNSIGNED)
1430 {
1f42f8b3
AM
1431 max = 1;
1432 max = max << (bits - 1);
1433 max = ((max - 1) << 1) | 1;
1434 if (value > max)
023d1155
TL
1435 retval = OP_OUT_OF_RANGE;
1436 }
1437 return retval;
1438}
1439
1440/* Assemble a single instruction:
1441 INSN is already parsed (that is, all operand values and types are set).
3739860c 1442 For instruction to be assembled, we need to find an appropriate template in
023d1155
TL
1443 the instruction table, meeting the following conditions:
1444 1: Has the same number of operands.
1445 2: Has the same operand types.
1446 3: Each operand size is sufficient to represent the instruction's values.
1fe1f39c
NC
1447 Returns 1 upon success, 0 upon failure. */
1448
1449static int
1450assemble_insn (char *mnemonic, ins *insn)
1451{
023d1155
TL
1452 /* Type of each operand in the current template. */
1453 argtype cur_type[MAX_OPERANDS];
1454 /* Size (in bits) of each operand in the current template. */
1455 unsigned int cur_size[MAX_OPERANDS];
1456 /* Flags of each operand in the current template. */
1457 unsigned int cur_flags[MAX_OPERANDS];
9bb1ebc2 1458 /* Instruction type to match. */
82d6ee2a 1459 unsigned int ins_type;
023d1155 1460 /* Boolean flag to mark whether a match was found. */
1fe1f39c 1461 int match = 0;
023d1155
TL
1462 int i;
1463 /* Nonzero if an instruction with same number of operands was found. */
1464 int found_same_number_of_operands = 0;
1465 /* Nonzero if an instruction with same argument types was found. */
1466 int found_same_argument_types = 0;
1467 /* Nonzero if a constant was found within the required range. */
1468 int found_const_within_range = 0;
1469 /* Argument number of an operand with invalid type. */
1470 int invalid_optype = -1;
1471 /* Argument number of an operand with invalid constant value. */
1472 int invalid_const = -1;
1473 /* Operand error (used for issuing various constant error messages). */
1474 op_err op_error, const_err = OP_LEGAL;
1475
1476/* Retrieve data (based on FUNC) for each operand of a given instruction. */
1477#define GET_CURRENT_DATA(FUNC, ARRAY) \
1478 for (i = 0; i < insn->nargs; i++) \
1479 ARRAY[i] = FUNC (instruction->operands[i].op_type)
1480
1481#define GET_CURRENT_TYPE GET_CURRENT_DATA(get_optype, cur_type)
1482#define GET_CURRENT_SIZE GET_CURRENT_DATA(get_opbits, cur_size)
1483#define GET_CURRENT_FLAGS GET_CURRENT_DATA(get_opflags, cur_flags)
1484
1485 /* Instruction has no operands -> only copy the constant opcode. */
1fe1f39c
NC
1486 if (insn->nargs == 0)
1487 {
1488 output_opcode[0] = BIN (instruction->match, instruction->match_bits);
1489 return 1;
1490 }
1491
9bb1ebc2
TL
1492 /* In some case, same mnemonic can appear with different instruction types.
1493 For example, 'storb' is supported with 3 different types :
1494 LD_STOR_INS, LD_STOR_INS_INC, STOR_IMM_INS.
3739860c 1495 We assume that when reaching this point, the instruction type was
9bb1ebc2
TL
1496 pre-determined. We need to make sure that the type stays the same
1497 during a search for matching instruction. */
1498 ins_type = CRX_INS_TYPE(instruction->flags);
1499
023d1155
TL
1500 while (/* Check that match is still not found. */
1501 match != 1
1fe1f39c
NC
1502 /* Check we didn't get to end of table. */
1503 && instruction->mnemonic != NULL
1504 /* Check that the actual mnemonic is still available. */
9bb1ebc2
TL
1505 && IS_INSN_MNEMONIC (mnemonic)
1506 /* Check that the instruction type wasn't changed. */
1507 && IS_INSN_TYPE(ins_type))
1fe1f39c 1508 {
023d1155
TL
1509 /* Check whether number of arguments is legal. */
1510 if (get_number_of_operands () != insn->nargs)
1511 goto next_insn;
1512 found_same_number_of_operands = 1;
1513
1514 /* Initialize arrays with data of each operand in current template. */
1515 GET_CURRENT_TYPE;
1516 GET_CURRENT_SIZE;
1517 GET_CURRENT_FLAGS;
1518
1519 /* Check for type compatibility. */
1fe1f39c
NC
1520 for (i = 0; i < insn->nargs; i++)
1521 {
023d1155 1522 if (cur_type[i] != insn->arg[i].type)
e92c9d66 1523 {
023d1155
TL
1524 if (invalid_optype == -1)
1525 invalid_optype = i + 1;
1526 goto next_insn;
e92c9d66
TL
1527 }
1528 }
023d1155 1529 found_same_argument_types = 1;
e92c9d66 1530
023d1155
TL
1531 for (i = 0; i < insn->nargs; i++)
1532 {
1533 /* Reverse the operand indices for certain opcodes:
1534 Index 0 -->> 1
3739860c 1535 Index 1 -->> 0
023d1155 1536 Other index -->> stays the same. */
3739860c
L
1537 int j = instruction->flags & REVERSE_MATCH ?
1538 i == 0 ? 1 :
1539 i == 1 ? 0 : i :
023d1155
TL
1540 i;
1541
3739860c
L
1542 /* Only check range - don't update the constant's value, since the
1543 current instruction may not be the last we try to match.
1544 The constant's value will be updated later, right before printing
023d1155 1545 it to the object file. */
3739860c
L
1546 if ((insn->arg[j].X_op == O_constant)
1547 && (op_error = check_range (&insn->arg[j].constant, cur_size[j],
023d1155
TL
1548 cur_flags[j], 0)))
1549 {
1550 if (invalid_const == -1)
1551 {
1552 invalid_const = j + 1;
1553 const_err = op_error;
1554 }
1555 goto next_insn;
1556 }
3739860c 1557 /* For symbols, we make sure the relocation size (which was already
023d1155
TL
1558 determined) is sufficient. */
1559 else if ((insn->arg[j].X_op == O_symbol)
3739860c 1560 && ((bfd_reloc_type_lookup (stdoutput, insn->rtype))->bitsize
023d1155
TL
1561 > cur_size[j]))
1562 goto next_insn;
1563 }
1564 found_const_within_range = 1;
1fe1f39c 1565
023d1155
TL
1566 /* If we got till here -> Full match is found. */
1567 match = 1;
1568 break;
1fe1f39c 1569
023d1155
TL
1570/* Try again with next instruction. */
1571next_insn:
1572 instruction++;
1fe1f39c
NC
1573 }
1574
023d1155 1575 if (!match)
1fe1f39c 1576 {
023d1155
TL
1577 /* We haven't found a match - instruction can't be assembled. */
1578 if (!found_same_number_of_operands)
1579 as_bad (_("Incorrect number of operands"));
1580 else if (!found_same_argument_types)
1581 as_bad (_("Illegal type of operand (arg %d)"), invalid_optype);
1582 else if (!found_const_within_range)
1583 {
1584 switch (const_err)
e3c52c53 1585 {
023d1155
TL
1586 case OP_OUT_OF_RANGE:
1587 as_bad (_("Operand out of range (arg %d)"), invalid_const);
1588 break;
1589 case OP_NOT_EVEN:
1590 as_bad (_("Operand has odd displacement (arg %d)"), invalid_const);
1591 break;
1592 case OP_ILLEGAL_DISPU4:
1593 as_bad (_("Invalid DISPU4 operand value (arg %d)"), invalid_const);
1594 break;
1595 case OP_ILLEGAL_CST4:
1596 as_bad (_("Invalid CST4 operand value (arg %d)"), invalid_const);
1597 break;
1598 case OP_NOT_UPPER_64KB:
3739860c 1599 as_bad (_("Operand value is not within upper 64 KB (arg %d)"),
023d1155
TL
1600 invalid_const);
1601 break;
1602 default:
1603 as_bad (_("Illegal operand (arg %d)"), invalid_const);
1604 break;
e3c52c53 1605 }
023d1155 1606 }
3739860c 1607
023d1155
TL
1608 return 0;
1609 }
1610 else
1611 /* Full match - print the encoding to output file. */
1612 {
33eaf5de 1613 /* Make further checking (such that couldn't be made earlier).
023d1155
TL
1614 Warn the user if necessary. */
1615 warn_if_needed (insn);
3739860c 1616
023d1155
TL
1617 /* Check whether we need to adjust the instruction pointer. */
1618 if (adjust_if_needed (insn))
3739860c 1619 /* If instruction pointer was adjusted, we need to update
023d1155
TL
1620 the size of the current template operands. */
1621 GET_CURRENT_SIZE;
9bb1ebc2 1622
023d1155 1623 for (i = 0; i < insn->nargs; i++)
9bb1ebc2 1624 {
3739860c
L
1625 int j = instruction->flags & REVERSE_MATCH ?
1626 i == 0 ? 1 :
1627 i == 1 ? 0 : i :
023d1155
TL
1628 i;
1629
1630 /* This time, update constant value before printing it. */
3739860c
L
1631 if ((insn->arg[j].X_op == O_constant)
1632 && (check_range (&insn->arg[j].constant, cur_size[j],
023d1155
TL
1633 cur_flags[j], 1) != OP_LEGAL))
1634 as_fatal (_("Illegal operand (arg %d)"), j+1);
9bb1ebc2
TL
1635 }
1636
023d1155
TL
1637 /* First, copy the instruction's opcode. */
1638 output_opcode[0] = BIN (instruction->match, instruction->match_bits);
9bb1ebc2 1639
023d1155 1640 for (i = 0; i < insn->nargs; i++)
1fe1f39c 1641 {
023d1155 1642 cur_arg_num = i;
3739860c 1643 print_operand (cur_size[i], instruction->operands[i].shift,
023d1155
TL
1644 &insn->arg[i]);
1645 }
1646 }
9bb1ebc2 1647
023d1155
TL
1648 return 1;
1649}
9bb1ebc2 1650
33eaf5de 1651/* Bunch of error checking.
023d1155 1652 The checks are made after a matching instruction was found. */
9bb1ebc2 1653
023d1155
TL
1654void
1655warn_if_needed (ins *insn)
1656{
3739860c
L
1657 /* If the post-increment address mode is used and the load/store
1658 source register is the same as rbase, the result of the
023d1155
TL
1659 instruction is undefined. */
1660 if (IS_INSN_TYPE (LD_STOR_INS_INC))
1661 {
1662 /* Enough to verify that one of the arguments is a simple reg. */
1663 if ((insn->arg[0].type == arg_r) || (insn->arg[1].type == arg_r))
1664 if (insn->arg[0].r == insn->arg[1].r)
3739860c 1665 as_bad (_("Same src/dest register is used (`r%d'), result is undefined"),
023d1155
TL
1666 insn->arg[0].r);
1667 }
9bb1ebc2 1668
023d1155
TL
1669 /* Some instruction assume the stack pointer as rptr operand.
1670 Issue an error when the register to be loaded is also SP. */
1671 if (instruction->flags & NO_SP)
1672 {
1673 if (getreg_image (insn->arg[0].r) == getreg_image (sp))
1674 as_bad (_("`%s' has undefined result"), ins_parse);
1675 }
1fe1f39c 1676
3739860c 1677 /* If the rptr register is specified as one of the registers to be loaded,
023d1155
TL
1678 the final contents of rptr are undefined. Thus, we issue an error. */
1679 if (instruction->flags & NO_RPTR)
1680 {
1681 if ((1 << getreg_image (insn->arg[0].r)) & insn->arg[1].constant)
3739860c 1682 as_bad (_("Same src/dest register is used (`r%d'), result is undefined"),
023d1155
TL
1683 getreg_image (insn->arg[0].r));
1684 }
1685}
1fe1f39c 1686
3739860c 1687/* In some cases, we need to adjust the instruction pointer although a
023d1155
TL
1688 match was already found. Here, we gather all these cases.
1689 Returns 1 if instruction pointer was adjusted, otherwise 0. */
1fe1f39c 1690
023d1155
TL
1691int
1692adjust_if_needed (ins *insn)
1693{
1694 int ret_value = 0;
1695
1696 /* Special check for 'addub $0, r0' instruction -
1697 The opcode '0000 0000 0000 0000' is not allowed. */
1698 if (IS_INSN_MNEMONIC ("addub"))
1699 {
1700 if ((instruction->operands[0].op_type == cst4)
1701 && instruction->operands[1].op_type == regr)
1fe1f39c 1702 {
023d1155
TL
1703 if (insn->arg[0].constant == 0 && insn->arg[1].r == r0)
1704 {
1705 instruction++;
1706 ret_value = 1;
1707 }
1fe1f39c
NC
1708 }
1709 }
1710
3739860c 1711 /* Optimization: Omit a zero displacement in bit operations,
023d1155
TL
1712 saving 2-byte encoding space (e.g., 'cbitw $8, 0(r1)'). */
1713 if (IS_INSN_TYPE (CSTBIT_INS))
1714 {
1715 if ((instruction->operands[1].op_type == rbase_disps12)
1716 && (insn->arg[1].X_op == O_constant)
1717 && (insn->arg[1].constant == 0))
1718 {
1719 instruction--;
1720 ret_value = 1;
1721 }
1722 }
1723
1724 return ret_value;
1fe1f39c
NC
1725}
1726
1727/* Set the appropriate bit for register 'r' in 'mask'.
1728 This indicates that this register is loaded or stored by
1729 the instruction. */
1730
1731static void
1732mask_reg (int r, unsigned short int *mask)
1733{
1734 if ((reg)r > (reg)sp)
1735 {
33eaf5de 1736 as_bad (_("Invalid register in register list"));
1fe1f39c
NC
1737 return;
1738 }
1739
1740 *mask |= (1 << r);
1741}
1742
1743/* Preprocess register list - create a 16-bit mask with one bit for each
1744 of the 16 general purpose registers. If a bit is set, it indicates
1745 that this register is loaded or stored by the instruction. */
1746
1747static char *
1748preprocess_reglist (char *param, int *allocated)
1749{
1750 char reg_name[MAX_REGNAME_LEN]; /* Current parsed register name. */
1751 char *regP; /* Pointer to 'reg_name' string. */
1752 int reg_counter = 0; /* Count number of parsed registers. */
1753 unsigned short int mask = 0; /* Mask for 16 general purpose registers. */
1754 char *new_param; /* New created operands string. */
33eaf5de 1755 char *paramP = param; /* Pointer to original operands string. */
1fe1f39c 1756 char maskstring[10]; /* Array to print the mask as a string. */
9bb1ebc2 1757 int hi_found = 0, lo_found = 0; /* Boolean flags for hi/lo registers. */
1fe1f39c
NC
1758 reg r;
1759 copreg cr;
1760
1761 /* If 'param' is already in form of a number, no need to preprocess. */
1762 if (strchr (paramP, '{') == NULL)
1763 return param;
1764
1765 /* Verifying correct syntax of operand. */
1766 if (strchr (paramP, '}') == NULL)
1767 as_fatal (_("Missing matching brackets : `%s'"), ins_parse);
1768
1769 while (*paramP++ != '{');
1770
add39d23 1771 new_param = XCNEWVEC (char, MAX_INST_LEN);
1fe1f39c
NC
1772 *allocated = 1;
1773 strncpy (new_param, param, paramP - param - 1);
1774
1775 while (*paramP != '}')
1776 {
1777 regP = paramP;
1778 memset (&reg_name, '\0', sizeof (reg_name));
1779
1780 while (ISALNUM (*paramP))
1781 paramP++;
1782
1783 strncpy (reg_name, regP, paramP - regP);
1784
48c9f030 1785 /* Coprocessor register c<N>. */
1fe1f39c
NC
1786 if (IS_INSN_TYPE (COP_REG_INS))
1787 {
9bb1ebc2
TL
1788 if (((cr = get_copregister (reg_name)) == nullcopregister)
1789 || (crx_copregtab[cr-MAX_REG].type != CRX_C_REGTYPE))
1790 as_fatal (_("Illegal register `%s' in cop-register list"), reg_name);
1fe1f39c
NC
1791 mask_reg (getreg_image (cr - c0), &mask);
1792 }
48c9f030
NC
1793 /* Coprocessor Special register cs<N>. */
1794 else if (IS_INSN_TYPE (COPS_REG_INS))
1795 {
9bb1ebc2
TL
1796 if (((cr = get_copregister (reg_name)) == nullcopregister)
1797 || (crx_copregtab[cr-MAX_REG].type != CRX_CS_REGTYPE))
3739860c 1798 as_fatal (_("Illegal register `%s' in cop-special-register list"),
48c9f030
NC
1799 reg_name);
1800 mask_reg (getreg_image (cr - cs0), &mask);
1801 }
9bb1ebc2
TL
1802 /* User register u<N>. */
1803 else if (instruction->flags & USER_REG)
1804 {
1805 if (streq(reg_name, "uhi"))
1806 {
1807 hi_found = 1;
1808 goto next_inst;
1809 }
1810 else if (streq(reg_name, "ulo"))
1811 {
1812 lo_found = 1;
1813 goto next_inst;
1814 }
1815 else if (((r = get_register (reg_name)) == nullregister)
1816 || (crx_regtab[r].type != CRX_U_REGTYPE))
1817 as_fatal (_("Illegal register `%s' in user register list"), reg_name);
3739860c
L
1818
1819 mask_reg (getreg_image (r - u0), &mask);
9bb1ebc2 1820 }
48c9f030 1821 /* General purpose register r<N>. */
1fe1f39c
NC
1822 else
1823 {
9bb1ebc2
TL
1824 if (streq(reg_name, "hi"))
1825 {
1826 hi_found = 1;
1827 goto next_inst;
1828 }
1829 else if (streq(reg_name, "lo"))
1830 {
1831 lo_found = 1;
1832 goto next_inst;
1833 }
1834 else if (((r = get_register (reg_name)) == nullregister)
1835 || (crx_regtab[r].type != CRX_R_REGTYPE))
1836 as_fatal (_("Illegal register `%s' in register list"), reg_name);
1837
1838 mask_reg (getreg_image (r - r0), &mask);
1fe1f39c
NC
1839 }
1840
1841 if (++reg_counter > MAX_REGS_IN_MASK16)
1842 as_bad (_("Maximum %d bits may be set in `mask16' operand"),
1843 MAX_REGS_IN_MASK16);
1844
9bb1ebc2 1845next_inst:
1fe1f39c
NC
1846 while (!ISALNUM (*paramP) && *paramP != '}')
1847 paramP++;
1848 }
1849
1850 if (*++paramP != '\0')
1851 as_warn (_("rest of line ignored; first ignored character is `%c'"),
1852 *paramP);
1853
9bb1ebc2
TL
1854 switch (hi_found + lo_found)
1855 {
1856 case 0:
1857 /* At least one register should be specified. */
1858 if (mask == 0)
1859 as_bad (_("Illegal `mask16' operand, operation is undefined - `%s'"),
1860 ins_parse);
1861 break;
1862
1863 case 1:
1864 /* HI can't be specified without LO (and vise-versa). */
1865 as_bad (_("HI/LO registers should be specified together"));
1866 break;
1867
1868 case 2:
1869 /* HI/LO registers mustn't be masked with additional registers. */
1870 if (mask != 0)
1871 as_bad (_("HI/LO registers should be specified without additional registers"));
1872
1873 default:
1874 break;
1875 }
1fe1f39c
NC
1876
1877 sprintf (maskstring, "$0x%x", mask);
1878 strcat (new_param, maskstring);
1879 return new_param;
1880}
1881
1882/* Print the instruction.
1883 Handle also cases where the instruction is relaxable/relocatable. */
1884
1885void
1886print_insn (ins *insn)
1887{
1888 unsigned int i, j, insn_size;
1889 char *this_frag;
1890 unsigned short words[4];
aea44f62 1891 int addr_mod;
1fe1f39c
NC
1892
1893 /* Arrange the insn encodings in a WORD size array. */
1894 for (i = 0, j = 0; i < 2; i++)
1895 {
1896 words[j++] = (output_opcode[i] >> 16) & 0xFFFF;
1897 words[j++] = output_opcode[i] & 0xFFFF;
1898 }
1899
33eaf5de 1900 /* Handle relaxation. */
1fe1f39c
NC
1901 if ((instruction->flags & RELAXABLE) && relocatable)
1902 {
1903 int relax_subtype;
1904
1905 /* Write the maximal instruction size supported. */
1906 insn_size = INSN_MAX_SIZE;
1907
1908 /* bCC */
1909 if (IS_INSN_TYPE (BRANCH_INS))
1910 relax_subtype = 0;
1911 /* bal */
1912 else if (IS_INSN_TYPE (DCR_BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
1913 relax_subtype = 3;
30c62922
TL
1914 /* cmpbr/bcop */
1915 else if (IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (COP_BRANCH_INS))
1fe1f39c
NC
1916 relax_subtype = 5;
1917 else
1918 abort ();
1919
1920 this_frag = frag_var (rs_machine_dependent, insn_size * 2,
1921 4, relax_subtype,
1922 insn->exp.X_add_symbol,
1923 insn->exp.X_add_number,
1924 0);
1925 }
1926 else
1927 {
1928 insn_size = instruction->size;
1929 this_frag = frag_more (insn_size * 2);
1930
1931 /* Handle relocation. */
1932 if ((relocatable) && (insn->rtype != BFD_RELOC_NONE))
1933 {
1934 reloc_howto_type *reloc_howto;
1935 int size;
1936
1937 reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
1938
1939 if (!reloc_howto)
1940 abort ();
1941
1942 size = bfd_get_reloc_size (reloc_howto);
1943
1944 if (size < 1 || size > 4)
1945 abort ();
1946
1947 fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
1948 size, &insn->exp, reloc_howto->pc_relative,
1949 insn->rtype);
1950 }
1951 }
1952
aea44f62
TL
1953 /* Verify a 2-byte code alignment. */
1954 addr_mod = frag_now_fix () & 1;
1955 if (frag_now->has_code && frag_now->insn_addr != addr_mod)
1956 as_bad (_("instruction address is not a multiple of 2"));
1957 frag_now->insn_addr = addr_mod;
1958 frag_now->has_code = 1;
1959
1fe1f39c
NC
1960 /* Write the instruction encoding to frag. */
1961 for (i = 0; i < insn_size; i++)
1962 {
1963 md_number_to_chars (this_frag, (valueT) words[i], 2);
1964 this_frag += 2;
1965 }
1966}
1967
1968/* This is the guts of the machine-dependent assembler. OP points to a
1969 machine dependent instruction. This function is supposed to emit
1970 the frags/bytes it assembles to. */
1971
1972void
1973md_assemble (char *op)
1974{
1975 ins crx_ins;
1976 char *param;
1977 char c;
1978
1979 /* Reset global variables for a new instruction. */
023d1155 1980 reset_vars (op);
1fe1f39c
NC
1981
1982 /* Strip the mnemonic. */
1983 for (param = op; *param != 0 && !ISSPACE (*param); param++)
1984 ;
1985 c = *param;
1986 *param++ = '\0';
1987
1988 /* Find the instruction. */
1989 instruction = (const inst *) hash_find (crx_inst_hash, op);
1990 if (instruction == NULL)
1991 {
1992 as_bad (_("Unknown opcode: `%s'"), op);
87975d2a 1993 param[-1] = c;
1fe1f39c
NC
1994 return;
1995 }
1996
1997 /* Tie dwarf2 debug info to the address at the start of the insn. */
1998 dwarf2_emit_insn (0);
1999
023d1155
TL
2000 /* Parse the instruction's operands. */
2001 parse_insn (&crx_ins, param);
1fe1f39c 2002
023d1155 2003 /* Assemble the instruction - return upon failure. */
1fe1f39c 2004 if (assemble_insn (op, &crx_ins) == 0)
87975d2a
AM
2005 {
2006 param[-1] = c;
2007 return;
2008 }
1fe1f39c
NC
2009
2010 /* Print the instruction. */
87975d2a 2011 param[-1] = c;
1fe1f39c
NC
2012 print_insn (&crx_ins);
2013}