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