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