gas: sparc: fix collision of registers and pseudo-ops.
[deliverable/binutils-gdb.git] / gas / config / tc-xgate.c
CommitLineData
f6c1a2d5 1/* tc-xgate.c -- Assembler code for Freescale XGATE
6f2750fe 2 Copyright (C) 2010-2016 Free Software Foundation, Inc.
f6c1a2d5
NC
3 Contributed by Sean Keys <skeys@ipdatasys.com>
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22#include "as.h"
23#include "safe-ctype.h"
24#include "subsegs.h"
25#include "opcode/xgate.h"
26#include "dwarf2dbg.h"
27#include "elf/xgate.h"
28
29const char comment_chars[] = ";!";
30const char line_comment_chars[] = "#*";
31const char line_separator_chars[] = "";
32const char EXP_CHARS[] = "eE";
33const char FLT_CHARS[] = "dD";
34
0e1c2434
SK
35/* Max opcodes per opcode handle. */
36#define MAX_OPCODES 0x05
37
234fa27c
AM
38#define SIXTEENTH_BIT 0x8000
39#define N_BITS_IN_WORD 16
40#define MAX_NUM_OPERANDS 3
f6c1a2d5
NC
41
42/* #define STATE_CONDITIONAL_BRANCH (1) */
43#define STATE_PC_RELATIVE (2)
44#define REGISTER_P(ptr) (ptr == 'r')
45#define INCREMENT 01
46#define DECREMENT 02
47#define MAXREGISTER 07
48#define MINREGISTER 00
49
50#define OPTION_MMCU 'm'
51
52/* This macro has no side-effects. */
53#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
54
19f55fe4
SK
55/* Each unique opcode name has a handle. That handle may
56 contain pointers to opcodes with the same name but
57 different address modes. */
f6c1a2d5
NC
58struct xgate_opcode_handle
59{
60 int number_of_modes;
61 char *name;
62 struct xgate_opcode *opc0[MAX_OPCODES];
63};
64
234fa27c
AM
65/* XGATE's registers all are 16-bit general purpose.
66 They are numbered according to the specifications. */
3879925e
SK
67typedef enum register_id
68{
69 REG_NONE = -1,
70 REG_R0 = 0,
71 REG_R1 = 1,
72 REG_R2 = 2,
73 REG_R3 = 3,
74 REG_R4 = 4,
75 REG_R5 = 5,
76 REG_R6 = 6,
77 REG_R7 = 7,
78 REG_PC = 8,
79 REG_CCR = 9
80} register_id;
81
82/* Operand Modifiers */
83typedef enum op_modifiers
84{
85 MOD_NONE = -1,
86 MOD_POSTINC = 1,
87 MOD_PREDEC = 2,
88 MOD_CONSTANT = 3,
89 MOD_LOAD_HIGH = 4,
90 MOD_LOAD_LOW = 5
91}op_modifiers;
92
93typedef struct s_operand
94{
95 expressionS exp;
96 register_id reg;
97 op_modifiers mod;
98} s_operand;
99
100
234fa27c
AM
101/* Forward declarations. */
102static inline char *skip_whitespace (char *);
103static void get_default_target (void);
104static char *extract_word (char *, char *, int);
105static struct xgate_opcode *xgate_find_match (struct xgate_opcode_handle *,
0e1c2434 106 int, s_operand [], unsigned int);
234fa27c
AM
107static int cmp_opcode (struct xgate_opcode *, struct xgate_opcode *);
108static void xgate_print_table (void);
109static unsigned int xgate_get_operands (char *, s_operand []);
110static register_id reg_name_search (char *);
111static op_modifiers xgate_determine_modifiers(char **);
112static void xgate_scan_operands (struct xgate_opcode *opcode, s_operand []);
113static unsigned int xgate_parse_operand (struct xgate_opcode *, int *, int,
114 char **, s_operand);
f6c1a2d5 115
f6c1a2d5
NC
116static struct hash_control *xgate_hash;
117
118/* Previous opcode. */
119static unsigned int prev = 0;
120
121static unsigned char fixup_required = 0;
122
123/* Used to enable clipping of 16 bit operands into 8 bit constraints. */
234fa27c 124static unsigned char autoHiLo = 0;
f6c1a2d5
NC
125
126static char oper_check;
127static char flag_print_insn_syntax = 0;
128static char flag_print_opcodes = 0;
129
130static int current_architecture;
131static const char *default_cpu;
132
133/* ELF flags to set in the output file header. */
134static int elf_flags = E_XGATE_F64;
135
136/* This table describes how you change sizes for the various types of variable
137 size expressions. This version only supports two kinds. */
138
139/* The fields are:
140 How far Forward this mode will reach.
141 How far Backward this mode will reach.
142 How many bytes this mode will add to the size of the frag.
143 Which mode to go to if the offset won't fit in this one. */
144
145relax_typeS md_relax_table[] =
146{
147 {1, 1, 0, 0}, /* First entries aren't used. */
148 {1, 1, 0, 0}, /* For no good reason except. */
149 {1, 1, 0, 0}, /* that the VAX doesn't either. */
150 {1, 1, 0, 0},
151 /* XGATE 9 and 10 bit pc rel todo complete and test */
152/*{(511), (-512), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)},
153 {(1023), (-1024), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)}, */
154 {0, 0, 0, 0}
155};
156
f6c1a2d5
NC
157/* This table describes all the machine specific pseudo-ops the assembler
158 has to support. The fields are: pseudo-op name without dot function to
159 call to execute this pseudo-op Integer arg to pass to the function. */
160const pseudo_typeS md_pseudo_table[] =
161{
162 /* The following pseudo-ops are supported for MRI compatibility. */
163 {0, 0, 0}
164};
165
166const char *md_shortopts = "m:";
167
168struct option md_longopts[] =
169{
170#define OPTION_PRINT_INSN_SYNTAX (OPTION_MD_BASE + 0)
171 { "print-insn-syntax", no_argument, NULL, OPTION_PRINT_INSN_SYNTAX },
172
173#define OPTION_PRINT_OPCODES (OPTION_MD_BASE + 1)
174 { "print-opcodes", no_argument, NULL, OPTION_PRINT_OPCODES },
175
176#define OPTION_GENERATE_EXAMPLE (OPTION_MD_BASE + 2)
177 { "generate-example", no_argument, NULL, OPTION_GENERATE_EXAMPLE },
178
179#define OPTION_MSHORT (OPTION_MD_BASE + 3)
180 { "mshort", no_argument, NULL, OPTION_MSHORT },
181
182#define OPTION_MLONG (OPTION_MD_BASE + 4)
183 { "mlong", no_argument, NULL, OPTION_MLONG },
184
185#define OPTION_MSHORT_DOUBLE (OPTION_MD_BASE + 5)
186 { "mshort-double", no_argument, NULL, OPTION_MSHORT_DOUBLE },
187
188#define OPTION_MLONG_DOUBLE (OPTION_MD_BASE + 6)
189 { "mlong-double", no_argument, NULL, OPTION_MLONG_DOUBLE },
190
191 { NULL, no_argument, NULL, 0 }
192};
193
194size_t md_longopts_size = sizeof(md_longopts);
195
6d4af3c2 196const char *
f6c1a2d5
NC
197md_atof (int type, char *litP, int *sizeP)
198{
199 return ieee_md_atof (type, litP, sizeP, TRUE);
200}
201
202int
17b9d67d 203md_parse_option (int c, const char *arg)
f6c1a2d5
NC
204{
205 switch (c)
206 {
207 case OPTION_MMCU:
208 if (strcasecmp (arg, "v1") == 0)
209 current_architecture = XGATE_V1;
210 else if (strcasecmp (arg, "v2") == 0)
211 current_architecture = XGATE_V2;
212 else if (strcasecmp (arg, "v3") == 0)
213 current_architecture = XGATE_V3;
214 else
215 as_bad (_(" architecture variant invalid"));
216 break;
217
218 case OPTION_PRINT_INSN_SYNTAX:
219 flag_print_insn_syntax = 1;
220 break;
221
222 case OPTION_PRINT_OPCODES:
223 flag_print_opcodes = 1;
224 break;
225
226 case OPTION_GENERATE_EXAMPLE:
227 flag_print_opcodes = 2;
228 break;
229
230 case OPTION_MSHORT:
231 elf_flags &= ~E_XGATE_I32;
232 break;
233
234 case OPTION_MLONG:
235 elf_flags |= E_XGATE_I32;
236 break;
237
238 case OPTION_MSHORT_DOUBLE:
239 elf_flags &= ~E_XGATE_F64;
240 break;
241
242 case OPTION_MLONG_DOUBLE:
243 elf_flags |= E_XGATE_F64;
244 break;
245
246 default:
247 return 0;
248 }
249 return 1;
250}
251
252const char *
253xgate_arch_format (void)
254{
255 get_default_target ();
256
257 if (current_architecture & cpuxgate)
258 return "elf32-xgate";
259
260 return "error";
261}
262
263static void
264get_default_target (void)
265{
266 const bfd_target *target;
267 bfd abfd;
268
269 if (current_architecture != 0)
270 return;
271
272 default_cpu = "unknown";
273 target = bfd_find_target (0, &abfd);
274
275 if (target && target->name)
276 {
277 if (strcmp (target->name, "elf32-xgate") == 0)
234fa27c
AM
278 {
279 current_architecture = cpuxgate;
280 default_cpu = "XGATE V1";
281 return;
282 }
f6c1a2d5
NC
283
284 as_bad (_("Default target `%s' is not supported."), target->name);
285 }
286}
287
288void
289md_begin (void)
290{
291 struct xgate_opcode *xgate_opcode_ptr = NULL;
292 struct xgate_opcode *xgate_op_table = NULL;
293 struct xgate_opcode_handle *op_handles = 0;
e0471c16 294 const char *prev_op_name = 0;
f6c1a2d5 295 int handle_enum = 0;
19f55fe4 296 int number_of_op_handles = 0;
f6c1a2d5
NC
297 int i, j = 0;
298
299 /* Create a local copy of our opcode table
300 including an extra line for NULL termination. */
add39d23 301 xgate_op_table = XNEWVEC (struct xgate_opcode, xgate_num_opcodes);
f6c1a2d5
NC
302
303 memset (xgate_op_table, 0,
19f55fe4 304 sizeof(struct xgate_opcode) * (xgate_num_opcodes));
f6c1a2d5
NC
305
306 for (xgate_opcode_ptr = (struct xgate_opcode*) xgate_opcodes, i = 0;
234fa27c 307 i < xgate_num_opcodes; i++)
f6c1a2d5
NC
308 xgate_op_table[i] = xgate_opcode_ptr[i];
309
310 qsort (xgate_op_table, xgate_num_opcodes, sizeof(struct xgate_opcode),
311 (int (*)(const void *, const void *)) cmp_opcode);
312
313 /* Calculate number of handles since this will be
314 smaller than the raw number of opcodes in the table. */
19f55fe4
SK
315 prev_op_name = "";
316 for (xgate_opcode_ptr = xgate_op_table, i = 0; i < xgate_num_opcodes;
234fa27c 317 xgate_opcode_ptr++, i++)
f6c1a2d5 318 {
19f55fe4 319 if (strcmp (prev_op_name, xgate_opcode_ptr->name))
234fa27c 320 number_of_op_handles++;
f6c1a2d5
NC
321 prev_op_name = xgate_opcode_ptr->name;
322 }
323
add39d23 324 op_handles = XNEWVEC (struct xgate_opcode_handle, number_of_op_handles);
f6c1a2d5 325
19f55fe4 326 /* Insert unique opcode names into hash table, aliasing duplicates. */
f6c1a2d5
NC
327 xgate_hash = hash_new ();
328
19f55fe4 329 prev_op_name = "";
f6c1a2d5 330 for (xgate_opcode_ptr = xgate_op_table, i = 0, j = 0; i < xgate_num_opcodes;
234fa27c 331 i++, xgate_opcode_ptr++)
f6c1a2d5 332 {
19f55fe4 333 if (!strcmp (prev_op_name, xgate_opcode_ptr->name))
234fa27c
AM
334 {
335 handle_enum++;
336 op_handles[j].opc0[handle_enum] = xgate_opcode_ptr;
337 }
19f55fe4 338 else
234fa27c
AM
339 {
340 handle_enum = 0;
341 if (i)
342 j++;
343 op_handles[j].name = xgate_opcode_ptr->name;
344 op_handles[j].opc0[0] = xgate_opcode_ptr;
345 hash_insert (xgate_hash, (char *) op_handles[j].name,
346 (char *) &(op_handles[j]));
347 }
f6c1a2d5
NC
348 op_handles[j].number_of_modes = handle_enum;
349 prev_op_name = op_handles[j].name;
350 }
351
f4b1f6a9
SK
352 if (flag_print_opcodes)
353 {
464e3686 354 xgate_print_table ();
f4b1f6a9
SK
355 exit (EXIT_SUCCESS);
356 }
f6c1a2d5
NC
357}
358
359void
360xgate_init_after_args (void)
361{
362}
363
364void
365md_show_usage (FILE * stream)
366{
367 get_default_target ();
368
234fa27c 369 fprintf (stream,
f6c1a2d5 370 _("\
234fa27c
AM
371Freescale XGATE co-processor options:\n\
372 -mshort use 16-bit int ABI (default)\n\
373 -mlong use 32-bit int ABI\n\
374 -mshort-double use 32-bit double ABI\n\
375 -mlong-double use 64-bit double ABI (default)\n\
376 --mxgate specify the processor variant[default %s]\n\
377 --print-insn-syntax print the syntax of instruction in case of error\n\
378 --print-opcodes print the list of instructions with syntax\n\
379 --generate-example generate an example of each instruction"),
f6c1a2d5
NC
380 default_cpu);
381}
382
383enum bfd_architecture
384xgate_arch (void)
385{
386 get_default_target ();
387 return bfd_arch_xgate;
388}
389
390int
391xgate_mach (void)
392{
393 return 0;
394}
395
234fa27c 396static void
f6c1a2d5
NC
397xgate_print_syntax (char *name)
398{
399 int i;
400
401 for (i = 0; i < xgate_num_opcodes; i++)
402 {
403 if (!strcmp (xgate_opcodes[i].name, name))
234fa27c
AM
404 {
405 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IDR))
406 printf ("\tFormat is %s\tRx, Rx, Rx+|-Rx|Rx\n",
f6c1a2d5 407 xgate_opcodes[i].name);
234fa27c
AM
408 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_INH))
409 printf ("\tFormat is %s\n", xgate_opcodes[i].name);
410 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_TRI))
411 printf ("\tFormat is %s\tRx, Rx, Rx\n", xgate_opcodes[i].name);
412 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_DYA))
413 printf ("\tFormat is %s\tRx, Rx\n", xgate_opcodes[i].name);
414 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM3))
415 printf ("\tFormat is %s\t<3-bit value>\n", xgate_opcodes[i].name);
416 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM4))
417 printf ("\tFormat is %s\t<4 -bit value>\n", xgate_opcodes[i].name);
418 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM8))
419 printf ("\tFormat is %s\tRx, <8-bit value>\n",
f6c1a2d5 420 xgate_opcodes[i].name);
234fa27c
AM
421 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM16))
422 printf ("\tFormat is %s\tRx, <16-bit value>\n",
f6c1a2d5 423 xgate_opcodes[i].name);
234fa27c
AM
424 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON_R_C))
425 printf ("\tFormat is %s\tRx, CCR\n", xgate_opcodes[i].name);
426 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON_C_R))
427 printf ("\tFormat is %s\tCCR, Rx\n", xgate_opcodes[i].name);
428 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON_R_P))
429 printf ("\tFormat is %s\tRx, PC\n", xgate_opcodes[i].name);
430 if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM16mLDW))
431 printf ("\tFormat is %s\tRx, <16-bit value>\n",
f6c1a2d5 432 xgate_opcodes[i].name);
234fa27c 433 }
f6c1a2d5
NC
434 }
435}
436
234fa27c 437static void
f6c1a2d5
NC
438xgate_print_table (void)
439{
440 int i;
441
442 for (i = 0; i < xgate_num_opcodes; i++)
443 xgate_print_syntax (xgate_opcodes[i].name);
444
445 return;
446}
447
448const char *
449xgate_listing_header (void)
450{
451 if (current_architecture & cpuxgate)
452 return "XGATE GAS ";
453
454 return "ERROR MC9S12X GAS ";
455}
456
457symbolS *
458md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
459{
460 return 0;
461}
462
463/* GAS will call this function for each section at the end of the assembly,
464 to permit the CPU backend to adjust the alignment of a section. */
465
466valueT
467md_section_align (asection * seg, valueT addr)
468{
469 int align = bfd_get_section_alignment (stdoutput, seg);
8d3842cd 470 return ((addr + (1 << align) - 1) & -(1 << align));
f6c1a2d5
NC
471}
472
473void
474md_assemble (char *input_line)
475{
476 struct xgate_opcode *opcode = 0;
477 struct xgate_opcode *macro_opcode = 0;
478 struct xgate_opcode_handle *opcode_handle = 0;
479 /* Caller expects it to be returned as it was passed. */
480 char *saved_input_line = input_line;
481 char op_name[9] = { 0 };
0e1c2434 482 unsigned int operandCount = 0;
f6c1a2d5
NC
483 char *p = 0;
484
3879925e
SK
485 s_operand new_operands[MAX_NUM_OPERANDS];
486
f6c1a2d5
NC
487 fixup_required = 0;
488 oper_check = 0; /* set error flags */
489 input_line = extract_word (input_line, op_name, sizeof(op_name));
490
491 /* Check to make sure we are not reading a bogus line. */
492 if (!op_name[0])
493 as_bad (_("opcode missing or not found on input line"));
494
495 if (!(opcode_handle = (struct xgate_opcode_handle *) hash_find (xgate_hash,
234fa27c 496 op_name)))
f6c1a2d5
NC
497 {
498 as_bad (_("opcode %s not found in opcode hash table"), op_name);
499 }
500 else
501 {
3879925e
SK
502 /* Parse operands so we can find the proper opcode bin. */
503
0e1c2434 504 operandCount = xgate_get_operands (input_line, new_operands);
f6c1a2d5
NC
505
506 opcode = xgate_find_match (opcode_handle, opcode_handle->number_of_modes,
0e1c2434 507 new_operands, operandCount);
f6c1a2d5
NC
508
509 if (!opcode)
234fa27c
AM
510 {
511 as_bad (_("matching operands to opcode "));
512 xgate_print_syntax (opcode_handle->opc0[0]->name);
513 }
f6c1a2d5 514 else if (opcode->size == 2)
234fa27c 515 {
f6c1a2d5 516 /* Size is one word - assemble that native insn. */
234fa27c
AM
517 xgate_scan_operands (opcode, new_operands);
518 }
f6c1a2d5 519 else
234fa27c 520 {
f6c1a2d5 521 /* Insn is a simplified instruction - expand it out. */
234fa27c
AM
522 autoHiLo = 1;
523 unsigned int i;
524
525 /* skip past our ';' separator. */
526 for (i = strlen (opcode->constraints), p = opcode->constraints; i > 0;
527 i--, p++)
528 {
529 if (*p == ';')
530 {
531 p++;
532 break;
533 }
534 }
535 input_line = skip_whitespace (input_line);
536 char *macro_inline = input_line;
537
538 /* Loop though the macro's opcode list and apply operands to
539 each real opcode. */
540 for (i = 0; *p && i < (opcode->size / 2); i++)
541 {
f6c1a2d5 542 /* Loop though macro operand list. */
234fa27c
AM
543 input_line = macro_inline; /* Rewind. */
544 p = extract_word (p, op_name, 10);
f6c1a2d5 545
234fa27c 546 if (!(opcode_handle = (struct xgate_opcode_handle *)
f6c1a2d5 547 hash_find (xgate_hash, op_name)))
234fa27c
AM
548 {
549 as_bad (_(": processing macro, real opcode handle"
550 " not found in hash"));
551 break;
552 }
553 else
554 {
0e1c2434
SK
555 operandCount = xgate_get_operands(input_line, new_operands);
556 macro_opcode = xgate_find_match (opcode_handle,
557 opcode_handle->number_of_modes, new_operands,
558 operandCount);
234fa27c 559 xgate_scan_operands (macro_opcode, new_operands);
234fa27c
AM
560 }
561 }
562 }
f6c1a2d5 563 }
8d8ad4eb 564 autoHiLo = 0;
f6c1a2d5
NC
565 input_line = saved_input_line;
566}
567
568/* Force truly undefined symbols to their maximum size, and generally set up
569 the frag list to be relaxed. */
570
571int
572md_estimate_size_before_relax (fragS *fragp, asection *seg)
573{
574 /* If symbol is undefined or located in a different section,
575 select the largest supported relocation. */
576 relax_substateT subtype;
234fa27c 577 relax_substateT rlx_state[] = { 0, 2 };
f6c1a2d5
NC
578
579 for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
580 {
581 if (fragp->fr_subtype == rlx_state[subtype]
234fa27c
AM
582 && (!S_IS_DEFINED (fragp->fr_symbol)
583 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
584 {
585 fragp->fr_subtype = rlx_state[subtype + 1];
586 break;
587 }
f6c1a2d5
NC
588 }
589
590 if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
591 abort ();
592
593 return md_relax_table[fragp->fr_subtype].rlx_length;
594}
595
596
597/* Relocation, relaxation and frag conversions. */
598
599/* PC-relative offsets are relative to the start of the
600 next instruction. That is, the address of the offset, plus its
601 size, since the offset is always the last part of the insn. */
602
603long
604md_pcrel_from (fixS * fixP)
605{
606 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
607}
608
609/* If while processing a fixup, a reloc really needs to be created
610 then it is done here. */
611
612arelent *
613tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
614{
615 arelent * reloc;
616
add39d23
TS
617 reloc = XNEW (arelent);
618 reloc->sym_ptr_ptr = XNEW (asymbol *);
f6c1a2d5
NC
619 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
620 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
621
622 if (fixp->fx_r_type == 0)
234fa27c 623 reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16);
f6c1a2d5 624 else
234fa27c 625 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
f6c1a2d5
NC
626
627 if (reloc->howto == (reloc_howto_type *) NULL)
628 {
629 as_bad_where (fixp->fx_file, fixp->fx_line, _
234fa27c
AM
630 ("Relocation %d is not supported by object file format."),
631 (int) fixp->fx_r_type);
f6c1a2d5
NC
632 return NULL;
633 }
634
635 /* Since we use Rel instead of Rela, encode the vtable entry to be
636 used in the relocation's section offset. */
637 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
638 reloc->address = fixp->fx_offset;
639 reloc->addend = 0;
640 return reloc;
641}
642
643/* Patch the instruction with the resolved operand. Elf relocation
644 info will also be generated to take care of linker/loader fixups.
645 The XGATE addresses only 16-bit addresses.The BFD_RELOC_32 is necessary
646 for the support of --gstabs. */
647
648void
649md_apply_fix (fixS * fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
650{
651 char *where;
652 long value = *valP;
653 int opcode = 0;
654 ldiv_t result;
655
234fa27c
AM
656 /* If the fixup is done mark it done so no further symbol resolution
657 will take place. */
f6c1a2d5 658 if (fixP->fx_addsy == (symbolS *) NULL)
234fa27c 659 fixP->fx_done = 1;
f6c1a2d5
NC
660
661 /* We don't actually support subtracting a symbol. */
662 if (fixP->fx_subsy != (symbolS *) NULL)
663 as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));
664
665 where = fixP->fx_frag->fr_literal + fixP->fx_where;
666 opcode = bfd_getl16 (where);
667 int mask = 0;
668
669 switch (fixP->fx_r_type)
670 {
671 case R_XGATE_PCREL_9:
672 if (value < -512 || value > 511)
673 as_bad_where (fixP->fx_file, fixP->fx_line,
234fa27c
AM
674 _("Value %ld too large for 9-bit PC-relative branch."),
675 value);
f6c1a2d5
NC
676 result = ldiv (value, 2); /* from bytes to words */
677 value = result.quot;
678 if (result.rem)
679 as_bad_where (fixP->fx_file, fixP->fx_line, _
234fa27c
AM
680 ("Value %ld not aligned by 2 for 9-bit"
681 " PC-relative branch."), value);
682 /* Clip into 8-bit field.
683 FIXME I'm sure there is a more proper place for this. */
684 mask = 0x1FF;
f6c1a2d5
NC
685 value &= mask;
686 number_to_chars_bigendian (where, (opcode | value), 2);
687 break;
688 case R_XGATE_PCREL_10:
689 if (value < -1024 || value > 1023)
690 as_bad_where (fixP->fx_file, fixP->fx_line,
234fa27c
AM
691 _("Value %ld too large for 10-bit PC-relative branch."),
692 value);
f6c1a2d5
NC
693 result = ldiv (value, 2); /* from bytes to words */
694 value = result.quot;
695 if (result.rem)
696 as_bad_where (fixP->fx_file, fixP->fx_line, _
234fa27c
AM
697 ("Value %ld not aligned by 2 for 10-bit"
698 " PC-relative branch."), value);
699 /* Clip into 9-bit field.
700 FIXME I'm sure there is a more proper place for this. */
701 mask = 0x3FF;
f6c1a2d5
NC
702 value &= mask;
703 number_to_chars_bigendian (where, (opcode | value), 2);
704 break;
705 case BFD_RELOC_XGATE_IMM8_HI:
706 if (value < -65537 || value > 65535)
707 as_bad_where (fixP->fx_file, fixP->fx_line,
708 _("Value out of 16-bit range."));
709 value >>= 8;
710 value &= 0x00ff;
711 bfd_putb16 ((bfd_vma) value | opcode, (void *) where);
712 break;
713 case BFD_RELOC_XGATE_24:
714 case BFD_RELOC_XGATE_IMM8_LO:
715 if (value < -65537 || value > 65535)
716 as_bad_where (fixP->fx_file, fixP->fx_line,
717 _("Value out of 16-bit range."));
718 value &= 0x00ff;
719 bfd_putb16 ((bfd_vma) value | opcode, (void *) where);
720 break;
721 case BFD_RELOC_XGATE_IMM3:
722 if (value < 0 || value > 7)
723 as_bad_where (fixP->fx_file, fixP->fx_line,
724 _("Value out of 3-bit range."));
725 value <<= 8; /* make big endian */
726 number_to_chars_bigendian (where, (opcode | value), 2);
727 break;
728 case BFD_RELOC_XGATE_IMM4:
729 if (value < 0 || value > 15)
730 as_bad_where (fixP->fx_file, fixP->fx_line,
731 _("Value out of 4-bit range."));
732 value <<= 4; /* align the operand bits */
733 number_to_chars_bigendian (where, (opcode | value), 2);
734 break;
735 case BFD_RELOC_XGATE_IMM5:
736 if (value < 0 || value > 31)
737 as_bad_where (fixP->fx_file, fixP->fx_line,
738 _("Value out of 5-bit range."));
739 value <<= 5; /* align the operand bits */
740 number_to_chars_bigendian (where, (opcode | value), 2);
741 break;
742 case BFD_RELOC_8:
743 ((bfd_byte *) where)[0] = (bfd_byte) value;
744 break;
745 case BFD_RELOC_32:
746 bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
f6c1a2d5
NC
747 break;
748 case BFD_RELOC_16:
749 bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
750 break;
751 default:
752 as_fatal (_("Line %d: unknown relocation type: 0x%x."), fixP->fx_line,
753 fixP->fx_r_type);
754 break;
755 }
756}
757
758/* See whether we need to force a relocation into the output file. */
759
760int
761tc_xgate_force_relocation (fixS * fixP)
762{
763 if (fixP->fx_r_type == BFD_RELOC_XGATE_RL_GROUP)
764 return 1;
765 return generic_force_reloc (fixP);
766}
767
768/* Here we decide which fixups can be adjusted to make them relative
769 to the beginning of the section instead of the symbol. Basically
770 we need to make sure that the linker relaxation is done
771 correctly, so in some cases we force the original symbol to be
772 used. */
773
774int
775tc_xgate_fix_adjustable (fixS * fixP)
776{
777 switch (fixP->fx_r_type)
778 {
779 /* For the linker relaxation to work correctly, these relocs
780 need to be on the symbol itself. */
781 case BFD_RELOC_16:
782 case BFD_RELOC_XGATE_RL_JUMP:
783 case BFD_RELOC_XGATE_RL_GROUP:
784 case BFD_RELOC_VTABLE_INHERIT:
785 case BFD_RELOC_VTABLE_ENTRY:
786 case BFD_RELOC_32:
787 return 0;
788 default:
789 return 1;
790 }
791}
792
793void
794md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
795 asection * sec ATTRIBUTE_UNUSED,
796 fragS * fragP ATTRIBUTE_UNUSED)
797{
798 as_bad (("md_convert_frag not implemented yet"));
799 abort ();
800}
801
802/* Set the ELF specific flags. */
803
804void
805xgate_elf_final_processing (void)
806{
807 elf_flags |= EF_XGATE_MACH;
808 elf_elfheader (stdoutput)->e_flags &= ~EF_XGATE_ABI;
809 elf_elfheader (stdoutput)->e_flags |= elf_flags;
810}
811
812static inline char *
813skip_whitespace (char *s)
814{
815 while (*s == ' ' || *s == '\t' || *s == '(' || *s == ')')
816 s++;
817
818 return s;
819}
820
821/* Extract a word (continuous alpha-numeric chars) from the input line. */
822
823static char *
824extract_word (char *from, char *to, int limit)
825{
826 char *op_end;
827 int size = 0;
828
829 /* Drop leading whitespace. */
830 from = skip_whitespace (from);
831 *to = 0;
832 /* Find the op code end. */
833 for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
834 {
835 to[size++] = *op_end++;
836 if (size + 1 >= limit)
234fa27c 837 break;
f6c1a2d5
NC
838 }
839 to[size] = 0;
840 return op_end;
841}
842
843static char *
844xgate_new_instruction (int size)
845{
846 char *f = frag_more (size);
847 dwarf2_emit_insn (size);
848 return f;
849}
850
234fa27c 851static unsigned short
f6c1a2d5
NC
852xgate_apply_operand (unsigned short new_mask,
853 unsigned short *availiable_mask_bits,
854 unsigned short mask,
855 unsigned char n_bits)
856{
857 unsigned short n_shifts;
858 unsigned int n_drop_bits;
859
234fa27c
AM
860 /* Shift until you find an available operand bit "1" and record
861 the number of shifts. */
f6c1a2d5
NC
862 for (n_shifts = 0;
863 !(*availiable_mask_bits & SIXTEENTH_BIT) && n_shifts < 16;
864 n_shifts++)
865 *availiable_mask_bits <<= 1;
866
234fa27c
AM
867 /* Shift for the number of bits your operand requires while bits
868 are available. */
f6c1a2d5
NC
869 for (n_drop_bits = n_bits;
870 n_drop_bits && (*availiable_mask_bits & SIXTEENTH_BIT);
871 --n_drop_bits)
872 *availiable_mask_bits <<= 1;
873
874 if (n_drop_bits)
875 as_bad (_(":operand has too many bits"));
876 *availiable_mask_bits >>= n_shifts + n_bits;
877 if ((n_drop_bits == 0) && (*availiable_mask_bits == 0))
878 {
879 oper_check = 1; /* flag operand check as good */
880 }
881 new_mask <<= N_BITS_IN_WORD - (n_shifts + n_bits);
882 mask |= new_mask;
883 return mask;
884}
885
886/* Parse ordinary expression. */
887
888static char *
889xgate_parse_exp (char *s, expressionS * op)
890{
891 input_line_pointer = s;
892 expression(op);
893 if (op->X_op == O_absent)
894 as_bad (_("missing operand"));
895 return input_line_pointer;
896}
897
3879925e
SK
898static int
899cmp_opcode (struct xgate_opcode *op1, struct xgate_opcode *op2)
900{
901 return strcmp (op1->name, op2->name);
902}
903
904static struct xgate_opcode *
905xgate_find_match (struct xgate_opcode_handle *opcode_handle,
0e1c2434 906 int numberOfModes, s_operand oprs[], unsigned int operandCount)
3879925e
SK
907{
908 int i;
f6c1a2d5 909
3879925e
SK
910 if (numberOfModes == 0)
911 return opcode_handle->opc0[0];
912
913 for (i = 0; i <= numberOfModes; i++)
0e1c2434
SK
914 {
915 switch (operandCount)
916 {
917 case 0:
918 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_INH))
919 return opcode_handle->opc0[i];
920 break;
921 case 1:
922 if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
923 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_MON))
924 return opcode_handle->opc0[i];
925 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_DYA_MON))
926 return opcode_handle->opc0[i];
927 if (oprs[0].reg == REG_NONE)
928 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM3))
929 return opcode_handle->opc0[i];
930 break;
931 case 2:
932 if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
933 {
934 if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
935 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_DYA))
936 return opcode_handle->opc0[i];
937 if (oprs[1].reg == REG_CCR)
938 if (!strcmp(opcode_handle->opc0[i]->constraints,
939 XGATE_OP_MON_R_C))
940 return opcode_handle->opc0[i];
941 if (oprs[1].reg == REG_PC)
942 if (!strcmp(opcode_handle->opc0[i]->constraints,
943 XGATE_OP_MON_R_P))
944 return opcode_handle->opc0[i];
945 if (oprs[1].reg == REG_NONE)
946 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM16)
947 || !strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM8)
948 || !strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM4)
949 || !strcmp(opcode_handle->opc0[i]->constraints,
950 XGATE_OP_IMM16mADD)
951 || !strcmp(opcode_handle->opc0[i]->constraints,
952 XGATE_OP_IMM16mAND)
953 || !strcmp(opcode_handle->opc0[i]->constraints,
954 XGATE_OP_IMM16mCPC)
955 || !strcmp(opcode_handle->opc0[i]->constraints,
956 XGATE_OP_IMM16mSUB)
957 || !strcmp(opcode_handle->opc0[i]->constraints,
958 XGATE_OP_IMM16mLDW))
959 return opcode_handle->opc0[i];
960 }
961 if (oprs[0].reg == REG_CCR)
962 if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_MON_C_R))
963 return opcode_handle->opc0[i];
964 break;
965 case 3:
966 if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
967 {
968 if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
969 {
970 if (oprs[2].reg >= REG_R0 && oprs[2].reg <= REG_R7)
971 {
972 if (!strcmp(opcode_handle->opc0[i]->constraints,
973 XGATE_OP_IDR)
974 || !strcmp(opcode_handle->opc0[i]->constraints,
975 XGATE_OP_TRI))
976 return opcode_handle->opc0[i];
977 }
978
979 if (oprs[2].reg == REG_NONE)
980 if (!strcmp(opcode_handle->opc0[i]->constraints,
981 XGATE_OP_IDO5))
982 return opcode_handle->opc0[i];
983 }
984 }
985 break;
986 default:
987 as_bad(_("unknown operand count"));
988 break;
989 }
990 }
991 return NULL ;
3879925e
SK
992}
993
994/* Because we are dealing with two different core that view the system
995 memory with different offsets, we must differentiate what core a
996 symbol belongs to, in order for the linker to cross-link. */
997
998int
999xgate_frob_symbol (symbolS *sym)
f6c1a2d5 1000{
3879925e
SK
1001 asymbol *bfdsym;
1002 elf_symbol_type *elfsym;
f6c1a2d5 1003
3879925e
SK
1004 bfdsym = symbol_get_bfdsym (sym);
1005 elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
f6c1a2d5 1006
3879925e 1007 gas_assert(elfsym);
f6c1a2d5 1008
3879925e
SK
1009 /* Mark the symbol as being *from XGATE */
1010 elfsym->internal_elf_sym.st_target_internal = 1;
f6c1a2d5 1011
3879925e 1012 return 0;
f6c1a2d5 1013}
f6c1a2d5 1014
234fa27c 1015static unsigned int
3879925e 1016xgate_get_operands (char *line, s_operand oprs[])
f6c1a2d5 1017{
3879925e
SK
1018 int num_operands;
1019
1020 /* If there are no operands, then it must be inherent. */
1021 if (*line == 0 || *line == '\n' || *line == '\r')
0e1c2434 1022 return 0;
3879925e
SK
1023
1024 for (num_operands = 0; strlen (line) && (num_operands < MAX_NUM_OPERANDS);
234fa27c 1025 num_operands++)
3879925e
SK
1026 {
1027 line = skip_whitespace (line);
1028 if (*line == '#')
234fa27c 1029 line++;
3879925e 1030
8d8ad4eb 1031 oprs[num_operands].mod = xgate_determine_modifiers (&line);
3879925e
SK
1032
1033 if ((oprs[num_operands].reg = reg_name_search (line)) == REG_NONE)
234fa27c 1034 line = xgate_parse_exp (line, &oprs[num_operands].exp);
3879925e
SK
1035
1036 /* skip to next operand */
1037 while (*line != 0)
234fa27c
AM
1038 {
1039 if (*line == ',')
1040 {
1041 line++;
1042 break;
1043 }
1044 line++;
1045 }
3879925e 1046 }
3879925e
SK
1047 if (num_operands > MAX_NUM_OPERANDS)
1048 return 0;
0e1c2434 1049 return num_operands;
3879925e
SK
1050}
1051
1052/* reg_name_search() finds the register number given its name.
1053 Returns the register number or REG_NONE on failure. */
1054static register_id
1055reg_name_search (char *name)
1056{
1057 if (strncasecmp (name, "r0", 2) == 0)
1058 return REG_R0;
1059 if (strncasecmp (name, "r1", 2) == 0)
1060 return REG_R1;
1061 if (strncasecmp (name, "r2", 2) == 0)
1062 return REG_R2;
1063 if (strncasecmp (name, "r3", 2) == 0)
1064 return REG_R3;
1065 if (strncasecmp (name, "r4", 2) == 0)
1066 return REG_R4;
1067 if (strncasecmp (name, "r5", 2) == 0)
1068 return REG_R5;
1069 if (strncasecmp (name, "r6", 2) == 0)
1070 return REG_R6;
1071 if (strncasecmp (name, "r7", 2) == 0)
1072 return REG_R7;
1073 if (strncasecmp (name, "pc", 2) == 0)
1074 return REG_PC;
1075 if (strncasecmp (name, "ccr", 3) == 0)
1076 return REG_CCR;
1077 return REG_NONE;
1078}
1079
8d8ad4eb
SK
1080/* Parse operand modifiers such as inc/dec/hi/low. */
1081
234fa27c 1082static op_modifiers
8d8ad4eb 1083xgate_determine_modifiers(char **line)
3879925e
SK
1084{
1085 char *local_line = line[0];
1086
1087 if (strncasecmp (local_line, "%hi", 3) == 0)
1088 {
1089 *line += 3;
1090 return MOD_LOAD_HIGH;
1091 }
1092 if (strncasecmp (local_line, "%lo", 3) == 0)
1093 {
1094 *line += 3;
1095 return MOD_LOAD_LOW;
1096 }
3879925e 1097 if (*(local_line + 2) == '+')
234fa27c 1098 return MOD_POSTINC;
3879925e
SK
1099 if (strncasecmp (local_line, "-r", 2) == 0)
1100 {
1101 *line += 1;
1102 return MOD_PREDEC;
234fa27c 1103 }
3879925e 1104 return MOD_NONE;
f6c1a2d5
NC
1105}
1106
1107/* Parse instruction operands. */
1108
234fa27c 1109static void
3879925e 1110xgate_scan_operands (struct xgate_opcode *opcode, s_operand oprs[])
f6c1a2d5
NC
1111{
1112 char *frag = xgate_new_instruction (opcode->size);
1113 int where = frag - frag_now->fr_literal;
1114 char *op = opcode->constraints;
1115 unsigned int bin = (int) opcode->bin_opcode;
f6c1a2d5
NC
1116 unsigned short oper_mask = 0;
1117 int operand_bit_length = 0;
1118 unsigned int operand = 0;
1119 char n_operand_bits = 0;
1120 char first_operand_equals_second = 0;
1121 int i = 0;
1122 char c = 0;
1123
1124 /* Generate available operand bits mask. */
1125 for (i = 0; (c = opcode->format[i]); i++)
1126 {
1127 if (ISDIGIT (c) || (c == 's'))
234fa27c
AM
1128 {
1129 oper_mask <<= 1;
1130 }
f6c1a2d5 1131 else
234fa27c
AM
1132 {
1133 oper_mask <<= 1;
1134 oper_mask += 1;
1135 n_operand_bits++;
1136 }
f6c1a2d5
NC
1137 }
1138
f6c1a2d5
NC
1139 /* Parse first operand. */
1140 if (*op)
1141 {
1142 if (*op == '=')
234fa27c
AM
1143 {
1144 first_operand_equals_second = 1;
1145 ++op;
1146 }
1147 operand = xgate_parse_operand (opcode, &operand_bit_length, where,
1148 &op, oprs[0]);
f6c1a2d5
NC
1149 ++op;
1150 bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
3879925e
SK
1151
1152 if(first_operand_equals_second)
234fa27c
AM
1153 bin = xgate_apply_operand (operand, &oper_mask, bin,
1154 operand_bit_length);
f6c1a2d5
NC
1155 /* Parse second operand. */
1156 if (*op)
234fa27c
AM
1157 {
1158 if (*op == ',')
1159 ++op;
1160 if (first_operand_equals_second)
1161 {
1162 bin = xgate_apply_operand (operand, &oper_mask, bin,
1163 operand_bit_length);
1164 ++op;
1165 }
1166 else
1167 {
1168 operand = xgate_parse_operand (opcode, &operand_bit_length, where,
1169 &op, oprs[1]);
1170 bin = xgate_apply_operand (operand, &oper_mask, bin,
1171 operand_bit_length);
1172 ++op;
1173 }
1174 }
f6c1a2d5
NC
1175 /* Parse the third register. */
1176 if (*op)
234fa27c
AM
1177 {
1178 if (*op == ',')
1179 ++op;
1180 operand = xgate_parse_operand (opcode, &operand_bit_length, where,
1181 &op, oprs[2]);
1182 bin = xgate_apply_operand (operand, &oper_mask, bin,
1183 operand_bit_length);
1184 }
f6c1a2d5
NC
1185 }
1186 if (opcode->size == 2 && fixup_required)
1187 {
1188 bfd_putl16 (bin, frag);
1189 }
0e1c2434
SK
1190 else if ( !strcmp (opcode->constraints, XGATE_OP_REL9)
1191 || !strcmp (opcode->constraints, XGATE_OP_REL10))
f6c1a2d5
NC
1192 {
1193 /* Write our data to a frag for further processing. */
3879925e 1194 bfd_putl16 (opcode->bin_opcode, frag);
f6c1a2d5
NC
1195 }
1196 else
1197 {
1198 /* Apply operand mask(s)to bin opcode and write the output. */
1199 /* Since we are done write this frag in xgate BE format. */
3879925e 1200 number_to_chars_bigendian (frag, bin, opcode->size);
f6c1a2d5
NC
1201 }
1202 prev = bin;
f6c1a2d5
NC
1203 return;
1204}
1205
1206static unsigned int
3879925e 1207xgate_parse_operand (struct xgate_opcode *opcode,
234fa27c
AM
1208 int *bit_width,
1209 int where,
1210 char **op_con,
1211 s_operand operand)
f6c1a2d5 1212{
f6c1a2d5
NC
1213 char *op_constraint = *op_con;
1214 unsigned int op_mask = 0;
f6c1a2d5
NC
1215 unsigned int pp_fix = 0;
1216 unsigned short max_size = 0;
1217 int i;
1218
1219 *bit_width = 0;
1220 /* Reset. */
1221
1222 switch (*op_constraint)
1223 {
1224 case '+': /* Indexed register operand +/- or plain r. */
f6c1a2d5
NC
1225 /* Default to neither inc or dec. */
1226 pp_fix = 0;
1227 *bit_width = 5;
3879925e 1228
8d8ad4eb 1229 if (operand.reg == REG_NONE)
234fa27c 1230 as_bad (_(": expected register name r0-r7 ") );
8d8ad4eb
SK
1231 op_mask = operand.reg;
1232 if(operand.mod == MOD_POSTINC)
234fa27c 1233 pp_fix = INCREMENT;
8d8ad4eb 1234 if(operand.mod == MOD_PREDEC)
234fa27c 1235 pp_fix = DECREMENT;
f6c1a2d5
NC
1236 op_mask <<= 2;
1237 op_mask |= pp_fix;
1238 break;
1239
1240 case 'r': /* Register operand. */
234fa27c
AM
1241 if (operand.reg == REG_NONE)
1242 as_bad (_(": expected register name r0-r7 "));
3879925e 1243
234fa27c 1244 *bit_width = 3;
3879925e 1245
234fa27c 1246 op_mask = operand.reg;
f6c1a2d5
NC
1247 break;
1248
1249 case 'i': /* Immediate value or expression expected. */
1250 /* Advance the original format pointer. */
1251 (*op_con)++;
1252 op_constraint++;
1253 if (ISDIGIT (*op_constraint))
234fa27c 1254 *bit_width = (int) *op_constraint - '0';
f6c1a2d5 1255 else if (*op_constraint == 'a')
234fa27c 1256 *bit_width = 0x0A;
f6c1a2d5 1257 else if (*op_constraint == 'f')
234fa27c
AM
1258 *bit_width = 0x0F;
1259
f6c1a2d5 1260 /* http://tigcc.ticalc.org/doc/gnuasm.html#SEC31 */
8d8ad4eb 1261 if (operand.exp.X_op == O_constant)
234fa27c
AM
1262 {
1263 op_mask = operand.exp.X_add_number;
1264 if (((opcode->name[strlen (opcode->name) - 1] == 'l') && autoHiLo)
1265 || operand.mod == MOD_LOAD_LOW)
1266 op_mask &= 0x00FF;
1267 else if (((opcode->name[strlen (opcode->name) - 1]) == 'h'
1268 && autoHiLo) || operand.mod == MOD_LOAD_HIGH)
1269 op_mask >>= 8;
1270
1271 /* Make sure it fits. */
1272 for (i = *bit_width; i; i--)
1273 {
1274 max_size <<= 1;
1275 max_size += 1;
1276 }
1277 if (op_mask > max_size)
1278 as_bad (_(":operand value(%d) too big for constraint"), op_mask);
1279 }
f6c1a2d5 1280 else
234fa27c
AM
1281 {
1282 /* Should be BFD_RELOC_XGATE_IMM8_LO instead of BFD_RELOC_XGATE_24
1283 TODO fix. */
1284 fixup_required = 1;
1285 if (*op_constraint == '8')
1286 {
1287 if (((opcode->name[strlen (opcode->name) - 1] == 'l')
1288 && autoHiLo) || operand.mod == MOD_LOAD_LOW)
1289 fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1290 BFD_RELOC_XGATE_24);
1291 else if (((opcode->name[strlen (opcode->name) - 1]) == 'h'
1292 && autoHiLo) || operand.mod == MOD_LOAD_HIGH )
1293 fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1294 BFD_RELOC_XGATE_IMM8_HI);
1295 else
1296 as_bad (_("you must use a hi/lo directive or 16-bit macro "
1297 "to load a 16-bit value."));
1298 }
1299 else if (*op_constraint == '5')
1300 fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1301 BFD_RELOC_XGATE_IMM5);
1302 else if (*op_constraint == '4')
1303 fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1304 BFD_RELOC_XGATE_IMM4);
1305 else if (*op_constraint == '3')
1306 fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1307 BFD_RELOC_XGATE_IMM3);
1308 else
1309 as_bad (_(":unknown relocation constraint size"));
1310 }
8d8ad4eb 1311 break;
f6c1a2d5
NC
1312
1313 case 'c': /* CCR register expected. */
3879925e 1314 *bit_width = 0;
8d8ad4eb 1315 if (operand.reg != REG_CCR)
234fa27c 1316 as_bad (_(": expected register name ccr "));
8d8ad4eb 1317 break;
f6c1a2d5
NC
1318
1319 case 'p': /* PC register expected. */
3879925e 1320 *bit_width = 0;
234fa27c
AM
1321 if (operand.reg != REG_PC)
1322 as_bad (_(": expected register name pc "));
f6c1a2d5
NC
1323 break;
1324
1325 case 'b': /* Branch expected. */
f6c1a2d5
NC
1326 (*op_con)++;
1327 op_constraint++;
f6c1a2d5 1328
8d8ad4eb 1329 if (operand.exp.X_op != O_register)
234fa27c
AM
1330 {
1331 if (*op_constraint == '9')
1332 fix_new_exp (frag_now, where, 2, &operand.exp, TRUE,
1333 R_XGATE_PCREL_9);
1334 else if (*op_constraint == 'a')
1335 fix_new_exp (frag_now, where, 2, &operand.exp, TRUE,
1336 R_XGATE_PCREL_10);
1337 }
3879925e 1338 else
234fa27c
AM
1339 as_fatal (_("Operand `%x' not recognized in fixup8."),
1340 operand.exp.X_op);
3879925e
SK
1341 break;
1342 case '?':
1343 break;
fe540416 1344
3879925e
SK
1345 default:
1346 as_bad (_("unknown constraint `%c'"), *op_constraint);
1347 break;
1348 }
1349 return op_mask;
fe540416 1350}
This page took 0.325781 seconds and 4 git commands to generate.