* config/tc-d10v.c (find_opcode): Remove unused variable "numops".
[deliverable/binutils-gdb.git] / gas / config / tc-tic80.c
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
24 \f
25 /* Generic assembler global variables which must be defined by all targets. */
26
27 /* Characters which always start a comment. */
28 const char comment_chars[] = ";";
29
30 /* Characters which start a comment at the beginning of a line. */
31 const char line_comment_chars[] = ";*";
32
33 /* Characters which may be used to separate multiple commands on a
34 single line. */
35 const char line_separator_chars[] = ";";
36
37 /* Characters which are used to indicate an exponent in a floating
38 point number. */
39 const char EXP_CHARS[] = "eE";
40
41 /* Characters which mean that a number is a floating point constant,
42 as in 0d1.0. */
43 const char FLT_CHARS[] = "dD";
44
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
50 */
51
52 const pseudo_typeS md_pseudo_table[] =
53 {
54 {"word", cons, 4},
55 { NULL, NULL, 0 }
56 };
57
58 /* Opcode hash table. */
59 static struct hash_control *tic80_hash;
60
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));
66
67 \f
68 int
69 md_estimate_size_before_relax (fragP, segment_type)
70 fragS *fragP;
71 segT segment_type;
72 {
73 as_fatal ("Relaxation is a luxury we can't afford\n");
74 return (-1);
75 }
76
77 /* We have no need to default values of symbols. */
78
79 /* ARGSUSED */
80 symbolS *
81 md_undefined_symbol (name)
82 char *name;
83 {
84 return 0;
85 }
86
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.
90 */
91
92 #define MAX_LITTLENUMS 4
93
94 char *
95 md_atof (type, litP, sizeP)
96 int type;
97 char *litP;
98 int *sizeP;
99 {
100 int prec;
101 LITTLENUM_TYPE words[MAX_LITTLENUMS];
102 LITTLENUM_TYPE *wordP;
103 char *t;
104 char *atof_ieee ();
105
106 switch (type)
107 {
108 case 'f':
109 case 'F':
110 case 's':
111 case 'S':
112 prec = 2;
113 break;
114
115 case 'd':
116 case 'D':
117 case 'r':
118 case 'R':
119 prec = 4;
120 break;
121
122 default:
123 *sizeP = 0;
124 return "bad call to md_atof ()";
125 }
126
127 t = atof_ieee (input_line_pointer, type, words);
128 if (t)
129 {
130 input_line_pointer = t;
131 }
132
133 *sizeP = prec * sizeof (LITTLENUM_TYPE);
134
135 for (wordP = words; prec--;)
136 {
137 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
138 litP += sizeof (LITTLENUM_TYPE);
139 }
140 return (NULL);
141 }
142
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. */
146
147 static int
148 reg_name_search (name)
149 char *name;
150 {
151 int middle, low, high;
152 int cmp;
153
154 low = 0;
155 high = tic80_num_regs - 1;
156
157 do
158 {
159 middle = (low + high) / 2;
160 cmp = strcasecmp (name, tic80_pre_defined_registers[middle].name);
161 if (cmp < 0)
162 {
163 high = middle - 1;
164 }
165 else if (cmp > 0)
166 {
167 low = middle + 1;
168 }
169 else
170 {
171 return (tic80_pre_defined_registers[middle].value);
172 }
173 }
174 while (low <= high);
175 return (-1);
176 }
177
178 /* register_name() checks the string at input_line_pointer
179 to see if it is a valid register name */
180
181 static int
182 register_name (expressionP)
183 expressionS *expressionP;
184 {
185 int reg_number;
186 char c;
187 char *p = input_line_pointer;
188
189 while (*p != '\000' && *p != '\n' && *p != '\r' && *p != ',' && *p != ' ' && *p != ')')
190 p++;
191
192 c = *p;
193 if (c)
194 {
195 *p++ = '\000';
196 }
197
198 /* look to see if it's in the register table */
199
200 reg_number = reg_name_search (input_line_pointer);
201 if (reg_number >= 0)
202 {
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;
208 return (1);
209 }
210 if (c)
211 {
212 *(p - 1) = c;
213 }
214 return (0);
215 }
216
217 /* get_operands() parses a string of operands and fills in a passed array of
218 expressions in EXP.
219
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)".
223
224 Returns the number of expressions that were placed in EXP.
225
226 */
227
228 static int
229 get_operands (exp)
230 expressionS exp[];
231 {
232 char *p = input_line_pointer;
233 int numexp = 0;
234 int mflag = 0;
235 int sflag = 0;
236 int parens = 0;
237
238 while (*p)
239 {
240 /* Skip leading whitespace */
241 while (*p == ' ' || *p == '\t' || *p == ',')
242 {
243 p++;
244 }
245
246 /* Check to see if we have any operands left to parse */
247 if (*p == 0 || *p == '\n' || *p == '\r')
248 {
249 break;
250 }
251
252 /* Notice scaling or direct memory operand modifiers and save them in
253 an O_absent expression after the expression that they modify. */
254
255 if (*p == ':')
256 {
257 p++;
258 exp[numexp].X_op = O_absent;
259 if (*p == 'm')
260 {
261 p++;
262 exp[numexp].X_add_number = TIC80_OPERAND_M_SI | TIC80_OPERAND_M_LI;
263 }
264 else if (*p == 's')
265 {
266 p++;
267 exp[numexp].X_add_number = TIC80_OPERAND_SCALED;
268 }
269 else
270 {
271 as_bad ("':' not followed by 'm' or 's'");
272 }
273 numexp++;
274 continue;
275 }
276
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. */
280
281 if (*p == '(')
282 {
283 if (++parens != 1)
284 {
285 as_bad ("paren nesting");
286 }
287 p++;
288 continue;
289 }
290
291 /* Handle trailing ')' on operands that use them, by reducing the
292 nesting level and then continuing. We complain if there were too
293 many closures. */
294
295 if (*p == ')')
296 {
297 /* Record that we have left a paren group and continue */
298 if (--parens < 0)
299 {
300 as_bad ("mismatched parenthesis");
301 }
302 p++;
303 continue;
304 }
305
306 /* Begin operand parsing at the current scan point. */
307
308 input_line_pointer = p;
309
310 /* Check to see if it might be a register name */
311
312 if (!register_name (&exp[numexp]))
313 {
314 /* parse as an expression */
315 expression (&exp[numexp]);
316 }
317
318 if (exp[numexp].X_op == O_illegal)
319 {
320 as_bad ("illegal operand");
321 }
322 else if (exp[numexp].X_op == O_absent)
323 {
324 as_bad ("missing operand");
325 }
326
327 numexp++;
328 p = input_line_pointer;
329 }
330
331 if (parens)
332 {
333 exp[numexp].X_op = O_absent;
334 exp[numexp++].X_add_number = TIC80_OPERAND_PARENS;
335 }
336
337 exp[numexp].X_op = 0;
338 return (numexp);
339 }
340
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
343 is found.
344
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)".
349
350 It then looks at all opcodes with the same name and use the operands to
351 choose the correct opcode. */
352
353
354 static struct tic80_opcode *
355 find_opcode (opcode, myops)
356 struct tic80_opcode *opcode;
357 expressionS myops[];
358 {
359 int i, match, done, numops;
360 struct tic80_opcode *next_opcode;
361
362 match = 0;
363
364 /* First parse all the operands so we only have to do it once. */
365
366 get_operands (myops);
367
368 /* Now search the opcode table table for one with operands that
369 matches what we've got. */
370
371 while (!match)
372 {
373 match = 1;
374 for (i = 0; opcode -> operands[i]; i++)
375 {
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;
379
380 if (X_op == 0)
381 {
382 match = 0;
383 break;
384 }
385
386 if (flags & TIC80_OPERAND_GPR)
387 {
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)))
392 {
393 match=0;
394 break;
395 }
396 }
397
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))))
403 {
404 match=0;
405 break;
406 }
407 }
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)
411 break;
412 else
413 match = 0;
414
415 next_opcode = opcode+1;
416 if (next_opcode->opcode == 0)
417 break;
418 if (strcmp(next_opcode->name, opcode->name))
419 break;
420 opcode = next_opcode;
421 }
422
423 if (!match)
424 {
425 as_bad ("bad opcode or operands");
426 return (0);
427 }
428
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 */
431 /* fix that here. */
432 for (i=0; opcode->operands[i]; i++)
433 {
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)
438 {
439 if (!(tic80_operands[opcode->operands[i]].flags & OPERAND_REG))
440 {
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;
445 }
446 }
447 }
448 return opcode;
449 }
450
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 */
453
454 static unsigned long
455 build_insn (opcode, opers, insn)
456 struct tic80_opcode *opcode;
457 expressionS *opers;
458 unsigned long insn;
459 {
460 return (0);
461 }
462
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
465 it assembles to.
466 */
467
468 void
469 md_assemble (str)
470 char *str;
471 {
472 char *scan;
473 unsigned char *input_line_save;
474 struct tic80_opcode *opcode;
475 expressionS myops[6];
476 unsigned long insn;
477
478 /* Ensure there is something there to assemble. */
479 assert (str);
480
481 /* Drop any leading whitespace. */
482 while (isspace (*str))
483 {
484 str++;
485 }
486
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++) {;}
490 if (*scan != '\000')
491 {
492 *scan++ = '\000';
493 }
494
495 /* Try to find this mnemonic in the hash table */
496 if ((opcode = (struct tic80_opcode *) hash_find (tic80_hash, str)) == NULL)
497 {
498 as_bad ("Invalid mnemonic: '%s'", str);
499 return;
500 }
501
502 str = scan;
503 while (isspace (*scan))
504 {
505 scan++;
506 }
507
508 input_line_save = input_line_pointer;
509 input_line_pointer = str;
510
511 opcode = find_opcode (opcode, myops);
512 if (opcode == NULL)
513 {
514 return;
515 }
516
517 input_line_pointer = input_line_save;
518 insn = build_insn (opcode, myops, 0);
519
520 /* FIXME - finish this */
521 }
522
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
525 need. */
526
527 void
528 md_begin ()
529 {
530 char *prev_name = "";
531 register const struct tic80_opcode *op;
532 register const struct tic80_opcode *op_end;
533
534 tic80_hash = hash_new();
535
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. */
540
541 op_end = tic80_opcodes + tic80_num_opcodes;
542 for (op = tic80_opcodes; op < op_end; op++)
543 {
544 if (strcmp (prev_name, op -> name) != 0)
545 {
546 prev_name = (char *) op -> name;
547 hash_insert (tic80_hash, op -> name, (char *) op);
548 }
549 }
550 }
551
552 \f
553
554 CONST char *md_shortopts = "";
555
556 struct option md_longopts[] = {
557 {NULL, no_argument, NULL, 0}
558 };
559
560 size_t md_longopts_size = sizeof(md_longopts);
561
562 /* Take care of the target-specific command-line options. */
563
564 int
565 md_parse_option (c, arg)
566 int c;
567 char *arg;
568 {
569 return (0);
570 }
571
572 /* Print a description of the command-line options that we accept. */
573
574 void
575 md_show_usage (stream)
576 FILE *stream;
577 {
578 }
579
580 \f
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.
584 */
585
586 void
587 md_apply_fix (fixP, val)
588 fixS *fixP;
589 long val;
590 {
591 as_fatal ("md_apply_fix() not implemented yet\n");
592 abort ();
593 }
594
595 \f
596 /* Functions concerning relocs. */
597
598 /* The location from which a PC relative jump should be calculated,
599 given a PC relative reloc. */
600
601 long
602 md_pcrel_from (fixP)
603 fixS *fixP;
604 {
605 as_fatal ("md_pcrel_from() not implemented yet\n");
606 abort ();
607 }
608
609 /*
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.
614 *
615 * Out: Any fixSs and constants are set up.
616 * Caller will turn frag into a ".space 0".
617 */
618
619 void
620 md_convert_frag (headers, seg, fragP)
621 object_headers *headers;
622 segT seg;
623 fragS *fragP;
624 {
625 as_fatal ("md_convert_frag() not implemented yet\n");
626 abort ();
627 }
628
629 \f
630 /*ARGSUSED*/
631 void
632 tc_coff_symbol_emit_hook (ignore)
633 symbolS *ignore;
634 {
635 }
636
637 #if defined OBJ_COFF
638
639 short
640 tc_coff_fix2rtype (fixP)
641 fixS *fixP;
642 {
643 as_fatal ("tc_coff_fix2rtype() not implemented yet\n");
644 abort ();
645 }
646
647 #endif /* OBJ_COFF */
648
649 /* end of tc-tic80.c */
This page took 0.042565 seconds and 4 git commands to generate.