2002-01-29 Daniel Jacobowitz <drow@mvista.com>
[deliverable/binutils-gdb.git] / gas / config / tc-tic30.c
CommitLineData
252b5132 1/* tc-c30.c -- Assembly code for the Texas Instruments TMS320C30
3882b010 2 Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
252b5132
RH
3 Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
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 2, 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 the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
19d63e5d 22/* Texas Instruments TMS320C30 machine specific gas.
252b5132
RH
23 Written by Steven Haworth (steve@pm.cse.rmit.edu.au).
24 Bugs & suggestions are completely welcome. This is free software.
19d63e5d 25 Please help us make it better. */
252b5132
RH
26
27#include "as.h"
3882b010 28#include "safe-ctype.h"
252b5132
RH
29#include "opcode/tic30.h"
30
19d63e5d
KH
31/* Put here all non-digit non-letter charcters that may occur in an
32 operand. */
252b5132 33static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]";
19d63e5d
KH
34static char *ordinal_names[] = {
35 "first", "second", "third", "fourth", "fifth"
36};
252b5132
RH
37
38const int md_reloc_size = 0;
39
40const char comment_chars[] = ";";
41const char line_comment_chars[] = "*";
42const char line_separator_chars[] = "";
43
44const char *md_shortopts = "";
19d63e5d 45struct option md_longopts[] = {
252b5132
RH
46 {NULL, no_argument, NULL, 0}
47};
48
49size_t md_longopts_size = sizeof (md_longopts);
50
19d63e5d 51/* Chars that mean this number is a floating point constant. */
252b5132
RH
52/* As in 0f12.456 */
53/* or 0d1.2345e12 */
54const char FLT_CHARS[] = "fFdDxX";
55
19d63e5d
KH
56/* Chars that can be used to separate mant from exp in floating point
57 nums. */
252b5132
RH
58const char EXP_CHARS[] = "eE";
59
60/* tables for lexical analysis */
61static char opcode_chars[256];
62static char register_chars[256];
63static char operand_chars[256];
64static char space_chars[256];
65static char identifier_chars[256];
66static char digit_chars[256];
67
68/* lexical macros */
69#define is_opcode_char(x) (opcode_chars[(unsigned char) x])
70#define is_operand_char(x) (operand_chars[(unsigned char) x])
71#define is_register_char(x) (register_chars[(unsigned char) x])
72#define is_space_char(x) (space_chars[(unsigned char) x])
73#define is_identifier_char(x) (identifier_chars[(unsigned char) x])
74#define is_digit_char(x) (digit_chars[(unsigned char) x])
75
19d63e5d 76const pseudo_typeS md_pseudo_table[] = {
252b5132
RH
77 {0, 0, 0}
78};
79
80#undef USE_STDOUT
81#define USE_STDOUT 1
82
83#ifdef USE_STDARG
84
85#include <stdarg.h>
86
87int
19d63e5d 88debug (const char *string, ...)
252b5132
RH
89{
90 if (flag_debug)
91 {
92 va_list argptr;
93 char str[100];
94
95 va_start (argptr, string);
96 vsprintf (str, string, argptr);
97 if (str[0] == '\0')
98 return (0);
99 va_end (argptr);
100 fputs (str, USE_STDOUT ? stdout : stderr);
101 return strlen (str);
102 }
103 else
104 return 0;
105}
106#else
107int
108debug (string, va_alist)
109 const char *string;
110 va_dcl
111{
112 if (flag_debug)
113 {
114 va_list argptr;
115 char str[100];
116 int cnt;
117
118 va_start (argptr, string);
119 cnt = vsprintf (str, string, argptr);
120 if (str[0] == NULL)
121 return (0);
122 va_end (argptr);
123 fputs (str, USE_STDOUT ? stdout : stderr);
124 return (cnt);
125 }
126 else
127 return 0;
128}
129#endif
130
131/* hash table for opcode lookup */
132static struct hash_control *op_hash;
133/* hash table for parallel opcode lookup */
134static struct hash_control *parop_hash;
135/* hash table for register lookup */
136static struct hash_control *reg_hash;
137/* hash table for indirect addressing lookup */
138static struct hash_control *ind_hash;
139
140void
141md_begin ()
142{
143 const char *hash_err;
144 debug ("In md_begin()\n");
145 op_hash = hash_new ();
146 {
147 const template *current_optab = tic30_optab;
148 for (; current_optab < tic30_optab_end; current_optab++)
149 {
150 hash_err = hash_insert (op_hash, current_optab->name, (char *) current_optab);
151 if (hash_err)
152 as_fatal ("Internal Error: Can't Hash %s: %s", current_optab->name, hash_err);
153 }
154 }
155 parop_hash = hash_new ();
156 {
157 const partemplate *current_parop = tic30_paroptab;
158 for (; current_parop < tic30_paroptab_end; current_parop++)
159 {
160 hash_err = hash_insert (parop_hash, current_parop->name, (char *) current_parop);
161 if (hash_err)
162 as_fatal ("Internal Error: Can't Hash %s: %s", current_parop->name, hash_err);
163 }
164 }
165 reg_hash = hash_new ();
166 {
167 const reg *current_reg = tic30_regtab;
168 for (; current_reg < tic30_regtab_end; current_reg++)
169 {
170 hash_err = hash_insert (reg_hash, current_reg->name, (char *) current_reg);
171 if (hash_err)
172 as_fatal ("Internal Error: Can't Hash %s: %s", current_reg->name, hash_err);
173 }
174 }
175 ind_hash = hash_new ();
176 {
177 const ind_addr_type *current_ind = tic30_indaddr_tab;
178 for (; current_ind < tic30_indaddrtab_end; current_ind++)
179 {
180 hash_err = hash_insert (ind_hash, current_ind->syntax, (char *) current_ind);
181 if (hash_err)
182 as_fatal ("Internal Error: Can't Hash %s: %s", current_ind->syntax, hash_err);
183 }
184 }
185 /* fill in lexical tables: opcode_chars, operand_chars, space_chars */
186 {
187 register int c;
188 register char *p;
189
190 for (c = 0; c < 256; c++)
191 {
3882b010 192 if (ISLOWER (c) || ISDIGIT (c))
252b5132
RH
193 {
194 opcode_chars[c] = c;
195 register_chars[c] = c;
196 }
3882b010 197 else if (ISUPPER (c))
252b5132 198 {
3882b010 199 opcode_chars[c] = TOLOWER (c);
252b5132
RH
200 register_chars[c] = opcode_chars[c];
201 }
202 else if (c == ')' || c == '(')
203 {
204 register_chars[c] = c;
205 }
3882b010 206 if (ISUPPER (c) || ISLOWER (c) || ISDIGIT (c))
252b5132 207 operand_chars[c] = c;
3882b010 208 if (ISDIGIT (c) || c == '-')
252b5132 209 digit_chars[c] = c;
3882b010 210 if (ISALPHA (c) || c == '_' || c == '.' || ISDIGIT (c))
252b5132
RH
211 identifier_chars[c] = c;
212 if (c == ' ' || c == '\t')
213 space_chars[c] = c;
214 if (c == '_')
215 opcode_chars[c] = c;
216 }
217 for (p = operand_special_chars; *p != '\0'; p++)
218 operand_chars[(unsigned char) *p] = *p;
219 }
220}
221
222/* Address Mode OR values */
223#define AM_Register 0x00000000
224#define AM_Direct 0x00200000
225#define AM_Indirect 0x00400000
226#define AM_Immediate 0x00600000
227#define AM_NotReq 0xFFFFFFFF
228
229/* PC Relative OR values */
230#define PC_Register 0x00000000
231#define PC_Relative 0x02000000
232
19d63e5d 233typedef struct {
252b5132 234 unsigned op_type;
19d63e5d
KH
235 struct {
236 int resolved;
237 unsigned address;
238 char *label;
239 expressionS direct_expr;
240 } direct;
241 struct {
242 unsigned mod;
243 int ARnum;
244 unsigned char disp;
245 } indirect;
246 struct {
247 unsigned opcode;
248 } reg;
249 struct {
250 int resolved;
251 int decimal_found;
252 float f_number;
253 int s_number;
254 unsigned int u_number;
255 char *label;
256 expressionS imm_expr;
257 } immediate;
258} operand;
252b5132
RH
259
260int tic30_parallel_insn PARAMS ((char *));
261operand *tic30_operand PARAMS ((char *));
262char *tic30_find_parallel_insn PARAMS ((char *, char *));
263
264template *opcode;
265
19d63e5d
KH
266struct tic30_insn {
267 template *tm; /* Template of current instruction */
268 unsigned opcode; /* Final opcode */
269 int operands; /* Number of given operands */
270 /* Type of operand given in instruction */
271 operand *operand_type[MAX_OPERANDS];
272 unsigned addressing_mode; /* Final addressing mode of instruction */
273};
252b5132
RH
274
275struct tic30_insn insn;
276static int found_parallel_insn;
277
278void
279md_assemble (line)
280 char *line;
281{
282 template *opcode;
283 char *current_posn;
284 char *token_start;
285 char save_char;
286 int count;
287
288 debug ("In md_assemble() with argument %s\n", line);
289 memset (&insn, '\0', sizeof (insn));
290 if (found_parallel_insn)
291 {
292 debug ("Line is second part of parallel instruction\n\n");
293 found_parallel_insn = 0;
294 return;
295 }
296 if ((current_posn = tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL)
297 current_posn = line;
298 else
299 found_parallel_insn = 1;
300 while (is_space_char (*current_posn))
301 current_posn++;
302 token_start = current_posn;
303 if (!is_opcode_char (*current_posn))
304 {
305 as_bad ("Invalid character %s in opcode", output_invalid (*current_posn));
306 return;
307 }
308 /* Check if instruction is a parallel instruction by seeing if the first
1dab94dd 309 character is a q. */
252b5132
RH
310 if (*token_start == 'q')
311 {
312 if (tic30_parallel_insn (token_start))
313 {
314 if (found_parallel_insn)
315 free (token_start);
316 return;
317 }
318 }
319 while (is_opcode_char (*current_posn))
320 current_posn++;
321 { /* Find instruction */
322 save_char = *current_posn;
323 *current_posn = '\0';
324 opcode = (template *) hash_find (op_hash, token_start);
325 if (opcode)
326 {
327 debug ("Found instruction %s\n", opcode->name);
328 insn.tm = opcode;
329 }
330 else
331 {
332 debug ("Didn't find insn\n");
333 as_bad ("Unknown TMS320C30 instruction: %s", token_start);
334 return;
335 }
336 *current_posn = save_char;
337 }
338 if (*current_posn != END_OF_INSN)
339 { /* Find operands */
340 int paren_not_balanced;
341 int expecting_operand = 0;
342 int this_operand;
343 do
344 {
345 /* skip optional white space before operand */
346 while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)
347 {
348 if (!is_space_char (*current_posn))
349 {
350 as_bad ("Invalid character %s before %s operand",
351 output_invalid (*current_posn),
352 ordinal_names[insn.operands]);
353 return;
354 }
355 current_posn++;
356 }
357 token_start = current_posn; /* after white space */
358 paren_not_balanced = 0;
359 while (paren_not_balanced || *current_posn != ',')
360 {
361 if (*current_posn == END_OF_INSN)
362 {
363 if (paren_not_balanced)
364 {
365 as_bad ("Unbalanced parenthesis in %s operand.",
366 ordinal_names[insn.operands]);
367 return;
368 }
369 else
370 break; /* we are done */
371 }
372 else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))
373 {
374 as_bad ("Invalid character %s in %s operand",
375 output_invalid (*current_posn),
376 ordinal_names[insn.operands]);
377 return;
378 }
379 if (*current_posn == '(')
380 ++paren_not_balanced;
381 if (*current_posn == ')')
382 --paren_not_balanced;
383 current_posn++;
384 }
385 if (current_posn != token_start)
386 { /* yes, we've read in another operand */
387 this_operand = insn.operands++;
388 if (insn.operands > MAX_OPERANDS)
389 {
390 as_bad ("Spurious operands; (%d operands/instruction max)",
391 MAX_OPERANDS);
392 return;
393 }
394 /* now parse operand adding info to 'insn' as we go along */
395 save_char = *current_posn;
396 *current_posn = '\0';
397 insn.operand_type[this_operand] = tic30_operand (token_start);
398 *current_posn = save_char;
399 if (insn.operand_type[this_operand] == NULL)
400 return;
401 }
402 else
403 {
404 if (expecting_operand)
405 {
406 as_bad ("Expecting operand after ','; got nothing");
407 return;
408 }
409 if (*current_posn == ',')
410 {
411 as_bad ("Expecting operand before ','; got nothing");
412 return;
413 }
414 }
415 /* now *current_posn must be either ',' or END_OF_INSN */
416 if (*current_posn == ',')
417 {
418 if (*++current_posn == END_OF_INSN)
419 { /* just skip it, if it's \n complain */
420 as_bad ("Expecting operand after ','; got nothing");
421 return;
422 }
423 expecting_operand = 1;
424 }
425 }
426 while (*current_posn != END_OF_INSN); /* until we get end of insn */
427 }
428 debug ("Number of operands found: %d\n", insn.operands);
429 /* Check that number of operands is correct */
430 if (insn.operands != insn.tm->operands)
431 {
432 int i;
433 int numops = insn.tm->operands;
434 /* If operands are not the same, then see if any of the operands are not
435 required. Then recheck with number of given operands. If they are still not
1dab94dd 436 the same, then give an error, otherwise carry on. */
252b5132
RH
437 for (i = 0; i < insn.tm->operands; i++)
438 if (insn.tm->operand_types[i] & NotReq)
439 numops--;
440 if (insn.operands != numops)
441 {
442 as_bad ("Incorrect number of operands given");
443 return;
444 }
445 }
446 insn.addressing_mode = AM_NotReq;
447 for (count = 0; count < insn.operands; count++)
448 {
449 if (insn.operand_type[count]->op_type & insn.tm->operand_types[count])
450 {
451 debug ("Operand %d matches\n", count + 1);
452 /* If instruction has two operands and has an AddressMode modifier then set
453 addressing mode type for instruction */
454 if (insn.tm->opcode_modifier == AddressMode)
455 {
456 int addr_insn = 0;
1dab94dd 457 /* Store instruction uses the second operand for the address mode. */
252b5132
RH
458 if ((insn.tm->operand_types[1] & (Indirect | Direct)) == (Indirect | Direct))
459 addr_insn = 1;
460 if (insn.operand_type[addr_insn]->op_type & (AllReg))
461 insn.addressing_mode = AM_Register;
462 else if (insn.operand_type[addr_insn]->op_type & Direct)
463 insn.addressing_mode = AM_Direct;
464 else if (insn.operand_type[addr_insn]->op_type & Indirect)
465 insn.addressing_mode = AM_Indirect;
466 else
467 insn.addressing_mode = AM_Immediate;
468 }
469 }
470 else
471 {
472 as_bad ("The %s operand doesn't match", ordinal_names[count]);
473 return;
474 }
475 }
1dab94dd 476 /* Now set the addressing mode for 3 operand instructions. */
252b5132
RH
477 if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2))
478 {
479 /* Set the addressing mode to the values used for 2 operand instructions in the
1dab94dd 480 G addressing field of the opcode. */
252b5132
RH
481 char *p;
482 switch (insn.operand_type[0]->op_type)
483 {
484 case Rn:
485 case ARn:
486 case DPReg:
487 case OtherReg:
488 if (insn.operand_type[1]->op_type & (AllReg))
489 insn.addressing_mode = AM_Register;
490 else if (insn.operand_type[1]->op_type & Indirect)
491 insn.addressing_mode = AM_Direct;
492 else
493 {
494 /* Shouldn't make it to this stage */
495 as_bad ("Incompatible first and second operands in instruction");
496 return;
497 }
498 break;
499 case Indirect:
500 if (insn.operand_type[1]->op_type & (AllReg))
501 insn.addressing_mode = AM_Indirect;
502 else if (insn.operand_type[1]->op_type & Indirect)
503 insn.addressing_mode = AM_Immediate;
504 else
505 {
506 /* Shouldn't make it to this stage */
507 as_bad ("Incompatible first and second operands in instruction");
508 return;
509 }
510 break;
511 }
512 /* Now make up the opcode for the 3 operand instructions. As in parallel
513 instructions, there will be no unresolved values, so they can be fully formed
1dab94dd 514 and added to the frag table. */
252b5132
RH
515 insn.opcode = insn.tm->base_opcode;
516 if (insn.operand_type[0]->op_type & Indirect)
517 {
518 insn.opcode |= (insn.operand_type[0]->indirect.ARnum);
519 insn.opcode |= (insn.operand_type[0]->indirect.mod << 3);
520 }
521 else
522 insn.opcode |= (insn.operand_type[0]->reg.opcode);
523 if (insn.operand_type[1]->op_type & Indirect)
524 {
525 insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8);
526 insn.opcode |= (insn.operand_type[1]->indirect.mod << 11);
527 }
528 else
529 insn.opcode |= (insn.operand_type[1]->reg.opcode << 8);
530 if (insn.operands == 3)
531 insn.opcode |= (insn.operand_type[2]->reg.opcode << 16);
532 insn.opcode |= insn.addressing_mode;
533 p = frag_more (INSN_SIZE);
534 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
535 }
536 else
537 { /* Not a three operand instruction */
538 char *p;
539 int am_insn = -1;
540 insn.opcode = insn.tm->base_opcode;
1dab94dd 541 /* Create frag for instruction - all instructions are 4 bytes long. */
252b5132
RH
542 p = frag_more (INSN_SIZE);
543 if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode))
544 {
545 insn.opcode |= insn.addressing_mode;
546 if (insn.addressing_mode == AM_Indirect)
547 {
548 /* Determine which operand gives the addressing mode */
549 if (insn.operand_type[0]->op_type & Indirect)
550 am_insn = 0;
551 if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect))
552 am_insn = 1;
553 insn.opcode |= (insn.operand_type[am_insn]->indirect.disp);
554 insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8);
555 insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11);
556 if (insn.operands > 1)
557 insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);
558 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
559 }
560 else if (insn.addressing_mode == AM_Register)
561 {
562 insn.opcode |= (insn.operand_type[0]->reg.opcode);
563 if (insn.operands > 1)
564 insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
565 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
566 }
567 else if (insn.addressing_mode == AM_Direct)
568 {
569 if (insn.operand_type[0]->op_type & Direct)
570 am_insn = 0;
571 if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct))
572 am_insn = 1;
573 if (insn.operands > 1)
574 insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);
575 if (insn.operand_type[am_insn]->direct.resolved == 1)
576 {
577 /* Resolved values can be placed straight into instruction word, and output */
578 insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF);
579 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
580 }
581 else
582 { /* Unresolved direct addressing mode instruction */
583 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
584 fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0);
585 }
586 }
587 else if (insn.addressing_mode == AM_Immediate)
588 {
589 if (insn.operand_type[0]->immediate.resolved == 1)
590 {
591 char *keeploc;
592 int size;
593 if (insn.operands > 1)
594 insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
595 switch (insn.tm->imm_arg_type)
596 {
597 case Imm_Float:
598 debug ("Floating point first operand\n");
599 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
600 keeploc = input_line_pointer;
601 input_line_pointer = insn.operand_type[0]->immediate.label;
602 if (md_atof ('f', p + 2, &size) != 0)
603 {
604 as_bad ("invalid short form floating point immediate operand");
605 return;
606 }
607 input_line_pointer = keeploc;
608 break;
609 case Imm_UInt:
610 debug ("Unsigned int first operand\n");
611 if (insn.operand_type[0]->immediate.decimal_found)
612 as_warn ("rounding down first operand float to unsigned int");
613 if (insn.operand_type[0]->immediate.u_number > 0xFFFF)
614 as_warn ("only lower 16-bits of first operand are used");
615 insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL);
616 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
617 break;
618 case Imm_SInt:
619 debug ("Int first operand\n");
620 if (insn.operand_type[0]->immediate.decimal_found)
621 as_warn ("rounding down first operand float to signed int");
622 if (insn.operand_type[0]->immediate.s_number < -32768 ||
623 insn.operand_type[0]->immediate.s_number > 32767)
624 {
625 as_bad ("first operand is too large for 16-bit signed int");
626 return;
627 }
628 insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL);
629 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
630 break;
631 }
632 }
633 else
634 { /* Unresolved immediate label */
635 if (insn.operands > 1)
636 insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
637 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
638 fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
639 }
640 }
641 }
642 else if (insn.tm->opcode_modifier == PCRel)
643 {
644 /* Conditional Branch and Call instructions */
645 if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp))
646 {
647 if (insn.operand_type[0]->op_type & (AllReg))
648 {
649 insn.opcode |= (insn.operand_type[0]->reg.opcode);
650 insn.opcode |= PC_Register;
651 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
652 }
653 else
654 {
655 insn.opcode |= PC_Relative;
656 if (insn.operand_type[0]->immediate.resolved == 1)
657 {
658 insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF);
659 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
660 }
661 else
662 {
663 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
664 fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0);
665 }
666 }
667 }
668 else if ((insn.tm->operand_types[0] & ARn) == ARn)
669 {
670 /* Decrement and Branch instructions */
671 insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22);
672 if (insn.operand_type[1]->op_type & (AllReg))
673 {
674 insn.opcode |= (insn.operand_type[1]->reg.opcode);
675 insn.opcode |= PC_Register;
676 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
677 }
678 else if (insn.operand_type[1]->immediate.resolved == 1)
679 {
680 if (insn.operand_type[0]->immediate.decimal_found)
681 {
682 as_bad ("first operand is floating point");
683 return;
684 }
685 if (insn.operand_type[0]->immediate.s_number < -32768 ||
686 insn.operand_type[0]->immediate.s_number > 32767)
687 {
688 as_bad ("first operand is too large for 16-bit signed int");
689 return;
690 }
691 insn.opcode |= (insn.operand_type[1]->immediate.s_number);
692 insn.opcode |= PC_Relative;
693 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
694 }
695 else
696 {
697 insn.opcode |= PC_Relative;
698 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
699 fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0);
700 }
701 }
702 }
703 else if (insn.tm->operand_types[0] == IVector)
704 {
705 /* Trap instructions */
706 if (insn.operand_type[0]->op_type & IVector)
707 insn.opcode |= (insn.operand_type[0]->immediate.u_number);
708 else
709 { /* Shouldn't get here */
710 as_bad ("interrupt vector for trap instruction out of range");
711 return;
712 }
713 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
714 }
715 else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate)
716 {
717 /* Push, Pop and Rotate instructions */
718 insn.opcode |= (insn.operand_type[0]->reg.opcode << 16);
719 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
720 }
721 else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct))
722 {
723 /* LDP Instruction needs to be tested for before the next section */
724 if (insn.operand_type[0]->op_type & Direct)
725 {
726 if (insn.operand_type[0]->direct.resolved == 1)
727 {
728 /* Direct addressing uses lower 8 bits of direct address */
729 insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16;
730 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
731 }
732 else
733 {
734 fixS *fix;
735 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
736 fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0);
737 /* Ensure that the assembler doesn't complain about fitting a 24-bit
1dab94dd 738 address into 8 bits. */
252b5132
RH
739 fix->fx_no_overflow = 1;
740 }
741 }
742 else
743 {
744 if (insn.operand_type[0]->immediate.resolved == 1)
745 {
746 /* Immediate addressing uses upper 8 bits of address */
747 if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)
748 {
749 as_bad ("LDP instruction needs a 24-bit operand");
750 return;
751 }
752 insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16);
753 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
754 }
755 else
756 {
757 fixS *fix;
758 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
759 fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
760 fix->fx_no_overflow = 1;
761 }
762 }
763 }
764 else if (insn.tm->operand_types[0] & (Imm24))
765 {
766 /* Unconditional Branch and Call instructions */
767 if (insn.operand_type[0]->immediate.resolved == 1)
768 {
769 if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)
770 as_warn ("first operand is too large for a 24-bit displacement");
771 insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF);
772 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
773 }
774 else
775 {
776 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
777 fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
778 }
779 }
780 else if (insn.tm->operand_types[0] & NotReq)
781 {
1dab94dd 782 /* Check for NOP instruction without arguments. */
252b5132
RH
783 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
784 }
785 else if (insn.tm->operands == 0)
786 {
1dab94dd 787 /* Check for instructions without operands. */
252b5132
RH
788 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
789 }
790 }
791 debug ("Addressing mode: %08X\n", insn.addressing_mode);
792 {
793 int i;
794 for (i = 0; i < insn.operands; i++)
795 {
796 if (insn.operand_type[i]->immediate.label)
797 free (insn.operand_type[i]->immediate.label);
798 free (insn.operand_type[i]);
799 }
800 }
801 debug ("Final opcode: %08X\n", insn.opcode);
802 debug ("\n");
803}
804
19d63e5d 805struct tic30_par_insn {
252b5132
RH
806 partemplate *tm; /* Template of current parallel instruction */
807 int operands[2]; /* Number of given operands for each insn */
808 /* Type of operand given in instruction */
809 operand *operand_type[2][MAX_OPERANDS];
1dab94dd 810 int swap_operands; /* Whether to swap operands around. */
252b5132
RH
811 unsigned p_field; /* Value of p field in multiply add/sub instructions */
812 unsigned opcode; /* Final opcode */
813};
814
815struct tic30_par_insn p_insn;
816
817int
818tic30_parallel_insn (char *token)
819{
820 static partemplate *p_opcode;
821 char *current_posn = token;
822 char *token_start;
823 char save_char;
824
825 debug ("In tic30_parallel_insn with %s\n", token);
826 memset (&p_insn, '\0', sizeof (p_insn));
827 while (is_opcode_char (*current_posn))
828 current_posn++;
829 { /* Find instruction */
830 save_char = *current_posn;
831 *current_posn = '\0';
832 p_opcode = (partemplate *) hash_find (parop_hash, token);
833 if (p_opcode)
834 {
835 debug ("Found instruction %s\n", p_opcode->name);
836 p_insn.tm = p_opcode;
837 }
838 else
839 {
840 char first_opcode[6] =
841 {0};
842 char second_opcode[6] =
843 {0};
844 int i;
845 int current_opcode = -1;
846 int char_ptr = 0;
847
848 for (i = 0; i < strlen (token); i++)
849 {
850 char ch = *(token + i);
851 if (ch == '_' && current_opcode == -1)
852 {
853 current_opcode = 0;
854 continue;
855 }
856 if (ch == '_' && current_opcode == 0)
857 {
858 current_opcode = 1;
859 char_ptr = 0;
860 continue;
861 }
862 switch (current_opcode)
863 {
864 case 0:
865 first_opcode[char_ptr++] = ch;
866 break;
867 case 1:
868 second_opcode[char_ptr++] = ch;
869 break;
870 }
871 }
872 debug ("first_opcode = %s\n", first_opcode);
873 debug ("second_opcode = %s\n", second_opcode);
874 sprintf (token, "q_%s_%s", second_opcode, first_opcode);
875 p_opcode = (partemplate *) hash_find (parop_hash, token);
876 if (p_opcode)
877 {
878 debug ("Found instruction %s\n", p_opcode->name);
879 p_insn.tm = p_opcode;
880 p_insn.swap_operands = 1;
881 }
882 else
883 return 0;
884 }
885 *current_posn = save_char;
886 }
887 { /* Find operands */
888 int paren_not_balanced;
889 int expecting_operand = 0;
890 int found_separator = 0;
891 do
892 {
893 /* skip optional white space before operand */
894 while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)
895 {
896 if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR)
897 {
898 as_bad ("Invalid character %s before %s operand",
899 output_invalid (*current_posn),
900 ordinal_names[insn.operands]);
901 return 1;
902 }
903 if (*current_posn == PARALLEL_SEPARATOR)
904 found_separator = 1;
905 current_posn++;
906 }
907 token_start = current_posn; /* after white space */
908 paren_not_balanced = 0;
909 while (paren_not_balanced || *current_posn != ',')
910 {
911 if (*current_posn == END_OF_INSN)
912 {
913 if (paren_not_balanced)
914 {
915 as_bad ("Unbalanced parenthesis in %s operand.",
916 ordinal_names[insn.operands]);
917 return 1;
918 }
919 else
920 break; /* we are done */
921 }
922 else if (*current_posn == PARALLEL_SEPARATOR)
923 {
924 while (is_space_char (*(current_posn - 1)))
925 current_posn--;
926 break;
927 }
928 else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))
929 {
930 as_bad ("Invalid character %s in %s operand",
931 output_invalid (*current_posn),
932 ordinal_names[insn.operands]);
933 return 1;
934 }
935 if (*current_posn == '(')
936 ++paren_not_balanced;
937 if (*current_posn == ')')
938 --paren_not_balanced;
939 current_posn++;
940 }
941 if (current_posn != token_start)
942 { /* yes, we've read in another operand */
943 p_insn.operands[found_separator]++;
944 if (p_insn.operands[found_separator] > MAX_OPERANDS)
945 {
946 as_bad ("Spurious operands; (%d operands/instruction max)",
947 MAX_OPERANDS);
948 return 1;
949 }
950 /* now parse operand adding info to 'insn' as we go along */
951 save_char = *current_posn;
952 *current_posn = '\0';
953 p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] =
954 tic30_operand (token_start);
955 *current_posn = save_char;
956 if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1])
957 return 1;
958 }
959 else
960 {
961 if (expecting_operand)
962 {
963 as_bad ("Expecting operand after ','; got nothing");
964 return 1;
965 }
966 if (*current_posn == ',')
967 {
968 as_bad ("Expecting operand before ','; got nothing");
969 return 1;
970 }
971 }
972 /* now *current_posn must be either ',' or END_OF_INSN */
973 if (*current_posn == ',')
974 {
975 if (*++current_posn == END_OF_INSN)
976 { /* just skip it, if it's \n complain */
977 as_bad ("Expecting operand after ','; got nothing");
978 return 1;
979 }
980 expecting_operand = 1;
981 }
982 }
983 while (*current_posn != END_OF_INSN); /* until we get end of insn */
984 }
985 if (p_insn.swap_operands)
986 {
987 int temp_num, i;
988 operand *temp_op;
989
990 temp_num = p_insn.operands[0];
991 p_insn.operands[0] = p_insn.operands[1];
992 p_insn.operands[1] = temp_num;
993 for (i = 0; i < MAX_OPERANDS; i++)
994 {
995 temp_op = p_insn.operand_type[0][i];
996 p_insn.operand_type[0][i] = p_insn.operand_type[1][i];
997 p_insn.operand_type[1][i] = temp_op;
998 }
999 }
1000 if (p_insn.operands[0] != p_insn.tm->operands_1)
1001 {
1002 as_bad ("incorrect number of operands given in the first instruction");
1003 return 1;
1004 }
1005 if (p_insn.operands[1] != p_insn.tm->operands_2)
1006 {
1007 as_bad ("incorrect number of operands given in the second instruction");
1008 return 1;
1009 }
1010 debug ("Number of operands in first insn: %d\n", p_insn.operands[0]);
1011 debug ("Number of operands in second insn: %d\n", p_insn.operands[1]);
1012 { /* Now check if operands are correct */
1013 int count;
1014 int num_rn = 0;
1015 int num_ind = 0;
1016 for (count = 0; count < 2; count++)
1017 {
1018 int i;
1019 for (i = 0; i < p_insn.operands[count]; i++)
1020 {
1021 if ((p_insn.operand_type[count][i]->op_type &
1022 p_insn.tm->operand_types[count][i]) == 0)
1023 {
1024 as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1);
1025 return 1;
1026 }
1027 /* Get number of R register and indirect reference contained within the first
1028 two operands of each instruction. This is required for the multiply
1029 parallel instructions which require two R registers and two indirect
1dab94dd 1030 references, but not in any particular place. */
252b5132
RH
1031 if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2)
1032 num_rn++;
1033 else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2)
1034 num_ind++;
1035 }
1036 }
1037 if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn))
1038 {
1039 /* Check for the multiply instructions */
1040 if (num_rn != 2)
1041 {
1042 as_bad ("incorrect format for multiply parallel instruction");
1043 return 1;
1044 }
1045 if (num_ind != 2)
1046 { /* Shouldn't get here */
1047 as_bad ("incorrect format for multiply parallel instruction");
1048 return 1;
1049 }
1050 if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) &&
1051 (p_insn.operand_type[0][2]->reg.opcode != 0x01))
1052 {
1053 as_bad ("destination for multiply can only be R0 or R1");
1054 return 1;
1055 }
1056 if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) &&
1057 (p_insn.operand_type[1][2]->reg.opcode != 0x03))
1058 {
1059 as_bad ("destination for add/subtract can only be R2 or R3");
1060 return 1;
1061 }
1062 /* Now determine the P field for the instruction */
1063 if (p_insn.operand_type[0][0]->op_type & Indirect)
1064 {
1065 if (p_insn.operand_type[0][1]->op_type & Indirect)
1066 p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn */
1067 else if (p_insn.operand_type[1][0]->op_type & Indirect)
1068 p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */
1069 else
1070 p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind */
1071 }
1072 else
1073 {
1074 if (p_insn.operand_type[0][1]->op_type & Rn)
1075 p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind */
1076 else if (p_insn.operand_type[1][0]->op_type & Indirect)
1077 {
1078 operand *temp;
1079 p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn */
1080 /* Need to swap the two multiply operands around so that everything is in
1081 its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */
1082 temp = p_insn.operand_type[0][0];
1083 p_insn.operand_type[0][0] = p_insn.operand_type[0][1];
1084 p_insn.operand_type[0][1] = temp;
1085 }
1086 else
1087 {
1088 operand *temp;
1089 p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind */
1090 temp = p_insn.operand_type[0][0];
1091 p_insn.operand_type[0][0] = p_insn.operand_type[0][1];
1092 p_insn.operand_type[0][1] = temp;
1093 }
1094 }
1095 }
1096 }
1097 debug ("P field: %08X\n", p_insn.p_field);
1098 /* Finalise opcode. This is easier for parallel instructions as they have to be
1099 fully resolved, there are no memory addresses allowed, except through indirect
1dab94dd 1100 addressing, so there are no labels to resolve. */
252b5132
RH
1101 {
1102 p_insn.opcode = p_insn.tm->base_opcode;
1103 switch (p_insn.tm->oporder)
1104 {
1105 case OO_4op1:
1106 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
1107 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
1108 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1109 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1110 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1111 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);
1112 break;
1113 case OO_4op2:
1114 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
1115 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
1116 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);
1117 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);
1118 p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19);
1119 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);
1120 if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode)
1121 as_warn ("loading the same register in parallel operation");
1122 break;
1123 case OO_4op3:
1124 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
1125 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
1126 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1127 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1128 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1129 p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22);
1130 break;
1131 case OO_5op1:
1132 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
1133 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
1134 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1135 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1136 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1137 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
1138 p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);
1139 break;
1140 case OO_5op2:
1141 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
1142 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
1143 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1144 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1145 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1146 p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);
1147 p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);
1148 break;
1149 case OO_PField:
1150 p_insn.opcode |= p_insn.p_field;
1151 if (p_insn.operand_type[0][2]->reg.opcode == 0x01)
1152 p_insn.opcode |= 0x00800000;
1153 if (p_insn.operand_type[1][2]->reg.opcode == 0x03)
1154 p_insn.opcode |= 0x00400000;
1155 switch (p_insn.p_field)
1156 {
1157 case 0x00000000:
1158 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
1159 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
1160 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
1161 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
1162 p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);
1163 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19);
1164 break;
1165 case 0x01000000:
1166 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum);
1167 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3);
1168 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
1169 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
1170 p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);
1171 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
1172 break;
1173 case 0x02000000:
1174 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);
1175 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);
1176 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);
1177 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);
1178 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16);
1179 p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);
1180 break;
1181 case 0x03000000:
1182 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);
1183 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);
1184 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
1185 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
1186 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1187 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
1188 break;
1189 }
1190 break;
1191 }
1dab94dd 1192 } /* Opcode is finalised at this point for all parallel instructions. */
252b5132
RH
1193 { /* Output opcode */
1194 char *p;
1195 p = frag_more (INSN_SIZE);
1196 md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE);
1197 }
1198 {
1199 int i, j;
1200 for (i = 0; i < 2; i++)
1201 for (j = 0; j < p_insn.operands[i]; j++)
1202 free (p_insn.operand_type[i][j]);
1203 }
1204 debug ("Final opcode: %08X\n", p_insn.opcode);
1205 debug ("\n");
1206 return 1;
1207}
1208
1209operand *
1210tic30_operand (token)
1211 char *token;
1212{
1213 int count;
1214 char ind_buffer[strlen (token)];
1215 operand *current_op;
1216
1217 debug ("In tic30_operand with %s\n", token);
1218 current_op = (operand *) malloc (sizeof (operand));
1219 memset (current_op, '\0', sizeof (operand));
1220 if (*token == DIRECT_REFERENCE)
1221 {
1222 char *token_posn = token + 1;
1223 int direct_label = 0;
1224 debug ("Found direct reference\n");
1225 while (*token_posn)
1226 {
1227 if (!is_digit_char (*token_posn))
1228 direct_label = 1;
1229 token_posn++;
1230 }
1231 if (direct_label)
1232 {
1233 char *save_input_line_pointer;
1234 segT retval;
1235 debug ("Direct reference is a label\n");
1236 current_op->direct.label = token + 1;
1237 save_input_line_pointer = input_line_pointer;
1238 input_line_pointer = token + 1;
1239 debug ("Current input_line_pointer: %s\n", input_line_pointer);
1240 retval = expression (&current_op->direct.direct_expr);
1241 debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op);
1242 debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number);
1243 debug ("Segment: %d\n", retval);
1244 input_line_pointer = save_input_line_pointer;
1245 if (current_op->direct.direct_expr.X_op == O_constant)
1246 {
1247 current_op->direct.address = current_op->direct.direct_expr.X_add_number;
1248 current_op->direct.resolved = 1;
1249 }
1250 }
1251 else
1252 {
1253 debug ("Direct reference is a number\n");
1254 current_op->direct.address = atoi (token + 1);
1255 current_op->direct.resolved = 1;
1256 }
1257 current_op->op_type = Direct;
1258 }
1259 else if (*token == INDIRECT_REFERENCE)
1260 { /* Indirect reference operand */
1261 int found_ar = 0;
1262 int found_disp = 0;
1263 int ar_number = -1;
1264 int disp_number = 0;
1265 int buffer_posn = 1;
1266 ind_addr_type *ind_addr_op;
1267 debug ("Found indirect reference\n");
1268 ind_buffer[0] = *token;
1269 for (count = 1; count < strlen (token); count++)
1270 { /* Strip operand */
3882b010 1271 ind_buffer[buffer_posn] = TOLOWER (*(token + count));
252b5132
RH
1272 if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') &&
1273 (*(token + count) == 'r' || *(token + count) == 'R'))
1274 {
1275 /* AR reference is found, so get its number and remove it from the buffer
1276 so it can pass through hash_find() */
1277 if (found_ar)
1278 {
1279 as_bad ("More than one AR register found in indirect reference");
1280 return NULL;
1281 }
1282 if (*(token + count + 1) < '0' || *(token + count + 1) > '7')
1283 {
1284 as_bad ("Illegal AR register in indirect reference");
1285 return NULL;
1286 }
1287 ar_number = *(token + count + 1) - '0';
1288 found_ar = 1;
1289 count++;
1290 }
1291 if (*(token + count) == '(')
1292 {
1293 /* Parenthesis found, so check if a displacement value is inside. If so, get
1dab94dd 1294 the value and remove it from the buffer. */
252b5132
RH
1295 if (is_digit_char (*(token + count + 1)))
1296 {
1297 char disp[10];
1298 int disp_posn = 0;
1299
1300 if (found_disp)
1301 {
1302 as_bad ("More than one displacement found in indirect reference");
1303 return NULL;
1304 }
1305 count++;
1306 while (*(token + count) != ')')
1307 {
1308 if (!is_digit_char (*(token + count)))
1309 {
1310 as_bad ("Invalid displacement in indirect reference");
1311 return NULL;
1312 }
1313 disp[disp_posn++] = *(token + (count++));
1314 }
1315 disp[disp_posn] = '\0';
1316 disp_number = atoi (disp);
1317 count--;
1318 found_disp = 1;
1319 }
1320 }
1321 buffer_posn++;
1322 }
1323 ind_buffer[buffer_posn] = '\0';
1324 if (!found_ar)
1325 {
1326 as_bad ("AR register not found in indirect reference");
1327 return NULL;
1328 }
1329 ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer);
1330 if (ind_addr_op)
1331 {
1332 debug ("Found indirect reference: %s\n", ind_addr_op->syntax);
1333 if (ind_addr_op->displacement == IMPLIED_DISP)
1334 {
1335 found_disp = 1;
1336 disp_number = 1;
1337 }
1338 else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp)
1339 {
1340 /* Maybe an implied displacement of 1 again */
1341 as_bad ("required displacement wasn't given in indirect reference");
1342 return 0;
1343 }
1344 }
1345 else
1346 {
1347 as_bad ("illegal indirect reference");
1348 return NULL;
1349 }
1350 if (found_disp && (disp_number < 0 || disp_number > 255))
1351 {
1352 as_bad ("displacement must be an unsigned 8-bit number");
1353 return NULL;
1354 }
1355 current_op->indirect.mod = ind_addr_op->modfield;
1356 current_op->indirect.disp = disp_number;
1357 current_op->indirect.ARnum = ar_number;
1358 current_op->op_type = Indirect;
1359 }
1360 else
1361 {
1362 reg *regop = (reg *) hash_find (reg_hash, token);
1363 if (regop)
1364 {
1365 debug ("Found register operand: %s\n", regop->name);
1366 if (regop->regtype == REG_ARn)
1367 current_op->op_type = ARn;
1368 else if (regop->regtype == REG_Rn)
1369 current_op->op_type = Rn;
1370 else if (regop->regtype == REG_DP)
1371 current_op->op_type = DPReg;
1372 else
1373 current_op->op_type = OtherReg;
1374 current_op->reg.opcode = regop->opcode;
1375 }
1376 else
1377 {
1378 if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h'))
1379 {
1380 char *save_input_line_pointer;
1381 segT retval;
1382 debug ("Probably a label: %s\n", token);
1383 current_op->immediate.label = (char *) malloc (strlen (token) + 1);
1384 strcpy (current_op->immediate.label, token);
1385 current_op->immediate.label[strlen (token)] = '\0';
1386 save_input_line_pointer = input_line_pointer;
1387 input_line_pointer = token;
1388 debug ("Current input_line_pointer: %s\n", input_line_pointer);
1389 retval = expression (&current_op->immediate.imm_expr);
1390 debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op);
1391 debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number);
1392 debug ("Segment: %d\n", retval);
1393 input_line_pointer = save_input_line_pointer;
1394 if (current_op->immediate.imm_expr.X_op == O_constant)
1395 {
1396 current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number;
1397 current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number;
1398 current_op->immediate.resolved = 1;
1399 }
1400 }
1401 else
1402 {
1403 unsigned count;
1404 debug ("Found a number or displacement\n");
1405 for (count = 0; count < strlen (token); count++)
1406 if (*(token + count) == '.')
1407 current_op->immediate.decimal_found = 1;
1408 current_op->immediate.label = (char *) malloc (strlen (token) + 1);
1409 strcpy (current_op->immediate.label, token);
1410 current_op->immediate.label[strlen (token)] = '\0';
1411 current_op->immediate.f_number = (float) atof (token);
1412 current_op->immediate.s_number = (int) atoi (token);
1413 current_op->immediate.u_number = (unsigned int) atoi (token);
1414 current_op->immediate.resolved = 1;
1415 }
1416 current_op->op_type = Disp | Abs24 | Imm16 | Imm24;
1417 if (current_op->immediate.u_number >= 0 && current_op->immediate.u_number <= 31)
1418 current_op->op_type |= IVector;
1419 }
1420 }
1421 return current_op;
1422}
1423
1424/* next_line points to the next line after the current instruction (current_line).
1425 Search for the parallel bars, and if found, merge two lines into internal syntax
1426 for a parallel instruction:
1427 q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2]
1428 By this stage, all comments are scrubbed, and only the bare lines are given.
1429 */
1430
1431#define NONE 0
1432#define START_OPCODE 1
1433#define END_OPCODE 2
1434#define START_OPERANDS 3
1435#define END_OPERANDS 4
1436
1437char *
1438tic30_find_parallel_insn (current_line, next_line)
1439 char *current_line;
1440 char *next_line;
1441{
1442 int found_parallel = 0;
1443 char first_opcode[256];
1444 char second_opcode[256];
1445 char first_operands[256];
1446 char second_operands[256];
1447 char *parallel_insn;
1448
1449 debug ("In tic30_find_parallel_insn()\n");
b75c0c92 1450 while (!is_end_of_line[(unsigned char) *next_line])
252b5132
RH
1451 {
1452 if (*next_line == PARALLEL_SEPARATOR && *(next_line + 1) == PARALLEL_SEPARATOR)
1453 {
1454 found_parallel = 1;
1455 next_line++;
1456 break;
1457 }
1458 next_line++;
1459 }
1460 if (!found_parallel)
1461 return NULL;
1462 debug ("Found a parallel instruction\n");
1463 {
1464 int i;
1465 char *opcode, *operands, *line;
1466
1467 for (i = 0; i < 2; i++)
1468 {
1469 if (i == 0)
1470 {
1471 opcode = &first_opcode[0];
1472 operands = &first_operands[0];
1473 line = current_line;
1474 }
1475 else
1476 {
1477 opcode = &second_opcode[0];
1478 operands = &second_operands[0];
1479 line = next_line;
1480 }
1481 {
1482 int search_status = NONE;
1483 int char_ptr = 0;
1484 char c;
1485
b75c0c92 1486 while (!is_end_of_line[(unsigned char) (c = *line)])
252b5132
RH
1487 {
1488 if (is_opcode_char (c) && search_status == NONE)
1489 {
3882b010 1490 opcode[char_ptr++] = TOLOWER (c);
252b5132
RH
1491 search_status = START_OPCODE;
1492 }
1493 else if (is_opcode_char (c) && search_status == START_OPCODE)
1494 {
3882b010 1495 opcode[char_ptr++] = TOLOWER (c);
252b5132
RH
1496 }
1497 else if (!is_opcode_char (c) && search_status == START_OPCODE)
1498 {
1499 opcode[char_ptr] = '\0';
1500 char_ptr = 0;
1501 search_status = END_OPCODE;
1502 }
1503 else if (is_operand_char (c) && search_status == START_OPERANDS)
1504 {
1505 operands[char_ptr++] = c;
1506 }
1507 if (is_operand_char (c) && search_status == END_OPCODE)
1508 {
1509 operands[char_ptr++] = c;
1510 search_status = START_OPERANDS;
1511 }
1512 line++;
1513 }
1514 if (search_status != START_OPERANDS)
1515 return NULL;
1516 operands[char_ptr] = '\0';
1517 }
1518 }
1519 }
1520 parallel_insn = (char *) malloc (strlen (first_opcode) + strlen (first_operands) +
1521 strlen (second_opcode) + strlen (second_operands) + 8);
1522 sprintf (parallel_insn, "q_%s_%s %s | %s", first_opcode, second_opcode, first_operands, second_operands);
1523 debug ("parallel insn = %s\n", parallel_insn);
1524 return parallel_insn;
1525}
1526
1527#undef NONE
1528#undef START_OPCODE
1529#undef END_OPCODE
1530#undef START_OPERANDS
1531#undef END_OPERANDS
1532
1533/* In order to get gas to ignore any | chars at the start of a line,
1dab94dd 1534 this function returns true if a | is found in a line. */
252b5132
RH
1535
1536int
1537tic30_unrecognized_line (c)
1538 int c;
1539{
1540 debug ("In tc_unrecognized_line\n");
1541 return (c == PARALLEL_SEPARATOR);
1542}
1543
1544int
1545md_estimate_size_before_relax (fragP, segment)
1546 fragS *fragP;
1547 segT segment;
1548{
1549 debug ("In md_estimate_size_before_relax()\n");
1550 return 0;
1551}
1552
1553void
1554md_convert_frag (abfd, sec, fragP)
1555 bfd *abfd;
1556 segT sec;
1557 register fragS *fragP;
1558{
1559 debug ("In md_convert_frag()\n");
1560}
1561
94f592af
NC
1562void
1563md_apply_fix3 (fixP, valP, seg)
252b5132
RH
1564 fixS *fixP;
1565 valueT *valP;
94f592af 1566 segT seg ATTRIBUTE_UNUSED;
252b5132
RH
1567{
1568 valueT value = *valP;
1569
1570 debug ("In md_apply_fix() with value = %ld\n", (long) value);
1571 debug ("Values in fixP\n");
1572 debug ("fx_size = %d\n", fixP->fx_size);
1573 debug ("fx_pcrel = %d\n", fixP->fx_pcrel);
1574 debug ("fx_where = %d\n", fixP->fx_where);
1575 debug ("fx_offset = %d\n", (int) fixP->fx_offset);
1576 {
1577 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
94f592af 1578
252b5132
RH
1579 value /= INSN_SIZE;
1580 if (fixP->fx_size == 1)
94f592af
NC
1581 /* Special fix for LDP instruction. */
1582 value = (value & 0x00FF0000) >> 16;
1583
252b5132
RH
1584 debug ("new value = %ld\n", (long) value);
1585 md_number_to_chars (buf, value, fixP->fx_size);
1586 }
94f592af
NC
1587
1588 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1589 fixP->fx_done = 1;
252b5132
RH
1590}
1591
1592int
1593md_parse_option (c, arg)
1594 int c;
1595 char *arg;
1596{
1597 int i;
1598
1599 debug ("In md_parse_option()\n");
1600 for (i = 0; i < c; i++)
1601 {
1602 printf ("%c\n", arg[c]);
1603 }
1604 return 0;
1605}
1606
1607void
1608md_show_usage (stream)
1609 FILE *stream;
1610{
1611 debug ("In md_show_usage()\n");
1612}
1613
1614symbolS *
1615md_undefined_symbol (name)
1616 char *name;
1617{
1618 debug ("In md_undefined_symbol()\n");
1619 return (symbolS *) 0;
1620}
1621
1622valueT
1623md_section_align (segment, size)
1624 segT segment;
1625 valueT size;
1626{
1627 debug ("In md_section_align() segment = %d and size = %d\n", segment, size);
1628 size = (size + 3) / 4;
1629 size *= 4;
1630 debug ("New size value = %d\n", size);
1631 return size;
1632}
1633
1634long
1635md_pcrel_from (fixP)
1636 fixS *fixP;
1637{
1638 int offset;
1639
1640 debug ("In md_pcrel_from()\n");
1641 debug ("fx_where = %d\n", fixP->fx_where);
1642 debug ("fx_size = %d\n", fixP->fx_size);
1643 /* Find the opcode that represents the current instruction in the fr_literal
1644 storage area, and check bit 21. Bit 21 contains whether the current instruction
1dab94dd 1645 is a delayed one or not, and then set the offset value appropriately. */
252b5132
RH
1646 if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20)
1647 offset = 3;
1648 else
1649 offset = 1;
1650 debug ("offset = %d\n", offset);
1651 /* PC Relative instructions have a format:
1652 displacement = Label - (PC + offset)
1653 This function returns PC + offset where:
1654 fx_where - fx_size = PC
1655 INSN_SIZE * offset = offset number of instructions
1656 */
1657 return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset);
1658}
1659
1660char *
1661md_atof (what_statement_type, literalP, sizeP)
1662 int what_statement_type;
1663 char *literalP;
1664 int *sizeP;
1665{
1666 int prec;
1667 char *token;
1668 char keepval;
1669 unsigned long value;
1670 /* char *atof_ieee (); */
1671 float float_value;
1672 debug ("In md_atof()\n");
1673 debug ("precision = %c\n", what_statement_type);
1674 debug ("literal = %s\n", literalP);
1675 debug ("line = ");
1676 token = input_line_pointer;
b75c0c92
AM
1677 while (!is_end_of_line[(unsigned char) *input_line_pointer]
1678 && (*input_line_pointer != ','))
252b5132
RH
1679 {
1680 debug ("%c", *input_line_pointer);
1681 input_line_pointer++;
1682 }
1683 keepval = *input_line_pointer;
1684 *input_line_pointer = '\0';
1685 debug ("\n");
1686 float_value = (float) atof (token);
1687 *input_line_pointer = keepval;
1688 debug ("float_value = %f\n", float_value);
1689 switch (what_statement_type)
1690 {
1691 case 'f':
1692 case 'F':
1693 case 's':
1694 case 'S':
1695 prec = 2;
1696 break;
1697
1698 case 'd':
1699 case 'D':
1700 case 'r':
1701 case 'R':
1702 prec = 4;
1703 break;
1704
1705 default:
1706 *sizeP = 0;
1707 return "Bad call to MD_ATOF()";
1708 }
1709 if (float_value == 0.0)
1710 {
1711 value = (prec == 2) ? 0x00008000L : 0x80000000L;
1712 }
1713 else
1714 {
1715 unsigned long exp, sign, mant, tmsfloat;
1716 tmsfloat = *((long *) &float_value);
1717 sign = tmsfloat & 0x80000000;
1718 mant = tmsfloat & 0x007FFFFF;
1719 exp = tmsfloat & 0x7F800000;
1720 exp <<= 1;
1721 if (exp == 0xFF000000)
1722 {
1723 if (mant == 0)
1724 value = 0x7F7FFFFF;
1725 else if (sign == 0)
1726 value = 0x7F7FFFFF;
1727 else
1728 value = 0x7F800000;
1729 }
1730 else
1731 {
1732 exp -= 0x7F000000;
1733 if (sign)
1734 {
1735 mant = mant & 0x007FFFFF;
1736 mant = -mant;
1737 mant = mant & 0x00FFFFFF;
1738 if (mant == 0)
1739 {
1740 mant |= 0x00800000;
1741 exp = (long) exp - 0x01000000;
1742 }
1743 }
1744 tmsfloat = exp | mant;
1745 value = tmsfloat;
1746 }
1747 if (prec == 2)
1748 {
1749 long exp, mant;
1750
1751 if (tmsfloat == 0x80000000)
1752 {
1753 value = 0x8000;
1754 }
1755 else
1756 {
1757 value = 0;
1758 exp = (tmsfloat & 0xFF000000);
1759 exp >>= 24;
1760 mant = tmsfloat & 0x007FFFFF;
1761 if (tmsfloat & 0x00800000)
1762 {
1763 mant |= 0xFF000000;
1764 mant += 0x00000800;
1765 mant >>= 12;
1766 mant |= 0x00000800;
1767 mant &= 0x0FFF;
1768 if (exp > 7)
1769 value = 0x7800;
1770 }
1771 else
1772 {
1773 mant |= 0x00800000;
1774 mant += 0x00000800;
1775 exp += (mant >> 24);
1776 mant >>= 12;
1777 mant &= 0x07FF;
1778 if (exp > 7)
1779 value = 0x77FF;
1780 }
1781 if (exp < -8)
1782 value = 0x8000;
1783 if (value == 0)
1784 {
1785 mant = (exp << 12) | mant;
1786 value = mant & 0xFFFF;
1787 }
1788 }
1789 }
1790 }
1791 md_number_to_chars (literalP, value, prec);
1792 *sizeP = prec;
1793 return 0;
1794}
1795
1796void
1797md_number_to_chars (buf, val, n)
1798 char *buf;
1799 valueT val;
1800 int n;
1801{
1802 debug ("In md_number_to_chars()\n");
1803 number_to_chars_bigendian (buf, val, n);
1804 /* number_to_chars_littleendian(buf,val,n); */
1805}
1806
1807#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
1808#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
1809
1810arelent *
1811tc_gen_reloc (section, fixP)
1812 asection *section;
1813 fixS *fixP;
1814{
1815 arelent *rel;
1816 bfd_reloc_code_real_type code = 0;
1817
1818 debug ("In tc_gen_reloc()\n");
1819 debug ("fixP.size = %d\n", fixP->fx_size);
1820 debug ("fixP.pcrel = %d\n", fixP->fx_pcrel);
1821 debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy));
1822 switch (F (fixP->fx_size, fixP->fx_pcrel))
1823 {
1824 MAP (1, 0, BFD_RELOC_TIC30_LDP);
1825 MAP (2, 0, BFD_RELOC_16);
1826 MAP (3, 0, BFD_RELOC_24);
1827 MAP (2, 1, BFD_RELOC_16_PCREL);
1828 MAP (4, 0, BFD_RELOC_32);
1829 default:
1830 as_bad ("Can not do %d byte %srelocation", fixP->fx_size,
1831 fixP->fx_pcrel ? "pc-relative " : "");
1832 }
1833#undef MAP
1834#undef F
1835
1836 rel = (arelent *) xmalloc (sizeof (arelent));
1837 assert (rel != 0);
310b5aa2
ILT
1838 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1839 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
252b5132
RH
1840 rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
1841 if (fixP->fx_pcrel)
1842 rel->addend = fixP->fx_addnumber;
1843 else
1844 rel->addend = 0;
1845 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
1846 if (!rel->howto)
1847 {
1848 const char *name;
1849 name = S_GET_NAME (fixP->fx_addsy);
1850 if (name == NULL)
1851 name = "<unknown>";
1852 as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code));
1853 }
1854 return rel;
1855}
1856
1857void
1858tc_aout_pre_write_hook ()
1859{
1860 debug ("In tc_aout_pre_write_hook()\n");
1861}
1862
1863void
1864md_operand (expressionP)
1865 expressionS *expressionP;
1866{
1867 debug ("In md_operand()\n");
1868}
1869
1870char output_invalid_buf[8];
1871
1872char *
1873output_invalid (c)
1874 char c;
1875{
3882b010 1876 if (ISPRINT (c))
252b5132
RH
1877 sprintf (output_invalid_buf, "'%c'", c);
1878 else
1879 sprintf (output_invalid_buf, "(0x%x)", (unsigned) c);
1880 return output_invalid_buf;
1881}
This page took 0.174795 seconds and 4 git commands to generate.