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