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