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)
5 This file is part of GAS, the GNU Assembler.
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)
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.
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
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. */
28 #include "safe-ctype.h"
29 #include "opcode/tic30.h"
30 #ifdef ANSI_PROTOTYPES
36 /* Put here all non-digit non-letter charcters that may occur in an
38 static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]";
39 static char *ordinal_names[] = {
40 "first", "second", "third", "fourth", "fifth"
43 const int md_reloc_size = 0;
45 const char comment_chars[] = ";";
46 const char line_comment_chars[] = "*";
47 const char line_separator_chars[] = "";
49 const char *md_shortopts = "";
50 struct option md_longopts[] = {
51 {NULL, no_argument, NULL, 0}
54 size_t md_longopts_size = sizeof (md_longopts);
56 /* Chars that mean this number is a floating point constant. */
59 const char FLT_CHARS[] = "fFdDxX";
61 /* Chars that can be used to separate mant from exp in floating point
63 const char EXP_CHARS[] = "eE";
65 /* tables for lexical analysis */
66 static char opcode_chars[256];
67 static char register_chars[256];
68 static char operand_chars[256];
69 static char space_chars[256];
70 static char identifier_chars[256];
71 static char digit_chars[256];
74 #define is_opcode_char(x) (opcode_chars[(unsigned char) x])
75 #define is_operand_char(x) (operand_chars[(unsigned char) x])
76 #define is_register_char(x) (register_chars[(unsigned char) x])
77 #define is_space_char(x) (space_chars[(unsigned char) x])
78 #define is_identifier_char(x) (identifier_chars[(unsigned char) x])
79 #define is_digit_char(x) (digit_chars[(unsigned char) x])
81 const pseudo_typeS md_pseudo_table[] = {
85 int debug PARAMS ((const char *string, ...));
88 debug VPARAMS ((const char *string, ...))
94 VA_OPEN (argptr, string);
95 VA_FIXEDARG (argptr, const char *, string);
96 vsprintf (str, string, argptr);
100 fputs (str, USE_STDOUT ? stdout : stderr);
107 /* hash table for opcode lookup */
108 static struct hash_control *op_hash;
109 /* hash table for parallel opcode lookup */
110 static struct hash_control *parop_hash;
111 /* hash table for register lookup */
112 static struct hash_control *reg_hash;
113 /* hash table for indirect addressing lookup */
114 static struct hash_control *ind_hash;
119 const char *hash_err;
120 debug ("In md_begin()\n");
121 op_hash = hash_new ();
123 const template *current_optab = tic30_optab;
124 for (; current_optab < tic30_optab_end; current_optab++)
126 hash_err = hash_insert (op_hash, current_optab->name, (char *) current_optab);
128 as_fatal ("Internal Error: Can't Hash %s: %s", current_optab->name, hash_err);
131 parop_hash = hash_new ();
133 const partemplate *current_parop = tic30_paroptab;
134 for (; current_parop < tic30_paroptab_end; current_parop++)
136 hash_err = hash_insert (parop_hash, current_parop->name, (char *) current_parop);
138 as_fatal ("Internal Error: Can't Hash %s: %s", current_parop->name, hash_err);
141 reg_hash = hash_new ();
143 const reg *current_reg = tic30_regtab;
144 for (; current_reg < tic30_regtab_end; current_reg++)
146 hash_err = hash_insert (reg_hash, current_reg->name, (char *) current_reg);
148 as_fatal ("Internal Error: Can't Hash %s: %s", current_reg->name, hash_err);
151 ind_hash = hash_new ();
153 const ind_addr_type *current_ind = tic30_indaddr_tab;
154 for (; current_ind < tic30_indaddrtab_end; current_ind++)
156 hash_err = hash_insert (ind_hash, current_ind->syntax, (char *) current_ind);
158 as_fatal ("Internal Error: Can't Hash %s: %s", current_ind->syntax, hash_err);
161 /* fill in lexical tables: opcode_chars, operand_chars, space_chars */
166 for (c = 0; c < 256; c++)
168 if (ISLOWER (c) || ISDIGIT (c))
171 register_chars[c] = c;
173 else if (ISUPPER (c))
175 opcode_chars[c] = TOLOWER (c);
176 register_chars[c] = opcode_chars[c];
178 else if (c == ')' || c == '(')
180 register_chars[c] = c;
182 if (ISUPPER (c) || ISLOWER (c) || ISDIGIT (c))
183 operand_chars[c] = c;
184 if (ISDIGIT (c) || c == '-')
186 if (ISALPHA (c) || c == '_' || c == '.' || ISDIGIT (c))
187 identifier_chars[c] = c;
188 if (c == ' ' || c == '\t')
193 for (p = operand_special_chars; *p != '\0'; p++)
194 operand_chars[(unsigned char) *p] = *p;
198 /* Address Mode OR values */
199 #define AM_Register 0x00000000
200 #define AM_Direct 0x00200000
201 #define AM_Indirect 0x00400000
202 #define AM_Immediate 0x00600000
203 #define AM_NotReq 0xFFFFFFFF
205 /* PC Relative OR values */
206 #define PC_Register 0x00000000
207 #define PC_Relative 0x02000000
215 expressionS direct_expr;
230 unsigned int u_number;
232 expressionS imm_expr;
236 int tic30_parallel_insn PARAMS ((char *));
237 operand *tic30_operand PARAMS ((char *));
238 char *tic30_find_parallel_insn PARAMS ((char *, char *));
243 template *tm; /* Template of current instruction */
244 unsigned opcode; /* Final opcode */
245 unsigned int operands; /* Number of given operands */
246 /* Type of operand given in instruction */
247 operand *operand_type[MAX_OPERANDS];
248 unsigned addressing_mode; /* Final addressing mode of instruction */
251 struct tic30_insn insn;
252 static int found_parallel_insn;
264 debug ("In md_assemble() with argument %s\n", line);
265 memset (&insn, '\0', sizeof (insn));
266 if (found_parallel_insn)
268 debug ("Line is second part of parallel instruction\n\n");
269 found_parallel_insn = 0;
272 if ((current_posn = tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL)
275 found_parallel_insn = 1;
276 while (is_space_char (*current_posn))
278 token_start = current_posn;
279 if (!is_opcode_char (*current_posn))
281 as_bad ("Invalid character %s in opcode", output_invalid (*current_posn));
284 /* Check if instruction is a parallel instruction by seeing if the first
286 if (*token_start == 'q')
288 if (tic30_parallel_insn (token_start))
290 if (found_parallel_insn)
295 while (is_opcode_char (*current_posn))
297 { /* Find instruction */
298 save_char = *current_posn;
299 *current_posn = '\0';
300 opcode = (template *) hash_find (op_hash, token_start);
303 debug ("Found instruction %s\n", opcode->name);
308 debug ("Didn't find insn\n");
309 as_bad ("Unknown TMS320C30 instruction: %s", token_start);
312 *current_posn = save_char;
314 if (*current_posn != END_OF_INSN)
315 { /* Find operands */
316 int paren_not_balanced;
317 int expecting_operand = 0;
321 /* skip optional white space before operand */
322 while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)
324 if (!is_space_char (*current_posn))
326 as_bad ("Invalid character %s before %s operand",
327 output_invalid (*current_posn),
328 ordinal_names[insn.operands]);
333 token_start = current_posn; /* after white space */
334 paren_not_balanced = 0;
335 while (paren_not_balanced || *current_posn != ',')
337 if (*current_posn == END_OF_INSN)
339 if (paren_not_balanced)
341 as_bad ("Unbalanced parenthesis in %s operand.",
342 ordinal_names[insn.operands]);
346 break; /* we are done */
348 else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))
350 as_bad ("Invalid character %s in %s operand",
351 output_invalid (*current_posn),
352 ordinal_names[insn.operands]);
355 if (*current_posn == '(')
356 ++paren_not_balanced;
357 if (*current_posn == ')')
358 --paren_not_balanced;
361 if (current_posn != token_start)
362 { /* yes, we've read in another operand */
363 this_operand = insn.operands++;
364 if (insn.operands > MAX_OPERANDS)
366 as_bad ("Spurious operands; (%d operands/instruction max)",
370 /* now parse operand adding info to 'insn' as we go along */
371 save_char = *current_posn;
372 *current_posn = '\0';
373 insn.operand_type[this_operand] = tic30_operand (token_start);
374 *current_posn = save_char;
375 if (insn.operand_type[this_operand] == NULL)
380 if (expecting_operand)
382 as_bad ("Expecting operand after ','; got nothing");
385 if (*current_posn == ',')
387 as_bad ("Expecting operand before ','; got nothing");
391 /* now *current_posn must be either ',' or END_OF_INSN */
392 if (*current_posn == ',')
394 if (*++current_posn == END_OF_INSN)
395 { /* just skip it, if it's \n complain */
396 as_bad ("Expecting operand after ','; got nothing");
399 expecting_operand = 1;
402 while (*current_posn != END_OF_INSN); /* until we get end of insn */
404 debug ("Number of operands found: %d\n", insn.operands);
405 /* Check that number of operands is correct */
406 if (insn.operands != insn.tm->operands)
409 unsigned int numops = insn.tm->operands;
410 /* If operands are not the same, then see if any of the operands are not
411 required. Then recheck with number of given operands. If they are still not
412 the same, then give an error, otherwise carry on. */
413 for (i = 0; i < insn.tm->operands; i++)
414 if (insn.tm->operand_types[i] & NotReq)
416 if (insn.operands != numops)
418 as_bad ("Incorrect number of operands given");
422 insn.addressing_mode = AM_NotReq;
423 for (count = 0; count < insn.operands; count++)
425 if (insn.operand_type[count]->op_type & insn.tm->operand_types[count])
427 debug ("Operand %d matches\n", count + 1);
428 /* If instruction has two operands and has an AddressMode modifier then set
429 addressing mode type for instruction */
430 if (insn.tm->opcode_modifier == AddressMode)
433 /* Store instruction uses the second operand for the address mode. */
434 if ((insn.tm->operand_types[1] & (Indirect | Direct)) == (Indirect | Direct))
436 if (insn.operand_type[addr_insn]->op_type & (AllReg))
437 insn.addressing_mode = AM_Register;
438 else if (insn.operand_type[addr_insn]->op_type & Direct)
439 insn.addressing_mode = AM_Direct;
440 else if (insn.operand_type[addr_insn]->op_type & Indirect)
441 insn.addressing_mode = AM_Indirect;
443 insn.addressing_mode = AM_Immediate;
448 as_bad ("The %s operand doesn't match", ordinal_names[count]);
452 /* Now set the addressing mode for 3 operand instructions. */
453 if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2))
455 /* Set the addressing mode to the values used for 2 operand instructions in the
456 G addressing field of the opcode. */
458 switch (insn.operand_type[0]->op_type)
464 if (insn.operand_type[1]->op_type & (AllReg))
465 insn.addressing_mode = AM_Register;
466 else if (insn.operand_type[1]->op_type & Indirect)
467 insn.addressing_mode = AM_Direct;
470 /* Shouldn't make it to this stage */
471 as_bad ("Incompatible first and second operands in instruction");
476 if (insn.operand_type[1]->op_type & (AllReg))
477 insn.addressing_mode = AM_Indirect;
478 else if (insn.operand_type[1]->op_type & Indirect)
479 insn.addressing_mode = AM_Immediate;
482 /* Shouldn't make it to this stage */
483 as_bad ("Incompatible first and second operands in instruction");
488 /* Now make up the opcode for the 3 operand instructions. As in parallel
489 instructions, there will be no unresolved values, so they can be fully formed
490 and added to the frag table. */
491 insn.opcode = insn.tm->base_opcode;
492 if (insn.operand_type[0]->op_type & Indirect)
494 insn.opcode |= (insn.operand_type[0]->indirect.ARnum);
495 insn.opcode |= (insn.operand_type[0]->indirect.mod << 3);
498 insn.opcode |= (insn.operand_type[0]->reg.opcode);
499 if (insn.operand_type[1]->op_type & Indirect)
501 insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8);
502 insn.opcode |= (insn.operand_type[1]->indirect.mod << 11);
505 insn.opcode |= (insn.operand_type[1]->reg.opcode << 8);
506 if (insn.operands == 3)
507 insn.opcode |= (insn.operand_type[2]->reg.opcode << 16);
508 insn.opcode |= insn.addressing_mode;
509 p = frag_more (INSN_SIZE);
510 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
513 { /* Not a three operand instruction */
516 insn.opcode = insn.tm->base_opcode;
517 /* Create frag for instruction - all instructions are 4 bytes long. */
518 p = frag_more (INSN_SIZE);
519 if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode))
521 insn.opcode |= insn.addressing_mode;
522 if (insn.addressing_mode == AM_Indirect)
524 /* Determine which operand gives the addressing mode */
525 if (insn.operand_type[0]->op_type & Indirect)
527 if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect))
529 insn.opcode |= (insn.operand_type[am_insn]->indirect.disp);
530 insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8);
531 insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11);
532 if (insn.operands > 1)
533 insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);
534 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
536 else if (insn.addressing_mode == AM_Register)
538 insn.opcode |= (insn.operand_type[0]->reg.opcode);
539 if (insn.operands > 1)
540 insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
541 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
543 else if (insn.addressing_mode == AM_Direct)
545 if (insn.operand_type[0]->op_type & Direct)
547 if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct))
549 if (insn.operands > 1)
550 insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);
551 if (insn.operand_type[am_insn]->direct.resolved == 1)
553 /* Resolved values can be placed straight into instruction word, and output */
554 insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF);
555 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
558 { /* Unresolved direct addressing mode instruction */
559 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
560 fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0);
563 else if (insn.addressing_mode == AM_Immediate)
565 if (insn.operand_type[0]->immediate.resolved == 1)
569 if (insn.operands > 1)
570 insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
571 switch (insn.tm->imm_arg_type)
574 debug ("Floating point first operand\n");
575 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
576 keeploc = input_line_pointer;
577 input_line_pointer = insn.operand_type[0]->immediate.label;
578 if (md_atof ('f', p + 2, &size) != 0)
580 as_bad ("invalid short form floating point immediate operand");
583 input_line_pointer = keeploc;
586 debug ("Unsigned int first operand\n");
587 if (insn.operand_type[0]->immediate.decimal_found)
588 as_warn ("rounding down first operand float to unsigned int");
589 if (insn.operand_type[0]->immediate.u_number > 0xFFFF)
590 as_warn ("only lower 16-bits of first operand are used");
591 insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL);
592 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
595 debug ("Int first operand\n");
596 if (insn.operand_type[0]->immediate.decimal_found)
597 as_warn ("rounding down first operand float to signed int");
598 if (insn.operand_type[0]->immediate.s_number < -32768 ||
599 insn.operand_type[0]->immediate.s_number > 32767)
601 as_bad ("first operand is too large for 16-bit signed int");
604 insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL);
605 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
610 { /* Unresolved immediate label */
611 if (insn.operands > 1)
612 insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
613 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
614 fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
618 else if (insn.tm->opcode_modifier == PCRel)
620 /* Conditional Branch and Call instructions */
621 if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp))
623 if (insn.operand_type[0]->op_type & (AllReg))
625 insn.opcode |= (insn.operand_type[0]->reg.opcode);
626 insn.opcode |= PC_Register;
627 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
631 insn.opcode |= PC_Relative;
632 if (insn.operand_type[0]->immediate.resolved == 1)
634 insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF);
635 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
639 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
640 fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0);
644 else if ((insn.tm->operand_types[0] & ARn) == ARn)
646 /* Decrement and Branch instructions */
647 insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22);
648 if (insn.operand_type[1]->op_type & (AllReg))
650 insn.opcode |= (insn.operand_type[1]->reg.opcode);
651 insn.opcode |= PC_Register;
652 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
654 else if (insn.operand_type[1]->immediate.resolved == 1)
656 if (insn.operand_type[0]->immediate.decimal_found)
658 as_bad ("first operand is floating point");
661 if (insn.operand_type[0]->immediate.s_number < -32768 ||
662 insn.operand_type[0]->immediate.s_number > 32767)
664 as_bad ("first operand is too large for 16-bit signed int");
667 insn.opcode |= (insn.operand_type[1]->immediate.s_number);
668 insn.opcode |= PC_Relative;
669 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
673 insn.opcode |= PC_Relative;
674 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
675 fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0);
679 else if (insn.tm->operand_types[0] == IVector)
681 /* Trap instructions */
682 if (insn.operand_type[0]->op_type & IVector)
683 insn.opcode |= (insn.operand_type[0]->immediate.u_number);
685 { /* Shouldn't get here */
686 as_bad ("interrupt vector for trap instruction out of range");
689 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
691 else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate)
693 /* Push, Pop and Rotate instructions */
694 insn.opcode |= (insn.operand_type[0]->reg.opcode << 16);
695 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
697 else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct))
699 /* LDP Instruction needs to be tested for before the next section */
700 if (insn.operand_type[0]->op_type & Direct)
702 if (insn.operand_type[0]->direct.resolved == 1)
704 /* Direct addressing uses lower 8 bits of direct address */
705 insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16;
706 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
711 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
712 fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0);
713 /* Ensure that the assembler doesn't complain about fitting a 24-bit
714 address into 8 bits. */
715 fix->fx_no_overflow = 1;
720 if (insn.operand_type[0]->immediate.resolved == 1)
722 /* Immediate addressing uses upper 8 bits of address */
723 if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)
725 as_bad ("LDP instruction needs a 24-bit operand");
728 insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16);
729 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
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]->immediate.imm_expr, 0, 0);
736 fix->fx_no_overflow = 1;
740 else if (insn.tm->operand_types[0] & (Imm24))
742 /* Unconditional Branch and Call instructions */
743 if (insn.operand_type[0]->immediate.resolved == 1)
745 if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)
746 as_warn ("first operand is too large for a 24-bit displacement");
747 insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF);
748 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
752 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
753 fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
756 else if (insn.tm->operand_types[0] & NotReq)
758 /* Check for NOP instruction without arguments. */
759 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
761 else if (insn.tm->operands == 0)
763 /* Check for instructions without operands. */
764 md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
767 debug ("Addressing mode: %08X\n", insn.addressing_mode);
770 for (i = 0; i < insn.operands; i++)
772 if (insn.operand_type[i]->immediate.label)
773 free (insn.operand_type[i]->immediate.label);
774 free (insn.operand_type[i]);
777 debug ("Final opcode: %08X\n", insn.opcode);
781 struct tic30_par_insn {
782 partemplate *tm; /* Template of current parallel instruction */
783 unsigned operands[2]; /* Number of given operands for each insn */
784 /* Type of operand given in instruction */
785 operand *operand_type[2][MAX_OPERANDS];
786 int swap_operands; /* Whether to swap operands around. */
787 unsigned p_field; /* Value of p field in multiply add/sub instructions */
788 unsigned opcode; /* Final opcode */
791 struct tic30_par_insn p_insn;
794 tic30_parallel_insn (char *token)
796 static partemplate *p_opcode;
797 char *current_posn = token;
801 debug ("In tic30_parallel_insn with %s\n", token);
802 memset (&p_insn, '\0', sizeof (p_insn));
803 while (is_opcode_char (*current_posn))
805 { /* Find instruction */
806 save_char = *current_posn;
807 *current_posn = '\0';
808 p_opcode = (partemplate *) hash_find (parop_hash, token);
811 debug ("Found instruction %s\n", p_opcode->name);
812 p_insn.tm = p_opcode;
816 char first_opcode[6] =
818 char second_opcode[6] =
821 int current_opcode = -1;
824 for (i = 0; i < strlen (token); i++)
826 char ch = *(token + i);
827 if (ch == '_' && current_opcode == -1)
832 if (ch == '_' && current_opcode == 0)
838 switch (current_opcode)
841 first_opcode[char_ptr++] = ch;
844 second_opcode[char_ptr++] = ch;
848 debug ("first_opcode = %s\n", first_opcode);
849 debug ("second_opcode = %s\n", second_opcode);
850 sprintf (token, "q_%s_%s", second_opcode, first_opcode);
851 p_opcode = (partemplate *) hash_find (parop_hash, token);
854 debug ("Found instruction %s\n", p_opcode->name);
855 p_insn.tm = p_opcode;
856 p_insn.swap_operands = 1;
861 *current_posn = save_char;
863 { /* Find operands */
864 int paren_not_balanced;
865 int expecting_operand = 0;
866 int found_separator = 0;
869 /* skip optional white space before operand */
870 while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)
872 if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR)
874 as_bad ("Invalid character %s before %s operand",
875 output_invalid (*current_posn),
876 ordinal_names[insn.operands]);
879 if (*current_posn == PARALLEL_SEPARATOR)
883 token_start = current_posn; /* after white space */
884 paren_not_balanced = 0;
885 while (paren_not_balanced || *current_posn != ',')
887 if (*current_posn == END_OF_INSN)
889 if (paren_not_balanced)
891 as_bad ("Unbalanced parenthesis in %s operand.",
892 ordinal_names[insn.operands]);
896 break; /* we are done */
898 else if (*current_posn == PARALLEL_SEPARATOR)
900 while (is_space_char (*(current_posn - 1)))
904 else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))
906 as_bad ("Invalid character %s in %s operand",
907 output_invalid (*current_posn),
908 ordinal_names[insn.operands]);
911 if (*current_posn == '(')
912 ++paren_not_balanced;
913 if (*current_posn == ')')
914 --paren_not_balanced;
917 if (current_posn != token_start)
918 { /* yes, we've read in another operand */
919 p_insn.operands[found_separator]++;
920 if (p_insn.operands[found_separator] > MAX_OPERANDS)
922 as_bad ("Spurious operands; (%d operands/instruction max)",
926 /* now parse operand adding info to 'insn' as we go along */
927 save_char = *current_posn;
928 *current_posn = '\0';
929 p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] =
930 tic30_operand (token_start);
931 *current_posn = save_char;
932 if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1])
937 if (expecting_operand)
939 as_bad ("Expecting operand after ','; got nothing");
942 if (*current_posn == ',')
944 as_bad ("Expecting operand before ','; got nothing");
948 /* now *current_posn must be either ',' or END_OF_INSN */
949 if (*current_posn == ',')
951 if (*++current_posn == END_OF_INSN)
952 { /* just skip it, if it's \n complain */
953 as_bad ("Expecting operand after ','; got nothing");
956 expecting_operand = 1;
959 while (*current_posn != END_OF_INSN); /* until we get end of insn */
961 if (p_insn.swap_operands)
966 temp_num = p_insn.operands[0];
967 p_insn.operands[0] = p_insn.operands[1];
968 p_insn.operands[1] = temp_num;
969 for (i = 0; i < MAX_OPERANDS; i++)
971 temp_op = p_insn.operand_type[0][i];
972 p_insn.operand_type[0][i] = p_insn.operand_type[1][i];
973 p_insn.operand_type[1][i] = temp_op;
976 if (p_insn.operands[0] != p_insn.tm->operands_1)
978 as_bad ("incorrect number of operands given in the first instruction");
981 if (p_insn.operands[1] != p_insn.tm->operands_2)
983 as_bad ("incorrect number of operands given in the second instruction");
986 debug ("Number of operands in first insn: %d\n", p_insn.operands[0]);
987 debug ("Number of operands in second insn: %d\n", p_insn.operands[1]);
988 { /* Now check if operands are correct */
992 for (count = 0; count < 2; count++)
995 for (i = 0; i < p_insn.operands[count]; i++)
997 if ((p_insn.operand_type[count][i]->op_type &
998 p_insn.tm->operand_types[count][i]) == 0)
1000 as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1);
1003 /* Get number of R register and indirect reference contained within the first
1004 two operands of each instruction. This is required for the multiply
1005 parallel instructions which require two R registers and two indirect
1006 references, but not in any particular place. */
1007 if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2)
1009 else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2)
1013 if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn))
1015 /* Check for the multiply instructions */
1018 as_bad ("incorrect format for multiply parallel instruction");
1022 { /* Shouldn't get here */
1023 as_bad ("incorrect format for multiply parallel instruction");
1026 if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) &&
1027 (p_insn.operand_type[0][2]->reg.opcode != 0x01))
1029 as_bad ("destination for multiply can only be R0 or R1");
1032 if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) &&
1033 (p_insn.operand_type[1][2]->reg.opcode != 0x03))
1035 as_bad ("destination for add/subtract can only be R2 or R3");
1038 /* Now determine the P field for the instruction */
1039 if (p_insn.operand_type[0][0]->op_type & Indirect)
1041 if (p_insn.operand_type[0][1]->op_type & Indirect)
1042 p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn */
1043 else if (p_insn.operand_type[1][0]->op_type & Indirect)
1044 p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */
1046 p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind */
1050 if (p_insn.operand_type[0][1]->op_type & Rn)
1051 p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind */
1052 else if (p_insn.operand_type[1][0]->op_type & Indirect)
1055 p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn */
1056 /* Need to swap the two multiply operands around so that everything is in
1057 its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */
1058 temp = p_insn.operand_type[0][0];
1059 p_insn.operand_type[0][0] = p_insn.operand_type[0][1];
1060 p_insn.operand_type[0][1] = temp;
1065 p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind */
1066 temp = p_insn.operand_type[0][0];
1067 p_insn.operand_type[0][0] = p_insn.operand_type[0][1];
1068 p_insn.operand_type[0][1] = temp;
1073 debug ("P field: %08X\n", p_insn.p_field);
1074 /* Finalise opcode. This is easier for parallel instructions as they have to be
1075 fully resolved, there are no memory addresses allowed, except through indirect
1076 addressing, so there are no labels to resolve. */
1078 p_insn.opcode = p_insn.tm->base_opcode;
1079 switch (p_insn.tm->oporder)
1082 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
1083 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
1084 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1085 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1086 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1087 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);
1090 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
1091 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
1092 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);
1093 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);
1094 p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19);
1095 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);
1096 if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode)
1097 as_warn ("loading the same register in parallel operation");
1100 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
1101 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
1102 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1103 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1104 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1105 p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22);
1108 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
1109 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
1110 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1111 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1112 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1113 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
1114 p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);
1117 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
1118 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
1119 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
1120 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
1121 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1122 p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);
1123 p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);
1126 p_insn.opcode |= p_insn.p_field;
1127 if (p_insn.operand_type[0][2]->reg.opcode == 0x01)
1128 p_insn.opcode |= 0x00800000;
1129 if (p_insn.operand_type[1][2]->reg.opcode == 0x03)
1130 p_insn.opcode |= 0x00400000;
1131 switch (p_insn.p_field)
1134 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
1135 p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
1136 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
1137 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
1138 p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);
1139 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19);
1142 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum);
1143 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3);
1144 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
1145 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
1146 p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);
1147 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
1150 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);
1151 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);
1152 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);
1153 p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);
1154 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16);
1155 p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);
1158 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);
1159 p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);
1160 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
1161 p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
1162 p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
1163 p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
1168 } /* Opcode is finalised at this point for all parallel instructions. */
1169 { /* Output opcode */
1171 p = frag_more (INSN_SIZE);
1172 md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE);
1176 for (i = 0; i < 2; i++)
1177 for (j = 0; j < p_insn.operands[i]; j++)
1178 free (p_insn.operand_type[i][j]);
1180 debug ("Final opcode: %08X\n", p_insn.opcode);
1186 tic30_operand (token)
1190 char ind_buffer[strlen (token)];
1191 operand *current_op;
1193 debug ("In tic30_operand with %s\n", token);
1194 current_op = (operand *) malloc (sizeof (operand));
1195 memset (current_op, '\0', sizeof (operand));
1196 if (*token == DIRECT_REFERENCE)
1198 char *token_posn = token + 1;
1199 int direct_label = 0;
1200 debug ("Found direct reference\n");
1203 if (!is_digit_char (*token_posn))
1209 char *save_input_line_pointer;
1211 debug ("Direct reference is a label\n");
1212 current_op->direct.label = token + 1;
1213 save_input_line_pointer = input_line_pointer;
1214 input_line_pointer = token + 1;
1215 debug ("Current input_line_pointer: %s\n", input_line_pointer);
1216 retval = expression (¤t_op->direct.direct_expr);
1217 debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op);
1218 debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number);
1219 debug ("Segment: %d\n", retval);
1220 input_line_pointer = save_input_line_pointer;
1221 if (current_op->direct.direct_expr.X_op == O_constant)
1223 current_op->direct.address = current_op->direct.direct_expr.X_add_number;
1224 current_op->direct.resolved = 1;
1229 debug ("Direct reference is a number\n");
1230 current_op->direct.address = atoi (token + 1);
1231 current_op->direct.resolved = 1;
1233 current_op->op_type = Direct;
1235 else if (*token == INDIRECT_REFERENCE)
1236 { /* Indirect reference operand */
1240 int disp_number = 0;
1241 int buffer_posn = 1;
1242 ind_addr_type *ind_addr_op;
1243 debug ("Found indirect reference\n");
1244 ind_buffer[0] = *token;
1245 for (count = 1; count < strlen (token); count++)
1246 { /* Strip operand */
1247 ind_buffer[buffer_posn] = TOLOWER (*(token + count));
1248 if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') &&
1249 (*(token + count) == 'r' || *(token + count) == 'R'))
1251 /* AR reference is found, so get its number and remove it from the buffer
1252 so it can pass through hash_find() */
1255 as_bad ("More than one AR register found in indirect reference");
1258 if (*(token + count + 1) < '0' || *(token + count + 1) > '7')
1260 as_bad ("Illegal AR register in indirect reference");
1263 ar_number = *(token + count + 1) - '0';
1267 if (*(token + count) == '(')
1269 /* Parenthesis found, so check if a displacement value is inside. If so, get
1270 the value and remove it from the buffer. */
1271 if (is_digit_char (*(token + count + 1)))
1278 as_bad ("More than one displacement found in indirect reference");
1282 while (*(token + count) != ')')
1284 if (!is_digit_char (*(token + count)))
1286 as_bad ("Invalid displacement in indirect reference");
1289 disp[disp_posn++] = *(token + (count++));
1291 disp[disp_posn] = '\0';
1292 disp_number = atoi (disp);
1299 ind_buffer[buffer_posn] = '\0';
1302 as_bad ("AR register not found in indirect reference");
1305 ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer);
1308 debug ("Found indirect reference: %s\n", ind_addr_op->syntax);
1309 if (ind_addr_op->displacement == IMPLIED_DISP)
1314 else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp)
1316 /* Maybe an implied displacement of 1 again */
1317 as_bad ("required displacement wasn't given in indirect reference");
1323 as_bad ("illegal indirect reference");
1326 if (found_disp && (disp_number < 0 || disp_number > 255))
1328 as_bad ("displacement must be an unsigned 8-bit number");
1331 current_op->indirect.mod = ind_addr_op->modfield;
1332 current_op->indirect.disp = disp_number;
1333 current_op->indirect.ARnum = ar_number;
1334 current_op->op_type = Indirect;
1338 reg *regop = (reg *) hash_find (reg_hash, token);
1341 debug ("Found register operand: %s\n", regop->name);
1342 if (regop->regtype == REG_ARn)
1343 current_op->op_type = ARn;
1344 else if (regop->regtype == REG_Rn)
1345 current_op->op_type = Rn;
1346 else if (regop->regtype == REG_DP)
1347 current_op->op_type = DPReg;
1349 current_op->op_type = OtherReg;
1350 current_op->reg.opcode = regop->opcode;
1354 if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h'))
1356 char *save_input_line_pointer;
1358 debug ("Probably a label: %s\n", token);
1359 current_op->immediate.label = (char *) malloc (strlen (token) + 1);
1360 strcpy (current_op->immediate.label, token);
1361 current_op->immediate.label[strlen (token)] = '\0';
1362 save_input_line_pointer = input_line_pointer;
1363 input_line_pointer = token;
1364 debug ("Current input_line_pointer: %s\n", input_line_pointer);
1365 retval = expression (¤t_op->immediate.imm_expr);
1366 debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op);
1367 debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number);
1368 debug ("Segment: %d\n", retval);
1369 input_line_pointer = save_input_line_pointer;
1370 if (current_op->immediate.imm_expr.X_op == O_constant)
1372 current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number;
1373 current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number;
1374 current_op->immediate.resolved = 1;
1380 debug ("Found a number or displacement\n");
1381 for (count = 0; count < strlen (token); count++)
1382 if (*(token + count) == '.')
1383 current_op->immediate.decimal_found = 1;
1384 current_op->immediate.label = (char *) malloc (strlen (token) + 1);
1385 strcpy (current_op->immediate.label, token);
1386 current_op->immediate.label[strlen (token)] = '\0';
1387 current_op->immediate.f_number = (float) atof (token);
1388 current_op->immediate.s_number = (int) atoi (token);
1389 current_op->immediate.u_number = (unsigned int) atoi (token);
1390 current_op->immediate.resolved = 1;
1392 current_op->op_type = Disp | Abs24 | Imm16 | Imm24;
1393 if (current_op->immediate.u_number <= 31)
1394 current_op->op_type |= IVector;
1400 /* next_line points to the next line after the current instruction (current_line).
1401 Search for the parallel bars, and if found, merge two lines into internal syntax
1402 for a parallel instruction:
1403 q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2]
1404 By this stage, all comments are scrubbed, and only the bare lines are given.
1408 #define START_OPCODE 1
1409 #define END_OPCODE 2
1410 #define START_OPERANDS 3
1411 #define END_OPERANDS 4
1414 tic30_find_parallel_insn (current_line, next_line)
1418 int found_parallel = 0;
1419 char first_opcode[256];
1420 char second_opcode[256];
1421 char first_operands[256];
1422 char second_operands[256];
1423 char *parallel_insn;
1425 debug ("In tic30_find_parallel_insn()\n");
1426 while (!is_end_of_line[(unsigned char) *next_line])
1428 if (*next_line == PARALLEL_SEPARATOR && *(next_line + 1) == PARALLEL_SEPARATOR)
1436 if (!found_parallel)
1438 debug ("Found a parallel instruction\n");
1441 char *opcode, *operands, *line;
1443 for (i = 0; i < 2; i++)
1447 opcode = &first_opcode[0];
1448 operands = &first_operands[0];
1449 line = current_line;
1453 opcode = &second_opcode[0];
1454 operands = &second_operands[0];
1458 int search_status = NONE;
1462 while (!is_end_of_line[(unsigned char) (c = *line)])
1464 if (is_opcode_char (c) && search_status == NONE)
1466 opcode[char_ptr++] = TOLOWER (c);
1467 search_status = START_OPCODE;
1469 else if (is_opcode_char (c) && search_status == START_OPCODE)
1471 opcode[char_ptr++] = TOLOWER (c);
1473 else if (!is_opcode_char (c) && search_status == START_OPCODE)
1475 opcode[char_ptr] = '\0';
1477 search_status = END_OPCODE;
1479 else if (is_operand_char (c) && search_status == START_OPERANDS)
1481 operands[char_ptr++] = c;
1483 if (is_operand_char (c) && search_status == END_OPCODE)
1485 operands[char_ptr++] = c;
1486 search_status = START_OPERANDS;
1490 if (search_status != START_OPERANDS)
1492 operands[char_ptr] = '\0';
1496 parallel_insn = (char *) malloc (strlen (first_opcode) + strlen (first_operands) +
1497 strlen (second_opcode) + strlen (second_operands) + 8);
1498 sprintf (parallel_insn, "q_%s_%s %s | %s", first_opcode, second_opcode, first_operands, second_operands);
1499 debug ("parallel insn = %s\n", parallel_insn);
1500 return parallel_insn;
1506 #undef START_OPERANDS
1509 /* In order to get gas to ignore any | chars at the start of a line,
1510 this function returns true if a | is found in a line. */
1513 tic30_unrecognized_line (c)
1516 debug ("In tc_unrecognized_line\n");
1517 return (c == PARALLEL_SEPARATOR);
1521 md_estimate_size_before_relax (fragP, segment)
1522 fragS *fragP ATTRIBUTE_UNUSED;
1523 segT segment ATTRIBUTE_UNUSED;
1525 debug ("In md_estimate_size_before_relax()\n");
1530 md_convert_frag (abfd, sec, fragP)
1531 bfd *abfd ATTRIBUTE_UNUSED;
1532 segT sec ATTRIBUTE_UNUSED;
1533 register fragS *fragP ATTRIBUTE_UNUSED;
1535 debug ("In md_convert_frag()\n");
1539 md_apply_fix3 (fixP, valP, seg)
1542 segT seg ATTRIBUTE_UNUSED;
1544 valueT value = *valP;
1546 debug ("In md_apply_fix() with value = %ld\n", (long) value);
1547 debug ("Values in fixP\n");
1548 debug ("fx_size = %d\n", fixP->fx_size);
1549 debug ("fx_pcrel = %d\n", fixP->fx_pcrel);
1550 debug ("fx_where = %d\n", fixP->fx_where);
1551 debug ("fx_offset = %d\n", (int) fixP->fx_offset);
1553 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1556 if (fixP->fx_size == 1)
1557 /* Special fix for LDP instruction. */
1558 value = (value & 0x00FF0000) >> 16;
1560 debug ("new value = %ld\n", (long) value);
1561 md_number_to_chars (buf, value, fixP->fx_size);
1564 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1569 md_parse_option (c, arg)
1570 int c ATTRIBUTE_UNUSED;
1571 char *arg ATTRIBUTE_UNUSED;
1573 debug ("In md_parse_option()\n");
1578 md_show_usage (stream)
1579 FILE *stream ATTRIBUTE_UNUSED;
1581 debug ("In md_show_usage()\n");
1585 md_undefined_symbol (name)
1586 char *name ATTRIBUTE_UNUSED;
1588 debug ("In md_undefined_symbol()\n");
1589 return (symbolS *) 0;
1593 md_section_align (segment, size)
1597 debug ("In md_section_align() segment = %d and size = %d\n", segment, size);
1598 size = (size + 3) / 4;
1600 debug ("New size value = %d\n", size);
1605 md_pcrel_from (fixP)
1610 debug ("In md_pcrel_from()\n");
1611 debug ("fx_where = %d\n", fixP->fx_where);
1612 debug ("fx_size = %d\n", fixP->fx_size);
1613 /* Find the opcode that represents the current instruction in the fr_literal
1614 storage area, and check bit 21. Bit 21 contains whether the current instruction
1615 is a delayed one or not, and then set the offset value appropriately. */
1616 if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20)
1620 debug ("offset = %d\n", offset);
1621 /* PC Relative instructions have a format:
1622 displacement = Label - (PC + offset)
1623 This function returns PC + offset where:
1624 fx_where - fx_size = PC
1625 INSN_SIZE * offset = offset number of instructions
1627 return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset);
1631 md_atof (what_statement_type, literalP, sizeP)
1632 int what_statement_type;
1639 unsigned long value;
1640 /* char *atof_ieee (); */
1642 debug ("In md_atof()\n");
1643 debug ("precision = %c\n", what_statement_type);
1644 debug ("literal = %s\n", literalP);
1646 token = input_line_pointer;
1647 while (!is_end_of_line[(unsigned char) *input_line_pointer]
1648 && (*input_line_pointer != ','))
1650 debug ("%c", *input_line_pointer);
1651 input_line_pointer++;
1653 keepval = *input_line_pointer;
1654 *input_line_pointer = '\0';
1656 float_value = (float) atof (token);
1657 *input_line_pointer = keepval;
1658 debug ("float_value = %f\n", float_value);
1659 switch (what_statement_type)
1677 return "Bad call to MD_ATOF()";
1679 if (float_value == 0.0)
1681 value = (prec == 2) ? 0x00008000L : 0x80000000L;
1685 unsigned long exp, sign, mant, tmsfloat;
1686 tmsfloat = *((long *) &float_value);
1687 sign = tmsfloat & 0x80000000;
1688 mant = tmsfloat & 0x007FFFFF;
1689 exp = tmsfloat & 0x7F800000;
1691 if (exp == 0xFF000000)
1705 mant = mant & 0x007FFFFF;
1707 mant = mant & 0x00FFFFFF;
1711 exp = (long) exp - 0x01000000;
1714 tmsfloat = exp | mant;
1721 if (tmsfloat == 0x80000000)
1728 exp = (tmsfloat & 0xFF000000);
1730 mant = tmsfloat & 0x007FFFFF;
1731 if (tmsfloat & 0x00800000)
1745 exp += (mant >> 24);
1755 mant = (exp << 12) | mant;
1756 value = mant & 0xFFFF;
1761 md_number_to_chars (literalP, value, prec);
1767 md_number_to_chars (buf, val, n)
1772 debug ("In md_number_to_chars()\n");
1773 number_to_chars_bigendian (buf, val, n);
1774 /* number_to_chars_littleendian(buf,val,n); */
1777 #define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
1778 #define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
1781 tc_gen_reloc (section, fixP)
1782 asection *section ATTRIBUTE_UNUSED;
1786 bfd_reloc_code_real_type code = 0;
1788 debug ("In tc_gen_reloc()\n");
1789 debug ("fixP.size = %d\n", fixP->fx_size);
1790 debug ("fixP.pcrel = %d\n", fixP->fx_pcrel);
1791 debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy));
1792 switch (F (fixP->fx_size, fixP->fx_pcrel))
1794 MAP (1, 0, BFD_RELOC_TIC30_LDP);
1795 MAP (2, 0, BFD_RELOC_16);
1796 MAP (3, 0, BFD_RELOC_24);
1797 MAP (2, 1, BFD_RELOC_16_PCREL);
1798 MAP (4, 0, BFD_RELOC_32);
1800 as_bad ("Can not do %d byte %srelocation", fixP->fx_size,
1801 fixP->fx_pcrel ? "pc-relative " : "");
1806 rel = (arelent *) xmalloc (sizeof (arelent));
1808 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1809 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1810 rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
1812 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
1816 name = S_GET_NAME (fixP->fx_addsy);
1819 as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code));
1825 md_operand (expressionP)
1826 expressionS *expressionP ATTRIBUTE_UNUSED;
1828 debug ("In md_operand()\n");
1831 char output_invalid_buf[8];
1838 sprintf (output_invalid_buf, "'%c'", c);
1840 sprintf (output_invalid_buf, "(0x%x)", (unsigned) c);
1841 return output_invalid_buf;