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