1 /* tc-tic80.c -- Assemble for the TI TMS320C80 (MV)
2 Copyright (C) 1996 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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)
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.
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
22 #include "opcode/tic80.h"
25 /* Generic assembler global variables which must be defined by all targets. */
27 /* Characters which always start a comment. */
28 const char comment_chars
[] = ";";
30 /* Characters which start a comment at the beginning of a line. */
31 const char line_comment_chars
[] = ";*";
33 /* Characters which may be used to separate multiple commands on a
35 const char line_separator_chars
[] = ";";
37 /* Characters which are used to indicate an exponent in a floating
39 const char EXP_CHARS
[] = "eE";
41 /* Characters which mean that a number is a floating point constant,
43 const char FLT_CHARS
[] = "dD";
45 /* This table describes all the machine specific pseudo-ops the assembler
46 has to support. The fields are:
47 pseudo-op name without dot
48 function to call to execute this pseudo-op
49 Integer arg to pass to the function
52 const pseudo_typeS md_pseudo_table
[] =
58 /* Opcode hash table. */
59 static struct hash_control
*tic80_hash
;
61 static struct tic80_opcode
* find_opcode
PARAMS ((struct tic80_opcode
*, expressionS
[]));
62 static unsigned long build_insn
PARAMS ((struct tic80_opcode
*, expressionS
*, unsigned long insn
));
63 static int get_operands
PARAMS ((expressionS exp
[]));
64 static int reg_name_search
PARAMS ((char *name
));
65 static int register_name
PARAMS ((expressionS
*expressionP
));
69 md_estimate_size_before_relax (fragP
, segment_type
)
73 as_fatal ("Relaxation is a luxury we can't afford\n");
77 /* We have no need to default values of symbols. */
81 md_undefined_symbol (name
)
87 /* Turn a string in input_line_pointer into a floating point constant of type
88 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
89 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
92 #define MAX_LITTLENUMS 4
95 md_atof (type
, litP
, sizeP
)
101 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
102 LITTLENUM_TYPE
*wordP
;
124 return "bad call to md_atof ()";
127 t
= atof_ieee (input_line_pointer
, type
, words
);
130 input_line_pointer
= t
;
133 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
135 for (wordP
= words
; prec
--;)
137 md_number_to_chars (litP
, (valueT
) (*wordP
++), sizeof (LITTLENUM_TYPE
));
138 litP
+= sizeof (LITTLENUM_TYPE
);
143 /* reg_name_search does a binary search of the tic80_pre_defined_registers
144 array to see if "name" is a valid regiter name. Returns the register
145 number from the array on success, or -1 on failure. */
148 reg_name_search (name
)
151 int middle
, low
, high
;
155 high
= tic80_num_regs
- 1;
159 middle
= (low
+ high
) / 2;
160 cmp
= strcasecmp (name
, tic80_pre_defined_registers
[middle
].name
);
171 return (tic80_pre_defined_registers
[middle
].value
);
178 /* register_name() checks the string at input_line_pointer
179 to see if it is a valid register name */
182 register_name (expressionP
)
183 expressionS
*expressionP
;
187 char *p
= input_line_pointer
;
189 while (*p
!= '\000' && *p
!= '\n' && *p
!= '\r' && *p
!= ',' && *p
!= ' ' && *p
!= ')')
198 /* look to see if it's in the register table */
200 reg_number
= reg_name_search (input_line_pointer
);
203 expressionP
-> X_op
= O_register
;
204 /* temporarily store a pointer to the string here */
205 expressionP
-> X_op_symbol
= (struct symbol
*) input_line_pointer
;
206 expressionP
-> X_add_number
= reg_number
;
207 input_line_pointer
= p
;
217 /* get_operands() parses a string of operands and fills in a passed array of
220 Note that we use O_absent expressions to record additional information
221 about the previous non-O_absent expression, such as ":m" or ":s"
222 modifiers or register numbers enclosed in parens like "(r10)".
224 Returns the number of expressions that were placed in EXP.
232 char *p
= input_line_pointer
;
240 /* Skip leading whitespace */
241 while (*p
== ' ' || *p
== '\t' || *p
== ',')
246 /* Check to see if we have any operands left to parse */
247 if (*p
== 0 || *p
== '\n' || *p
== '\r')
252 /* Notice scaling or direct memory operand modifiers and save them in
253 an O_absent expression after the expression that they modify. */
258 exp
[numexp
].X_op
= O_absent
;
262 exp
[numexp
].X_add_number
= TIC80_OPERAND_M_SI
| TIC80_OPERAND_M_LI
;
267 exp
[numexp
].X_add_number
= TIC80_OPERAND_SCALED
;
271 as_bad ("':' not followed by 'm' or 's'");
277 /* Handle leading '(' on operands that use them, by recording that we
278 have entered a paren nesting level and then continuing. We complain
279 about multiple nesting. */
285 as_bad ("paren nesting");
291 /* Handle trailing ')' on operands that use them, by reducing the
292 nesting level and then continuing. We complain if there were too
297 /* Record that we have left a paren group and continue */
300 as_bad ("mismatched parenthesis");
306 /* Begin operand parsing at the current scan point. */
308 input_line_pointer
= p
;
310 /* Check to see if it might be a register name */
312 if (!register_name (&exp
[numexp
]))
314 /* parse as an expression */
315 expression (&exp
[numexp
]);
318 if (exp
[numexp
].X_op
== O_illegal
)
320 as_bad ("illegal operand");
322 else if (exp
[numexp
].X_op
== O_absent
)
324 as_bad ("missing operand");
328 p
= input_line_pointer
;
333 exp
[numexp
].X_op
= O_absent
;
334 exp
[numexp
++].X_add_number
= TIC80_OPERAND_PARENS
;
337 exp
[numexp
].X_op
= 0;
341 /* find_opcode() gets a pointer to the entry in the opcode table that
342 matches the instruction being assembled, or returns NULL if no such match
345 First it parses all the operands and save them as expressions. Note that
346 we use O_absent expressions to record additional information about the
347 previous non-O_absent expression, such as ":m" or ":s" modifiers or
348 register numbers enclosed in parens like "(r10)".
350 It then looks at all opcodes with the same name and use the operands to
351 choose the correct opcode. */
354 static struct tic80_opcode
*
355 find_opcode (opcode
, myops
)
356 struct tic80_opcode
*opcode
;
359 int i
, match
, done
, numops
;
360 struct tic80_opcode
*next_opcode
;
364 /* First parse all the operands so we only have to do it once. */
366 get_operands (myops
);
368 /* Now search the opcode table table for one with operands that
369 matches what we've got. */
374 for (i
= 0; opcode
-> operands
[i
]; i
++)
376 int flags
= tic80_operands
[opcode
->operands
[i
]].flags
;
377 int X_op
= myops
[i
].X_op
;
378 int num
= myops
[i
].X_add_number
;
386 if (flags
& TIC80_OPERAND_GPR
)
388 if ((X_op
!= O_register
) ||
389 ((flags
& OPERAND_ACC
) != (num
& OPERAND_ACC
)) ||
390 ((flags
& OPERAND_FLAG
) != (num
& OPERAND_FLAG
)) ||
391 ((flags
& OPERAND_CONTROL
) != (num
& OPERAND_CONTROL
)))
398 if (((flags
& OPERAND_MINUS
) && ((X_op
!= O_absent
) || (num
!= OPERAND_MINUS
))) ||
399 ((flags
& OPERAND_PLUS
) && ((X_op
!= O_absent
) || (num
!= OPERAND_PLUS
))) ||
400 ((flags
& OPERAND_ATMINUS
) && ((X_op
!= O_absent
) || (num
!= OPERAND_ATMINUS
))) ||
401 ((flags
& OPERAND_ATPAR
) && ((X_op
!= O_absent
) || (num
!= OPERAND_ATPAR
))) ||
402 ((flags
& OPERAND_ATSIGN
) && ((X_op
!= O_absent
) || (num
!= OPERAND_ATSIGN
))))
408 /* we're only done if the operands matched so far AND there
409 are no more to check */
410 if (match
&& myops
[i
].X_op
==0)
415 next_opcode
= opcode
+1;
416 if (next_opcode
->opcode
== 0)
418 if (strcmp(next_opcode
->name
, opcode
->name
))
420 opcode
= next_opcode
;
425 as_bad ("bad opcode or operands");
429 /* Check that all registers that are required to be even are. */
430 /* Also, if any operands were marked as registers, but were really symbols */
432 for (i
=0; opcode
->operands
[i
]; i
++)
434 if ((tic80_operands
[opcode
->operands
[i
]].flags
& OPERAND_EVEN
) &&
435 (myops
[i
].X_add_number
& 1))
436 as_fatal("Register number must be EVEN");
437 if (myops
[i
].X_op
== O_register
)
439 if (!(tic80_operands
[opcode
->operands
[i
]].flags
& OPERAND_REG
))
441 myops
[i
].X_op
= O_symbol
;
442 myops
[i
].X_add_symbol
= symbol_find_or_make ((char *)myops
[i
].X_op_symbol
);
443 myops
[i
].X_add_number
= 0;
444 myops
[i
].X_op_symbol
= NULL
;
451 /* build_insn takes a pointer to the opcode entry in the opcode table
452 and the array of operand expressions and returns the instruction */
455 build_insn (opcode
, opers
, insn
)
456 struct tic80_opcode
*opcode
;
463 /* This is the main entry point for the machine-dependent assembler. STR points to a
464 machine dependent instruction. This function is supposed to emit the frags/bytes
473 unsigned char *input_line_save
;
474 struct tic80_opcode
*opcode
;
475 expressionS myops
[6];
478 /* Ensure there is something there to assemble. */
481 /* Drop any leading whitespace. */
482 while (isspace (*str
))
487 /* Isolate the mnemonic from the rest of the string by finding the first
488 whitespace character and zapping it to a null byte. */
489 for (scan
= str
; *scan
!= '\000' && !isspace (*scan
); scan
++) {;}
495 /* Try to find this mnemonic in the hash table */
496 if ((opcode
= (struct tic80_opcode
*) hash_find (tic80_hash
, str
)) == NULL
)
498 as_bad ("Invalid mnemonic: '%s'", str
);
503 while (isspace (*scan
))
508 input_line_save
= input_line_pointer
;
509 input_line_pointer
= str
;
511 opcode
= find_opcode (opcode
, myops
);
517 input_line_pointer
= input_line_save
;
518 insn
= build_insn (opcode
, myops
, 0);
520 /* FIXME - finish this */
523 /* This function is called once, at assembler startup time. It should
524 set up all the tables, etc., that the MD part of the assembler will
530 char *prev_name
= "";
531 register const struct tic80_opcode
*op
;
532 register const struct tic80_opcode
*op_end
;
534 tic80_hash
= hash_new();
536 /* Insert unique names into hash table. The TIc80 instruction set
537 has many identical opcode names that have different opcodes based
538 on the operands. This hash table then provides a quick index to
539 the first opcode with a particular name in the opcode table. */
541 op_end
= tic80_opcodes
+ tic80_num_opcodes
;
542 for (op
= tic80_opcodes
; op
< op_end
; op
++)
544 if (strcmp (prev_name
, op
-> name
) != 0)
546 prev_name
= (char *) op
-> name
;
547 hash_insert (tic80_hash
, op
-> name
, (char *) op
);
554 CONST
char *md_shortopts
= "";
556 struct option md_longopts
[] = {
557 {NULL
, no_argument
, NULL
, 0}
560 size_t md_longopts_size
= sizeof(md_longopts
);
562 /* Take care of the target-specific command-line options. */
565 md_parse_option (c
, arg
)
572 /* Print a description of the command-line options that we accept. */
575 md_show_usage (stream
)
581 /* Attempt to simplify or even eliminate a fixup. The return value is
582 ignored; perhaps it was once meaningful, but now it is historical.
583 To indicate that a fixup has been eliminated, set fixP->fx_done.
587 md_apply_fix (fixP
, val
)
591 as_fatal ("md_apply_fix() not implemented yet\n");
596 /* Functions concerning relocs. */
598 /* The location from which a PC relative jump should be calculated,
599 given a PC relative reloc. */
605 as_fatal ("md_pcrel_from() not implemented yet\n");
610 * Called after relax() is finished.
611 * In: Address of frag.
612 * fr_type == rs_machine_dependent.
613 * fr_subtype is what the address relaxed to.
615 * Out: Any fixSs and constants are set up.
616 * Caller will turn frag into a ".space 0".
620 md_convert_frag (headers
, seg
, fragP
)
621 object_headers
*headers
;
625 as_fatal ("md_convert_frag() not implemented yet\n");
632 tc_coff_symbol_emit_hook (ignore
)
640 tc_coff_fix2rtype (fixP
)
643 as_fatal ("tc_coff_fix2rtype() not implemented yet\n");
647 #endif /* OBJ_COFF */
649 /* end of tc-tic80.c */