From: Ian Lance Taylor Date: Tue, 3 Feb 1998 00:17:20 +0000 (+0000) Subject: Mon Feb 2 18:30:34 1998 Steve Haworth X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0e034c7751ab65989cc41d80e398c1fc6e835f8c;p=binutils-gdb.git Mon Feb 2 18:30:34 1998 Steve Haworth Add tms320c30 support: * config/tc-tic30.h: New file. * config/tc-tic30.c: New file. * config/obj-coff.h: If TC_TIC30, include coff/tic30.h and define TARGET_FORMAT as "coff-tic30". * configure.in (tic30-*-*aout*, tic30-*-*coff*): New targets. * Makefile.am: Rebuild dependencies. (CPU_TYPES): Add tic30. (CPU_OBJ_VALID): tic30-aout is valid. (TARGET_CPU_CFILES): Add config/tc-tic30.c. (TARGET_CPU_HFILES): Add config/tc-tic30.h. * configure, Makefile.in: Rebuild. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 03a6811f1e4..db44d9ebaca 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,22 @@ +Mon Feb 2 18:38:18 1998 Ian Lance Taylor + + * config/tc-sparc.c: Only include elf/sparc.h if OBJ_ELF. + +Mon Feb 2 18:30:34 1998 Steve Haworth + + Add tms320c30 support: + * config/tc-tic30.h: New file. + * config/tc-tic30.c: New file. + * config/obj-coff.h: If TC_TIC30, include coff/tic30.h and define + TARGET_FORMAT as "coff-tic30". + * configure.in (tic30-*-*aout*, tic30-*-*coff*): New targets. + * Makefile.am: Rebuild dependencies. + (CPU_TYPES): Add tic30. + (CPU_OBJ_VALID): tic30-aout is valid. + (TARGET_CPU_CFILES): Add config/tc-tic30.c. + (TARGET_CPU_HFILES): Add config/tc-tic30.h. + * configure, Makefile.in: Rebuild. + Mon Feb 2 10:20:37 1998 Nick Clifton * config/tc-v850.c (md_assemble): Improvements to error messages diff --git a/gas/Makefile.am b/gas/Makefile.am index 948ea73b913..310e6c3b521 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -53,6 +53,7 @@ CPU_TYPES = \ sh \ sparc \ tahoe \ + tic30 \ vax \ w65 \ v850 \ @@ -82,7 +83,7 @@ CPU_OBJ_VALID = \ case $$o in \ aout) \ case $$c in \ - a29k | arm | i386 | i860 | m68k | mips | ns32k | sparc | tahoe | vax) \ + a29k | arm | i386 | i860 | m68k | mips | ns32k | sparc | tahoe | tic30 | vax) \ valid=yes ;; \ esac ;; \ bout) \ @@ -199,6 +200,7 @@ TARGET_CPU_CFILES = \ config/tc-sh.c \ config/tc-sparc.c \ config/tc-tahoe.c \ + config/tc-tic30.c \ config/tc-vax.c \ config/tc-w65.c \ config/tc-v850.c \ @@ -227,6 +229,7 @@ TARGET_CPU_HFILES = \ config/tc-sh.h \ config/tc-sparc.h \ config/tc-tahoe.h \ + config/tc-tic30.h \ config/tc-vax.h \ config/tc-w65.h \ config/tc-v850.h \ @@ -827,6 +830,7 @@ subsegs.o: subsegs.c subsegs.h $(INCDIR)/obstack.h symbols.o: symbols.c $(INCDIR)/obstack.h subsegs.h write.o: write.c subsegs.h $(INCDIR)/obstack.h output-file.h gasp.o: gasp.c sb.h macro.h +itbl-ops.o: itbl-ops.c itbl-ops.h e-i386coff.o: $(srcdir)/config/e-i386coff.c emul.h \ emul-target.h e-i386elf.o: $(srcdir)/config/e-i386elf.c emul.h emul-target.h @@ -886,10 +890,11 @@ TCDEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/obstack.h $(INCDIR)/opcode/d10v.h $(INCDIR)/elf/ppc.h TCDEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \ - $(INCDIR)/bfdlink.h $(INCDIR)/opcode/h8300.h + $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h TCDEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ - $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h $(INCDIR)/opcode/h8300.h + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h subsegs.h \ + $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h TCDEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/h8500-opc.h @@ -1028,7 +1033,7 @@ TCDEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \ TCDEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h subsegs.h \ - $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h + $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h $(INCDIR)/elf/sparc.h TCDEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \ $(INCDIR)/opcode/tahoe.h @@ -1039,6 +1044,14 @@ TCDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h $(INCDIR)/obstack.h \ $(INCDIR)/opcode/tahoe.h +TCDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ + $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h +TCDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ + $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h +TCDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h $(INCDIR)/opcode/tic30.h TCDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(srcdir)/config/vax-inst.h \ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h @@ -1277,6 +1290,16 @@ OBJDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h subsegs.h \ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h +OBJDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ + $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/obstack.h +OBJDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ + $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h +OBJDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h subsegs.h \ + $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h OBJDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \ $(INCDIR)/obstack.h @@ -1465,6 +1488,14 @@ DEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \ DEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h +DEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ + $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h +DEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ + $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h +DEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h DEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h DEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \ diff --git a/gas/Makefile.in b/gas/Makefile.in index b19c85d657f..17e8380a1ff 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -127,6 +127,7 @@ CPU_TYPES = \ sh \ sparc \ tahoe \ + tic30 \ vax \ w65 \ v850 \ @@ -156,7 +157,7 @@ CPU_OBJ_VALID = \ case $$o in \ aout) \ case $$c in \ - a29k | arm | i386 | i860 | m68k | mips | ns32k | sparc | tahoe | vax) \ + a29k | arm | i386 | i860 | m68k | mips | ns32k | sparc | tahoe | tic30 | vax) \ valid=yes ;; \ esac ;; \ bout) \ @@ -273,6 +274,7 @@ TARGET_CPU_CFILES = \ config/tc-sh.c \ config/tc-sparc.c \ config/tc-tahoe.c \ + config/tc-tic30.c \ config/tc-vax.c \ config/tc-w65.c \ config/tc-v850.c \ @@ -301,6 +303,7 @@ TARGET_CPU_HFILES = \ config/tc-sh.h \ config/tc-sparc.h \ config/tc-tahoe.h \ + config/tc-tic30.h \ config/tc-vax.h \ config/tc-w65.h \ config/tc-v850.h \ @@ -534,10 +537,11 @@ TCDEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/obstack.h $(INCDIR)/opcode/d10v.h $(INCDIR)/elf/ppc.h TCDEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \ - $(INCDIR)/bfdlink.h $(INCDIR)/opcode/h8300.h + $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h TCDEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ - $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h $(INCDIR)/opcode/h8300.h + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h subsegs.h \ + $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h TCDEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/h8500-opc.h @@ -676,7 +680,7 @@ TCDEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \ TCDEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h subsegs.h \ - $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h + $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h $(INCDIR)/elf/sparc.h TCDEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \ $(INCDIR)/opcode/tahoe.h @@ -687,6 +691,14 @@ TCDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h $(INCDIR)/obstack.h \ $(INCDIR)/opcode/tahoe.h +TCDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ + $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h +TCDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ + $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h +TCDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h $(INCDIR)/opcode/tic30.h TCDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(srcdir)/config/vax-inst.h \ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h @@ -925,6 +937,16 @@ OBJDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h subsegs.h \ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h +OBJDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ + $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/obstack.h +OBJDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ + $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h +OBJDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h subsegs.h \ + $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h OBJDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \ $(INCDIR)/obstack.h @@ -1113,6 +1135,14 @@ DEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \ DEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h +DEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ + $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h +DEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ + $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h +DEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h DEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h DEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \ @@ -1937,6 +1967,7 @@ subsegs.o: subsegs.c subsegs.h $(INCDIR)/obstack.h symbols.o: symbols.c $(INCDIR)/obstack.h subsegs.h write.o: write.c subsegs.h $(INCDIR)/obstack.h output-file.h gasp.o: gasp.c sb.h macro.h +itbl-ops.o: itbl-ops.c itbl-ops.h e-i386coff.o: $(srcdir)/config/e-i386coff.c emul.h \ emul-target.h e-i386elf.o: $(srcdir)/config/e-i386elf.c emul.h emul-target.h diff --git a/gas/NEWS b/gas/NEWS index 63b869ddc6b..2542e2e0184 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,16 @@ -*- text -*- +Changes in 2.9: + +Texas Instruction c30 (tms320c30) support added. + +Added --gstabs option to generates stabs debugging information. + +The -a option takes a new suboption, m (e.g., -alm) to expand macros in a +listing. + +Added -MD option to print dependencies. + Changes in 2.8: BeOS support added. @@ -22,6 +33,9 @@ The ELF assembler has a new pseudo-op, .symver, used for symbol versioning. The -a option takes a new suboption, c (e.g., -alc), to skip false conditionals in listings. +Added new pseudo-op, .equiv; it's like .equ, except that it is an error if the +symbol is already defined. + Changes in 2.7: The PowerPC assembler now allows the use of symbolic register names (r0, etc.) diff --git a/gas/config/.Sanitize b/gas/config/.Sanitize index 6be825169f2..5e44569c857 100644 --- a/gas/config/.Sanitize +++ b/gas/config/.Sanitize @@ -135,6 +135,8 @@ tc-sparc.c tc-sparc.h tc-tahoe.c tc-tahoe.h +tc-tic30.c +tc-tic30.h tc-v850.c tc-v850.h tc-vax.c diff --git a/gas/config/tc-tic30.c b/gas/config/tc-tic30.c new file mode 100644 index 00000000000..f78c6f81fe1 --- /dev/null +++ b/gas/config/tc-tic30.c @@ -0,0 +1,1909 @@ +/* tc-c30.c -- Assembly code for the Texas Instruments TMS320C30 + Copyright (C) 1998 Free Software Foundation. + Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* + Texas Instruments TMS320C30 machine specific gas. + Written by Steven Haworth (steve@pm.cse.rmit.edu.au). + Bugs & suggestions are completely welcome. This is free software. + Please help us make it better. + */ + +#include "as.h" +#include "opcode/tic30.h" + +/* put here all non-digit non-letter charcters that may occur in an operand */ +static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]"; +static char *ordinal_names[] = +{"first", "second", "third", "fourth", "fifth"}; + +const int md_reloc_size = 0; +int md_long_jump_size = 0; +int md_short_jump_size = 0; + +const char comment_chars[] = ";"; +const char line_comment_chars[] = "*"; +const char line_separator_chars[] = ""; + +const char *md_shortopts = ""; +struct option md_longopts[] = +{ + {NULL, no_argument, NULL, 0} +}; + +size_t md_longopts_size = sizeof (md_longopts); + +/* Chars that mean this number is a floating point constant */ +/* As in 0f12.456 */ +/* or 0d1.2345e12 */ +const char FLT_CHARS[] = "fFdDxX"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +const char EXP_CHARS[] = "eE"; + +/* tables for lexical analysis */ +static char opcode_chars[256]; +static char register_chars[256]; +static char operand_chars[256]; +static char space_chars[256]; +static char identifier_chars[256]; +static char digit_chars[256]; + +/* lexical macros */ +#define is_opcode_char(x) (opcode_chars[(unsigned char) x]) +#define is_operand_char(x) (operand_chars[(unsigned char) x]) +#define is_register_char(x) (register_chars[(unsigned char) x]) +#define is_space_char(x) (space_chars[(unsigned char) x]) +#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) +#define is_digit_char(x) (digit_chars[(unsigned char) x]) + +const pseudo_typeS md_pseudo_table[] = +{ + {0, 0, 0} +}; + +#undef USE_STDOUT +#define USE_STDOUT 1 + +#ifdef USE_STDARG + +#include + +int +debug (const char *string,...) +{ + if (flag_debug) + { + va_list argptr; + char str[100]; + + va_start (argptr, string); + vsprintf (str, string, argptr); + if (str[0] == '\0') + return (0); + va_end (argptr); + fputs (str, USE_STDOUT ? stdout : stderr); + return strlen (str); + } + else + return 0; +} +#else +int +debug (string, va_alist) + const char *string; + va_dcl +{ + if (flag_debug) + { + va_list argptr; + char str[100]; + int cnt; + + va_start (argptr, string); + cnt = vsprintf (str, string, argptr); + if (str[0] == NULL) + return (0); + va_end (argptr); + fputs (str, USE_STDOUT ? stdout : stderr); + return (cnt); + } + else + return 0; +} +#endif + +/* hash table for opcode lookup */ +static struct hash_control *op_hash; +/* hash table for parallel opcode lookup */ +static struct hash_control *parop_hash; +/* hash table for register lookup */ +static struct hash_control *reg_hash; +/* hash table for indirect addressing lookup */ +static struct hash_control *ind_hash; + +void +md_begin () +{ + const char *hash_err; + debug ("In md_begin()\n"); + op_hash = hash_new (); + { + const template *current_optab = tic30_optab; + for (; current_optab < tic30_optab_end; current_optab++) + { + hash_err = hash_insert (op_hash, current_optab->name, (char *) current_optab); + if (hash_err) + as_fatal ("Internal Error: Can't Hash %s: %s", current_optab->name, hash_err); + } + } + parop_hash = hash_new (); + { + const partemplate *current_parop = tic30_paroptab; + for (; current_parop < tic30_paroptab_end; current_parop++) + { + hash_err = hash_insert (parop_hash, current_parop->name, (char *) current_parop); + if (hash_err) + as_fatal ("Internal Error: Can't Hash %s: %s", current_parop->name, hash_err); + } + } + reg_hash = hash_new (); + { + const reg *current_reg = tic30_regtab; + for (; current_reg < tic30_regtab_end; current_reg++) + { + hash_err = hash_insert (reg_hash, current_reg->name, (char *) current_reg); + if (hash_err) + as_fatal ("Internal Error: Can't Hash %s: %s", current_reg->name, hash_err); + } + } + ind_hash = hash_new (); + { + const ind_addr_type *current_ind = tic30_indaddr_tab; + for (; current_ind < tic30_indaddrtab_end; current_ind++) + { + hash_err = hash_insert (ind_hash, current_ind->syntax, (char *) current_ind); + if (hash_err) + as_fatal ("Internal Error: Can't Hash %s: %s", current_ind->syntax, hash_err); + } + } + /* fill in lexical tables: opcode_chars, operand_chars, space_chars */ + { + register int c; + register char *p; + + for (c = 0; c < 256; c++) + { + if (islower (c) || isdigit (c)) + { + opcode_chars[c] = c; + register_chars[c] = c; + } + else if (isupper (c)) + { + opcode_chars[c] = tolower (c); + register_chars[c] = opcode_chars[c]; + } + else if (c == ')' || c == '(') + { + register_chars[c] = c; + } + if (isupper (c) || islower (c) || isdigit (c)) + operand_chars[c] = c; + if (isdigit (c) || c == '-') + digit_chars[c] = c; + if (isalpha (c) || c == '_' || c == '.' || isdigit (c)) + identifier_chars[c] = c; + if (c == ' ' || c == '\t') + space_chars[c] = c; + if (c == '_') + opcode_chars[c] = c; + } + for (p = operand_special_chars; *p != '\0'; p++) + operand_chars[(unsigned char) *p] = *p; + } +} + +/* Address Mode OR values */ +#define AM_Register 0x00000000 +#define AM_Direct 0x00200000 +#define AM_Indirect 0x00400000 +#define AM_Immediate 0x00600000 +#define AM_NotReq 0xFFFFFFFF + +/* PC Relative OR values */ +#define PC_Register 0x00000000 +#define PC_Relative 0x02000000 + +typedef struct +{ + unsigned op_type; + struct + { + int resolved; + unsigned address; + char *label; + expressionS direct_expr; + } + direct; + struct + { + unsigned mod; + int ARnum; + unsigned char disp; + } + indirect; + struct + { + unsigned opcode; + } + reg; + struct + { + int resolved; + int decimal_found; + float f_number; + int s_number; + unsigned int u_number; + char *label; + expressionS imm_expr; + } + immediate; +} +operand; + +int tic30_parallel_insn PARAMS ((char *)); +operand *tic30_operand PARAMS ((char *)); +char *tic30_find_parallel_insn PARAMS ((char *, char *)); + +template *opcode; + +struct tic30_insn + { + template *tm; /* Template of current instruction */ + unsigned opcode; /* Final opcode */ + int operands; /* Number of given operands */ + /* Type of operand given in instruction */ + operand *operand_type[MAX_OPERANDS]; + unsigned addressing_mode; /* Final addressing mode of instruction */ + }; + +struct tic30_insn insn; +static int found_parallel_insn; + +void +md_assemble (line) + char *line; +{ + template *opcode; + char *current_posn; + char *token_start; + char save_char; + int count; + + debug ("In md_assemble() with argument %s\n", line); + memset (&insn, '\0', sizeof (insn)); + if (found_parallel_insn) + { + debug ("Line is second part of parallel instruction\n\n"); + found_parallel_insn = 0; + return; + } + if ((current_posn = tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL) + current_posn = line; + else + found_parallel_insn = 1; + while (is_space_char (*current_posn)) + current_posn++; + token_start = current_posn; + if (!is_opcode_char (*current_posn)) + { + as_bad ("Invalid character %s in opcode", output_invalid (*current_posn)); + return; + } + /* Check if instruction is a parallel instruction by seeing if the first + character is a q. */ + if (*token_start == 'q') + { + if (tic30_parallel_insn (token_start)) + { + if (found_parallel_insn) + free (token_start); + return; + } + } + while (is_opcode_char (*current_posn)) + current_posn++; + { /* Find instruction */ + save_char = *current_posn; + *current_posn = '\0'; + opcode = (template *) hash_find (op_hash, token_start); + if (opcode) + { + debug ("Found instruction %s\n", opcode->name); + insn.tm = opcode; + } + else + { + debug ("Didn't find insn\n"); + as_bad ("Unknown TMS320C30 instruction: %s", token_start); + return; + } + *current_posn = save_char; + } + if (*current_posn != END_OF_INSN) + { /* Find operands */ + int paren_not_balanced; + int expecting_operand = 0; + int this_operand; + do + { + /* skip optional white space before operand */ + while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN) + { + if (!is_space_char (*current_posn)) + { + as_bad ("Invalid character %s before %s operand", + output_invalid (*current_posn), + ordinal_names[insn.operands]); + return; + } + current_posn++; + } + token_start = current_posn; /* after white space */ + paren_not_balanced = 0; + while (paren_not_balanced || *current_posn != ',') + { + if (*current_posn == END_OF_INSN) + { + if (paren_not_balanced) + { + as_bad ("Unbalanced parenthesis in %s operand.", + ordinal_names[insn.operands]); + return; + } + else + break; /* we are done */ + } + else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn)) + { + as_bad ("Invalid character %s in %s operand", + output_invalid (*current_posn), + ordinal_names[insn.operands]); + return; + } + if (*current_posn == '(') + ++paren_not_balanced; + if (*current_posn == ')') + --paren_not_balanced; + current_posn++; + } + if (current_posn != token_start) + { /* yes, we've read in another operand */ + this_operand = insn.operands++; + if (insn.operands > MAX_OPERANDS) + { + as_bad ("Spurious operands; (%d operands/instruction max)", + MAX_OPERANDS); + return; + } + /* now parse operand adding info to 'insn' as we go along */ + save_char = *current_posn; + *current_posn = '\0'; + insn.operand_type[this_operand] = tic30_operand (token_start); + *current_posn = save_char; + if (insn.operand_type[this_operand] == NULL) + return; + } + else + { + if (expecting_operand) + { + as_bad ("Expecting operand after ','; got nothing"); + return; + } + if (*current_posn == ',') + { + as_bad ("Expecting operand before ','; got nothing"); + return; + } + } + /* now *current_posn must be either ',' or END_OF_INSN */ + if (*current_posn == ',') + { + if (*++current_posn == END_OF_INSN) + { /* just skip it, if it's \n complain */ + as_bad ("Expecting operand after ','; got nothing"); + return; + } + expecting_operand = 1; + } + } + while (*current_posn != END_OF_INSN); /* until we get end of insn */ + } + debug ("Number of operands found: %d\n", insn.operands); + /* Check that number of operands is correct */ + if (insn.operands != insn.tm->operands) + { + int i; + int numops = insn.tm->operands; + /* If operands are not the same, then see if any of the operands are not + required. Then recheck with number of given operands. If they are still not + the same, then give an error, otherwise carry on. */ + for (i = 0; i < insn.tm->operands; i++) + if (insn.tm->operand_types[i] & NotReq) + numops--; + if (insn.operands != numops) + { + as_bad ("Incorrect number of operands given"); + return; + } + } + insn.addressing_mode = AM_NotReq; + for (count = 0; count < insn.operands; count++) + { + if (insn.operand_type[count]->op_type & insn.tm->operand_types[count]) + { + debug ("Operand %d matches\n", count + 1); + /* If instruction has two operands and has an AddressMode modifier then set + addressing mode type for instruction */ + if (insn.tm->opcode_modifier == AddressMode) + { + int addr_insn = 0; + /* Store instruction uses the second operand for the address mode. */ + if ((insn.tm->operand_types[1] & (Indirect | Direct)) == (Indirect | Direct)) + addr_insn = 1; + if (insn.operand_type[addr_insn]->op_type & (AllReg)) + insn.addressing_mode = AM_Register; + else if (insn.operand_type[addr_insn]->op_type & Direct) + insn.addressing_mode = AM_Direct; + else if (insn.operand_type[addr_insn]->op_type & Indirect) + insn.addressing_mode = AM_Indirect; + else + insn.addressing_mode = AM_Immediate; + } + } + else + { + as_bad ("The %s operand doesn't match", ordinal_names[count]); + return; + } + } + /* Now set the addressing mode for 3 operand instructions. */ + if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2)) + { + /* Set the addressing mode to the values used for 2 operand instructions in the + G addressing field of the opcode. */ + char *p; + switch (insn.operand_type[0]->op_type) + { + case Rn: + case ARn: + case DPReg: + case OtherReg: + if (insn.operand_type[1]->op_type & (AllReg)) + insn.addressing_mode = AM_Register; + else if (insn.operand_type[1]->op_type & Indirect) + insn.addressing_mode = AM_Direct; + else + { + /* Shouldn't make it to this stage */ + as_bad ("Incompatible first and second operands in instruction"); + return; + } + break; + case Indirect: + if (insn.operand_type[1]->op_type & (AllReg)) + insn.addressing_mode = AM_Indirect; + else if (insn.operand_type[1]->op_type & Indirect) + insn.addressing_mode = AM_Immediate; + else + { + /* Shouldn't make it to this stage */ + as_bad ("Incompatible first and second operands in instruction"); + return; + } + break; + } + /* Now make up the opcode for the 3 operand instructions. As in parallel + instructions, there will be no unresolved values, so they can be fully formed + and added to the frag table. */ + insn.opcode = insn.tm->base_opcode; + if (insn.operand_type[0]->op_type & Indirect) + { + insn.opcode |= (insn.operand_type[0]->indirect.ARnum); + insn.opcode |= (insn.operand_type[0]->indirect.mod << 3); + } + else + insn.opcode |= (insn.operand_type[0]->reg.opcode); + if (insn.operand_type[1]->op_type & Indirect) + { + insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8); + insn.opcode |= (insn.operand_type[1]->indirect.mod << 11); + } + else + insn.opcode |= (insn.operand_type[1]->reg.opcode << 8); + if (insn.operands == 3) + insn.opcode |= (insn.operand_type[2]->reg.opcode << 16); + insn.opcode |= insn.addressing_mode; + p = frag_more (INSN_SIZE); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { /* Not a three operand instruction */ + char *p; + int am_insn = -1; + insn.opcode = insn.tm->base_opcode; + /* Create frag for instruction - all instructions are 4 bytes long. */ + p = frag_more (INSN_SIZE); + if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode)) + { + insn.opcode |= insn.addressing_mode; + if (insn.addressing_mode == AM_Indirect) + { + /* Determine which operand gives the addressing mode */ + if (insn.operand_type[0]->op_type & Indirect) + am_insn = 0; + if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect)) + am_insn = 1; + insn.opcode |= (insn.operand_type[am_insn]->indirect.disp); + insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8); + insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11); + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.addressing_mode == AM_Register) + { + insn.opcode |= (insn.operand_type[0]->reg.opcode); + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.addressing_mode == AM_Direct) + { + if (insn.operand_type[0]->op_type & Direct) + am_insn = 0; + if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct)) + am_insn = 1; + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); + if (insn.operand_type[am_insn]->direct.resolved == 1) + { + /* Resolved values can be placed straight into instruction word, and output */ + insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { /* Unresolved direct addressing mode instruction */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0); + } + } + else if (insn.addressing_mode == AM_Immediate) + { + if (insn.operand_type[0]->immediate.resolved == 1) + { + char *keeploc; + int size; + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); + switch (insn.tm->imm_arg_type) + { + case Imm_Float: + debug ("Floating point first operand\n"); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + keeploc = input_line_pointer; + input_line_pointer = insn.operand_type[0]->immediate.label; + if (md_atof ('f', p + 2, &size) != 0) + { + as_bad ("invalid short form floating point immediate operand"); + return; + } + input_line_pointer = keeploc; + break; + case Imm_UInt: + debug ("Unsigned int first operand\n"); + if (insn.operand_type[0]->immediate.decimal_found) + as_warn ("rounding down first operand float to unsigned int"); + if (insn.operand_type[0]->immediate.u_number > 0xFFFF) + as_warn ("only lower 16-bits of first operand are used"); + insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + break; + case Imm_SInt: + debug ("Int first operand\n"); + if (insn.operand_type[0]->immediate.decimal_found) + as_warn ("rounding down first operand float to signed int"); + if (insn.operand_type[0]->immediate.s_number < -32768 || + insn.operand_type[0]->immediate.s_number > 32767) + { + as_bad ("first operand is too large for 16-bit signed int"); + return; + } + insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + break; + } + } + else + { /* Unresolved immediate label */ + if (insn.operands > 1) + insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0); + } + } + } + else if (insn.tm->opcode_modifier == PCRel) + { + /* Conditional Branch and Call instructions */ + if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp)) + { + if (insn.operand_type[0]->op_type & (AllReg)) + { + insn.opcode |= (insn.operand_type[0]->reg.opcode); + insn.opcode |= PC_Register; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + insn.opcode |= PC_Relative; + if (insn.operand_type[0]->immediate.resolved == 1) + { + insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0); + } + } + } + else if ((insn.tm->operand_types[0] & ARn) == ARn) + { + /* Decrement and Branch instructions */ + insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22); + if (insn.operand_type[1]->op_type & (AllReg)) + { + insn.opcode |= (insn.operand_type[1]->reg.opcode); + insn.opcode |= PC_Register; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.operand_type[1]->immediate.resolved == 1) + { + if (insn.operand_type[0]->immediate.decimal_found) + { + as_bad ("first operand is floating point"); + return; + } + if (insn.operand_type[0]->immediate.s_number < -32768 || + insn.operand_type[0]->immediate.s_number > 32767) + { + as_bad ("first operand is too large for 16-bit signed int"); + return; + } + insn.opcode |= (insn.operand_type[1]->immediate.s_number); + insn.opcode |= PC_Relative; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + insn.opcode |= PC_Relative; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0); + } + } + } + else if (insn.tm->operand_types[0] == IVector) + { + /* Trap instructions */ + if (insn.operand_type[0]->op_type & IVector) + insn.opcode |= (insn.operand_type[0]->immediate.u_number); + else + { /* Shouldn't get here */ + as_bad ("interrupt vector for trap instruction out of range"); + return; + } + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate) + { + /* Push, Pop and Rotate instructions */ + insn.opcode |= (insn.operand_type[0]->reg.opcode << 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct)) + { + /* LDP Instruction needs to be tested for before the next section */ + if (insn.operand_type[0]->op_type & Direct) + { + if (insn.operand_type[0]->direct.resolved == 1) + { + /* Direct addressing uses lower 8 bits of direct address */ + insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + fixS *fix; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0); + /* Ensure that the assembler doesn't complain about fitting a 24-bit + address into 8 bits. */ + fix->fx_no_overflow = 1; + } + } + else + { + if (insn.operand_type[0]->immediate.resolved == 1) + { + /* Immediate addressing uses upper 8 bits of address */ + if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) + { + as_bad ("LDP instruction needs a 24-bit operand"); + return; + } + insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + fixS *fix; + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->immediate.imm_expr, 0, 0); + fix->fx_no_overflow = 1; + } + } + } + else if (insn.tm->operand_types[0] & (Imm24)) + { + /* Unconditional Branch and Call instructions */ + if (insn.operand_type[0]->immediate.resolved == 1) + { + if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) + as_warn ("first operand is too large for a 24-bit displacement"); + insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF); + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else + { + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0); + } + } + else if (insn.tm->operand_types[0] & NotReq) + { + /* Check for NOP instruction without arguments. */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + else if (insn.tm->operands == 0) + { + /* Check for instructions without operands. */ + md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); + } + } + debug ("Addressing mode: %08X\n", insn.addressing_mode); + { + int i; + for (i = 0; i < insn.operands; i++) + { + if (insn.operand_type[i]->immediate.label) + free (insn.operand_type[i]->immediate.label); + free (insn.operand_type[i]); + } + } + debug ("Final opcode: %08X\n", insn.opcode); + debug ("\n"); +} + +struct tic30_par_insn +{ + partemplate *tm; /* Template of current parallel instruction */ + int operands[2]; /* Number of given operands for each insn */ + /* Type of operand given in instruction */ + operand *operand_type[2][MAX_OPERANDS]; + int swap_operands; /* Whether to swap operands around. */ + unsigned p_field; /* Value of p field in multiply add/sub instructions */ + unsigned opcode; /* Final opcode */ +}; + +struct tic30_par_insn p_insn; + +int +tic30_parallel_insn (char *token) +{ + static partemplate *p_opcode; + char *current_posn = token; + char *token_start; + char save_char; + + debug ("In tic30_parallel_insn with %s\n", token); + memset (&p_insn, '\0', sizeof (p_insn)); + while (is_opcode_char (*current_posn)) + current_posn++; + { /* Find instruction */ + save_char = *current_posn; + *current_posn = '\0'; + p_opcode = (partemplate *) hash_find (parop_hash, token); + if (p_opcode) + { + debug ("Found instruction %s\n", p_opcode->name); + p_insn.tm = p_opcode; + } + else + { + char first_opcode[6] = + {0}; + char second_opcode[6] = + {0}; + int i; + int current_opcode = -1; + int char_ptr = 0; + + for (i = 0; i < strlen (token); i++) + { + char ch = *(token + i); + if (ch == '_' && current_opcode == -1) + { + current_opcode = 0; + continue; + } + if (ch == '_' && current_opcode == 0) + { + current_opcode = 1; + char_ptr = 0; + continue; + } + switch (current_opcode) + { + case 0: + first_opcode[char_ptr++] = ch; + break; + case 1: + second_opcode[char_ptr++] = ch; + break; + } + } + debug ("first_opcode = %s\n", first_opcode); + debug ("second_opcode = %s\n", second_opcode); + sprintf (token, "q_%s_%s", second_opcode, first_opcode); + p_opcode = (partemplate *) hash_find (parop_hash, token); + if (p_opcode) + { + debug ("Found instruction %s\n", p_opcode->name); + p_insn.tm = p_opcode; + p_insn.swap_operands = 1; + } + else + return 0; + } + *current_posn = save_char; + } + { /* Find operands */ + int paren_not_balanced; + int expecting_operand = 0; + int found_separator = 0; + do + { + /* skip optional white space before operand */ + while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN) + { + if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR) + { + as_bad ("Invalid character %s before %s operand", + output_invalid (*current_posn), + ordinal_names[insn.operands]); + return 1; + } + if (*current_posn == PARALLEL_SEPARATOR) + found_separator = 1; + current_posn++; + } + token_start = current_posn; /* after white space */ + paren_not_balanced = 0; + while (paren_not_balanced || *current_posn != ',') + { + if (*current_posn == END_OF_INSN) + { + if (paren_not_balanced) + { + as_bad ("Unbalanced parenthesis in %s operand.", + ordinal_names[insn.operands]); + return 1; + } + else + break; /* we are done */ + } + else if (*current_posn == PARALLEL_SEPARATOR) + { + while (is_space_char (*(current_posn - 1))) + current_posn--; + break; + } + else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn)) + { + as_bad ("Invalid character %s in %s operand", + output_invalid (*current_posn), + ordinal_names[insn.operands]); + return 1; + } + if (*current_posn == '(') + ++paren_not_balanced; + if (*current_posn == ')') + --paren_not_balanced; + current_posn++; + } + if (current_posn != token_start) + { /* yes, we've read in another operand */ + p_insn.operands[found_separator]++; + if (p_insn.operands[found_separator] > MAX_OPERANDS) + { + as_bad ("Spurious operands; (%d operands/instruction max)", + MAX_OPERANDS); + return 1; + } + /* now parse operand adding info to 'insn' as we go along */ + save_char = *current_posn; + *current_posn = '\0'; + p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] = + tic30_operand (token_start); + *current_posn = save_char; + if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1]) + return 1; + } + else + { + if (expecting_operand) + { + as_bad ("Expecting operand after ','; got nothing"); + return 1; + } + if (*current_posn == ',') + { + as_bad ("Expecting operand before ','; got nothing"); + return 1; + } + } + /* now *current_posn must be either ',' or END_OF_INSN */ + if (*current_posn == ',') + { + if (*++current_posn == END_OF_INSN) + { /* just skip it, if it's \n complain */ + as_bad ("Expecting operand after ','; got nothing"); + return 1; + } + expecting_operand = 1; + } + } + while (*current_posn != END_OF_INSN); /* until we get end of insn */ + } + if (p_insn.swap_operands) + { + int temp_num, i; + operand *temp_op; + + temp_num = p_insn.operands[0]; + p_insn.operands[0] = p_insn.operands[1]; + p_insn.operands[1] = temp_num; + for (i = 0; i < MAX_OPERANDS; i++) + { + temp_op = p_insn.operand_type[0][i]; + p_insn.operand_type[0][i] = p_insn.operand_type[1][i]; + p_insn.operand_type[1][i] = temp_op; + } + } + if (p_insn.operands[0] != p_insn.tm->operands_1) + { + as_bad ("incorrect number of operands given in the first instruction"); + return 1; + } + if (p_insn.operands[1] != p_insn.tm->operands_2) + { + as_bad ("incorrect number of operands given in the second instruction"); + return 1; + } + debug ("Number of operands in first insn: %d\n", p_insn.operands[0]); + debug ("Number of operands in second insn: %d\n", p_insn.operands[1]); + { /* Now check if operands are correct */ + int count; + int num_rn = 0; + int num_ind = 0; + for (count = 0; count < 2; count++) + { + int i; + for (i = 0; i < p_insn.operands[count]; i++) + { + if ((p_insn.operand_type[count][i]->op_type & + p_insn.tm->operand_types[count][i]) == 0) + { + as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1); + return 1; + } + /* Get number of R register and indirect reference contained within the first + two operands of each instruction. This is required for the multiply + parallel instructions which require two R registers and two indirect + references, but not in any particular place. */ + if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2) + num_rn++; + else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2) + num_ind++; + } + } + if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn)) + { + /* Check for the multiply instructions */ + if (num_rn != 2) + { + as_bad ("incorrect format for multiply parallel instruction"); + return 1; + } + if (num_ind != 2) + { /* Shouldn't get here */ + as_bad ("incorrect format for multiply parallel instruction"); + return 1; + } + if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) && + (p_insn.operand_type[0][2]->reg.opcode != 0x01)) + { + as_bad ("destination for multiply can only be R0 or R1"); + return 1; + } + if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) && + (p_insn.operand_type[1][2]->reg.opcode != 0x03)) + { + as_bad ("destination for add/subtract can only be R2 or R3"); + return 1; + } + /* Now determine the P field for the instruction */ + if (p_insn.operand_type[0][0]->op_type & Indirect) + { + if (p_insn.operand_type[0][1]->op_type & Indirect) + p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn */ + else if (p_insn.operand_type[1][0]->op_type & Indirect) + p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */ + else + p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind */ + } + else + { + if (p_insn.operand_type[0][1]->op_type & Rn) + p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind */ + else if (p_insn.operand_type[1][0]->op_type & Indirect) + { + operand *temp; + p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn */ + /* Need to swap the two multiply operands around so that everything is in + its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */ + temp = p_insn.operand_type[0][0]; + p_insn.operand_type[0][0] = p_insn.operand_type[0][1]; + p_insn.operand_type[0][1] = temp; + } + else + { + operand *temp; + p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind */ + temp = p_insn.operand_type[0][0]; + p_insn.operand_type[0][0] = p_insn.operand_type[0][1]; + p_insn.operand_type[0][1] = temp; + } + } + } + } + debug ("P field: %08X\n", p_insn.p_field); + /* Finalise opcode. This is easier for parallel instructions as they have to be + fully resolved, there are no memory addresses allowed, except through indirect + addressing, so there are no labels to resolve. */ + { + p_insn.opcode = p_insn.tm->base_opcode; + switch (p_insn.tm->oporder) + { + case OO_4op1: + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); + break; + case OO_4op2: + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); + if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode) + as_warn ("loading the same register in parallel operation"); + break; + case OO_4op3: + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22); + break; + case OO_5op1: + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); + p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); + break; + case OO_5op2: + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); + p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); + break; + case OO_PField: + p_insn.opcode |= p_insn.p_field; + if (p_insn.operand_type[0][2]->reg.opcode == 0x01) + p_insn.opcode |= 0x00800000; + if (p_insn.operand_type[1][2]->reg.opcode == 0x03) + p_insn.opcode |= 0x00400000; + switch (p_insn.p_field) + { + case 0x00000000: + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19); + break; + case 0x01000000: + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); + break; + case 0x02000000: + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); + break; + case 0x03000000: + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); + p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); + p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); + p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); + p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); + break; + } + break; + } + } /* Opcode is finalised at this point for all parallel instructions. */ + { /* Output opcode */ + char *p; + p = frag_more (INSN_SIZE); + md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE); + } + { + int i, j; + for (i = 0; i < 2; i++) + for (j = 0; j < p_insn.operands[i]; j++) + free (p_insn.operand_type[i][j]); + } + debug ("Final opcode: %08X\n", p_insn.opcode); + debug ("\n"); + return 1; +} + +operand * +tic30_operand (token) + char *token; +{ + int count; + char ind_buffer[strlen (token)]; + operand *current_op; + + debug ("In tic30_operand with %s\n", token); + current_op = (operand *) malloc (sizeof (operand)); + memset (current_op, '\0', sizeof (operand)); + if (*token == DIRECT_REFERENCE) + { + char *token_posn = token + 1; + int direct_label = 0; + debug ("Found direct reference\n"); + while (*token_posn) + { + if (!is_digit_char (*token_posn)) + direct_label = 1; + token_posn++; + } + if (direct_label) + { + char *save_input_line_pointer; + segT retval; + debug ("Direct reference is a label\n"); + current_op->direct.label = token + 1; + save_input_line_pointer = input_line_pointer; + input_line_pointer = token + 1; + debug ("Current input_line_pointer: %s\n", input_line_pointer); + retval = expression (¤t_op->direct.direct_expr); + debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op); + debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number); + debug ("Segment: %d\n", retval); + input_line_pointer = save_input_line_pointer; + if (current_op->direct.direct_expr.X_op == O_constant) + { + current_op->direct.address = current_op->direct.direct_expr.X_add_number; + current_op->direct.resolved = 1; + } + } + else + { + debug ("Direct reference is a number\n"); + current_op->direct.address = atoi (token + 1); + current_op->direct.resolved = 1; + } + current_op->op_type = Direct; + } + else if (*token == INDIRECT_REFERENCE) + { /* Indirect reference operand */ + int found_ar = 0; + int found_disp = 0; + int ar_number = -1; + int disp_number = 0; + int buffer_posn = 1; + ind_addr_type *ind_addr_op; + debug ("Found indirect reference\n"); + ind_buffer[0] = *token; + for (count = 1; count < strlen (token); count++) + { /* Strip operand */ + ind_buffer[buffer_posn] = tolower (*(token + count)); + if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') && + (*(token + count) == 'r' || *(token + count) == 'R')) + { + /* AR reference is found, so get its number and remove it from the buffer + so it can pass through hash_find() */ + if (found_ar) + { + as_bad ("More than one AR register found in indirect reference"); + return NULL; + } + if (*(token + count + 1) < '0' || *(token + count + 1) > '7') + { + as_bad ("Illegal AR register in indirect reference"); + return NULL; + } + ar_number = *(token + count + 1) - '0'; + found_ar = 1; + count++; + } + if (*(token + count) == '(') + { + /* Parenthesis found, so check if a displacement value is inside. If so, get + the value and remove it from the buffer. */ + if (is_digit_char (*(token + count + 1))) + { + char disp[10]; + int disp_posn = 0; + + if (found_disp) + { + as_bad ("More than one displacement found in indirect reference"); + return NULL; + } + count++; + while (*(token + count) != ')') + { + if (!is_digit_char (*(token + count))) + { + as_bad ("Invalid displacement in indirect reference"); + return NULL; + } + disp[disp_posn++] = *(token + (count++)); + } + disp[disp_posn] = '\0'; + disp_number = atoi (disp); + count--; + found_disp = 1; + } + } + buffer_posn++; + } + ind_buffer[buffer_posn] = '\0'; + if (!found_ar) + { + as_bad ("AR register not found in indirect reference"); + return NULL; + } + ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer); + if (ind_addr_op) + { + debug ("Found indirect reference: %s\n", ind_addr_op->syntax); + if (ind_addr_op->displacement == IMPLIED_DISP) + { + found_disp = 1; + disp_number = 1; + } + else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp) + { + /* Maybe an implied displacement of 1 again */ + as_bad ("required displacement wasn't given in indirect reference"); + return 0; + } + } + else + { + as_bad ("illegal indirect reference"); + return NULL; + } + if (found_disp && (disp_number < 0 || disp_number > 255)) + { + as_bad ("displacement must be an unsigned 8-bit number"); + return NULL; + } + current_op->indirect.mod = ind_addr_op->modfield; + current_op->indirect.disp = disp_number; + current_op->indirect.ARnum = ar_number; + current_op->op_type = Indirect; + } + else + { + reg *regop = (reg *) hash_find (reg_hash, token); + if (regop) + { + debug ("Found register operand: %s\n", regop->name); + if (regop->regtype == REG_ARn) + current_op->op_type = ARn; + else if (regop->regtype == REG_Rn) + current_op->op_type = Rn; + else if (regop->regtype == REG_DP) + current_op->op_type = DPReg; + else + current_op->op_type = OtherReg; + current_op->reg.opcode = regop->opcode; + } + else + { + if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h')) + { + char *save_input_line_pointer; + segT retval; + debug ("Probably a label: %s\n", token); + current_op->immediate.label = (char *) malloc (strlen (token) + 1); + strcpy (current_op->immediate.label, token); + current_op->immediate.label[strlen (token)] = '\0'; + save_input_line_pointer = input_line_pointer; + input_line_pointer = token; + debug ("Current input_line_pointer: %s\n", input_line_pointer); + retval = expression (¤t_op->immediate.imm_expr); + debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op); + debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number); + debug ("Segment: %d\n", retval); + input_line_pointer = save_input_line_pointer; + if (current_op->immediate.imm_expr.X_op == O_constant) + { + current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number; + current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number; + current_op->immediate.resolved = 1; + } + } + else + { + unsigned count; + debug ("Found a number or displacement\n"); + for (count = 0; count < strlen (token); count++) + if (*(token + count) == '.') + current_op->immediate.decimal_found = 1; + current_op->immediate.label = (char *) malloc (strlen (token) + 1); + strcpy (current_op->immediate.label, token); + current_op->immediate.label[strlen (token)] = '\0'; + current_op->immediate.f_number = (float) atof (token); + current_op->immediate.s_number = (int) atoi (token); + current_op->immediate.u_number = (unsigned int) atoi (token); + current_op->immediate.resolved = 1; + } + current_op->op_type = Disp | Abs24 | Imm16 | Imm24; + if (current_op->immediate.u_number >= 0 && current_op->immediate.u_number <= 31) + current_op->op_type |= IVector; + } + } + return current_op; +} + +/* next_line points to the next line after the current instruction (current_line). + Search for the parallel bars, and if found, merge two lines into internal syntax + for a parallel instruction: + q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2] + By this stage, all comments are scrubbed, and only the bare lines are given. + */ + +#define NONE 0 +#define START_OPCODE 1 +#define END_OPCODE 2 +#define START_OPERANDS 3 +#define END_OPERANDS 4 + +char * +tic30_find_parallel_insn (current_line, next_line) + char *current_line; + char *next_line; +{ + int found_parallel = 0; + char first_opcode[256]; + char second_opcode[256]; + char first_operands[256]; + char second_operands[256]; + char *parallel_insn; + + debug ("In tic30_find_parallel_insn()\n"); + while (!is_end_of_line[(int) *next_line]) + { + if (*next_line == PARALLEL_SEPARATOR && *(next_line + 1) == PARALLEL_SEPARATOR) + { + found_parallel = 1; + next_line++; + break; + } + next_line++; + } + if (!found_parallel) + return NULL; + debug ("Found a parallel instruction\n"); + { + int i; + char *opcode, *operands, *line; + + for (i = 0; i < 2; i++) + { + if (i == 0) + { + opcode = &first_opcode[0]; + operands = &first_operands[0]; + line = current_line; + } + else + { + opcode = &second_opcode[0]; + operands = &second_operands[0]; + line = next_line; + } + { + int search_status = NONE; + int char_ptr = 0; + char c; + + while (!is_end_of_line[(int) (c = *line)] && *line) + { + if (is_opcode_char (c) && search_status == NONE) + { + opcode[char_ptr++] = tolower (c); + search_status = START_OPCODE; + } + else if (is_opcode_char (c) && search_status == START_OPCODE) + { + opcode[char_ptr++] = tolower (c); + } + else if (!is_opcode_char (c) && search_status == START_OPCODE) + { + opcode[char_ptr] = '\0'; + char_ptr = 0; + search_status = END_OPCODE; + } + else if (is_operand_char (c) && search_status == START_OPERANDS) + { + operands[char_ptr++] = c; + } + if (is_operand_char (c) && search_status == END_OPCODE) + { + operands[char_ptr++] = c; + search_status = START_OPERANDS; + } + line++; + } + if (search_status != START_OPERANDS) + return NULL; + operands[char_ptr] = '\0'; + } + } + } + parallel_insn = (char *) malloc (strlen (first_opcode) + strlen (first_operands) + + strlen (second_opcode) + strlen (second_operands) + 8); + sprintf (parallel_insn, "q_%s_%s %s | %s", first_opcode, second_opcode, first_operands, second_operands); + debug ("parallel insn = %s\n", parallel_insn); + return parallel_insn; +} + +#undef NONE +#undef START_OPCODE +#undef END_OPCODE +#undef START_OPERANDS +#undef END_OPERANDS + +/* In order to get gas to ignore any | chars at the start of a line, + this function returns true if a | is found in a line. */ + +int +tic30_unrecognized_line (c) + int c; +{ + debug ("In tc_unrecognized_line\n"); + return (c == PARALLEL_SEPARATOR); +} + +int +md_estimate_size_before_relax (fragP, segment) + fragS *fragP; + segT segment; +{ + debug ("In md_estimate_size_before_relax()\n"); + return 0; +} + +void +md_convert_frag (abfd, sec, fragP) + bfd *abfd; + segT sec; + register fragS *fragP; +{ + debug ("In md_convert_frag()\n"); +} + +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + debug ("In md_create_short_jump()\n"); +} + +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr, to_addr; + fragS *frag; + symbolS *to_symbol; +{ + debug ("In md_create_long_jump()\n"); +} + +int +md_apply_fix (fixP, valP) + fixS *fixP; + valueT *valP; +{ + valueT value = *valP; + + debug ("In md_apply_fix() with value = %ld\n", (long) value); + debug ("Values in fixP\n"); + debug ("fx_size = %d\n", fixP->fx_size); + debug ("fx_pcrel = %d\n", fixP->fx_pcrel); + debug ("fx_where = %d\n", fixP->fx_where); + debug ("fx_offset = %d\n", (int) fixP->fx_offset); + { + char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; + value /= INSN_SIZE; + if (fixP->fx_size == 1) + { /* Special fix for LDP instruction. */ + value = (value & 0x00FF0000) >> 16; + } + debug ("new value = %ld\n", (long) value); + md_number_to_chars (buf, value, fixP->fx_size); + } + return 1; +} + +int +md_parse_option (c, arg) + int c; + char *arg; +{ + int i; + + debug ("In md_parse_option()\n"); + for (i = 0; i < c; i++) + { + printf ("%c\n", arg[c]); + } + return 0; +} + +void +md_show_usage (stream) + FILE *stream; +{ + debug ("In md_show_usage()\n"); +} + +symbolS * +md_undefined_symbol (name) + char *name; +{ + debug ("In md_undefined_symbol()\n"); + return (symbolS *) 0; +} + +valueT +md_section_align (segment, size) + segT segment; + valueT size; +{ + debug ("In md_section_align() segment = %d and size = %d\n", segment, size); + size = (size + 3) / 4; + size *= 4; + debug ("New size value = %d\n", size); + return size; +} + +long +md_pcrel_from (fixP) + fixS *fixP; +{ + int offset; + + debug ("In md_pcrel_from()\n"); + debug ("fx_where = %d\n", fixP->fx_where); + debug ("fx_size = %d\n", fixP->fx_size); + /* Find the opcode that represents the current instruction in the fr_literal + storage area, and check bit 21. Bit 21 contains whether the current instruction + is a delayed one or not, and then set the offset value appropriately. */ + if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20) + offset = 3; + else + offset = 1; + debug ("offset = %d\n", offset); + /* PC Relative instructions have a format: + displacement = Label - (PC + offset) + This function returns PC + offset where: + fx_where - fx_size = PC + INSN_SIZE * offset = offset number of instructions + */ + return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset); +} + +char * +md_atof (what_statement_type, literalP, sizeP) + int what_statement_type; + char *literalP; + int *sizeP; +{ + int prec; + char *token; + char keepval; + unsigned long value; + /* char *atof_ieee (); */ + float float_value; + debug ("In md_atof()\n"); + debug ("precision = %c\n", what_statement_type); + debug ("literal = %s\n", literalP); + debug ("line = "); + token = input_line_pointer; + while (!is_end_of_line[(unsigned) *input_line_pointer] && (*input_line_pointer) && (*input_line_pointer != ',')) + { + debug ("%c", *input_line_pointer); + input_line_pointer++; + } + keepval = *input_line_pointer; + *input_line_pointer = '\0'; + debug ("\n"); + float_value = (float) atof (token); + *input_line_pointer = keepval; + debug ("float_value = %f\n", float_value); + switch (what_statement_type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + default: + *sizeP = 0; + return "Bad call to MD_ATOF()"; + } + if (float_value == 0.0) + { + value = (prec == 2) ? 0x00008000L : 0x80000000L; + } + else + { + unsigned long exp, sign, mant, tmsfloat; + tmsfloat = *((long *) &float_value); + sign = tmsfloat & 0x80000000; + mant = tmsfloat & 0x007FFFFF; + exp = tmsfloat & 0x7F800000; + exp <<= 1; + if (exp == 0xFF000000) + { + if (mant == 0) + value = 0x7F7FFFFF; + else if (sign == 0) + value = 0x7F7FFFFF; + else + value = 0x7F800000; + } + else + { + exp -= 0x7F000000; + if (sign) + { + mant = mant & 0x007FFFFF; + mant = -mant; + mant = mant & 0x00FFFFFF; + if (mant == 0) + { + mant |= 0x00800000; + exp = (long) exp - 0x01000000; + } + } + tmsfloat = exp | mant; + value = tmsfloat; + } + if (prec == 2) + { + long exp, mant; + + if (tmsfloat == 0x80000000) + { + value = 0x8000; + } + else + { + value = 0; + exp = (tmsfloat & 0xFF000000); + exp >>= 24; + mant = tmsfloat & 0x007FFFFF; + if (tmsfloat & 0x00800000) + { + mant |= 0xFF000000; + mant += 0x00000800; + mant >>= 12; + mant |= 0x00000800; + mant &= 0x0FFF; + if (exp > 7) + value = 0x7800; + } + else + { + mant |= 0x00800000; + mant += 0x00000800; + exp += (mant >> 24); + mant >>= 12; + mant &= 0x07FF; + if (exp > 7) + value = 0x77FF; + } + if (exp < -8) + value = 0x8000; + if (value == 0) + { + mant = (exp << 12) | mant; + value = mant & 0xFFFF; + } + } + } + } + md_number_to_chars (literalP, value, prec); + *sizeP = prec; + return 0; +} + +void +md_number_to_chars (buf, val, n) + char *buf; + valueT val; + int n; +{ + debug ("In md_number_to_chars()\n"); + number_to_chars_bigendian (buf, val, n); + /* number_to_chars_littleendian(buf,val,n); */ +} + +#define F(SZ,PCREL) (((SZ) << 1) + (PCREL)) +#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break + +arelent * +tc_gen_reloc (section, fixP) + asection *section; + fixS *fixP; +{ + arelent *rel; + bfd_reloc_code_real_type code = 0; + + debug ("In tc_gen_reloc()\n"); + debug ("fixP.size = %d\n", fixP->fx_size); + debug ("fixP.pcrel = %d\n", fixP->fx_pcrel); + debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy)); + switch (F (fixP->fx_size, fixP->fx_pcrel)) + { + MAP (1, 0, BFD_RELOC_TIC30_LDP); + MAP (2, 0, BFD_RELOC_16); + MAP (3, 0, BFD_RELOC_24); + MAP (2, 1, BFD_RELOC_16_PCREL); + MAP (4, 0, BFD_RELOC_32); + default: + as_bad ("Can not do %d byte %srelocation", fixP->fx_size, + fixP->fx_pcrel ? "pc-relative " : ""); + } +#undef MAP +#undef F + + rel = (arelent *) xmalloc (sizeof (arelent)); + assert (rel != 0); + rel->sym_ptr_ptr = &fixP->fx_addsy->bsym; + rel->address = fixP->fx_frag->fr_address + fixP->fx_where; + if (fixP->fx_pcrel) + rel->addend = fixP->fx_addnumber; + else + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (stdoutput, code); + if (!rel->howto) + { + const char *name; + name = S_GET_NAME (fixP->fx_addsy); + if (name == NULL) + name = ""; + as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code)); + } + return rel; +} + +void +tc_aout_pre_write_hook () +{ + debug ("In tc_aout_pre_write_hook()\n"); +} + +void +md_operand (expressionP) + expressionS *expressionP; +{ + debug ("In md_operand()\n"); +} + +char output_invalid_buf[8]; + +char * +output_invalid (c) + char c; +{ + if (isprint (c)) + sprintf (output_invalid_buf, "'%c'", c); + else + sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); + return output_invalid_buf; +} diff --git a/gas/config/tc-tic30.h b/gas/config/tc-tic30.h new file mode 100644 index 00000000000..2fb9cb6f31c --- /dev/null +++ b/gas/config/tc-tic30.h @@ -0,0 +1,53 @@ +/* tc-tic30.h -- Header file for tc-tic30.c + Copyright (C) 1998 Free Software Foundation. + Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef _TC_TIC30_H_ +#define _TC_TIC30_H_ + +#define TC_TIC30 1 + +#ifdef OBJ_AOUT +#define TARGET_FORMAT "a.out-tic30" +#endif + +#define TARGET_ARCH bfd_arch_tic30 +#define TARGET_BYTES_BIG_ENDIAN 1 + +char *output_invalid PARAMS ((int c)); + +#define END_OF_INSN '\0' +#define MAX_OPERANDS 6 +#define DIRECT_REFERENCE '@' +#define INDIRECT_REFERENCE '*' +#define PARALLEL_SEPARATOR '|' +#define INSN_SIZE 4 + +/* Define this to 1 if you want the debug output to be on stdout, + otherwise stderr will be used. If stderr is used, there will be a + better synchronisation with the as_bad outputs, but you can't + capture the output. */ +#define USE_STDOUT 0 + +#define tc_unrecognized_line tic30_unrecognized_line + +extern int tic30_unrecognized_line PARAMS ((int)); + +#endif diff --git a/gas/configure b/gas/configure index c0b71835d75..813efca86b8 100755 --- a/gas/configure +++ b/gas/configure @@ -1527,6 +1527,8 @@ EOF sparc-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;; sparc-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;; + tic30-*-*aout*) fmt=aout bfd_gas=yes ;; + tic30-*-*coff*) fmt=coff bfd_gas=yes ;; # start-sanitize-tic80 tic80-*-*) fmt=coff ;; # end-sanitize-tic80 @@ -1585,7 +1587,7 @@ EOF # do we need the opcodes library? case ${cpu_type} in - vax | i386) + vax | i386 | tic30) ;; *) need_opcodes=yes @@ -1967,7 +1969,7 @@ EOF # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1971: checking for $ac_word" >&5 +echo "configure:1973: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1996,7 +1998,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2000: checking for $ac_word" >&5 +echo "configure:2002: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2044,7 +2046,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:2048: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:2050: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -2054,11 +2056,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -2078,12 +2080,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2082: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2084: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:2087: checking whether we are using GNU C" >&5 +echo "configure:2089: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2092,7 +2094,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2096: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2098: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -2107,7 +2109,7 @@ if test $ac_cv_prog_gcc = yes; then ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:2111: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:2113: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2140,7 +2142,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2144: checking for $ac_word" >&5 +echo "configure:2146: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2172,7 +2174,7 @@ test -n "$YACC" || YACC="yacc" # Extract the first word of "flex", so it can be a program name with args. set dummy flex; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2176: checking for $ac_word" >&5 +echo "configure:2178: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2205,7 +2207,7 @@ then *) ac_lib=l ;; esac echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6 -echo "configure:2209: checking for yywrap in -l$ac_lib" >&5 +echo "configure:2211: checking for yywrap in -l$ac_lib" >&5 ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2213,7 +2215,7 @@ else ac_save_LIBS="$LIBS" LIBS="-l$ac_lib $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2230: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2247,7 +2249,7 @@ fi fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:2251: checking how to run the C preprocessor" >&5 +echo "configure:2253: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -2262,13 +2264,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2272: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2274: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -2279,13 +2281,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2289: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2291: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -2308,7 +2310,7 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking lex output file root""... $ac_c" 1>&6 -echo "configure:2312: checking lex output file root" >&5 +echo "configure:2314: checking lex output file root" >&5 if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2329,7 +2331,7 @@ echo "$ac_t""$ac_cv_prog_lex_root" 1>&6 LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6 -echo "configure:2333: checking whether yytext is a pointer" >&5 +echo "configure:2335: checking whether yytext is a pointer" >&5 if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2341,14 +2343,14 @@ echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c ac_save_LIBS="$LIBS" LIBS="$LIBS $LEXLIB" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2354: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_prog_lex_yytext_pointer=yes else @@ -2371,7 +2373,7 @@ fi echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 -echo "configure:2375: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo "configure:2377: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" @@ -2389,19 +2391,19 @@ fi echo $ac_n "checking for Cygwin32 environment""... $ac_c" 1>&6 -echo "configure:2393: checking for Cygwin32 environment" >&5 +echo "configure:2395: checking for Cygwin32 environment" >&5 if eval "test \"`echo '$''{'am_cv_cygwin32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2407: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_cygwin32=yes else @@ -2418,19 +2420,19 @@ echo "$ac_t""$am_cv_cygwin32" 1>&6 CYGWIN32= test "$am_cv_cygwin32" = yes && CYGWIN32=yes echo $ac_n "checking for Mingw32 environment""... $ac_c" 1>&6 -echo "configure:2422: checking for Mingw32 environment" >&5 +echo "configure:2424: checking for Mingw32 environment" >&5 if eval "test \"`echo '$''{'am_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2436: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_mingw32=yes else @@ -2449,7 +2451,7 @@ test "$am_cv_mingw32" = yes && MINGW32=yes echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:2453: checking for executable suffix" >&5 +echo "configure:2455: checking for executable suffix" >&5 if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2478,17 +2480,17 @@ for ac_hdr in string.h stdlib.h memory.h strings.h unistd.h stdarg.h varargs.h e do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2482: checking for $ac_hdr" >&5 +echo "configure:2484: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2492: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2494: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2518,7 +2520,7 @@ done # Put this here so that autoconf's "cross-compiling" message doesn't confuse # people who are not cross-compiling but are compiling cross-assemblers. echo $ac_n "checking whether compiling a cross-assembler""... $ac_c" 1>&6 -echo "configure:2522: checking whether compiling a cross-assembler" >&5 +echo "configure:2524: checking whether compiling a cross-assembler" >&5 if test "${host}" = "${target}"; then cross_gas=no else @@ -2533,19 +2535,19 @@ echo "$ac_t""$cross_gas" 1>&6 # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:2537: checking for working alloca.h" >&5 +echo "configure:2539: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:2549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -2566,12 +2568,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:2570: checking for alloca" >&5 +echo "configure:2572: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -2626,12 +2628,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:2630: checking whether alloca needs Cray hooks" >&5 +echo "configure:2632: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2660: checking for $ac_func" >&5 +echo "configure:2662: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2690: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2711,7 +2713,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2715: checking stack direction for C alloca" >&5 +echo "configure:2717: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2719,7 +2721,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -2760,21 +2762,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:2764: checking for inline" >&5 +echo "configure:2766: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2780: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -2804,12 +2806,12 @@ esac for ac_func in unlink remove do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2808: checking for $ac_func" >&5 +echo "configure:2810: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2861,12 +2863,12 @@ done for ac_func in sbrk do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2865: checking for $ac_func" >&5 +echo "configure:2867: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2918,12 +2920,12 @@ done # enough, but on some of those systems, the assert macro relies on requoting # working properly! echo $ac_n "checking for working assert macro""... $ac_c" 1>&6 -echo "configure:2922: checking for working assert macro" >&5 +echo "configure:2924: checking for working assert macro" >&5 if eval "test \"`echo '$''{'gas_cv_assert_ok'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2939,7 +2941,7 @@ assert (a == b ; return 0; } EOF -if { (eval echo configure:2943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2945: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* gas_cv_assert_ok=yes else @@ -2980,12 +2982,12 @@ gas_test_headers=" " echo $ac_n "checking whether declaration is required for strstr""... $ac_c" 1>&6 -echo "configure:2984: checking whether declaration is required for strstr" >&5 +echo "configure:2986: checking whether declaration is required for strstr" >&5 if eval "test \"`echo '$''{'gas_cv_decl_needed_strstr'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3002: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* gas_cv_decl_needed_strstr=no else @@ -3017,12 +3019,12 @@ EOF echo $ac_n "checking whether declaration is required for malloc""... $ac_c" 1>&6 -echo "configure:3021: checking whether declaration is required for malloc" >&5 +echo "configure:3023: checking whether declaration is required for malloc" >&5 if eval "test \"`echo '$''{'gas_cv_decl_needed_malloc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* gas_cv_decl_needed_malloc=no else @@ -3054,12 +3056,12 @@ EOF echo $ac_n "checking whether declaration is required for free""... $ac_c" 1>&6 -echo "configure:3058: checking whether declaration is required for free" >&5 +echo "configure:3060: checking whether declaration is required for free" >&5 if eval "test \"`echo '$''{'gas_cv_decl_needed_free'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3076: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* gas_cv_decl_needed_free=no else @@ -3091,12 +3093,12 @@ EOF echo $ac_n "checking whether declaration is required for sbrk""... $ac_c" 1>&6 -echo "configure:3095: checking whether declaration is required for sbrk" >&5 +echo "configure:3097: checking whether declaration is required for sbrk" >&5 if eval "test \"`echo '$''{'gas_cv_decl_needed_sbrk'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* gas_cv_decl_needed_sbrk=no else @@ -3131,12 +3133,12 @@ EOF # for it? echo $ac_n "checking whether declaration is required for errno""... $ac_c" 1>&6 -echo "configure:3135: checking whether declaration is required for errno" >&5 +echo "configure:3137: checking whether declaration is required for errno" >&5 if eval "test \"`echo '$''{'gas_cv_decl_needed_errno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* gas_cv_decl_needed_errno=no else diff --git a/gas/configure.in b/gas/configure.in index 534fe3ce3b0..2c023e6f8c3 100644 --- a/gas/configure.in +++ b/gas/configure.in @@ -286,6 +286,8 @@ changequote([,])dnl sparc-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;; sparc-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;; + tic30-*-*aout*) fmt=aout bfd_gas=yes ;; + tic30-*-*coff*) fmt=coff bfd_gas=yes ;; # start-sanitize-tic80 tic80-*-*) fmt=coff ;; # end-sanitize-tic80 @@ -344,7 +346,7 @@ changequote([,])dnl # do we need the opcodes library? case ${cpu_type} in - vax | i386) + vax | i386 | tic30) ;; *) need_opcodes=yes