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