* config/tc-tic80.c: Numerous changes and additions to flesh
[deliverable/binutils-gdb.git] / gas / config / tc-tic80.c
CommitLineData
64556643
FF
1/* tc-tic80.c -- Assemble for the TI TMS320C80 (MV)
2 Copyright (C) 1996 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21#include "as.h"
22#include "opcode/tic80.h"
23
11e08196
FF
24#define internal_error(what) \
25 as_fatal("internal error:%s:%d: %s\n",__FILE__,__LINE__,what)
26#define internal_error_a(what,arg) \
27 as_fatal("internal error:%s:%d: %s %d\n",__FILE__,__LINE__,what,arg)
28
64556643
FF
29\f
30/* Generic assembler global variables which must be defined by all targets. */
31
32/* Characters which always start a comment. */
33const char comment_chars[] = ";";
34
35/* Characters which start a comment at the beginning of a line. */
36const char line_comment_chars[] = ";*";
37
38/* Characters which may be used to separate multiple commands on a
11e08196
FF
39 single line. */
40const char line_separator_chars[] = "";
64556643
FF
41
42/* Characters which are used to indicate an exponent in a floating
43 point number. */
44const char EXP_CHARS[] = "eE";
45
46/* Characters which mean that a number is a floating point constant,
47 as in 0d1.0. */
48const char FLT_CHARS[] = "dD";
49
f1ce6af4
FF
50/* This table describes all the machine specific pseudo-ops the assembler
51 has to support. The fields are:
52 pseudo-op name without dot
53 function to call to execute this pseudo-op
54 Integer arg to pass to the function
55 */
56
57const pseudo_typeS md_pseudo_table[] =
58{
59 {"word", cons, 4},
60 { NULL, NULL, 0 }
61};
62
63/* Opcode hash table. */
64static struct hash_control *tic80_hash;
65
66static struct tic80_opcode * find_opcode PARAMS ((struct tic80_opcode *, expressionS []));
11e08196 67static void build_insn PARAMS ((struct tic80_opcode *, expressionS *));
f1ce6af4 68static int get_operands PARAMS ((expressionS exp[]));
f1ce6af4 69static int register_name PARAMS ((expressionS *expressionP));
11e08196
FF
70static int is_bitnum PARAMS ((expressionS *expressionP));
71static int is_ccode PARAMS ((expressionS *expressionP));
72static int const_overflow PARAMS ((unsigned long num, int bits, int flags));
f1ce6af4 73
64556643 74\f
f1ce6af4
FF
75int
76md_estimate_size_before_relax (fragP, segment_type)
77 fragS *fragP;
78 segT segment_type;
79{
11e08196 80 internal_error ("Relaxation is a luxury we can't afford");
f1ce6af4
FF
81 return (-1);
82}
83
84/* We have no need to default values of symbols. */
85
86/* ARGSUSED */
87symbolS *
88md_undefined_symbol (name)
89 char *name;
90{
91 return 0;
92}
93
94/* Turn a string in input_line_pointer into a floating point constant of type
95 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
96 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
97 */
98
99#define MAX_LITTLENUMS 4
100
101char *
102md_atof (type, litP, sizeP)
103 int type;
104 char *litP;
105 int *sizeP;
106{
107 int prec;
108 LITTLENUM_TYPE words[MAX_LITTLENUMS];
109 LITTLENUM_TYPE *wordP;
110 char *t;
111 char *atof_ieee ();
112
113 switch (type)
114 {
115 case 'f':
116 case 'F':
117 case 's':
118 case 'S':
119 prec = 2;
120 break;
121
122 case 'd':
123 case 'D':
124 case 'r':
125 case 'R':
126 prec = 4;
127 break;
128
129 default:
130 *sizeP = 0;
131 return "bad call to md_atof ()";
132 }
133
134 t = atof_ieee (input_line_pointer, type, words);
135 if (t)
136 {
137 input_line_pointer = t;
138 }
139
140 *sizeP = prec * sizeof (LITTLENUM_TYPE);
141
142 for (wordP = words; prec--;)
143 {
144 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
145 litP += sizeof (LITTLENUM_TYPE);
146 }
147 return (NULL);
148}
149
11e08196
FF
150/* register_name() checks the string at input_line_pointer
151 to see if it is a valid register name */
f1ce6af4
FF
152
153static int
11e08196
FF
154register_name (expressionP)
155 expressionS *expressionP;
f1ce6af4 156{
11e08196
FF
157 int reg_number, class;
158 char c;
159 char *p = input_line_pointer;
160
161 while (*p != '\000' && *p != '\n' && *p != '\r' && *p != ',' && *p != ' ' && *p != '(' && *p != ')')
162 p++;
163
164 c = *p;
165 if (c)
166 {
167 *p++ = '\000';
168 }
f1ce6af4 169
11e08196 170 /* look to see if it's in the register table */
f1ce6af4 171
11e08196
FF
172 class = TIC80_OPERAND_FPA | TIC80_OPERAND_CR | TIC80_OPERAND_GPR;
173 reg_number = tic80_symbol_to_value (input_line_pointer, class);
174 if (reg_number != -1)
f1ce6af4 175 {
11e08196
FF
176 expressionP -> X_op = O_register;
177 /* temporarily store a pointer to the string here */
178 expressionP -> X_op_symbol = (struct symbol *) input_line_pointer;
179 expressionP -> X_add_number = reg_number;
180 input_line_pointer = p;
181 return (1);
f1ce6af4 182 }
11e08196
FF
183 if (c)
184 {
185 *(p - 1) = c;
186 }
187 return (0);
f1ce6af4
FF
188}
189
11e08196
FF
190/* is_bitnum() checks the string at input_line_pointer
191 to see if it is a valid predefined symbol for the BITNUM field */
f1ce6af4
FF
192
193static int
11e08196 194is_bitnum (expressionP)
f1ce6af4
FF
195 expressionS *expressionP;
196{
11e08196 197 int bitnum_val, class;
f1ce6af4
FF
198 char c;
199 char *p = input_line_pointer;
200
11e08196 201 while (*p != '\000' && *p != '\n' && *p != '\r' && *p != ',' && *p != ' ' && *p != '(' && *p != ')')
f1ce6af4
FF
202 p++;
203
204 c = *p;
205 if (c)
206 {
207 *p++ = '\000';
208 }
209
210 /* look to see if it's in the register table */
211
11e08196
FF
212 class = TIC80_OPERAND_BITNUM;
213 bitnum_val = tic80_symbol_to_value (input_line_pointer, class);
214 if (bitnum_val != -1)
f1ce6af4 215 {
11e08196 216 expressionP -> X_op = O_constant;
f1ce6af4
FF
217 /* temporarily store a pointer to the string here */
218 expressionP -> X_op_symbol = (struct symbol *) input_line_pointer;
11e08196
FF
219 /* Bitnums are stored as one's complement */
220 expressionP -> X_add_number = ~bitnum_val & 0x1F;
f1ce6af4
FF
221 input_line_pointer = p;
222 return (1);
223 }
224 if (c)
225 {
226 *(p - 1) = c;
227 }
228 return (0);
229}
230
11e08196
FF
231/* is_ccode() checks the string at input_line_pointer
232 to see if it is a valid predefined symbol for the a condition code */
233
234static int
235is_ccode (expressionP)
236 expressionS *expressionP;
237{
238 int ccode_val, class;
239 char c;
240 char *p = input_line_pointer;
241
242 while (*p != '\000' && *p != '\n' && *p != '\r' && *p != ',' && *p != ' ' && *p != '(' && *p != ')')
243 p++;
244
245 c = *p;
246 if (c)
247 {
248 *p++ = '\000';
249 }
250
251 /* look to see if it's in the register table */
252
253 class = TIC80_OPERAND_CC;
254 ccode_val = tic80_symbol_to_value (input_line_pointer, class);
255 if (ccode_val != -1)
256 {
257 expressionP -> X_op = O_constant;
258 /* temporarily store a pointer to the string here */
259 expressionP -> X_op_symbol = (struct symbol *) input_line_pointer;
260 expressionP -> X_add_number = ccode_val & 0x1F;
261 input_line_pointer = p;
262 return (1);
263 }
264 if (c)
265 {
266 *(p - 1) = c;
267 }
268 return (0);
269}
270
271/* Check to see if the constant value in NUM will fit in a field of
272 width BITS if it has flags FLAGS. */
273
274static int
275const_overflow (num, bits, flags)
276 unsigned long num;
277 int bits;
278 int flags;
279{
280 long min, max;
281 int retval = 0;
282
283 /* Only need to check fields less than 32 bits wide */
284 if (bits < 32)
285 if (flags & TIC80_OPERAND_SIGNED)
286 {
287 max = (1 << (bits - 1)) - 1;
288 min = - (1 << (bits - 1));
289 retval = ((long) num > max) || ((long) num < min);
290 }
291 else
292 {
293 max = (1 << bits) - 1;
294 min = 0;
295 retval = (num > max) || (num < min);
296 }
297 return (retval);
298}
299
f1ce6af4
FF
300/* get_operands() parses a string of operands and fills in a passed array of
301 expressions in EXP.
302
303 Note that we use O_absent expressions to record additional information
304 about the previous non-O_absent expression, such as ":m" or ":s"
305 modifiers or register numbers enclosed in parens like "(r10)".
306
307 Returns the number of expressions that were placed in EXP.
308
309 */
310
311static int
312get_operands (exp)
313 expressionS exp[];
314{
315 char *p = input_line_pointer;
316 int numexp = 0;
317 int mflag = 0;
318 int sflag = 0;
319 int parens = 0;
320
321 while (*p)
322 {
323 /* Skip leading whitespace */
324 while (*p == ' ' || *p == '\t' || *p == ',')
325 {
326 p++;
327 }
328
329 /* Check to see if we have any operands left to parse */
330 if (*p == 0 || *p == '\n' || *p == '\r')
331 {
332 break;
333 }
334
335 /* Notice scaling or direct memory operand modifiers and save them in
336 an O_absent expression after the expression that they modify. */
337
338 if (*p == ':')
339 {
340 p++;
341 exp[numexp].X_op = O_absent;
342 if (*p == 'm')
343 {
344 p++;
345 exp[numexp].X_add_number = TIC80_OPERAND_M_SI | TIC80_OPERAND_M_LI;
346 }
347 else if (*p == 's')
348 {
349 p++;
350 exp[numexp].X_add_number = TIC80_OPERAND_SCALED;
351 }
352 else
353 {
354 as_bad ("':' not followed by 'm' or 's'");
355 }
356 numexp++;
357 continue;
358 }
359
360 /* Handle leading '(' on operands that use them, by recording that we
361 have entered a paren nesting level and then continuing. We complain
362 about multiple nesting. */
363
364 if (*p == '(')
365 {
366 if (++parens != 1)
367 {
368 as_bad ("paren nesting");
369 }
370 p++;
371 continue;
372 }
373
374 /* Handle trailing ')' on operands that use them, by reducing the
375 nesting level and then continuing. We complain if there were too
376 many closures. */
377
378 if (*p == ')')
379 {
380 /* Record that we have left a paren group and continue */
381 if (--parens < 0)
382 {
383 as_bad ("mismatched parenthesis");
384 }
385 p++;
386 continue;
387 }
388
389 /* Begin operand parsing at the current scan point. */
390
391 input_line_pointer = p;
392
11e08196
FF
393 /* Check to see if it might be a register name or some other
394 predefined symbol name that translates into a constant value. */
f1ce6af4 395
11e08196
FF
396 if (!register_name (&exp[numexp]) &&
397 !is_bitnum (&exp[numexp]) &&
398 !is_ccode (&exp[numexp]))
f1ce6af4
FF
399 {
400 /* parse as an expression */
401 expression (&exp[numexp]);
402 }
403
404 if (exp[numexp].X_op == O_illegal)
405 {
406 as_bad ("illegal operand");
407 }
408 else if (exp[numexp].X_op == O_absent)
409 {
410 as_bad ("missing operand");
411 }
412
413 numexp++;
414 p = input_line_pointer;
415 }
416
417 if (parens)
418 {
419 exp[numexp].X_op = O_absent;
420 exp[numexp++].X_add_number = TIC80_OPERAND_PARENS;
421 }
422
11e08196
FF
423 /* Mark the end of the valid operands with an illegal expression. */
424 exp[numexp].X_op = O_illegal;
425
f1ce6af4
FF
426 return (numexp);
427}
428
429/* find_opcode() gets a pointer to the entry in the opcode table that
430 matches the instruction being assembled, or returns NULL if no such match
431 is found.
432
433 First it parses all the operands and save them as expressions. Note that
434 we use O_absent expressions to record additional information about the
435 previous non-O_absent expression, such as ":m" or ":s" modifiers or
436 register numbers enclosed in parens like "(r10)".
437
11e08196 438 It then looks at all opcodes with the same name and uses the operands to
f1ce6af4
FF
439 choose the correct opcode. */
440
f1ce6af4
FF
441static struct tic80_opcode *
442find_opcode (opcode, myops)
443 struct tic80_opcode *opcode;
444 expressionS myops[];
445{
11e08196
FF
446 int numexp; /* Number of expressions from parsing operands */
447 int expi; /* Index of current expression to match */
448 int opi; /* Index of current operand to match */
449 int match = 0; /* Set to 1 when an operand match is found */
450 struct tic80_opcode *opc = opcode; /* Pointer to current opcode table entry */
451 const struct tic80_opcode *end; /* Pointer to end of opcode table */
452
453 /* First parse all the operands so we only have to do it once. There may
454 be more expressions generated than there are operands. */
455
456 numexp = get_operands (myops);
457
458 /* For each opcode with the same name, try to match it against the parsed
459 operands. */
460
461 end = tic80_opcodes + tic80_num_opcodes;
462 while (!match && (opc < end) && (strcmp (opc -> name, opcode -> name) == 0))
463 {
464 /* Start off assuming a match. If we find a mismatch, then this is
465 reset and the operand/expr matching loop terminates with match
466 equal to zero, which allows us to try the next opcode. */
467
468 match = 1;
469
470 /* For each expression, try to match it against the current operand
471 for the current opcode. Upon any mismatch, we abandon further
472 matching for the current opcode table entry. */
f1ce6af4 473
11e08196
FF
474 for (expi = 0, opi = -1; (expi < numexp) && match; expi++)
475 {
476 int bits, flags, X_op, num;
f1ce6af4 477
11e08196
FF
478 X_op = myops[expi].X_op;
479 num = myops[expi].X_add_number;
480 if (X_op != O_absent)
481 {
482 /* The O_absent expressions apply to the previously seen
483 operand, so only increment the operand index when the
484 current expression needs to be matched against the next
485 operand. */
486 opi++;
487 }
488 flags = tic80_operands[opc -> operands[opi]].flags;
489 bits = tic80_operands[opc -> operands[opi]].bits;
f1ce6af4 490
11e08196
FF
491 switch (X_op)
492 {
493 case O_register:
494 /* Also check that registers that are supposed to be even actually
495 are even. */
496 if (((flags & TIC80_OPERAND_GPR) != (num & TIC80_OPERAND_GPR)) ||
497 ((flags & TIC80_OPERAND_FPA) != (num & TIC80_OPERAND_FPA)) ||
498 ((flags & TIC80_OPERAND_CR) != (num & TIC80_OPERAND_CR)) ||
499 ((flags & TIC80_OPERAND_EVEN) && (num & 1)) ||
500 const_overflow (num & ~TIC80_OPERAND_MASK, bits, flags))
501 {
502 match = 0;
503 }
504 break;
505 case O_constant:
506 if ((flags & TIC80_OPERAND_ENDMASK) && (num == 32))
507 {
508 /* Endmask values of 0 and 32 give identical results */
509 num = 0;
510 }
511 if ((flags & (TIC80_OPERAND_FPA | TIC80_OPERAND_GPR)) ||
512 const_overflow (num, bits, flags))
513 {
514 match = 0;
515 }
516 break;
517 case O_illegal:
518 case O_absent:
519 case O_symbol:
520 case O_symbol_rva:
521 case O_big:
522 case O_uminus:
523 case O_bit_not:
524 case O_logical_not:
525 case O_multiply:
526 case O_divide:
527 case O_modulus:
528 case O_left_shift:
529 case O_right_shift:
530 case O_bit_inclusive_or:
531 case O_bit_or_not:
532 case O_bit_exclusive_or:
533 case O_bit_and:
534 case O_add:
535 case O_subtract:
536 case O_eq:
537 case O_ne:
538 case O_lt:
539 case O_le:
540 case O_ge:
541 case O_gt:
542 case O_logical_and:
543 case O_logical_or:
544 case O_max:
545 default:
546 internal_error_a ("unhandled expression type", X_op);
547 }
548 }
549 if (!match)
550 {
551 opc++;
552 }
553 }
554
555 return (match ? opc : NULL);
556
557#if 0
f1ce6af4
FF
558
559 /* Now search the opcode table table for one with operands that
560 matches what we've got. */
561
562 while (!match)
563 {
564 match = 1;
565 for (i = 0; opcode -> operands[i]; i++)
566 {
567 int flags = tic80_operands[opcode->operands[i]].flags;
568 int X_op = myops[i].X_op;
569 int num = myops[i].X_add_number;
570
571 if (X_op == 0)
572 {
573 match = 0;
574 break;
575 }
576
11e08196 577 if (flags & (TIC80_OPERAND_GPR | TIC80_OPERAND_FPA | TIC80_OPERAND_CR))
f1ce6af4
FF
578 {
579 if ((X_op != O_register) ||
11e08196
FF
580 ((flags & TIC80_OPERAND_GPR) != (num & TIC80_OPERAND_GPR)) ||
581 ((flags & TIC80_OPERAND_FPA) != (num & TIC80_OPERAND_FPA)) ||
582 ((flags & TIC80_OPERAND_CR) != (num & TIC80_OPERAND_CR)))
f1ce6af4
FF
583 {
584 match=0;
585 break;
586 }
587 }
588
11e08196
FF
589 if (((flags & TIC80_OPERAND_MINUS) && ((X_op != O_absent) || (num != TIC80_OPERAND_MINUS))) ||
590 ((flags & TIC80_OPERAND_PLUS) && ((X_op != O_absent) || (num != TIC80_OPERAND_PLUS))) ||
591 ((flags & TIC80_OPERAND_ATMINUS) && ((X_op != O_absent) || (num != TIC80_OPERAND_ATMINUS))) ||
592 ((flags & TIC80_OPERAND_ATPAR) && ((X_op != O_absent) || (num != TIC80_OPERAND_ATPAR))) ||
593 ((flags & TIC80_OPERAND_ATSIGN) && ((X_op != O_absent) || (num != TIC80_OPERAND_ATSIGN))))
f1ce6af4
FF
594 {
595 match=0;
596 break;
597 }
598 }
599 /* we're only done if the operands matched so far AND there
600 are no more to check */
601 if (match && myops[i].X_op==0)
602 break;
603 else
604 match = 0;
605
606 next_opcode = opcode+1;
607 if (next_opcode->opcode == 0)
608 break;
609 if (strcmp(next_opcode->name, opcode->name))
610 break;
611 opcode = next_opcode;
612 }
613
614 if (!match)
615 {
616 as_bad ("bad opcode or operands");
617 return (0);
618 }
619
620 /* Check that all registers that are required to be even are. */
621 /* Also, if any operands were marked as registers, but were really symbols */
622 /* fix that here. */
623 for (i=0; opcode->operands[i]; i++)
624 {
11e08196 625 if ((tic80_operands[opcode->operands[i]].flags & TIC80_OPERAND_EVEN) &&
f1ce6af4 626 (myops[i].X_add_number & 1))
11e08196 627 as_fatal ("Register number must be EVEN");
f1ce6af4
FF
628 if (myops[i].X_op == O_register)
629 {
11e08196 630 if (!(tic80_operands[opcode->operands[i]].flags & TIC80_OPERAND_REG))
f1ce6af4
FF
631 {
632 myops[i].X_op = O_symbol;
633 myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol);
634 myops[i].X_add_number = 0;
635 myops[i].X_op_symbol = NULL;
636 }
637 }
638 }
11e08196
FF
639
640#endif
f1ce6af4
FF
641}
642
643/* build_insn takes a pointer to the opcode entry in the opcode table
11e08196 644 and the array of operand expressions and writes out the instruction. */
f1ce6af4 645
11e08196
FF
646static void
647build_insn (opcode, opers)
f1ce6af4
FF
648 struct tic80_opcode *opcode;
649 expressionS *opers;
f1ce6af4 650{
11e08196
FF
651 int expi; /* Index of current expression to match */
652 int opi; /* Index of current operand to match */
653 unsigned long insn[2]; /* Instruction and long immediate (if any) */
654 int extended = 0; /* Nonzero if instruction is 8 bytes */
655 char *f; /* Temporary pointer to output location */
656
657 /* Start with the raw opcode bits from the opcode table. */
658 insn[0] = opcode -> opcode;
659
660 /* For each operand expression, insert the appropriate bits into the
661 instruction . */
662 for (expi = 0, opi = -1; opers[expi].X_op != O_illegal; expi++)
663 {
664 int bits, shift, flags, X_op, num;
665
666 X_op = opers[expi].X_op;
667 num = opers[expi].X_add_number;
668 if (X_op != O_absent)
669 {
670 /* The O_absent expressions apply to the previously seen
671 operand, so only increment the operand index when the
672 current expression needs to be matched against the next
673 operand. */
674 opi++;
675 }
676 else
677 {
678 /* Found a modifier that applies to the previously
679 seen operand, so handle it. */
680 switch (opers[expi].X_add_number)
681 {
682 case TIC80_OPERAND_M_SI | TIC80_OPERAND_M_LI:
683 internal_error_a ("unhandled operand modifier", opers[expi].X_add_number);
684 break;
685 case TIC80_OPERAND_SCALED:
686 internal_error_a ("unhandled operand modifier", opers[expi].X_add_number);
687 break;
688 case TIC80_OPERAND_PARENS:
689 internal_error_a ("unhandled operand modifier", opers[expi].X_add_number);
690 break;
691 default:
692 internal_error_a ("unhandled operand modifier", opers[expi].X_add_number);
693 break;
694 }
695 }
696 flags = tic80_operands[opcode -> operands[opi]].flags;
697 bits = tic80_operands[opcode -> operands[opi]].bits;
698 shift = tic80_operands[opcode -> operands[opi]].shift;
699
700 switch (X_op)
701 {
702 case O_register:
703 num &= ~TIC80_OPERAND_MASK;
704 insn[0] = insn[0] | (num << shift);
705 break;
706 case O_constant:
707 if ((flags & TIC80_OPERAND_ENDMASK) && (num == 32))
708 {
709 /* Endmask values of 0 and 32 give identical results */
710 num = 0;
711 }
712 /* Mask off upper bits, just it case it is signed and is negative */
713 if (bits < 32)
714 {
715 num &= (1 << bits) - 1;
716 insn[0] = insn[0] | (num << shift);
717 }
718 else
719 {
720 extended++;
721 insn[1] = num;
722 }
723 break;
724 case O_illegal:
725 case O_absent:
726 case O_symbol:
727 case O_symbol_rva:
728 case O_big:
729 case O_uminus:
730 case O_bit_not:
731 case O_logical_not:
732 case O_multiply:
733 case O_divide:
734 case O_modulus:
735 case O_left_shift:
736 case O_right_shift:
737 case O_bit_inclusive_or:
738 case O_bit_or_not:
739 case O_bit_exclusive_or:
740 case O_bit_and:
741 case O_add:
742 case O_subtract:
743 case O_eq:
744 case O_ne:
745 case O_lt:
746 case O_le:
747 case O_ge:
748 case O_gt:
749 case O_logical_and:
750 case O_logical_or:
751 case O_max:
752 default:
753 internal_error_a ("unhandled expression", X_op);
754 break;
755 }
756 }
757
758 /* Write out the instruction, either 4 or 8 bytes. */
759
760 f = frag_more (4);
761 md_number_to_chars (f, insn[0], 4);
762 if (extended)
763 {
764 f = frag_more (4);
765 md_number_to_chars (f, insn[1], 4);
766 }
f1ce6af4
FF
767}
768
769/* This is the main entry point for the machine-dependent assembler. STR points to a
770 machine dependent instruction. This function is supposed to emit the frags/bytes
771 it assembles to.
772 */
773
774void
775md_assemble (str)
776 char *str;
777{
778 char *scan;
779 unsigned char *input_line_save;
780 struct tic80_opcode *opcode;
11e08196 781 expressionS myops[16];
f1ce6af4
FF
782 unsigned long insn;
783
784 /* Ensure there is something there to assemble. */
785 assert (str);
786
787 /* Drop any leading whitespace. */
788 while (isspace (*str))
789 {
790 str++;
791 }
792
793 /* Isolate the mnemonic from the rest of the string by finding the first
794 whitespace character and zapping it to a null byte. */
795 for (scan = str; *scan != '\000' && !isspace (*scan); scan++) {;}
796 if (*scan != '\000')
797 {
798 *scan++ = '\000';
799 }
800
801 /* Try to find this mnemonic in the hash table */
802 if ((opcode = (struct tic80_opcode *) hash_find (tic80_hash, str)) == NULL)
803 {
804 as_bad ("Invalid mnemonic: '%s'", str);
805 return;
806 }
807
808 str = scan;
809 while (isspace (*scan))
810 {
811 scan++;
812 }
813
814 input_line_save = input_line_pointer;
815 input_line_pointer = str;
816
817 opcode = find_opcode (opcode, myops);
818 if (opcode == NULL)
819 {
11e08196 820 as_bad ("Invalid operands: '%s'", input_line_save);
f1ce6af4
FF
821 }
822
823 input_line_pointer = input_line_save;
11e08196 824 build_insn (opcode, myops);
f1ce6af4
FF
825}
826
827/* This function is called once, at assembler startup time. It should
828 set up all the tables, etc., that the MD part of the assembler will
829 need. */
830
831void
832md_begin ()
833{
834 char *prev_name = "";
835 register const struct tic80_opcode *op;
836 register const struct tic80_opcode *op_end;
837
838 tic80_hash = hash_new();
839
840 /* Insert unique names into hash table. The TIc80 instruction set
841 has many identical opcode names that have different opcodes based
842 on the operands. This hash table then provides a quick index to
843 the first opcode with a particular name in the opcode table. */
844
845 op_end = tic80_opcodes + tic80_num_opcodes;
846 for (op = tic80_opcodes; op < op_end; op++)
847 {
848 if (strcmp (prev_name, op -> name) != 0)
849 {
850 prev_name = (char *) op -> name;
851 hash_insert (tic80_hash, op -> name, (char *) op);
852 }
853 }
854}
855
856\f
857
858CONST char *md_shortopts = "";
859
860struct option md_longopts[] = {
861 {NULL, no_argument, NULL, 0}
862};
863
864size_t md_longopts_size = sizeof(md_longopts);
865
866/* Take care of the target-specific command-line options. */
867
868int
869md_parse_option (c, arg)
870 int c;
871 char *arg;
872{
873 return (0);
874}
875
876/* Print a description of the command-line options that we accept. */
877
878void
879md_show_usage (stream)
880 FILE *stream;
881{
882}
883
884\f
885/* Attempt to simplify or even eliminate a fixup. The return value is
886 ignored; perhaps it was once meaningful, but now it is historical.
887 To indicate that a fixup has been eliminated, set fixP->fx_done.
888 */
889
890void
891md_apply_fix (fixP, val)
892 fixS *fixP;
893 long val;
894{
11e08196 895 internal_error ("md_apply_fix() not implemented yet");
f1ce6af4
FF
896 abort ();
897}
898
899\f
900/* Functions concerning relocs. */
901
902/* The location from which a PC relative jump should be calculated,
903 given a PC relative reloc. */
904
905long
906md_pcrel_from (fixP)
907 fixS *fixP;
908{
11e08196 909 internal_error ("md_pcrel_from() not implemented yet");
f1ce6af4
FF
910 abort ();
911}
912
913/*
914 * Called after relax() is finished.
915 * In: Address of frag.
916 * fr_type == rs_machine_dependent.
917 * fr_subtype is what the address relaxed to.
918 *
919 * Out: Any fixSs and constants are set up.
920 * Caller will turn frag into a ".space 0".
921 */
922
923void
924md_convert_frag (headers, seg, fragP)
925 object_headers *headers;
926 segT seg;
927 fragS *fragP;
928{
11e08196 929 internal_error ("md_convert_frag() not implemented yet");
f1ce6af4
FF
930 abort ();
931}
932
933\f
934/*ARGSUSED*/
935void
936tc_coff_symbol_emit_hook (ignore)
937 symbolS *ignore;
938{
939}
940
941#if defined OBJ_COFF
942
943short
944tc_coff_fix2rtype (fixP)
945 fixS *fixP;
946{
11e08196 947 internal_error ("tc_coff_fix2rtype() not implemented yet");
f1ce6af4
FF
948 abort ();
949}
950
951#endif /* OBJ_COFF */
952
64556643 953/* end of tc-tic80.c */
This page took 0.064325 seconds and 4 git commands to generate.