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