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