From: MaartenBrock Date: Sun, 29 Oct 2006 16:29:34 +0000 (+0000) Subject: * as/asx8051.dsp: corrected output directories X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=4d083eb86c1055c201f3f82e80b0ff4a7e49cb66;p=fw%2Fsdcc * as/asx8051.dsp: corrected output directories * as/link/hc08: new directory for hc08 linker * as/hc08/aslink.h, as/link/aslink.h, * as/hc08/aslink.mak, as/link/hc08/aslink.mak, * as/hc08/clean.mk, as/link/hc08/clean.mk, * as/hc08/link_hc08.dsp, as/link/hc08/link_hc08.dsp, * as/hc08/lkaomf51.c, as/link/hc08/lkaomf51.c, * as/hc08/lkarea.c, as/link/hc08/lkarea.c, * as/hc08/lkdata.c, as/link/hc08/lkdata.c, * as/hc08/lkelf.c, as/link/hc08/lkelf.c, * as/hc08/lkihx.c, as/link/hc08/lkihx.c, * as/hc08/lklibr.c, as/link/hc08/lklibr.c, * as/hc08/lkmain.c, as/link/hc08/lkmain.c, * as/hc08/lkmem.c, as/link/hc08/lkmem.c, * as/hc08/lkrloc.c, as/link/hc08/lkrloc.c, * as/hc08/lks19.c, as/link/hc08/lks19.c, * as/hc08/Makefile.aslink, as/link/hc08/Makefile.aslink, * as/hc08/Makefile.bcc, as/link/hc08/Makefile.bcc, * as/hc08/Makefile.in, as/link/hc08/Makefile.in, * as/link/hc08/conf.mk, * configure, * configure.in, * Makefile.in, * sdcc.dsw: moved hc08 linker to as/link/hc08 * as/hc08/lkeval.c, as/link/mcs51/lkeval.c, as/link/lkeval.c, * as/hc08/lkhead.c, as/link/mcs51/lkhead.c, as/link/lkhead.c, * as/hc08/lklex.c, as/link/mcs51/lklex.c, as/link/lklex.c, * as/hc08/lklist.c, as/link/mcs51/lklist.c, as/link/lklist.c, * as/hc08/lknoice.c, as/link/mcs51/lknoice.c, as/link/lknoice.c, * as/hc08/lksym.c, as/link/mcs51/lksym.c, as/link/lksym.c, * as/link/mcs51/aslink.dsp, * as/link/mcs51/Makefile.in: factored out the common files * as/hc08/lkstore.c: deleted, use the one already in as/link/ * as/clean.mk: extra cleaning common files * as/link/mcs51/strcmpi.c, as/strcmpi.c: moved * as/link/mcs51/strcmpi.h: deleted, moved protoype to aslink.h * as/mcs51/asm.h: include sdccconf.h or sdcc_vc.h git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4442 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index bafc801c..121a959b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2006-10-29 Maarten Brock + + * as/asx8051.dsp: corrected output directories + * as/link/hc08: new directory for hc08 linker + * as/hc08/aslink.h, as/link/aslink.h, + * as/hc08/aslink.mak, as/link/hc08/aslink.mak, + * as/hc08/clean.mk, as/link/hc08/clean.mk, + * as/hc08/link_hc08.dsp, as/link/hc08/link_hc08.dsp, + * as/hc08/lkaomf51.c, as/link/hc08/lkaomf51.c, + * as/hc08/lkarea.c, as/link/hc08/lkarea.c, + * as/hc08/lkdata.c, as/link/hc08/lkdata.c, + * as/hc08/lkelf.c, as/link/hc08/lkelf.c, + * as/hc08/lkihx.c, as/link/hc08/lkihx.c, + * as/hc08/lklibr.c, as/link/hc08/lklibr.c, + * as/hc08/lkmain.c, as/link/hc08/lkmain.c, + * as/hc08/lkmem.c, as/link/hc08/lkmem.c, + * as/hc08/lkrloc.c, as/link/hc08/lkrloc.c, + * as/hc08/lks19.c, as/link/hc08/lks19.c, + * as/hc08/Makefile.aslink, as/link/hc08/Makefile.aslink, + * as/hc08/Makefile.bcc, as/link/hc08/Makefile.bcc, + * as/hc08/Makefile.in, as/link/hc08/Makefile.in, + * as/link/hc08/conf.mk, + * configure, + * configure.in, + * Makefile.in, + * sdcc.dsw: moved hc08 linker to as/link/hc08 + * as/hc08/lkeval.c, as/link/mcs51/lkeval.c, as/link/lkeval.c, + * as/hc08/lkhead.c, as/link/mcs51/lkhead.c, as/link/lkhead.c, + * as/hc08/lklex.c, as/link/mcs51/lklex.c, as/link/lklex.c, + * as/hc08/lklist.c, as/link/mcs51/lklist.c, as/link/lklist.c, + * as/hc08/lknoice.c, as/link/mcs51/lknoice.c, as/link/lknoice.c, + * as/hc08/lksym.c, as/link/mcs51/lksym.c, as/link/lksym.c, + * as/link/mcs51/aslink.dsp, + * as/link/mcs51/Makefile.in: factored out the common files + * as/hc08/lkstore.c: deleted, use the one already in as/link/ + * as/clean.mk: extra cleaning common files + * as/link/mcs51/strcmpi.c, as/strcmpi.c: moved + * as/link/mcs51/strcmpi.h: deleted, moved protoype to aslink.h + * as/mcs51/asm.h: include sdccconf.h or sdcc_vc.h + 2006-10-29 Raphael Neider * src/pic/ralloc.c (newReg): create aliases for registers with @@ -19,12 +59,12 @@ * device/lib/_putchar.c, device/lib/_getchar.c, device/lib/inituart.c: Removed. - + 2006-10-26 Jesus Calvino-Fraga * device/lib/_putchar.c, device/lib/_getchar.c, device/lib/inituart.c: Initialize uart only if SM0 and SM1 are zero. Also, use flag to turn - on/off CR to CRLF conversion. + on/off CR to CRLF conversion. 2006-10-25 Frieder Ferlemann diff --git a/Makefile.in b/Makefile.in index 54f76486..43da4eac 100644 --- a/Makefile.in +++ b/Makefile.in @@ -21,7 +21,7 @@ SDCC_PACKIHX = support/packihx SDCC_LIBRARIAN = support/librarian ifeq ($(OPT_DISABLE_HC08), 0) -SDCC_ASLINK += as/hc08 +SDCC_ASLINK += as/hc08 as/link/hc08 endif ifeq ($(OPT_DISABLE_MCS51), 0) diff --git a/as/asx8051.dsp b/as/asx8051.dsp index c6683405..f59aa2f4 100644 --- a/as/asx8051.dsp +++ b/as/asx8051.dsp @@ -32,13 +32,13 @@ RSC=rc.exe # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "xa51\Debug" -# PROP BASE Intermediate_Dir "xa51\Debug" +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "xa51\Debug" -# PROP Intermediate_Dir "xa51\Debug" +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /FD /GZ /c @@ -56,14 +56,14 @@ LINK32=link.exe # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "xa51\Release" -# PROP BASE Intermediate_Dir "xa51\Release" +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "xa51\Release" -# PROP Intermediate_Dir "xa51\Release" +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c diff --git a/as/clean.mk b/as/clean.mk index ee9489db..5d9b58fe 100644 --- a/as/clean.mk +++ b/as/clean.mk @@ -1,5 +1,9 @@ clean: $(MAKE) -C z80 clean BUILDDIR=$(BUILDDIR) + rm -f *core *[%~] *.[oa] + rm -f .[a-z]*~ + rm -f *.dep + rm -rf obj distclean: $(MAKE) -C z80 distclean BUILDDIR=$(BUILDDIR) diff --git a/as/hc08/Makefile.aslink b/as/hc08/Makefile.aslink deleted file mode 100644 index 0aebe56e..00000000 --- a/as/hc08/Makefile.aslink +++ /dev/null @@ -1,68 +0,0 @@ -CC=gcc -LEX=flex -YACC=bison -INCROOT=. -CFLAGS=-ggdb -O2 -I $(INCROOT) -TARGETS=$(SDCCDIR)/bin/aslink -ALLOBJECTS= lkmain.o lkhead.o lkarea.o lkdata.o\ - lkeval.o lklex.o lksym.o lkrloc.o\ - lklibr.o lklist.o lkihx.o lks19.o\ - lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o -all:: $(TARGETS) - -clean:: - rm -f $(TARGETS) $(ALLOBJECTS) - -lkmain.o : lkmain.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmain.o lkmain.c - -lkhead.o : lkhead.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkhead.o lkhead.c - -lkarea.o : lkarea.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkarea.o lkarea.c - -lkdata.o : lkdata.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkdata.o lkdata.c - -lkeval.o : lkeval.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkeval.o lkeval.c - -lklex.o : lklex.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklex.o lklex.c - -lksym.o : lksym.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lksym.o lksym.c - -lkrloc.o : lkrloc.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkrloc.o lkrloc.c - -lklibr.o : lklibr.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklibr.o lklibr.c - -lklist.o : lklist.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklist.o lklist.c - -lkihx.o : lkihx.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkihx.o lkihx.c - -lks19.o : lks19.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lks19.o lks19.c - -lkstore.o : lkstore.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkstore.o lkstore.c - -lknoice.o : lknoice.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lknoice.o lknoice.c - -strcmpi.o : strcmpi.c strcmpi.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o strcmpi.o strcmpi.c - -lkmem.o : lkmem.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmem.o lkmem.c - -lkaomf51.o : lkaomf51.c aslink.h - $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkaomf51.o lkaomf51.c - -$(TARGETS): $(ALLOBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALLOBJECTS) diff --git a/as/hc08/Makefile.bcc b/as/hc08/Makefile.bcc index b30978c4..a621c679 100644 --- a/as/hc08/Makefile.bcc +++ b/as/hc08/Makefile.bcc @@ -8,18 +8,9 @@ ASOBJECTS = asmain.obj aslex.obj assym.obj assubr.obj asnoice.obj \ asexpr.obj asdata.obj aslist.obj asout.obj asstore.obj \ h08ext.obj h08pst.obj h08mch.obj h08adr.obj strcmpi.obj -LKOBJECTS = lkmain.obj lkhead.obj lkarea.obj lkdata.obj \ - lkeval.obj lklex.obj lksym.obj lkrloc.obj \ - lklibr.obj lklist.obj lkihx.obj lks19.obj \ - lkstore.obj lknoice.obj lkmem.obj lkaomf51.obj strcmpi.obj - ASX8051 = $(PRJDIR)/bin/asx8051.exe -ASLINK = $(PRJDIR)/bin/aslink.exe -all: $(ASX8051) $(ASLINK) +all: $(ASX8051) $(ASX8051): $(ASOBJECTS) $(CC) $(CFLAGS) -e$@ $(ASOBJECTS) - -$(ASLINK): $(LKOBJECTS) - $(CC) $(CFLAGS) -e$@ $(LKOBJECTS) diff --git a/as/hc08/Makefile.in b/as/hc08/Makefile.in index 799da3d3..d5186282 100644 --- a/as/hc08/Makefile.in +++ b/as/hc08/Makefile.in @@ -42,14 +42,7 @@ ASOBJECTS = asmain.o aslex.o assym.o assubr.o asnoice.o \ m08ext.o m08pst.o m08mch.o m08adr.o strcmpi.o ASSOURCES = $(patsubst %.o,%.c,$(ASOBJECTS)) -LKOBJECTS = lkmain.o lkhead.o lkarea.o lkdata.o \ - lkeval.o lklex.o lksym.o lkrloc.o \ - lklibr.o lklist.o lkihx.o lks19.o lkelf.o \ - lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o -LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS)) - ASHC08 = $(top_builddir)bin/as-hc08$(EXEEXT) -ASLINK = $(top_builddir)bin/link-hc08$(EXEEXT) transform = @program_transform_name@ @@ -60,21 +53,16 @@ all: checkconf $(ASHC08) $(ASLINK) $(ASHC08): $(ASOBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ASOBJECTS) -$(ASLINK): $(LKOBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LKOBJECTS) - # Compiling and installing everything and runing test # --------------------------------------------------- install: all installdirs $(INSTALL) $(ASHC08) `echo $(DESTDIR)$(bindir)/as-hc08$(EXEEXT)|sed '$(transform)'` $(STRIP) `echo $(DESTDIR)$(bindir)/as-hc08$(EXEEXT)|sed '$(transform)'` - $(INSTALL) $(ASLINK) `echo $(DESTDIR)$(bindir)/link-hc08$(EXEEXT)|sed '$(transform)'` - $(STRIP) `echo $(DESTDIR)$(bindir)/link-hc08$(EXEEXT)|sed '$(transform)'` # Deleting all the installed files # -------------------------------- uninstall: - rm -f $(DESTDIR)$(bindir)/as-hc08$(EXEEXT) $(DESTDIR)$(bindir)/link-hc08$(EXEEXT) + rm -f $(DESTDIR)$(bindir)/as-hc08$(EXEEXT) # Performing self-test @@ -97,7 +85,7 @@ installdirs: # --------------------- dep: Makefile.dep -Makefile.dep: $(ASSOURCES) $(LKSOURCES) $(srcdir)/*.h $(top_builddir)*.h $(top_srcdir)/*.h +Makefile.dep: $(ASSOURCES) $(srcdir)/*.h $(top_builddir)*.h $(top_srcdir)/*.h $(CPP) $(CPPFLAGS) $(M_OR_MM) $(filter %.c,$^) >Makefile.dep ifeq "$(findstring $(MAKECMDGOALS),uninstall check installcheck installdirs \ diff --git a/as/hc08/aslink.h b/as/hc08/aslink.h deleted file mode 100644 index a3c0ea79..00000000 --- a/as/hc08/aslink.h +++ /dev/null @@ -1,783 +0,0 @@ -/* aslink.h */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 28-Oct-97 JLH: - * - add proto for StoreString - * - change s_id from [NCPS] to pointer - * - change NCPS to 80 - * - case sensitive - * - add R_J11 for 8051 assembler - * 31-Oct-97 JLH: - * - add jflag and jfp for NoICE output - * 30-Jan-98 JLH: - * - add memory space flags to a_flag for 8051 - */ - -#define VERSION "V01.70 + NoICE + SDCC Feb 1999" - -/* - * Case Sensitivity Flag - */ -#define CASE_SENSITIVE 1 - -/*)Module asmlnk.h - * - * The module asmlnk.h contains the definitions for constants, - * structures, global variables, and LKxxxx functions - * contained in the LKxxxx.c files. - */ - -/*)BUILD - $(PROGRAM) = ASLINK - $(INCLUDE) = ASLINK.H - $(FILES) = { - LKMAIN.C - LKLEX.C - LKAREA.C - LKHEAD.C - LKSYM.C - LKEVAL.C - LKDATA.C - LKLIST.C - LKRLOC.C - LKLIBR.C - LKS19.C - LKIHX.C - } - $(STACK) = 2000 -*/ - -/* DECUS C void definition */ -/* File/extension seperator */ - -#ifdef decus -#define VOID char -#define FSEPX '.' -#endif - -/* PDOS C void definition */ -/* File/extension seperator */ - -#ifdef PDOS -#define VOID char -#define FSEPX ':' -#endif - -/* Default void definition */ -/* File/extension seperator */ - -#ifndef VOID -#define VOID void -#define FSEPX '.' -#define OTHERSYSTEM -#endif - -/* - * PATH_MAX - */ -#include -#ifndef PATH_MAX /* POSIX, but not required */ - #if defined(__BORLANDC__) || defined(_MSC_VER) - #include - #define PATH_MAX _MAX_PATH - #else - #define PATH_MAX 255 /* define a reasonable value */ - #endif -#endif - -/* - * This file defines the format of the - * relocatable binary file. - */ - -#define NCPS 80 /* characters per symbol (JLH: change from 8) */ -#define NDATA 16 /* actual data */ -#define NINPUT PATH_MAX /* Input buffer size */ -#define NHASH 64 /* Buckets in hash table */ -#define HMASK 077 /* Hash mask */ -#define NLPP 60 /* Lines per page */ -#define NTXT 16 /* T values */ - -/* - * The "R_" relocation constants define values used in - * generating the assembler relocation output data for - * areas, symbols, and code. - * - * - * Relocation types. - * - * 7 6 5 4 3 2 1 0 - * +-----+-----+-----+-----+-----+-----+-----+-----+ - * | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT | - * +-----+-----+-----+-----+-----+-----+-----+-----+ - */ - -#define R_WORD 0x00 /* 16 bit */ -#define R_BYTE 0x01 /* 8 bit */ - -#define R_AREA 0x00 /* Base type */ -#define R_SYM 0x02 - -#define R_NORM 0x00 /* PC adjust */ -#define R_PCR 0x04 - -#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */ -#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */ - -#define R_SGND 0x00 /* Signed Byte */ -#define R_USGN 0x10 /* Unsigned Byte */ - -#define R_NOPAG 0x00 /* Page Mode */ -#define R_PAG0 0x20 /* Page '0' */ -#define R_PAG 0x40 /* Page 'nnn' */ - -#define R_LSB 0x00 /* low byte */ -#define R_MSB 0x80 /* high byte */ - -#define R_BYT3 0x100 /* if R_BYTE is set, this is a - * 3 byte address, of which - * the linker must select one byte. - */ -#define R_HIB 0x200 /* If R_BYTE & R_BYT3 are set, linker - * will select byte 3 of the relocated - * 24 bit address. - */ - -#define R_J11 (R_WORD|R_BYT2) /* JLH: 11 bit JMP and CALL (8051) */ -#define R_J19 (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */ -#define R_C24 (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */ -#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB) - -#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19) -#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11) -#define IS_C24(x) (((x) & R_J19_MASK) == R_C24) - -#define R_ESCAPE_MASK 0xf0 /* Used to escape relocation modes - * greater than 0xff in the .rel - * file. - */ - -/* - * Global symbol types. - */ -#define S_REF 1 /* referenced */ -#define S_DEF 2 /* defined */ - -/* - * Area type flags - */ -#define A_CON 0000 /* concatenate */ -#define A_OVR 0004 /* overlay */ -#define A_REL 0000 /* relocatable */ -#define A_ABS 0010 /* absolute */ -#define A_NOPAG 0000 /* non-paged */ -#define A_PAG 0020 /* paged */ - -/* Additional flags for 8051 address spaces */ -#define A_DATA 0000 /* data space (default)*/ -#define A_CODE 0040 /* code space */ -#define A_XDATA 0100 /* external data space */ -#define A_BIT 0200 /* bit addressable space */ - -#define A_NOLOAD 0400 /* nonloadable */ -#define A_LOAD 0000 /* loadable (default) */ - -/* - * File types - */ -#define F_STD 1 /* stdin */ -#define F_LNK 2 /* File.lnk */ -#define F_REL 3 /* File.rel */ - -/* - * General assembler address type - */ -typedef unsigned int Addr_T; - -/* - * The structures of head, area, areax, and sym are created - * as the REL files are read during the first pass of the - * linker. The struct head is created upon encountering a - * H directive in the REL file. The structure contains a - * link to a link file structure (struct lfile) which describes - * the file containing the H directive, the number of data/code - * areas contained in this header segment, the number of - * symbols referenced/defined in this header segment, a pointer - * to an array of pointers to areax structures (struct areax) - * created as each A directive is read, and a pointer to an - * array of pointers to symbol structures (struct sym) for - * all referenced/defined symbols. As H directives are read - * from the REL files a linked list of head structures is - * created by placing a link to the new head structure - * in the previous head structure. - */ -struct head -{ - struct head *h_hp; /* Header link */ - struct lfile *h_lfile;/* Associated file */ - int h_narea; /* # of areas */ - struct areax **a_list; /* Area list */ - int h_nglob; /* # of global symbols */ - struct sym **s_list; /* Globle symbol list */ - char m_id[NCPS]; /* Module name */ -}; - -/* - * A structure area is created for each 'unique' data/code - * area definition found as the REL files are read. The - * struct area contains the name of the area, a flag byte - * which contains the area attributes (REL/CON/OVR/ABS), - * an area subtype (not used in this assembler), and the - * area base address and total size which will be filled - * in at the end of the first pass through the REL files. - * As A directives are read from the REL files a linked - * list of unique area structures is created by placing a - * link to the new area structure in the previous area structure. - */ -struct area -{ - struct area *a_ap; /* Area link */ - struct areax *a_axp; /* Area extension link */ - Addr_T a_addr; /* Beginning address of area */ - Addr_T a_size; /* Total size of the area */ - char a_type; /* Area subtype */ - int a_flag; /* Flag byte */ - char a_id[NCPS]; /* Name */ - char *a_image; - char *a_used; -}; - -/* - * An areax structure is created for every A directive found - * while reading the REL files. The struct areax contains a - * link to the 'unique' area structure referenced by the A - * directive and to the head structure this area segment is - * a part of. The size of this area segment as read from the - * A directive is placed in the areax structure. The beginning - * address of this segment will be filled in at the end of the - * first pass through the REL files. As A directives are read - * from the REL files a linked list of areax structures is - * created for each unique area. The final areax linked - * list has at its head the 'unique' area structure linked - * to the linked areax structures (one areax structure for - * each A directive for this area). - */ -struct areax -{ - struct areax *a_axp; /* Area extension link */ - struct area *a_bap; /* Base area link */ - struct head *a_bhp; /* Base header link */ - Addr_T a_addr; /* Beginning address of section */ - Addr_T a_size; /* Size of the area in section */ -}; - -/* - * A sym structure is created for every unique symbol - * referenced/defined while reading the REL files. The - * struct sym contains the symbol's name, a flag value - * (not used in this linker), a symbol type denoting - * referenced/defined, and an address which is loaded - * with the relative address within the area in which - * the symbol was defined. The sym structure also - * contains a link to the area where the symbol was defined. - * The sym structures are linked into linked lists using - * the symbol link element. - */ -struct sym -{ - struct sym *s_sp; /* Symbol link */ - struct areax *s_axp; /* Symbol area link */ - char s_type; /* Symbol subtype */ - char s_flag; /* Flag byte */ - Addr_T s_addr; /* Address */ - char *s_id; /* Name: JLH change from [NCPS] */ -}; - -/* - * The structure lfile contains a pointer to a - * file specification string, the file type, and - * a link to the next lfile structure. - */ -struct lfile -{ - struct lfile *f_flp; /* lfile link */ - int f_type; /* File type */ - char *f_idp; /* Pointer to file spec */ -}; - -/* - * The struct base contains a pointer to a - * base definition string and a link to the next - * base structure. - */ -struct base -{ - struct base *b_base; /* Base link */ - char *b_strp; /* String pointer */ -}; - -/* - * The struct globl contains a pointer to a - * global definition string and a link to the next - * global structure. - */ -struct globl -{ - struct globl *g_globl; /* Global link */ - char *g_strp; /* String pointer */ -}; - -/* - * A structure sdp is created for each 'unique' paged - * area definition found as the REL files are read. - * As P directives are read from the REL files a linked - * list of unique sdp structures is created by placing a - * link to the new sdp structure in the previous area structure. - */ -struct sdp -{ - struct area *s_area; /* Paged Area link */ - struct areax *s_areax; /* Paged Area Extension Link */ - Addr_T s_addr; /* Page address offset */ -}; - -/* - * The structure rerr is loaded with the information - * required to report an error during the linking - * process. The structure contains an index value - * which selects the areax structure from the header - * areax structure list, a mode value which selects - * symbol or area relocation, the base address in the - * area section, an area/symbol list index value, and - * an area/symbol offset value. - */ -struct rerr -{ - int aindex; /* Linking area */ - int mode; /* Relocation mode */ - Addr_T rtbase; /* Base address in section */ - int rindex; /* Area/Symbol reloaction index */ - Addr_T rval; /* Area/Symbol offset value */ -}; - -/* - * The structure lbpath is created for each library - * path specification input by the -k option. The - * lbpath structures are linked into a list using - * the next link element. - */ -struct lbpath { - struct lbpath *next; - char *path; -}; - -/* - * The structure lbname is created for all combinations of the - * library path specifications (input by the -k option) and the - * library file specifications (input by the -l option) that - * lead to an existing file. The element path points to - * the path string, element libfil points to the library - * file string, and the element libspc is the concatenation - * of the valid path and libfil strings. - * - * The lbpath structures are linked into a list - * using the next link element. - * - * Each library file contains a list of object files - * that are contained in the particular library. e.g.: - * - * \iolib\termio - * \inilib\termio - * - * Only one specification per line is allowed. - */ -struct lbname { - struct lbname *next; - char *path; - char *libfil; - char *libspc; -}; - -/* - * The function fndsym() searches through all combinations of the - * library path specifications (input by the -k option) and the - * library file specifications (input by the -l option) that - * lead to an existing file for a symbol definition. - * - * The structure lbfile is created for the first library - * object file which contains the definition for the - * specified undefined symbol. - * - * The element libspc points to the library file path specification - * and element relfil points to the object file specification string. - * The element filspc is the complete path/file specification for - * the library file to be imported into the linker. The - * file specicifation may be formed in one of two ways: - * - * (1) If the library file contained an absolute - * path/file specification then this becomes filspc. - * (i.e. C:\...) - * - * (2) If the library file contains a relative path/file - * specification then the concatenation of the path - * and this file specification becomes filspc. - * (i.e. \...) - * - * The lbpath structures are linked into a list - * using the next link element. - */ -struct lbfile { - struct lbfile *next; - char *libspc; - char *relfil; - char *filspc; - long offset; /*>=0 if rel file is embedded in a lib file at this offset*/ -}; - -/* - * External Definitions for all Global Variables - */ - -extern char *_abs_; /* = { ". .ABS." }; - */ -extern int lkerr; /* ASLink error flag - */ -extern char *ip; /* pointer into the REL file - * text line in ib[] - */ -extern char ib[NINPUT]; /* REL file text line - */ -extern char *rp; /* pointer into the LST file - * text line in rb[] - */ -extern char rb[NINPUT]; /* LST file text line being - * address relocated - */ -extern unsigned char ctype[]; /* array of character types, one per - * ASCII character - */ - -extern char sdccopt[NINPUT]; -extern char sdccopt_module[NINPUT]; -extern char curr_module[NINPUT]; - -/* - * Character Type Definitions - */ -#define SPACE 0000 -#define ETC 0000 -#define LETTER 0001 -#define DIGIT 0002 -#define BINOP 0004 -#define RAD2 0010 -#define RAD8 0020 -#define RAD10 0040 -#define RAD16 0100 -#define ILL 0200 - -#define DGT2 DIGIT|RAD16|RAD10|RAD8|RAD2 -#define DGT8 DIGIT|RAD16|RAD10|RAD8 -#define DGT10 DIGIT|RAD16|RAD10 -#define LTR16 LETTER|RAD16 - -#if CASE_SENSITIVE -#else -extern char ccase[]; /* an array of characters which - * perform the case translation function - */ -#endif - -extern struct lfile *filep; /* The pointers (lfile *) filep, - * (lfile *) cfp, and (FILE *) sfp - * are used in conjunction with - * the routine as_getline() to read - * asmlnk commands from - * (1) the standard input or - * (2) or a command file - * and to read the REL files - * sequentially as defined by the - * asmlnk input commands. - * - * The pointer *filep points to the - * beginning of a linked list of - * lfile structures. - */ -extern struct lfile *cfp; /* The pointer *cfp points to the - * current lfile structure - */ -extern struct lfile *startp;/* asmlnk startup file structure - */ -extern struct lfile *linkp; /* pointer to first lfile structure - * containing an input REL file - * specification - */ -extern struct lfile *lfp; /* pointer to current lfile structure - * being processed by parse() - */ -extern struct head *headp; /* The pointer to the first - * head structure of a linked list - */ -extern struct head *hp; /* Pointer to the current - * head structure - */ -extern struct area *areap; /* The pointer to the first - * area structure of a linked list - */ -extern struct area *ap; /* Pointer to the current - * area structure - */ -extern struct areax *axp; /* Pointer to the current - * areax structure - */ -extern struct sym *symhash[NHASH]; /* array of pointers to NHASH - * linked symbol lists - */ -extern struct base *basep; /* The pointer to the first - * base structure - */ -extern struct base *bsp; /* Pointer to the current - * base structure - */ -extern struct globl *globlp;/* The pointer to the first - * globl structure - */ -extern struct globl *gsp; /* Pointer to the current - * globl structure - */ -extern struct sdp sdp; /* Base Paged structure - */ -extern struct rerr rerr; /* Structure containing the - * linker error information - */ -extern FILE *ofp; /* Linker Output file handle - */ -extern FILE *mfp; /* Map output file handle - */ -extern FILE *jfp; /* NoICE output file handle - */ -extern FILE *rfp; /* File handle for output - * address relocated ASxxxx - * listing file - */ -extern FILE *sfp; /* The file handle sfp points to the - * currently open file - */ -extern FILE *tfp; /* File handle for input - * ASxxxx listing file - */ -extern FILE *dfp; /* File handle for debug info output - */ -extern int dflag; /* Output debug information flag - */ -extern int oflag; /* Output file type flag - */ -extern int mflag; /* Map output flag - */ -extern int sflag; /* JCF: Memory usage output flag - */ -extern int jflag; /* NoICE output flag - */ -extern int xflag; /* Map file radix type flag - */ -extern int pflag; /* print linker command file flag - */ -extern int uflag; /* Listing relocation flag - */ -extern int rflag; /* Extended linear address record flag. - */ -extern int radix; /* current number conversion radix: - * 2 (binary), 8 (octal), 10 (decimal), - * 16 (hexadecimal) - */ -extern int line; /* current line number - */ -extern int page; /* current page number - */ -extern int lop; /* current line number on page - */ -extern int pass; /* linker pass number - */ -extern int rtcnt; /* count of elements in the - * rtval[] and rtflg[] arrays - */ -extern Addr_T rtval[]; /* data associated with relocation - */ -extern int rtflg[]; /* indicates if rtval[] value is - * to be sent to the output file. - * (always set in this linker) - */ -extern int hilo; /* REL file byte ordering - */ -extern int gline; /* LST file relocation active - * for current line - */ -extern int gcntr; /* LST file relocation active - * counter - */ -extern struct lbpath *lbphead; /* pointer to the first - * library path structure - */ -extern struct lbname *lbnhead; /* pointer to the first - * library name structure - */ -extern struct lbfile *lbfhead; /* pointer to the first - * library file structure - */ -extern Addr_T iram_size; /* internal ram size - */ -extern long xram_size; /* external ram size - */ -extern long code_size; /* code size - */ - - -/* C Library function definitions */ -/* for reference only -extern VOID exit(); -extern int fclose(); -extern char * fgets(); -extern FILE * fopen(); -extern int fprintf(); -extern VOID free(); -extern VOID * malloc(); -extern char putc(); -extern char * strcpy(); -extern int strlen(); -extern char * strncpy(); -*/ - -/* Program function definitions */ - -/* lkmain.c */ -extern FILE * afile(); -extern VOID bassav(); -extern VOID gblsav(); -extern VOID iramsav(); -extern VOID xramsav(); -extern VOID codesav(); -extern VOID iramcheck(); -extern VOID link_main(); -extern VOID lkexit(); -extern int main(); -extern VOID map(); -extern int parse(); -extern VOID setbas(); -extern VOID setgbl(); -extern VOID usage(); -extern VOID copyfile(); - -/* lklex.c */ -extern char endline(); -extern char get(); -extern VOID getfid(); -extern VOID getid(); -extern VOID getSid(); -extern int as_getline(); -extern int getmap(); -extern char getnb(); -extern int more(); -extern VOID skip(); -extern VOID unget(); -extern VOID chop_crlf(); - -/* lkarea.c */ -extern VOID lkparea(); -extern VOID lnkarea(); -extern Addr_T lnksect(struct area *tap); -extern VOID newarea(); - -/* lkhead.c */ -extern VOID module(); -extern VOID newhead(); - -/* lksym.c */ -extern int hash(); -extern struct sym * lkpsym(); -extern VOID * new(); -extern struct sym * newsym(); -extern VOID symdef(); -extern int symeq(); -extern VOID syminit(); -extern VOID symmod(); -extern Addr_T symval(); - -/* lkeval.c */ -extern int digit(); -extern Addr_T eval(); -extern Addr_T expr(); -extern int oprio(); -extern Addr_T term(); - -/* lklist.c */ -extern int dgt(); -extern VOID lkulist(); -extern VOID lkalist(); -extern VOID lkglist(); -extern VOID lstarea(); -extern VOID newpag(); -extern VOID slew(); - -/* lkrloc.c */ -extern Addr_T adb_b(); -extern Addr_T adb_hi(); -extern Addr_T adb_lo(); -extern Addr_T adb_24_hi(Addr_T v, int i); -extern Addr_T adb_24_mid(Addr_T v, int i); -extern Addr_T adb_24_lo(Addr_T v, int i); -extern Addr_T adw_w(); -extern Addr_T adw_24(Addr_T, int); -extern Addr_T adw_hi(); -extern Addr_T adw_lo(); -extern Addr_T evword(); -extern VOID rele(); -extern VOID reloc(); -extern VOID relt(); -extern VOID relr(); -extern VOID relp(); -extern VOID relerr(); -extern char * errmsg[]; -extern VOID errdmp(); -extern VOID relerp(); -extern VOID erpdmp(); -extern VOID prntval(); -extern int lastExtendedAddress; - -/* lklibr.c */ -extern int addfile(); -extern VOID addlib(); -extern VOID addpath(); -extern int fndsym(); -extern VOID library(); -extern VOID loadfile(); -extern VOID search(); - -/* lks19.c */ -extern VOID s19(); - -/* lkihx.c */ -extern VOID ihx(); -extern VOID ihxEntendedLinearAddress(Addr_T); -extern VOID newArea(); - -/* lkstore.c */ -extern char *StoreString( char *str ); - -/* lknoice.c */ -extern void DefineNoICE( char *name, Addr_T value, int page ); - -/* JCF: lkmem.c */ -extern int summary(struct area * xp); - -/* JCF: lkaomf51.c */ -extern void SaveLinkedFilePath(char * filepath); -extern void CreateAOMF51(void); - -/* EEP: lkelf.c */ -extern VOID elf(); diff --git a/as/hc08/aslink.mak b/as/hc08/aslink.mak deleted file mode 100644 index 300803d9..00000000 --- a/as/hc08/aslink.mak +++ /dev/null @@ -1,263 +0,0 @@ -ORIGIN = Symantec C++ -ORIGIN_VER = Version 7.00 -VERSION = RELEASE - -!IFDEF SUB_DEBUG -DEBUG = $(SUB_DEBUG) -NDEBUG = !$(SUB_DEBUG) -!ELSE -DEBUG = 0 -NDEBUG = 1 -!ENDIF - -PROJ = ASLINK -APPTYPE = DOS EXE -PROJTYPE = EXE - -CC = SC -CPP = SPP -MAKE = SMAKE -RC = RCC -HC = HC31 -ASM = SC -DISASM = OBJ2ASM -LNK = LINK -DLLS = - -HEADERS = ..\linksrc\aslink.h - -DEFFILE = ASLINK.DEF - -!IF $(DEBUG) -OUTPUTDIR = . -CREATEOUTPUTDIR = -TARGETDIR = . -CREATETARGETDIR = - -LIBS = - -CFLAGS = -A -Jm -J -ms -o+time -S -2 -a2 -c -LFLAGS = /PACKF -DEFINES = -D_DEBUG=1 -!ELSE -OUTPUTDIR = . -CREATEOUTPUTDIR = -TARGETDIR = . -CREATETARGETDIR = - -LIBS = - -CFLAGS = -A -Jm -J -ms -o+time -S -2 -a2 -c -LFLAGS = /PACKF -DEFINES = -!ENDIF - -HFLAGS = $(CFLAGS) -MFLAGS = MASTERPROJ=$(PROJ) -LIBFLAGS = /C -RESFLAGS = -DEBUGGERFLAGS = -LOADSYMBOLS -AFLAGS = $(CFLAGS) -HELPFLAGS = - -MODEL = S - -PAR = PROJS BATS OBJS - -RCDEFINES = - -LIBDIRS = - -INCLUDES = -Ic:\asxxxx\linksrc - -INCLUDEDOBJS = - -OBJS = $(OUTPUTDIR)\lkarea.OBJ $(OUTPUTDIR)\lkdata.OBJ $(OUTPUTDIR)\lkeval.OBJ \ - $(OUTPUTDIR)\lkhead.OBJ $(OUTPUTDIR)\lkihx.OBJ $(OUTPUTDIR)\lklex.OBJ $(OUTPUTDIR)\lklibr.OBJ \ - $(OUTPUTDIR)\lklist.OBJ $(OUTPUTDIR)\lkmain.OBJ $(OUTPUTDIR)\lkrloc.OBJ $(OUTPUTDIR)\lks19.OBJ \ - $(OUTPUTDIR)\lksym.OBJ - -RCFILES = - -RESFILES = - -SYMS = - -HELPFILES = - -BATS = - -.SUFFIXES: .C .CP .CPP .CXX .CC .H .HPP .HXX .COM .EXE .DLL .LIB .RTF .DLG .ASM .RES .RC .OBJ - -.C.OBJ: - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.c - -.CPP.OBJ: - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cpp - -.CXX.OBJ: - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cxx - -.CC.OBJ: - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cc - -.CP.OBJ: - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cp - -.H.SYM: - $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.h - -.HPP.SYM: - $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hpp - -.HXX.SYM: - $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hxx - -.C.EXP: - $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.c -o$*.lst - -.CPP.EXP: - $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cpp -o$*.lst - -.CXX.EXP: - $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cxx -o$*.lst - -.CP.EXP: - $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cp -o$*.lst - -.CC.EXP: - $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cc -o$*.lst - -.ASM.EXP: - $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.asm -o$*.lst - -.OBJ.COD: - $(DISASM) $*.OBJ >$*.cod - -.OBJ.EXE: - $(LNK) $(LFLAGS) @$(PROJ).LNK - -.RTF.HLP: - $(HC) $(HELPFLAGS) $*.HPJ - -.ASM.OBJ: - $(ASM) $(AFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.asm - -.RC.RES: - $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $*.rc -o$*.res - -.DLG.RES: - echo ^#include "windows.h" >$$$*.rc - echo ^IF EXIST "$*.h" >>$$$*.rc - echo ^#include "$*.h" >>$$$*.rc - echo ^#include "$*.dlg" >>$$$*.rc - $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $$$*.rc - -del $*.res - -ren $$$*.res $*.res - - - -all: createdir $(PRECOMPILE) $(SYMS) $(OBJS) $(INCLUDEDOBJS) $(POSTCOMPILE) $(TARGETDIR)\$(PROJ).$(PROJTYPE) $(POSTLINK) _done - -createdir: - $(CREATEOUTPUTDIR) - $(CREATETARGETDIR) - -$(TARGETDIR)\$(PROJ).$(PROJTYPE): $(OBJS) $(INCLUDEDOBJS) $(RCFILES) $(RESFILES) $(HELPFILES) - $(LNK) $(LFLAGS) @$(PROJ).LNK; - -del $(TARGETDIR)\$(PROJ).$(PROJTYPE) - -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE) - -echo $(TARGETDIR)\$(PROJ).$(PROJTYPE) built - -_done: - -echo $(PROJ).$(PROJTYPE) done - -buildall: clean all - - -clean: - -del $(TARGETDIR)\$$SCW$$.$(PROJTYPE) - -del $(TARGETDIR)\$(PROJ).CLE - -del $(OUTPUTDIR)\SCPH.SYM - -del $(OBJS) - -cleanres: - -res: cleanres $(RCFILES) all - - -link: - $(LNK) $(LFLAGS) @$(PROJ).LNK; - -del $(TARGETDIR)\$(PROJ).$(PROJTYPE) - -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE) - - - - -!IF EXIST (ASLINK.dpd) -!INCLUDE ASLINK.dpd -!ENDIF - - - -$(OUTPUTDIR)\lkarea.OBJ: ..\linksrc\lkarea.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkarea.obj ..\linksrc\lkarea.c - - - -$(OUTPUTDIR)\lkdata.OBJ: ..\linksrc\lkdata.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkdata.obj ..\linksrc\lkdata.c - - - -$(OUTPUTDIR)\lkeval.OBJ: ..\linksrc\lkeval.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkeval.obj ..\linksrc\lkeval.c - - - -$(OUTPUTDIR)\lkhead.OBJ: ..\linksrc\lkhead.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkhead.obj ..\linksrc\lkhead.c - - - -$(OUTPUTDIR)\lkihx.OBJ: ..\linksrc\lkihx.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkihx.obj ..\linksrc\lkihx.c - - - -$(OUTPUTDIR)\lklex.OBJ: ..\linksrc\lklex.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklex.obj ..\linksrc\lklex.c - - - -$(OUTPUTDIR)\lklibr.OBJ: ..\linksrc\lklibr.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklibr.obj ..\linksrc\lklibr.c - - - -$(OUTPUTDIR)\lklist.OBJ: ..\linksrc\lklist.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklist.obj ..\linksrc\lklist.c - - - -$(OUTPUTDIR)\lkmain.OBJ: ..\linksrc\lkmain.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkmain.obj ..\linksrc\lkmain.c - - - -$(OUTPUTDIR)\lkrloc.OBJ: ..\linksrc\lkrloc.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkrloc.obj ..\linksrc\lkrloc.c - - - -$(OUTPUTDIR)\lks19.OBJ: ..\linksrc\lks19.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lks19.obj ..\linksrc\lks19.c - - - -$(OUTPUTDIR)\lksym.OBJ: ..\linksrc\lksym.c - $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lksym.obj ..\linksrc\lksym.c - - - - diff --git a/as/hc08/clean.mk b/as/hc08/clean.mk index 6b47bf1c..44d3d52a 100644 --- a/as/hc08/clean.mk +++ b/as/hc08/clean.mk @@ -5,7 +5,7 @@ include $(top_builddir)Makefile.common clean: rm -f *core *[%~] *.[oa] rm -f .[a-z]*~ - rm -f $(top_builddir)bin/as-hc08$(EXEEXT) $(top_builddir)bin/link-hc08$(EXEEXT) as-hc08$(EXEEXT) link-hc08$(EXEEXT) + rm -f $(top_builddir)bin/as-hc08$(EXEEXT) as-hc08$(EXEEXT) # Deleting all files created by configuring or building the program diff --git a/as/hc08/link_hc08.dsp b/as/hc08/link_hc08.dsp deleted file mode 100644 index fe598cb2..00000000 --- a/as/hc08/link_hc08.dsp +++ /dev/null @@ -1,357 +0,0 @@ -# Microsoft Developer Studio Project File - Name="link_hc08" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=link_hc08 - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "link_hc08.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "link_hc08.mak" CFG="link_hc08 - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "link_hc08 - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "link_hc08 - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "link_hc08___Win32_Release" -# PROP BASE Intermediate_Dir "link_hc08___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\..\bin_vc\link-hc08.exe" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "link_hc08___Win32_Debug" -# PROP BASE Intermediate_Dir "link_hc08___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\bin_vc\link-hc08.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "link_hc08 - Win32 Release" -# Name "link_hc08 - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\lkaomf51.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkarea.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkdata.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkelf.c -# End Source File -# Begin Source File - -SOURCE=.\lkeval.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkhead.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkihx.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lklex.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lklibr.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lklist.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkmain.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkmem.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lknoice.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkrloc.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lks19.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lkstore.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\lksym.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\strcmpi.c - -!IF "$(CFG)" == "link_hc08 - Win32 Release" - -# PROP Intermediate_Dir "Release" - -!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" - -# PROP Intermediate_Dir "Debug" - -!ENDIF - -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/as/hc08/lkaomf51.c b/as/hc08/lkaomf51.c deleted file mode 100644 index f81a96a9..00000000 --- a/as/hc08/lkaomf51.c +++ /dev/null @@ -1,980 +0,0 @@ -/*------------------------------------------------------------------------- - lkaomf51.c - Create an absolute object memory format 51 file - - Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002) - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --------------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include "aslink.h" - -#define EQ(A,B) !strcmp((A),(B)) -#define MEMSIZE 0x10000 -//#define DODUMP 1 - -typedef struct -{ - char PathName[PATH_MAX]; - char ModuleName[PATH_MAX]; -} _infn; - -int numin=0; -_infn * infn=NULL; - -char ihxFileName[PATH_MAX]; -char aomf51FileName[PATH_MAX]; - -typedef struct -{ - char name[0x100]; - int FileNameNumber; - int Procedure;//If the symbol belongs to a function - int Static; //If the symbol is only public on its file - int Address; - int UsageType; -} _symbol; - -int numsym=0; -_symbol * symbol=NULL; - -typedef struct -{ - char name[0x100]; - int FileNameNumber; - int BeginAdd; - int EndAdd; -} _procedure; - -int numproc=0; -_procedure * procedure=NULL; - -typedef struct -{ - int Number; - int Address; - int Procedure; - int FileNameNumber; -} _linenum; - -int numlinenum=0; -_linenum * linenum=NULL; -#if 0 -typedef struct -{ - char * name; - int usage; -} -_UsageType; - -_UsageType UsageType[]= -{ - {"CSEG", 0}, - {"GSINIT", 0}, - {"GSFINAL", 0}, - {"HOME", 0}, - {"XINIT", 0}, - {"XSEG", 1}, - {"XISEG", 1}, - {"REG_BANK_0", 2}, - {"REG_BANK_1", 2}, - {"REG_BANK_2", 2}, - {"REG_BANK_3", 2}, - {"DSEG", 2}, - {"OSEG", 2}, - {"SSEG", 2}, - {"ISEG", 3}, - {"BSEG", 4}, - {"", 5} /*A typeless number?*/ -}; -#endif -char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"}; -int AddNumber; -unsigned char * ihxBuff=NULL; -FILE * aomf51out; -int GlobalChkSum=0; -int HexSize, HexBegin=0x10000; - - -void GetName(char * filepath, char * name) -{ - int j, k; - for(j=strlen(filepath); j>0; j--) - if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break; - for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++) - name[k]=filepath[j]; - name[k]=0; -} - -void SaveLinkedFilePath(char * filepath) -{ - int j; - - if((dflag) && (!rflag)) - { - infn=realloc(infn, sizeof(_infn)*(numin+1)); - - strcpy(infn[numin].PathName, filepath); - j=strlen(infn[numin].PathName); - - /*If there is an extension remove it*/ - if(j>=4) - { - if(EQ(&infn[numin].PathName[j-4], ".rel")) - { - infn[numin].PathName[j-4]=0; - } - } - - /*Get the module name=filename, no drive, no dir, no ext*/ - GetName(infn[numin].PathName, infn[numin].ModuleName); - //printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName); - - /*Check if this filename is already in*/ - for(j=0; j=0)?procedure[symbol[j].Procedure].name:"GLOBAL", - symbol[j].Address, - k<6?UsageTypeName[k]:"???"); - } - - fprintf(DumpFile,"\nPROCEDURES:\n"); - for(j=0; j %s\n", - linenum[j].Number, - linenum[j].Address, - infn[linenum[j].FileNameNumber].PathName, - (linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know"); - } - - fclose(DumpFile); -} -#endif - -void OutputAOEMF51(void) -{ - int i, j, k, recsize; - char MHRname[0x100], Mname[0x100]; - - strcpy(aomf51FileName, infn[0].PathName); - - aomf51out=fopen(aomf51FileName, "wb"); - if(aomf51out==NULL) - { - printf("Couldn't create file %s\n", aomf51FileName); - return; - } - - GetName(infn[0].PathName, MHRname); - GlobalChkSum=0; - - /*Module header record*/ - OutputByte(0x02);/*REC TYPE*/ - OutputWord((strlen(MHRname)+1)+3);/*Record Length*/ - OutputName(MHRname);/*Module Name*/ - OutputByte(0xff);/*TRN ID: RL51?*/ - OutputByte(0x00); - OutputChkSum(); - - for(j=0; j2) /*If there are any symbols*/ - { - OutputByte(0x12); /*REC TYPE*/ - OutputWord(recsize);/*Record Length*/ - OutputByte(0x01); /*DEF TYPE: Public symbols*/ - for(k=0; k2) /*If there are any symbols*/ - { - OutputByte(0x12); /*REC TYPE*/ - OutputWord(recsize);/*Record Length*/ - OutputByte(0x00); /*DEF TYPE: Local symbols*/ - for(k=0; k2) /*If there are any symbols*/ - { - OutputByte(0x12); /*REC TYPE*/ - OutputWord(recsize);/*Record Length*/ - OutputByte(0x00); /*DEF TYPE: Local symbols*/ - for(i=0; i2) /*If there are any line numbers*/ - { - OutputByte(0x12); /*REC TYPE*/ - OutputWord(recsize);/*Record Length*/ - OutputByte(0x03); /*DEF TYPE: Line numbers*/ - for(i=0; i|L}$$$(),
,," - char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s"; - char c; - char scope[0x100]; - char name[0x100]; - char level[0x100]; - char block[0x100]; - char Bfmt[]="%[^)] %c %c %c %c %d %c %d"; - char TypeInfo[0x100]; - char AddressSpace; - int OnStack; - int StackOffset; - int Address, CLine; - - if(numin==0) return; - - if (dfp != NULL) - { - fclose(dfp); - dfp=NULL; - } - - /*Build the source filename*/ - strcpy(SourceName, infn[0].PathName); - strcat(SourceName, ".cdb"); - CDBin=fopen(SourceName, "r"); - if(CDBin==NULL) - { - printf("Couldn't open file '%s'\n", SourceName); - lkexit(1); - } - - CurrentModule=0; /*Set the active module as the first one*/ - while(!feof(CDBin)) - { - fgets(buff, sizeof(buff)-1, CDBin); - - if(!feof(CDBin)) switch(buff[0]) - { - /*Example: "M:adq"*/ - case 'M': - sscanf(&buff[2], "%s", name); - for(j=0; j(),
,,*/ - sscanf(block, Bfmt, - TypeInfo, &c, &c, - &AddressSpace, &c, - &OnStack, &c, - &StackOffset); - - i=-1; k=-1; - switch(scope[2]) - { - case 'G': /*Global symbol*/ - break; - case 'L': /*Local symbol of a procedure*/ - for(j=0; j=procedure[k].BeginAdd) && - (linenum[j].Address<=procedure[k].EndAdd) && - (linenum[j].FileNameNumber==procedure[k].FileNameNumber) ) - { - linenum[j].Procedure=k; - } - } - } - - fclose(CDBin); -} - -int hex2dec (unsigned char hex_digit) -{ - if (isdigit(hex_digit)) - return hex_digit-'0'; - else - return toupper(hex_digit)-'A'+10; -} - -unsigned char GetByte(char * buffer) -{ - return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]); -} - -unsigned short GetWord(char * buffer) -{ - return hex2dec(buffer[0])*0x1000+ - hex2dec(buffer[1])*0x100+ - hex2dec(buffer[2])*0x10+ - hex2dec(buffer[3]); -} - -int ReadHexFile(int * Begin) -{ - char buffer[1024]; - FILE * filein; - int j; - unsigned char linesize, recordtype, rchksum, value; - unsigned short address; - int MaxAddress=0; - int chksum; - - /*If the hexfile is already open, close it*/ - if(ofp!=NULL) - { - fclose(ofp); - ofp=NULL; - } - - strcpy(ihxFileName, infn[0].PathName); - strcat(ihxFileName, ".ihx"); - - if ( (filein=fopen(ihxFileName, "r")) == NULL ) - { - printf("Error: Can't open file `%s`.\r\n", ihxFileName); - return 0; - } - - ihxBuff=calloc(MEMSIZE, sizeof(unsigned char)); - if(ihxBuff==NULL) - { - printf("Insufficient memory\n"); - fclose(filein); - return -1; - } - - for(j=0; j -#include -#include "aslink.h" - -/*)Module lkarea.c - * - * The module lkarea.c contains the functions which - * create and link together all area definitions read - * from the .rel file(s). - * - * lkarea.c contains the following functions: - * VOID lnkarea() - * VOID lnksect() - * VOID lkparea() - * VOID newarea() - * - * lkarea.c contains no global variables. - */ - -/*)Function VOID newarea() - * - * The function newarea() creates and/or modifies area - * and areax structures for each A directive read from - * the .rel file(s). The function lkparea() is called - * to find tha area structure associated with this name. - * If the area does not yet exist then a new area - * structure is created and linked to any existing - * linked area structures. The area flags are copied - * into the area flag variable. For each occurence of - * an A directive an areax structure is created and - * linked to the areax structures associated with this - * area. The size of this area section is placed into - * the areax structure. The flag value for all subsequent - * area definitions for the same area are compared and - * flagged as an error if they are not identical. - * The areax structure created for every occurence of - * an A directive is loaded with a pointer to the base - * area structure and a pointer to the associated - * head structure. And finally, a pointer to this - * areax structure is loaded into the list of areax - * structures in the head structure. Refer to lkdata.c - * for details of the structures and their linkage. - * - * local variables: - * areax **halp pointer to an array of pointers - * int i counter, loop variable, value - * char id[] id string - * int narea number of areas in this head structure - * areax * taxp pointer to an areax structure - * to areax structures - * - * global variables: - * area *ap Pointer to the current - * area structure - * areax *axp Pointer to the current - * areax structure - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * - * functions called: - * Addr_T eval() lkeval.c - * VOID exit() c_library - * int fprintf() c_library - * VOID getid() lklex.c - * VOID lkparea() lkarea.c - * VOID skip() lklex.c - * - * side effects: - * The area and areax structures are created and - * linked with the appropriate head structures. - * Failure to allocate area or areax structure - * space will terminate the linker. Other internal - * errors most likely caused by corrupted .rel - * files will also terminate the linker. - */ - -/* - * Create an area entry. - * - * A xxxxxx size nnnn flags mm - * | | | - * | | `-- ap->a_flag - * | `------------- axp->a_size - * `------------------------- ap->a_id - * - */ -VOID -newarea() -{ - register int i, narea; - struct areax *taxp; - struct areax **halp; - char id[NCPS]; - - /* - * Create Area entry - */ - getid(id, -1); - lkparea(id); - /* - * Evaluate area size - */ - skip(-1); - axp->a_size = eval(); - /* - * Evaluate flags - */ - skip(-1); - i = 0; - taxp = ap->a_axp; - while (taxp->a_axp) { - ++i; - taxp = taxp->a_axp; - } - if (i == 0) { - ap->a_flag = eval(); - } else { - i = eval(); -/* if (i && (ap->a_flag != i)) { */ -/* fprintf(stderr, "Conflicting flags in area %8s\n", id); */ -/* lkerr++; */ -/* } */ - } - /* - * Evaluate area address - */ - skip(-1); - axp->a_addr = eval(); - /* - * Place pointer in header area list - */ - if (headp == NULL) { - fprintf(stderr, "No header defined\n"); - lkexit(1); - } - narea = hp->h_narea; - halp = hp->a_list; - for (i=0; i < narea ;++i) { - if (halp[i] == NULL) { - halp[i] = taxp; - return; - } - } - fprintf(stderr, "Header area list overflow\n"); - lkexit(1); -} - -/*)Function VOID lkparea(id) - * - * char * id pointer to the area name string - * - * The function lkparea() searches the linked area structures - * for a name match. If the name is not found then an area - * structure is created. An areax structure is created and - * appended to the areax structures linked to the area structure. - * The associated base area and head structure pointers are - * loaded into the areax structure. - * - * local variables: - * area * tap pointer to an area structure - * areax * taxp pointer to an areax structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * area *areap The pointer to the first - * area structure of a linked list - * areax *axp Pointer to the current - * areax structure - * - * functions called: - * VOID * new() lksym() - * char * strcpy() c_library - * int symeq() lksym.c - * - * side effects: - * Area and/or areax structures are created. - * Failure to allocate space for created structures - * will terminate the linker. - */ - -VOID -lkparea(char *id) -{ - register struct area *tap; - register struct areax *taxp; - - ap = areap; - axp = (struct areax *) new (sizeof(struct areax)); - while (ap) { - if (symeq(id, ap->a_id)) { - taxp = ap->a_axp; - while (taxp->a_axp) - taxp = taxp->a_axp; - taxp->a_axp = axp; - axp->a_bap = ap; - axp->a_bhp = hp; - return; - } - ap = ap->a_ap; - } - ap = (struct area *) new (sizeof(struct area)); - if (areap == NULL) { - areap = ap; - } else { - tap = areap; - while (tap->a_ap) - tap = tap->a_ap; - tap->a_ap = ap; - } - ap->a_axp = axp; - axp->a_bap = ap; - axp->a_bhp = hp; - strncpy(ap->a_id, id, NCPS); - ap->a_addr = 0; -} - -/*)Function VOID lnkarea() - * - * The function lnkarea() resolves all area addresses. - * The function evaluates each area structure (and all - * the associated areax structures) in sequence. The - * linking process supports four (4) possible area types: - * - * ABS/OVR - All sections (each individual areax - * section) starts at the identical base - * area address overlaying all other - * areax sections for this area. The - * size of the area is largest of the area - * sections. - * - * ABS/CON - All sections (each individual areax - * section) are concatenated with the - * first section starting at the base - * area address. The size of the area - * is the sum of the section sizes. - * - * NOTE: Multiple absolute (ABS) areas are - * never concatenated with each other, - * thus absolute area A and absolute area - * B will overlay each other if they begin - * at the same location (the default is - * always address 0 for absolute areas). - * - * REL/OVR - All sections (each individual areax - * section) starts at the identical base - * area address overlaying all other - * areax sections for this area. The - * size of the area is largest of the area - * sections. - * - * REL/CON - All sections (each individual areax - * section) are concatenated with the - * first section starting at the base - * area address. The size of the area - * is the sum of the section sizes. - * - * NOTE: Relocatable (REL) areas ae always concatenated - * with each other, thus relocatable area B - * (defined after area A) will follow - * relocatable area A independent of the - * starting address of area A. Within a - * specific area each areax section may be - * overlayed or concatenated with other - * areax sections. - * - * - * If a base address for an area is specified then the - * area will start at that address. Any relocatable - * areas defined subsequently will be concatenated to the - * previous relocatable area if it does not have a base - * address specified. - * - * The names s_ and l_ are created to - * define the starting address and length of each area. - * - * local variables: - * Addr_T rloc ;current relocation address - * char temp[] ;temporary string - * struct symbol *sp ;symbol structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * area *areap The pointer to the first - * area structure of a linked list - * - * functions called: - * int fprintf() c_library - * VOID lnksect() lkarea.c - * symbol *lkpsym() lksysm.c - * char * strncpy() c_library - * int symeq() lksysm.c - * - * side effects: - * All area and areax addresses and sizes are - * determined and saved in their respective - * structures. - */ - -unsigned long codemap[2048]; -/* - * Resolve all area addresses. - */ -VOID -lnkarea() -{ - Addr_T rloc[4] = {0, 0, 0, 0}; - Addr_T gs_size = 0; - int locIndex; - char temp[NCPS]; - struct sym *sp; - /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/ - struct area *ta[5]; - int j; - struct area *abs_ap = NULL; - struct area *gs0_ap = NULL; - - memset(codemap, 0, sizeof(codemap)); - - /* first sort all absolute areas to the front */ - ap = areap; - /* no need to check first area, it's in front anyway */ - while (ap && ap->a_ap) - { - if (ap->a_ap->a_flag & A_ABS) - {/* next area is absolute, move it to front, - reversed sequence is no problem for absolutes */ - abs_ap = ap->a_ap; - ap->a_ap = abs_ap->a_ap; - abs_ap->a_ap = areap; - areap = abs_ap; - } - ap = ap->a_ap; - } - - /* next accumulate all GSINITx/GSFINAL area sizes - into GSINIT so they stay together */ - ap = areap; - while (ap) - { - if (!strncmp(ap->a_id, "GS", 2)) - {/* GSxxxxx area */ - if (ap->a_size == 0) - { - axp = ap->a_axp; - while (axp) - { - ap->a_size += axp->a_size; - axp = axp->a_axp; - } - } - gs_size += ap->a_size; - if (!strcmp(ap->a_id, "GSINIT0")) - {/* GSINIT0 area */ - gs0_ap = ap; - } - } - ap = ap->a_ap; - } - if (gs0_ap) - gs0_ap->a_size = gs_size; - - ap = areap; - while (ap) { - if (ap->a_flag & A_ABS) { - /* - * Absolute sections - */ - lnksect(ap); - } else { - /* Determine memory space */ - locIndex = 0; - #if 0 - if (ap->a_flag & A_CODE) { - locIndex = 1; - } - if (ap->a_flag & A_XDATA) { - locIndex = 2; - } - if (ap->a_flag & A_BIT) { - locIndex = 3; - } - #endif - /* - * Relocatable sections - */ - if (ap->a_type == 0) { /* JLH */ - if (ap->a_flag & A_NOLOAD) { - locIndex = 2; - ap->a_addr = 0; - } else { - ap->a_addr = rloc[ locIndex ]; - } - ap->a_type = 1; - } - rloc[ locIndex ] = lnksect(ap); - } - - /* - * Create symbols called: - * s_ the start address of the area - * l_ the length of the area - */ - - if (! symeq(ap->a_id, _abs_)) { - strncpy(temp+2,ap->a_id,NCPS-2); - *(temp+1) = '_'; - - *temp = 's'; - sp = lkpsym(temp, 1); - sp->s_addr = ap->a_addr ; - /* sp->s_axp = ap->a_axp; JLH: was NULL; */ - sp->s_type |= S_DEF; - - *temp = 'l'; - sp = lkpsym(temp, 1); - sp->s_addr = ap->a_size; - sp->s_axp = NULL; - sp->s_type |= S_DEF; - - } - - /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG - to compute the byte size of BSEG_BYTES: */ - if (!strcmp(ap->a_id, "BSEG")) { - ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/ - } - else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap; - else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap; - else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap; - else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap; - else if (!strcmp(ap->a_id, "BSEG_BYTES")) - { - ta[4]=ap; - for(j=4; j>1; j--) - { - /*If upper register banks are not used roll back the relocation counter*/ - if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) ) - { - rloc[0]-=8; - } - else break; - } - } - ap = ap->a_ap; - } -} - -static -Addr_T find_empty_space(Addr_T start, Addr_T size) -{ - int i, j, k; - unsigned long mask, b; - - while (1) - { - Addr_T a = start; - i = start >> 5; - j = (start + size) >> 5; - mask = -(1 << (start & 0x1F)); - - while (i < j) - { - if (codemap[i] & mask) - { - k = 32; - for (b=0x80000000; b!=0; b>>=1, k--) - { - if (codemap[i] & b) - break; - } - start = a + k; - break; - } - i++; - mask = 0xFFFFFFFF; - a += 32; - } - if (start > a) - continue; - - mask &= (1 << ((start + size) & 0x1F)) - 1; - if (codemap[i] & mask) - { - k = 32; - for (b=0x80000000; b!=0; b>>=1, k--) - { - if (codemap[i] & b) - break; - } - start = (a & ~0x1F) + k; - } - if (start <= a) - break; - } - return start; -} - -static -Addr_T allocate_space(Addr_T start, Addr_T size, char* id) -{ - int i, j; - unsigned long mask; - Addr_T a = start; - i = start >> 5; - j = (start + size) >> 5; - mask = -(1 << (start & 0x1F)); - - while (i < j) - { - if (codemap[i] & mask) - { - fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id); - } - codemap[i++] |= mask; - mask = 0xFFFFFFFF; - a += 32; - } - mask &= (1 << ((start + size) & 0x1F)) - 1; - if (codemap[i] & mask) - { - fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id); - } - codemap[i] |= mask; - return start; -} - -/*)Function VOID lnksect() - * - * area * tap pointer to an area structure - * - * The function lnksect() is the function called by - * lnkarea() to resolve the areax addresses. Refer - * to the function lnkarea() for more detail. Pageing - * boundary and length errors will be reported by this - * function. - * - * local variables: - * Addr_T size size of area - * Addr_T addr address of area - * areax * taxp pointer to an areax structure - * - * global variables: - * int lkerr error flag - * - * functions called: - * none - * - * side effects: - * All area and areax addresses and sizes area determined - * and linked into the structures. - */ - -Addr_T lnksect(struct area *tap) -{ - register Addr_T size, addr; - register struct areax *taxp; - - size = 0; - addr = tap->a_addr; - - /* MB: is this possible for hc08 ??? */ - if ((tap->a_flag&A_PAG) && (addr & 0xFF)) { - fprintf(stderr, - "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); - lkerr++; - } - - taxp = tap->a_axp; - if (tap->a_flag&A_OVR) { - /* - * Overlayed sections - */ - while (taxp) { - taxp->a_addr = addr; - if (taxp->a_size > size) - size = taxp->a_size; - taxp = taxp->a_axp; - } - } else if (tap->a_flag & A_ABS) { - /* - * Absolute sections - */ - while (taxp) { - allocate_space(taxp->a_addr, taxp->a_size, tap->a_id); - taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */ - size += taxp->a_size; - taxp = taxp->a_axp; - } - } else { - /* - * Concatenated sections - */ - if (tap->a_size) { - addr = find_empty_space(addr, tap->a_size); - } - while (taxp) { - //find next unused address now - if (taxp->a_size) - { - addr = find_empty_space(addr, taxp->a_size); - allocate_space(addr, taxp->a_size, tap->a_id); - } - taxp->a_addr = addr; - addr += taxp->a_size; - size += taxp->a_size; - taxp = taxp->a_axp; - } - } - tap->a_size = size; - - /* MB: is this possible for hc08 ??? */ - if ((tap->a_flag&A_PAG) && (size > 256)) { - fprintf(stderr, - "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id); - lkerr++; - } - - return addr; -} diff --git a/as/hc08/lkdata.c b/as/hc08/lkdata.c deleted file mode 100644 index 44e44233..00000000 --- a/as/hc08/lkdata.c +++ /dev/null @@ -1,491 +0,0 @@ -/* lkdata.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 28-Oct-97 JLH: - * - change s_id from [NCPS] to pointer (comment) - * 31-Oct-97 JLH: - * - add jflag and jfp for NoICE output - */ - -#include -#include -#include "aslink.h" - -/*)Module lkdata.c - * - * The module lkdata contains the global variables - * and structures used in the linker aslink. - */ - -/* - * Definitions for all Global Variables - */ - -char *_abs_ = { ". .ABS." }; - -int lkerr; /* Linker error flag - */ -char *ip; /* Pointer into the REL file text line in ib[] - */ -char ib[NINPUT]; /* REL file text line - */ -char *rp; /* pointer into the LST file - * text line in rb[] - */ -char rb[NINPUT]; /* LST file text line being - * address relocated - */ - -char sdccopt[NINPUT]=""; -char sdccopt_module[NINPUT]=""; -char curr_module[NINPUT]=""; - -int dflag; /* Debug information output flag - */ -int oflag; /* Output file type flag - */ -int mflag; /* Map output flag - */ -int sflag; /* JCF: Memory usage output flag - */ -int aflag; /* Overlapping area warning flag - */ -int jflag; /* NoICE output flag - */ -int xflag; /* Map file radix type flag - */ -int pflag; /* print linker command file flag - */ -int uflag; /* Listing relocation flag - */ -int rflag; /* Extended linear address record flag. - */ -int radix; /* current number conversion radix: - * 2 (binary), 8 (octal), 10 (decimal), - * 16 (hexadecimal) - */ -int line; /* current line number - */ -int page; /* current page number - */ -int lop; /* current line number on page - */ -int pass; /* linker pass number - */ -int rtcnt; /* count of elements in the - * rtval[] and rtflg[] arrays - */ -Addr_T rtval[NTXT]; /* data associated with relocation - */ -int rtflg[NTXT]; /* indicates if rtval[] value is - * to be sent to the output file. - * (always set in this linker) - */ -int hilo; /* REL file byte ordering - */ -int gline; /* LST file relocation active - * for current line - */ -int gcntr; /* LST file relocation active - * counter - */ -Addr_T iram_size; /* internal ram size - */ -long xram_size=-1; /* external ram size - */ -long code_size=-1; /* code size - */ - -/* - * The structure lfile contains a pointer to a - * file specification string, the file type, and - * a link to the next lfile structure. - * - * struct lfile - * { - * struct lfile *f_flp; lfile link - * int f_type; File type - * char *f_idp; Pointer to file spec - * }; - */ -struct lfile *filep; /* The pointers (lfile *) filep, - * (lfile *) cfp, and (FILE *) sfp - * are used in conjunction with - * the routine as_getline() to read - * asmlnk commands from - * (1) the standard input or - * (2) or a command file - * and to read the REL files - * sequentially as defined by the - * asmlnk input commands. - * - * The pointer *filep points to the - * beginning of a linked list of - * lfile structures. - */ -struct lfile *cfp; /* The pointer *cfp points to the - * current lfile structure - */ -struct lfile *startp;/* asmlnk startup file structure - */ -struct lfile *linkp; /* pointer to first lfile structure - * containing an input REL file - * specification - */ -struct lfile *lfp; /* pointer to current lfile structure - * being processed by parse() - */ -FILE *ofp; /* Output file handle - * for word formats - */ -FILE *mfp; /* Map output file handle - */ -FILE *jfp; /* NoICE output file handle - */ -FILE *rfp; /* File handle for output - * address relocated ASxxxx - * listing file - */ -FILE *sfp; /* The file handle sfp points to the - * currently open file - */ -FILE *tfp; /* File handle for input - * ASxxxx listing file - */ -FILE *dfp = NULL ; /* - * File handle for debug - * information output file - */ -/* - * The structures of head, area, areax, and sym are created - * as the REL files are read during the first pass of the - * linker. The struct head is created upon encountering a - * H directive in the REL file. The structure contains a - * link to a link file structure (struct lfile) which describes - * the file containing the H directive, the number of data/code - * areas contained in this header segment, the number of - * symbols referenced/defined in this header segment, a pointer - * to an array of pointers to areax structures (struct areax) - * created as each A directive is read, and a pointer to an - * array of pointers to symbol structures (struct sym) for - * all referenced/defined symbols. As H directives are read - * from the REL files a linked list of head structures is - * created by placing a link to the new head structure - * in the previous head structure. - * - * struct head - * { - * struct head *h_hp; Header link - * struct lfile *h_lfile; Associated file - * int h_narea; # of areas - * struct areax **a_list; Area list - * int h_nglob; # of global symbols - * struct sym **s_list; Global symbol list - * char m_id[NCPS]; Module name - * }; - */ -struct head *headp; /* The pointer to the first - * head structure of a linked list - */ -struct head *hp; /* Pointer to the current - * head structure - */ - -/* - * A structure area is created for each 'unique' data/code - * area definition found as the REL files are read. The - * struct area contains the name of the area, a flag byte - * which contains the area attributes (REL/CON/OVR/ABS), - * an area subtype (not used in this assembler), and the - * area base address and total size which will be filled - * in at the end of the first pass through the REL files. - * As A directives are read from the REL files a linked - * list of unique area structures is created by placing a - * link to the new area structure in the previous area structure. - * - * struct area - * { - * struct area *a_ap; Area link - * struct areax *a_axp; Area extension link - * Addr_T a_addr; Beginning address of area - * Addr_T a_size; Total size of the area - * char a_type; Area subtype - * char a_flag; Flag byte - * char a_id[NCPS]; Name - * }; - */ -struct area *areap; /* The pointer to the first - * area structure of a linked list - */ -struct area *ap; /* Pointer to the current - * area structure - */ - -/* - * An areax structure is created for every A directive found - * while reading the REL files. The struct areax contains a - * link to the 'unique' area structure referenced by the A - * directive and to the head structure this area segment is - * a part of. The size of this area segment as read from the - * A directive is placed in the areax structure. The beginning - * address of this segment will be filled in at the end of the - * first pass through the REL files. As A directives are read - * from the REL files a linked list of areax structures is - * created for each unique area. The final areax linked - * list has at its head the 'unique' area structure linked - * to the linked areax structures (one areax structure for - * each A directive for this area). - * - * struct areax - * { - * struct areax *a_axp; Area extension link - * struct area *a_bap; Base area link - * struct head *a_bhp; Base header link - * Addr_T a_addr; Beginning address of section - * Addr_T a_size; Size of the area in section - * }; - */ -struct areax *axp; /* Pointer to the current - * areax structure - */ - -/* - * A sym structure is created for every unique symbol - * referenced/defined while reading the REL files. The - * struct sym contains the symbol's name, a flag value - * (not used in this linker), a symbol type denoting - * referenced/defined, and an address which is loaded - * with the relative address within the area in which - * the symbol was defined. The sym structure also - * contains a link to the area where the symbol was defined. - * The sym structures are linked into linked lists using - * the symbol link element. - * - * struct sym - * { - * struct sym *s_sp; Symbol link - * struct areax *s_axp; Symbol area link - * char s_type; Symbol subtype - * char s_flag; Flag byte - * Addr_T s_addr; Address - * char *s_id; Name (JLH) - * }; - */ -struct sym *symhash[NHASH]; /* array of pointers to NHASH - * linked symbol lists - */ -/* - * The struct base contains a pointer to a - * base definition string and a link to the next - * base structure. - * - * struct base - * { - * struct base *b_base; Base link - * char *b_strp; String pointer - * }; - */ -struct base *basep; /* The pointer to the first - * base structure - */ -struct base *bsp; /* Pointer to the current - * base structure - */ - -/* - * The struct globl contains a pointer to a - * global definition string and a link to the next - * global structure. - * - * struct globl - * { - * struct globl *g_globl; Global link - * char *g_strp; String pointer - * }; - */ -struct globl *globlp;/* The pointer to the first - * globl structure - */ -struct globl *gsp; /* Pointer to the current - * globl structure - */ - -/* - * A structure sdp is created for each 'unique' paged - * area definition found as the REL files are read. - * As P directives are read from the REL files a linked - * list of unique sdp structures is created by placing a - * link to the new sdp structure in the previous area structure. - * - * struct sdp - * { - * struct area *s_area; Paged Area link - * struct areax *s_areax; Paged Area Extension Link - * Addr_T s_addr; Page address offset - * }; - */ -struct sdp sdp; /* Base Page Structure */ - -/* - * The structure rerr is loaded with the information - * required to report an error during the linking - * process. The structure contains an index value - * which selects the areax structure from the header - * areax structure list, a mode value which selects - * symbol or area relocation, the base address in the - * area section, an area/symbol list index value, and - * an area/symbol offset value. - * - * struct rerr - * { - * int aindex; Linking area - * int mode; Relocation mode - * Addr_T rtbase; Base address in section - * int rindex; Area/Symbol reloaction index - * Addr_T rval; Area/Symbol offset value - * }; - */ -struct rerr rerr; /* Structure containing the - * linker error information - */ - -/* - * The structure lbpath is created for each library - * path specification input by the -k option. The - * lbpath structures are linked into a list using - * the next link element. - * - * struct lbpath { - * struct lbpath *next; - * char *path; - * }; - */ -struct lbpath *lbphead; /* pointer to the first - * library path structure - */ - -/* - * The structure lbname is created for all combinations of the - * library path specifications (input by the -k option) and the - * library file specifications (input by the -l option) that - * lead to an existing file. The element path points to - * the path string, element libfil points to the library - * file string, and the element libspc is the concatenation - * of the valid path and libfil strings. - * - * The lbpath structures are linked into a list - * using the next link element. - * - * Each library file contains a list of object files - * that are contained in the particular library. e.g.: - * - * \iolib\termio - * \inilib\termio - * - * Only one specification per line is allowed. - * - * struct lbname { - * struct lbname *next; - * char *path; - * char *libfil; - * char *libspc; - * }; - */ -struct lbname *lbnhead; /* pointer to the first - * library name structure - */ - -/* - * The function fndsym() searches through all combinations of the - * library path specifications (input by the -k option) and the - * library file specifications (input by the -l option) that - * lead to an existing file for a symbol definition. - * - * The structure lbfile is created for the first library - * object file which contains the definition for the - * specified undefined symbol. - * - * The element libspc points to the library file path specification - * and element relfil points to the object file specification string. - * The element filspc is the complete path/file specification for - * the library file to be imported into the linker. The - * file specicifation may be formed in one of two ways: - * - * (1) If the library file contained an absolute - * path/file specification then this becomes filspc. - * (i.e. C:\...) - * - * (2) If the library file contains a relative path/file - * specification then the concatenation of the path - * and this file specification becomes filspc. - * (i.e. \...) - * - * The lbpath structures are linked into a list - * using the next link element. - * - * struct lbfile { - * struct lbfile *next; - * char *libspc; - * char *relfil; - * char *filspc; - * }; - */ -struct lbfile *lbfhead; /* pointer to the first - * library file structure - */ - -/* - * array of character types, one per - * ASCII character - */ -unsigned char ctype[128] = { -/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL, -/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*CAN*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*SPC*/ SPACE, ETC, ETC, ETC, LETTER, BINOP, BINOP, ETC, -/*(*/ ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, BINOP, -/*0*/ DGT2, DGT2, DGT8, DGT8, DGT8, DGT8, DGT8, DGT8, -/*8*/ DGT10, DGT10, ETC, ETC, BINOP, ETC, BINOP, ETC, -/*@*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER, -/*H*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/*P*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/*X*/ LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER, -/*`*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER, -/*h*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/*p*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/*x*/ LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC -}; - -/* - * an array of characters which - * perform the case translation function - */ -#if CASE_SENSITIVE -#else -char ccase[128] = { -/*NUL*/ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', -/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', -/*DLE*/ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', -/*CAN*/ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', -/*SPC*/ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', -/*(*/ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', -/*0*/ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', -/*8*/ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', -/*@*/ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', -/*H*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', -/*P*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', -/*X*/ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', -/*`*/ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', -/*h*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', -/*p*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', -/*x*/ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177' -}; -#endif diff --git a/as/hc08/lkelf.c b/as/hc08/lkelf.c deleted file mode 100644 index 3cc602fd..00000000 --- a/as/hc08/lkelf.c +++ /dev/null @@ -1,784 +0,0 @@ -/*------------------------------------------------------------------------- - lkelf.c - Create an executable ELF/DWARF file - - Written By - Erik Petrich, epetrich@users.sourceforge.net (2004) - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --------------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include "aslink.h" - -#ifdef _WIN32 -# ifdef __MINGW32__ /* GCC MINGW32 depends on configure */ -# include "sdccconf.h" -# else -# include "sdcc_vc.h" -# endif -#else /* Assume Un*x style system */ -# include "sdccconf.h" -#endif - -static int execStartMSB; -static int execStartLSB; -static char execStartMSBfound; -static char execStartLSBfound; - -typedef TYPE_UDWORD Elf32_Addr; -typedef TYPE_WORD Elf32_Half; -typedef TYPE_UDWORD Elf32_Off; -typedef TYPE_DWORD Elf32_Sword; -typedef TYPE_UDWORD Elf32_Word; - -enum -{ - EI_MAG0 = 0, - EI_MAG1, - EI_MAG2, - EI_MAG3, - EI_CLASS, - EI_DATA, - EI_VERSION, - EI_PAD, - EI_NIDENT = 16 -}; - -enum -{ - ELFMAG0 = 0x7f, - ELFMAG1 = 'E', - ELFMAG2 = 'L', - ELFMAG3 = 'F' -}; - -enum -{ - ET_NONE = 0, - ET_REL, - ET_EXEC, - ET_DYN, - ET_CORE -}; - -/* These e_machine values are from "Motorola 8- and 16-bit Embedded */ -/* Application Binary Interface (M8/16EABI)" version 2.0 */ -enum -{ - EM_NONE = 0, - EM_68HC05 = 72, - EM_68HC08 = 71, - EM_68HC11 = 70, - EM_68HC12 = 53, - EM_68HC16 = 69 -}; - -enum -{ - EV_NONE = 0, - EV_CURRENT -}; - -enum -{ - ELFCLASSNONE = 0, - ELFCLASS32, - ELFCLASS64 -}; - -enum -{ - ELFDATANONE = 0, - ELFDATA2LSB, - ELFDATA2MSB -}; - -enum -{ - SHT_NULL = 0, - SHT_PROGBITS, - SHT_SYMTAB, - SHT_STRTAB, - SHT_RELA, - SHT_HASH, - SHT_DYNAMIC, - SHT_NOTE, - SHT_NOBITS, - SHT_REL, - SHT_SHLIB, - SHT_DYNSYM -}; - -enum -{ - SHF_WRITE = (1 << 0), - SHF_ALLOC = (1 << 1), - SHF_EXECINSTR = (1 << 2), -}; - -enum -{ - PT_NULL = 0, - PT_LOAD -}; - -enum -{ - PF_X = (1 << 0), - PF_W = (1 << 1), - PF_R = (1 << 2) -}; - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct strtabString -{ - char * string; - struct strtabString * prev; - struct strtabString * next; - Elf32_Word index; -} strtabString; - -typedef struct -{ - strtabString * first; - strtabString * last; -} strtabList; - -static strtabList shstrtab; - - -typedef struct listEntry -{ - void * item; - struct listEntry * prev; - struct listEntry * next; -} listEntry; - -typedef struct -{ - listEntry * first; - listEntry * last; - int count; -} listHeader; - - - -static void -listAdd (listHeader * lhp, void * item) -{ - listEntry * lep; - - lep = new (sizeof (*lep)); - lep->item = item; - lep->prev = lhp->last; - if (lep->prev) - lep->prev->next = lep; - - lhp->last = lep; - if (!lhp->first) - lhp->first = lep; - - lhp->count++; -} - -static listHeader * -listNew (void) -{ - listHeader * lhp; - - lhp = new (sizeof (*lhp)); - - return lhp; -} - - -#if 0 -static Elf32_Word -strtabFind (strtabList * strtab, char * str) -{ - strtabString * sp; - sp = strtab->first; - - while (sp) - { - if (!strcmp (str, sp->string)) - return sp->index; - sp = sp->next; - } - - return 0; -} -#endif - -/*-------------------------------------------------------------------*/ -/* strtabFindOrAdd - Finds a string in a string table or adds the */ -/* string if it does not already exist. Returns the offset of the */ -/* string in the table. */ -/*-------------------------------------------------------------------*/ -static Elf32_Word -strtabFindOrAdd (strtabList * strtab, char * str) -{ - strtabString * sp; - sp = strtab->first; - - while (sp) - { - if (!strcmp (str, sp->string)) - return sp->index; - sp = sp->next; - } - - sp = new (sizeof(*sp)); - if (strtab->last) - sp->index = strtab->last->index + 1 + strlen (strtab->last->string); - else - sp->index = 1; - sp->string = new (1+strlen (str)); - strcpy (sp->string, str); - - sp->prev = strtab->last; - if (sp->prev) - sp->prev->next = sp; - strtab->last = sp; - if (!strtab->first) - strtab->first = sp; - - return sp->index; -} - -/*-------------------------------------------------------------------*/ -/* fputElfStrtab - writes a string table to a file */ -/*-------------------------------------------------------------------*/ -static void -fputElfStrtab (strtabList *strtab, FILE *fp) -{ - strtabString * sp; - - fputc (0, fp); /* index 0 must be the null character */ - - sp = strtab->first; - while (sp) - { - fputs (sp->string, fp); - fputc (0, fp); - sp = sp->next; - } -} - -/*-------------------------------------------------------------------*/ -/* fputElf32_Word - writes an Elf32_Word value to a file */ -/*-------------------------------------------------------------------*/ -static void -fputElf32_Word (Elf32_Word x, FILE *fp) -{ - if (hilo == 0) - { - fputc (x & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - fputc ((x >> 16) & 0xff, fp); - fputc ((x >> 24) & 0xff, fp); - } - else - { - fputc ((x >> 24) & 0xff, fp); - fputc ((x >> 16) & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - fputc (x & 0xff, fp); - } -} - -/*-------------------------------------------------------------------*/ -/* fputElf32_Off - writes an Elf32_Off value to a file */ -/*-------------------------------------------------------------------*/ -static void -fputElf32_Off (Elf32_Off x, FILE *fp) -{ - if (hilo == 0) - { - fputc (x & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - fputc ((x >> 16) & 0xff, fp); - fputc ((x >> 24) & 0xff, fp); - } - else - { - fputc ((x >> 24) & 0xff, fp); - fputc ((x >> 16) & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - fputc (x & 0xff, fp); - } -} - -/*-------------------------------------------------------------------*/ -/* fputElf32_Addr - writes an Elf32_Addr value to a file */ -/*-------------------------------------------------------------------*/ -static void -fputElf32_Addr (Elf32_Addr x, FILE *fp) -{ - if (hilo == 0) - { - fputc (x & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - fputc ((x >> 16) & 0xff, fp); - fputc ((x >> 24) & 0xff, fp); - } - else - { - fputc ((x >> 24) & 0xff, fp); - fputc ((x >> 16) & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - fputc (x & 0xff, fp); - } -} - -/*-------------------------------------------------------------------*/ -/* fputElf32_Half - writes an Elf32_Half value to a file */ -/*-------------------------------------------------------------------*/ -static void -fputElf32_Half (Elf32_Half x, FILE *fp) -{ - if (hilo == 0) - { - fputc (x & 0xff, fp); - fputc ((x >> 8) & 0xff, fp); - } - else - { - fputc ((x >> 8) & 0xff, fp); - fputc (x & 0xff, fp); - } -} - -/*------------------------------------------------------------------------*/ -/* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */ -/*------------------------------------------------------------------------*/ -static void -fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp) -{ - int i; - - for (i=0; ie_ident[i], fp); - - fputElf32_Half (ehdr->e_type, fp); - fputElf32_Half (ehdr->e_machine, fp); - fputElf32_Word (ehdr->e_version, fp); - fputElf32_Addr (ehdr->e_entry, fp); - fputElf32_Off (ehdr->e_phoff, fp); - fputElf32_Off (ehdr->e_shoff, fp); - fputElf32_Word (ehdr->e_flags, fp); - fputElf32_Half (ehdr->e_ehsize, fp); - fputElf32_Half (ehdr->e_phentsize, fp); - fputElf32_Half (ehdr->e_phnum, fp); - fputElf32_Half (ehdr->e_shentsize, fp); - fputElf32_Half (ehdr->e_shnum, fp); - fputElf32_Half (ehdr->e_shstrndx, fp); -} - -/*-------------------------------------------------------------------------*/ -/* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */ -/*-------------------------------------------------------------------------*/ -static void -fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp) -{ - fputElf32_Word (shdr->sh_name, fp); - fputElf32_Word (shdr->sh_type, fp); - fputElf32_Word (shdr->sh_flags, fp); - fputElf32_Addr (shdr->sh_addr, fp); - fputElf32_Off (shdr->sh_offset, fp); - fputElf32_Word (shdr->sh_size, fp); - fputElf32_Word (shdr->sh_link, fp); - fputElf32_Word (shdr->sh_info, fp); - fputElf32_Word (shdr->sh_addralign, fp); - fputElf32_Word (shdr->sh_entsize, fp); -} - -/*-------------------------------------------------------------------------*/ -/* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */ -/*-------------------------------------------------------------------------*/ -static void -fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp) -{ - fputElf32_Word (phdr->p_type, fp); - fputElf32_Off (phdr->p_offset, fp); - fputElf32_Addr (phdr->p_vaddr, fp); - fputElf32_Addr (phdr->p_paddr, fp); - fputElf32_Word (phdr->p_filesz, fp); - fputElf32_Word (phdr->p_memsz, fp); - fputElf32_Word (phdr->p_flags, fp); - fputElf32_Word (phdr->p_align, fp); -} - - -/*--------------------------------------------------------------------------*/ -/* elfGenerateAbs - generates segments and sections for an absolute area. */ -/* This is a little more complicated than a relative area since it may */ -/* contain noncontiguous regions. */ -/*--------------------------------------------------------------------------*/ -static void -elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections) -{ - Elf32_Addr ofs; - Elf32_Addr addr; - Elf32_Word size; - Elf32_Phdr * phdrp; - Elf32_Shdr * shdrp; - - if (!ap->a_image) - { - return; - } - - ofs = 0; - for (;;) - { - /* Find the start of a contiguously */ - /* used region within this area */ - while (ofs < ap->a_size && !ap->a_used[ofs]) - ofs++; - if (ofs >= ap->a_size) - return; - - /* Find the end of the region */ - addr = ap->a_addr + ofs; - while (ofs < ap->a_size && ap->a_used[ofs]) - ofs++; - size = ap->a_addr + ofs - addr; - - /* create a segment header for this region if loadable */ - if (!(ap->a_flag & A_NOLOAD)) - { - phdrp = new (sizeof (*phdrp)); - phdrp->p_type = PT_LOAD; - phdrp->p_offset = ftell (ofp); - phdrp->p_vaddr = addr; - phdrp->p_paddr = addr; - phdrp->p_filesz = size; - phdrp->p_memsz = size; - phdrp->p_flags = PF_R; - if (ap->a_flag & A_CODE) - phdrp->p_flags |= PF_X; - phdrp->p_align = 1; - listAdd (segments, phdrp); - } - - /* create a section header for this region */ - shdrp = new (sizeof (*shdrp)); - shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id); - shdrp->sh_type = SHT_PROGBITS; - shdrp->sh_flags = 0; - if (!(ap->a_flag & A_NOLOAD)) - shdrp->sh_flags |= SHF_ALLOC; - if (ap->a_flag & A_CODE) - shdrp->sh_flags |= SHF_EXECINSTR; - shdrp->sh_addr = addr; - shdrp->sh_offset = ftell (ofp); - shdrp->sh_size = size; - shdrp->sh_link = 0; - shdrp->sh_info = 0; - shdrp->sh_addralign = 0; - shdrp->sh_entsize = 0; - listAdd (sections, shdrp); - - fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp); - } -} - -/*--------------------------------------------------------------------------*/ -/* elfGenerateRel - generates a segment and section for a relative area. */ -/*--------------------------------------------------------------------------*/ -static void -elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections) -{ - Elf32_Phdr * phdrp; - Elf32_Shdr * shdrp; - - if (!ap->a_image) - { - return; - } - - /* create a segment header for this area if loadable */ - if (!(ap->a_flag & A_NOLOAD)) - { - phdrp = new (sizeof (*phdrp)); - phdrp->p_type = PT_LOAD; - phdrp->p_offset = ftell (ofp); - phdrp->p_vaddr = ap->a_addr; - phdrp->p_paddr = ap->a_addr; - phdrp->p_filesz = ap->a_size; - phdrp->p_memsz = ap->a_size; - phdrp->p_flags = PF_R; - if (ap->a_flag & A_CODE) - phdrp->p_flags |= PF_X; - phdrp->p_align = 1; - listAdd (segments, phdrp); - } - - /* create a section header for this area */ - shdrp = new (sizeof (*shdrp)); - shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id); - shdrp->sh_type = SHT_PROGBITS; - shdrp->sh_flags = 0; - if (!(ap->a_flag & A_NOLOAD)) - shdrp->sh_flags |= SHF_ALLOC; - if (ap->a_flag & A_CODE) - shdrp->sh_flags |= SHF_EXECINSTR; - shdrp->sh_addr = ap->a_addr; - shdrp->sh_offset = ftell (ofp); - shdrp->sh_size = ap->a_size; - shdrp->sh_link = 0; - shdrp->sh_info = 0; - shdrp->sh_addralign = 0; - shdrp->sh_entsize = 0; - listAdd (sections, shdrp); - - fwrite (ap->a_image, 1, ap->a_size, ofp); -} - -/*--------------------------------------------------------------------------*/ -/* elfGenerate - generates the complete ELF file */ -/*--------------------------------------------------------------------------*/ -static void -elfGenerate (void) -{ - listHeader * sections = listNew(); - listHeader * segments = listNew(); - struct area *ap; - Elf32_Ehdr ehdr; - Elf32_Shdr * shdrp; - Elf32_Phdr * phdrp; - listEntry * lep; - int i; - Elf32_Word shstrtabName; - - /* create the null section header for index 0 */ - shdrp = new (sizeof (*shdrp)); - shdrp->sh_name = 0; - shdrp->sh_type = SHT_NULL; - shdrp->sh_flags = 0; - shdrp->sh_addr = 0; - shdrp->sh_offset = 0; - shdrp->sh_size = 0; - shdrp->sh_link = 0; - shdrp->sh_info = 0; - shdrp->sh_addralign = 0; - shdrp->sh_entsize = 0; - listAdd (sections, shdrp); - - /* Initialize the ELF header */ - for (i=0; ia_size) - { - if (ap->a_flag & A_ABS) - elfGenerateAbs (ap, segments, sections); - else - elfGenerateRel (ap, segments, sections); - } - ap = ap->a_ap; - } - - /* Create the string table section after the other sections */ - shdrp = new (sizeof (*shdrp)); - shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab"); - shdrp->sh_type = SHT_STRTAB; - shdrp->sh_flags = 0; - shdrp->sh_addr = 0; - shdrp->sh_offset = ftell (ofp); - shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1; - shdrp->sh_link = 0; - shdrp->sh_info = 0; - shdrp->sh_addralign = 0; - shdrp->sh_entsize = 0; - listAdd (sections, shdrp); - fputElfStrtab (&shstrtab, ofp); - - /* Find the index of the section string table */ - /* header and save it in the ELF header */ - ehdr.e_shstrndx = 0; - shstrtabName = shdrp->sh_name; - lep = sections->first; - while (lep) - { - shdrp = lep->item; - if (shdrp->sh_name == shstrtabName) - break; - ehdr.e_shstrndx++; - lep = lep->next; - } - - /* Write out the segment headers */ - ehdr.e_phnum = segments->count; - ehdr.e_phoff = ftell (ofp); - lep = segments->first; - while (lep) - { - phdrp = lep->item; - fputElf32_Phdr (phdrp, ofp); - lep = lep->next; - } - - /* Write out the section headers */ - ehdr.e_shnum = sections->count; - ehdr.e_shoff = ftell (ofp); - lep = sections->first; - while (lep) - { - shdrp = lep->item; - fputElf32_Shdr (shdrp, ofp); - lep = lep->next; - } - - /* All the values in the ELF header have now been computed; write */ - /* over the placeholder header with the final values */ - fseek (ofp, 0, SEEK_SET); - fputElf32_Ehdr (&ehdr, ofp); - fseek (ofp, 0, SEEK_END); -} - -/*--------------------------------------------------------------------------*/ -/* elf - incrementally called by the linker core to generate ELF file data. */ -/* The parameter is nonzero when there is data available and zero when */ -/* the linker is finished. */ -/*--------------------------------------------------------------------------*/ -void -elf (int i) -{ - Addr_T address; - - /* Buffer the data until we have it all */ - if (i) - { - if (hilo == 0) - address = rtval[0] + (rtval[1] << 8); /* little endian order */ - else - address = rtval[1] + (rtval[0] << 8); /* big endian order */ - - /* If this area doesn't have an image buffer, create one */ - if (!ap->a_image) - { - ap->a_image = new (ap->a_size); - if (ap->a_flag & A_ABS) - ap->a_used = new (ap->a_size); - } - - /* Copy the data into the image buffer */ - for (i = 2; i < rtcnt ; i++) - { - if (rtflg[i]) - { - ap->a_image[address-ap->a_addr] = rtval[i]; - if (ap->a_used) - ap->a_used[address-ap->a_addr] = 1; - - /* Make note of the reset vector */ - if (!(ap->a_flag & A_NOLOAD)) - { - if (address == 0xfffe) - { - execStartMSB = rtval[i]; - execStartMSBfound = 1; - } - if (address == 0xffff) - { - execStartLSB = rtval[i]; - execStartLSBfound = 1; - } - } - address++; - } - } - } - else - elfGenerate(); -} diff --git a/as/hc08/lkeval.c b/as/hc08/lkeval.c deleted file mode 100644 index 90df0031..00000000 --- a/as/hc08/lkeval.c +++ /dev/null @@ -1,396 +0,0 @@ -/* lkeval.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*)Module lkeval.c - * - * The module lkeval.c contains the routines to evaluate - * arithmetic/numerical expressions. The functions in - * lkeval.c perform a recursive evaluation of the arithmetic - * expression read from the input text line. - * The expression may include binary/unary operators, brackets, - * symbols, labels, and constants in hexadecimal, decimal, octal - * and binary. Arithmetic operations are prioritized and - * evaluated by normal arithmetic conventions. - * - * lkeval.c contains the following functions: - * int digit() - * Addr_T eval() - * Addr_T expr() - * int oprio() - * Addr_T term() - * - * lkeval.c contains no local/static variables - */ - -/*)Function Addr_T eval() - * - * The function eval() evaluates a character string to a - * numerical value. - * - * local variables: - * int c character from input string - * int v value of character in current radix - * Addr_T n evaluation value - * - * global variables: - * int radix current number conversion radix - * - * functions called: - * int digit() lkeval.c - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * Input test is scanned and evaluated to a - * numerical value. - */ - -Addr_T -eval() -{ - register int c, v; - register Addr_T n; - - c = getnb(); - n = 0; - while ((v = digit(c, radix)) >= 0) { - n = n*radix + v; - c = get(); - } - unget(c); - return(n); -} - -/*)Function Addr_T expr(n) - * - * int n a firewall priority; all top - * level calls (from the user) - * should be made with n set to 0. - * - * The function expr() evaluates an expression and - * returns the value. - * - * local variables: - * int c current input text character - * int p current operator priority - * Addr_T v value returned by term() - * Addr_T ve value returned by a - * recursive call to expr() - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * int lkerr error flag - * FILE * stderr c_library - * - * functions called: - * VOID expr() lkeval.c - * int fprintf() c_library - * int getnb() lklex.c - * int oprio() lkeval.c - * VOID term() lkeval.c - * VOID unget() lklex.c - * - * - * side effects: - * An expression is evaluated by scanning the input - * text string. - */ - -Addr_T -expr (n) -{ - register int c, p; - register Addr_T v, ve; - - v = term(); - while (ctype[c = getnb()] & BINOP) { - if ((p = oprio(c)) <= n) - break; - if ((c == '>' || c == '<') && c != get()) { - fprintf(stderr, "Invalid expression"); - lkerr++; - return(v); - } - ve = expr(p); - if (c == '+') { - v += ve; - } else - if (c == '-') { - v -= ve; - } else { - switch (c) { - - case '*': - v *= ve; - break; - - case '/': - v /= ve; - break; - - case '&': - v &= ve; - break; - - case '|': - v |= ve; - break; - - case '%': - v %= ve; - break; - - case '^': - v ^= ve; - break; - - case '<': - v <<= ve; - break; - - case '>': - v >>= ve; - break; - } - } - } - unget(c); - return(v); -} - -/*)Function Addr_T term() - * - * The function term() evaluates a single constant - * or symbol value prefaced by any unary operator - * ( +, -, ~, ', ", >, or < ). - * - * local variables: - * int c current character - * char id[] symbol name - * int n value of digit in current radix - * int r current evaluation radix - * sym * sp pointer to a sym structure - * Addr_T v evaluation value - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * int lkerr error flag - * - * functions called: - * int digit() lkeval.c - * VOID expr() lkeval.c - * int fprintf() c_library - * int get() lklex.c - * VOID getid() lklex.c - * int getmap() lklex.c - * int getnb() lklex.c - * sym * lkpsym() lksym.c - * Addr_T symval() lksym.c - * VOID unget() lklex.c - * - * side effects: - * An arithmetic term is evaluated by scanning input text. - */ - -Addr_T -term() -{ - register int c, r, n; - register Addr_T v; - struct sym *sp; - char id[NCPS]; - - c = getnb(); - if (c == '#') { c = getnb(); } - if (c == '(') { - v = expr(0); - if (getnb() != ')') { - fprintf(stderr, "Missing delimiter"); - lkerr++; - } - return(v); - } - if (c == '-') { - return(0-expr(100)); - } - if (c == '~') { - return(~expr(100)); - } - if (c == '\'') { - return(getmap(-1)&0377); - } - if (c == '\"') { - if (hilo) { - v = (getmap(-1)&0377)<<8; - v |= getmap(-1)&0377; - } else { - v = getmap(-1)&0377; - v |= (getmap(-1)&0377)<<8; - } - return(v); - } - if (c == '>' || c == '<') { - v = expr(100); - if (c == '>') - v >>= 8; - return(v&0377); - } - if (ctype[c] & DIGIT) { - r = 10; - if (c == '0') { - c = get(); - switch (c) { - case 'b': - case 'B': - r = 2; - c = get(); - break; - case '@': - case 'o': - case 'O': - case 'q': - case 'Q': - r = 8; - c = get(); - break; - case 'd': - case 'D': - r = 10; - c = get(); - break; - case 'h': - case 'H': - case 'x': - case 'X': - r = 16; - c = get(); - break; - default: - break; - } - } - v = 0; - while ((n = digit(c, r)) >= 0) { - v = r*v + n; - c = get(); - } - unget(c); - return(v); - } - if (ctype[c] & LETTER) { - getid(id, c); - if ((sp = lkpsym(id, 0)) == NULL) { - fprintf(stderr, "Undefined symbol %8s\n", id); - lkerr++; - return(0); - } else { - return(symval(sp)); - } - } - return(0); -} - -/*)Function int digit(c, r) - * - * int c digit character - * int r current radix - * - * The function digit() returns the value of c - * in the current radix r. If the c value is not - * a number of the current radix then a -1 is returned. - * - * local variables: - * none - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * - * functions called: - * none - * - * side effects: - * none - */ - -int -digit(c, r) -register int c, r; -{ - if (r == 16) { - if (ctype[c] & RAD16) { - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - return (c - '0'); - } - } else - if (r == 10) { - if (ctype[c] & RAD10) - return (c - '0'); - } else - if (r == 8) { - if (ctype[c] & RAD8) - return (c - '0'); - } else - if (r == 2) { - if (ctype[c] & RAD2) - return (c - '0'); - } - return (-1); -} - -/*)Function int oprio(c) - * - * int c operator character - * - * The function oprio() returns a relative priority - * for all valid unary and binary operators. - * - * local variables: - * none - * - * global variables: - * none - * - * functions called: - * none - * - * side effects: - * none - */ - -int -oprio(c) -register int c; -{ - if (c == '*' || c == '/' || c == '%') - return (10); - if (c == '+' || c == '-') - return (7); - if (c == '<' || c == '>') - return (5); - if (c == '^') - return (4); - if (c == '&') - return (3); - if (c == '|') - return (1); - return (0); -} diff --git a/as/hc08/lkhead.c b/as/hc08/lkhead.c deleted file mode 100644 index 41a5198c..00000000 --- a/as/hc08/lkhead.c +++ /dev/null @@ -1,153 +0,0 @@ -/* lkhead.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*Module lkhead.c - * - * The module lkhead.c contains the function newhead() which - * creates a head structure and the function module() which - * loads the module name into the current head structure. - * - * lkhead.c contains the following functions: - * VOID newhead() - * VOID module() - * - * lkhead.c contains no local variables. - */ - -/*)Function VOID newhead() - * - * The function newhead() creates a head structure. All head - * structures are linked to form a linked list of head structures - * with the current head structure at the tail of the list. - * - * local variables: - * int i evaluation value - * head * thp temporary pointer - * to a header structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * lfile *cfp The pointer *cfp points to the - * current lfile structure - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * - * functions called: - * Addr_T expr() lkeval.c - * VOID * new() lksym.c - * VOID lkparea() lkarea.c - * - * side effects: - * A new head structure is created and linked to any - * existing linked head structure. The head structure - * parameters of file handle, number of areas, and number - * of global symbols are loaded into the structure. - * The default area "_abs_" is created when the first - * head structure is created and an areax structure is - * created for every head structure called. - */ - -/* - * Create a new header entry. - * - * H n areas n global symbols - * | | - * | `---- hp->h_nglob - * `------------ hp->h_narea - * - */ -VOID -newhead() -{ - register int i; - struct head *thp; - - hp = (struct head *) new (sizeof(struct head)); - if (headp == NULL) { - headp = hp; - } else { - thp = headp; - while (thp->h_hp) - thp = thp->h_hp; - thp->h_hp = hp; - } - /* - * Set file pointer - */ - hp->h_lfile = cfp; - /* - * Evaluate and build Area pointer list - */ - i = hp->h_narea = eval(); - if (i) - hp->a_list = (struct areax **) new (i*sizeof(struct areax *)); - /* - * Evaluate and build Global symbol pointer list - */ - skip(-1); - i = hp->h_nglob = eval(); - if (i) - hp->s_list = (struct sym **) new (i*sizeof(struct sym *)); - /* - * Setup Absolute DEF linkage. - */ - lkparea(_abs_); - ap->a_flag = A_ABS; -} - -/*)Function VOID module() - * - * The function module() copies the module name into - * the current head structure. - * - * local variables: - * char id[] module id string - * - * global variables: - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * FILE * stderr c_library - * - * functions called: - * int fprintf() c_library - * VOID getid() lklex.c - * char * strncpy() c_library - * - * side effects: - * The module name is copied into the head structure. - */ - -/* - * Module Name - */ -VOID -module() -{ - char id[NCPS]; - - if (headp) { - getid(id, -1); - strncpy(hp->m_id, id, NCPS); - } else { - fprintf(stderr, "No header defined\n"); - lkerr++; - } -} diff --git a/as/hc08/lkihx.c b/as/hc08/lkihx.c deleted file mode 100644 index 28c2f500..00000000 --- a/as/hc08/lkihx.c +++ /dev/null @@ -1,262 +0,0 @@ -/* lkihx.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*)Module lkihx.c - * - * The module lkihx.c contains the function to - * output the relocated object code in the - * Intel Hex format. - * - * lkihx.c contains the following functions: - * VOID hexRecord(addr, rtvalIndex) - * VOID ihx(i) - * VOID ihxEntendedLinearAddress(a) - * - * local variables: hexPageOverrun, lastHexAddr - */ - -/*Intel Hex Format - * Record Mark Field - This field signifies the start of a - * record, and consists of an ascii colon - * (:). - * - * Record Length Field - This field consists of two ascii - * characters which indicate the number of - * data bytes in this record. The - * characters are the result of converting - * the number of bytes in binary to two - * ascii characters, high digit first. An - * End of File record contains two ascii - * zeros in this field. - * - * Load Address Field - This field consists of the four ascii - * characters which result from converting - * the the binary value of the address in - * which to begin loading this record. The - * order is as follows: - * - * High digit of high byte of address. - * Low digit of high byte of address. - * High digit of low byte of address. - * Low digit of low byte of address. - * - * In an End of File record this field con- - * sists of either four ascii zeros or the - * program entry address. Currently the - * entry address option is not supported. - * - * Record Type Field - This field identifies the record type, - * which is either 0 for data records or 1 - * for an End of File record. It consists - * of two ascii characters, with the high - * digit of the record type first, followed - * by the low digit of the record type. - * - * Data Field - This field consists of the actual data, - * converted to two ascii characters, high - * digit first. There are no data bytes in - * the End of File record. - * - * Checksum Field - The checksum field is the 8 bit binary - * sum of the record length field, the load - * address field, the record type field, - * and the data field. This sum is then - * negated (2's complement) and converted - * to two ascii characters, high digit - * first. - */ - -/* Static variable which holds the count of hex page overruns - * (crossings of the 64kB boundary). Cleared at explicit extended - * address output. - */ -static int hexPageOverrun = 0; - -/* Global which holds the last (16 bit) address of hex record. - * Cleared at begin of new area or when the extended address is output. - */ -unsigned int lastHexAddr = 0; - - -/*)Function hexRecord(addr, rtvalIndex) - * - * unsigned addr starting address of hex record - * int rtvalIndex starting index into the rtval[] array - * - * The function hexRecord() outputs the relocated data - * in the standard Intel Hex format (with inserting - * the extended address record if necessary). - * - * local variables: - * Addr_T chksum byte checksum - * int i index for loops - * int overrun temporary storage for hexPageOverrun - * int bytes counter for bytes written - * - * global variables: - * FILE * ofp output file handle - * int rtcnt count of data words - * int rtflg[] output the data flag - * Addr_T rtval[] relocated data - * - * functions called: - * int fprintf() c_library - * ihxEntendedLinearAddress() lkihx.c - * hexRecord() lkihx.c (recursion) - * - * side effects: - * hexPageOverrun is eventually incremented, - * lastHexAddr is updated - */ - -VOID -hexRecord(unsigned addr, int rtvalIndex) -{ - Addr_T chksum; - int i, overrun, bytes; - - for (i = rtvalIndex, chksum = 0; i < rtcnt; i++) { - if (rtflg[i]) { - if (addr + ++chksum > 0xffff) - break; - } - } - if (chksum == 0) - return; // nothing to output - - if (lastHexAddr > addr) { - overrun = hexPageOverrun + 1; - ihxEntendedLinearAddress(lastExtendedAddress + overrun); - hexPageOverrun = overrun; - hexRecord(addr, rtvalIndex); - return; - } - - lastHexAddr = addr; - fprintf(ofp, ":%02X%04X00", chksum, addr); - chksum += (addr >> 8) + (addr & 0xff); - for (i = rtvalIndex, bytes = 0; i < rtcnt; i++) { - if (rtflg[i]) { - fprintf(ofp, "%02X", rtval[i]); - chksum += rtval[i]; -#if 0 - if (addr + ++bytes > 0xffff) { - if (rflag) { - fprintf(ofp, "%02X\n", (0-chksum) & 0xff); - overrun = hexPageOverrun + 1; - ihxEntendedLinearAddress(lastExtendedAddress + overrun); - hexPageOverrun = overrun; - hexRecord(0, i + 1); - return; - } else { - fprintf(stderr, - "warning: extended linear address encountered; " - "you probably want the -r flag.\n"); - } - } -#endif - } - } - fprintf(ofp, "%02X\n", (0-chksum) & 0xff); -} - -/*)Function ihx(i) - * - * int i 0 - process data - * 1 - end of data - * - * The function ihx() calls the hexRecord() function for processing data - * or writes the End of Data record to the file defined by ofp. - * - * local variables: - * Addr_T n auxiliary variable - * - * global variables: - * int hilo byte order - * FILE * ofp output file handle - * Addr_T rtval[] relocated data - * - * functions called: - * VOID hexRecord() lkihx.c - * int fprintf() c_library - * - * side effects: - * The sequence of rtval[0], rtval[1] is eventually changed. - */ - -VOID -ihx(i) -{ - Addr_T n; - if (i) { - if (ap->a_flag & A_NOLOAD) - return; - if (hilo == 0) { - n = rtval[0]; - rtval[0] = rtval[1]; - rtval[1] = n; - } - hexRecord((rtval[0]<<8) + rtval[1], 2); - } else { - fprintf(ofp, ":00000001FF\n"); - } -} - -/*)Function newArea(i) - * The function newArea() is called when processing of new area is started. - * It resets the value of lastHexAddr. - */ - -VOID -newArea() -{ - lastHexAddr = 0; -} - -/*)Function ihxEntendedLinearAddress(i) - * - * Addr_T i 16 bit extended linear address. - * - * The function ihxEntendedLinearAddress() writes an extended - * linear address record (type 04) to the output file. - * - * local variables: - * Addr_T chksum byte checksum - * - * global variables: - * FILE * ofp output file handle - * - * functions called: - * int fprintf() c_library - * - * side effects: - * The data is output to the file defined by ofp. - * hexPageOverrun and lastHexAddr is cleared - */ -VOID -ihxEntendedLinearAddress(Addr_T a) -{ - Addr_T chksum; - - /* The checksum is the complement of the bytes in the - * record: the 2 is record length, 4 is the extended linear - * address record type, plus the two address bytes. - */ - chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff); - - fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (0-chksum) & 0xff); - hexPageOverrun = 0; - lastHexAddr = 0; -} diff --git a/as/hc08/lklex.c b/as/hc08/lklex.c deleted file mode 100644 index 7c481300..00000000 --- a/as/hc08/lklex.c +++ /dev/null @@ -1,640 +0,0 @@ -/* lklex.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*)Module lklex.c - * - * The module lklex.c contains the general lexical analysis - * functions used to scan the text lines from the .rel files. - * - * lklex.c contains the fllowing functions: - * char endline() - * char get() - * VOID getfid() - * VOID getid() - * VOID getSid() - * int as_getline() - * int getmap() - * char getnb() - * int more() - * VOID skip() - * VOID unget() - * - * lklex.c contains no local variables. - */ - -/*)Function VOID getid(id,c) - * - * char * id a pointer to a string of - * maximum length NCPS - * int c mode flag - * >=0 this is first character to - * copy to the string buffer - * <0 skip white space - * - * The function getid() scans the current input text line - * from the current position copying the next LETTER | DIGIT string - * into the external string buffer (id). The string ends when a non - * LETTER or DIGIT character is found. The maximum number of - * characters copied is NCPS. If the input string is larger than - * NCPS characters then the string is truncated, if the input string - * is shorter than NCPS characters then the string is NULL filled. - * If the mode argument (c) is >=0 then (c) is the first character - * copied to the string buffer, if (c) is <0 then intervening white - * space (SPACES and TABS) are skipped. - * - * local variables: - * char * p pointer to external string buffer - * int c current character value - * - * global variables: - * char ctype[] a character array which defines the - * type of character being processed. - * This index is the character - * being processed. - * - * called functions: - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of getnb(), get(), and unget() updates the - * global pointer ip the position in the current - * input text line. - */ - -VOID -getid(id, c) -register int c; -char *id; -{ - register char *p; - - if (c < 0) { - c = getnb(); - } - p = id; - do { - if (p < &id[NCPS]) - *p++ = c; - } while (ctype[c=get()] & (LETTER|DIGIT)); - unget(c); - while (p < &id[NCPS]) - *p++ = 0; -} - -/*)Function VOID getSid (char *id) - * - * char * id a pointer to a string of - * maximum length NCPS - * - * getSid is derived from getid. It is called from newsym() - * in lksym.c, when an S-record has to be scanned. getSid accepts - * much more characters than getid, which is necessary for SDCC. - * - * The function getSid() scans the current input text line - * from the current position copying the next string - * into the external string buffer (id). The string ends when a space - * character (space, tab, \0) is found. The maximum number of - * characters copied is NCPS. If the input string is larger than - * NCPS characters then the string is truncated, if the input string - * is shorter than NCPS characters then the string is NULL filled. - * Intervening white space (SPACES and TABS) are skipped. - * - * local variables: - * char * p pointer to external string buffer - * int c current character value - * - * global variables: - * char ctype[] a character array which defines the - * type of character being processed. - * This index is the character - * being processed. - * - * called functions: - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of getnb(), get(), and unget() updates the - * global pointer ip the position in the current - * input text line. - */ - -VOID -getSid (id) -char *id; -{ - register int c; - register char *p; - - c = getnb(); - p = id; - do { - if (p < &id[NCPS]) - *p++ = c; - c = get(); - } while (c != '\0' && c != ' ' && c != '\t'); - unget(c); - while (p < &id[NCPS]) - *p++ = 0; -} - -/*)Function VOID getfid(fid,c) - * - * char * str a pointer to a string of - * maximum length PATH_MAX - * int c this is first character to - * copy to the string buffer - * - * The function getfid() scans the current input text line from - * the current position copying the next string into the external - * string buffer (str). The string ends when end of line is found. - * Trailing spacers are removed. The maximum number of characters - * copied is PATH_MAX. If the input string is larger than PATH_MAX - * characters then the string is truncated. The string is NULL - * terminated. - * - * local variables: - * char * p pointer to external string buffer - * int c current character value - * - * global variables: - * char ctype[] a character array which defines the - * type of character being processed. - * This index is the character - * being processed. - * - * called functions: - * char get() lklex.c - * - * side effects: - * use of get() updates the global pointer ip - * the position in the current input text line. - */ - -VOID -getfid(str, c) -register int c; -char *str; -{ - register char *p; - - p = str; - do - { - if (p < &str[PATH_MAX-1]) - *p++ = c; - c = get(); - if (c == ';') - while (c) - c = get(); - } while (c); - /* trim trailing spaces */ - --p; - while (p >= str && ctype[(int)*p] == SPACE) - --p; - /* terminate the string */ - *(++p) = '\0'; -} - -/*)Function char getnb() - * - * The function getnb() scans the current input text - * line returning the first character not a SPACE or TAB. - * - * local variables: - * int c current character from input - * - * global variables: - * none - * - * called functions: - * char get() lklex.c - * - * side effects: - * use of get() updates the global pointer ip, the position - * in the current input text line - */ - -char -getnb() -{ - register int c; - - while ((c=get())==' ' || c=='\t') - ; - return (c); -} - -/*)Function VOID skip() - * - * The function skip() scans the input text skipping all - * letters and digits. - * - * local variables: - * none - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * - * functions called: - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * Input letters and digits are skipped. - */ - -VOID -skip(c) -register int c; -{ - if (c < 0) - c = getnb(); - while (ctype[c=get()] & (LETTER|DIGIT)) { ; } - unget(c); -} - -/*)Function char get() - * - * The function get() returns the next character in the - * input text line, at the end of the line a - * NULL character is returned. - * - * local variables: - * int c current character from - * input text line - * - * global variables: - * char * ip pointer into the current - * input text line - * - * called functions: - * none - * - * side effects: - * updates ip to the next character position in the - * input text line. If ip is at the end of the - * line, ip is not updated. - */ - -char -get() -{ - register int c; - - if ((c = *ip) != 0) - ++ip; - return (c); -} - -/*)Function VOID unget(c) - * - * int c value of last character - * read from input text line - * - * If (c) is not a NULL character then the global pointer ip - * is updated to point to the preceeding character in the - * input text line. - * - * NOTE: This function does not push the character (c) - * back into the input text line, only - * the pointer ip is changed. - * - * local variables: - * int c last character read - * from input text line - * - * global variables: - * char * ip position into the current - * input text line - * - * called functions: - * none - * - * side effects: - * ip decremented by 1 character position - */ - -VOID -unget(c) -{ - if (c != 0) - --ip; -} - -/*)Function int getmap(d) - * - * int d value to compare with the - * input text line character - * - * The function getmap() converts the 'C' style characters \b, \f, - * \n, \r, and \t to their equivalent ascii values and also - * converts 'C' style octal constants '\123' to their equivalent - * numeric values. If the first character is equivalent to (d) then - * a (-1) is returned, if the end of the line is detected then - * a 'q' error terminates the parse for this line, or if the first - * character is not a \ then the character value is returned. - * - * local variables: - * int c value of character - * from input text line - * int n looping counter - * int v current value of numeric conversion - * - * global variables: - * none - * - * called functions: - * char get() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of get() updates the global pointer ip the position - * in the current input text line - */ - -int -getmap(d) -{ - register int c, n, v; - - if ((c = get()) == '\0') - return (-1); - if (c == d) - return (-1); - if (c == '\\') { - c = get(); - switch (c) { - - case 'b': - c = '\b'; - break; - - case 'f': - c = '\f'; - break; - - case 'n': - c = '\n'; - break; - - case 'r': - c = '\r'; - break; - - case 't': - c = '\t'; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - n = 0; - v = 0; - while (++n<=3 && c>='0' && c<='7') { - v = (v<<3) + c - '0'; - c = get(); - } - unget(c); - c = v; - break; - } - } - return (c); -} - -/*)Function int as_getline() - * - * The function as_getline() reads a line of input text from a - * .rel source text file, a .lnk command file or from stdin. - * Lines of text are processed from a single .lnk file or - * multiple .rel files until all files have been read. - * The input text line is copied into the global string ib[] - * and converted to a NULL terminated string. The function - * as_getline() returns a (1) after succesfully reading a line - * or a (0) if all files have been read. - * This function also opens each input .lst file and output - * .rst file as each .rel file is processed. - * - * local variables: - * int i string length - * int ftype file type - * char * fid file name - * - * global variables: - * lfile *cfp The pointer *cfp points to the - * current lfile structure - * lfile *filep The pointer *filep points to the - * beginning of a linked list of - * lfile structures. - * int gline get a line from the LST file - * to translate for the RST file - * char ib[NINPUT] REL file text line - * int pass linker pass number - * int pflag print linker command file flag - * FILE *rfp The file handle to the current - * output RST file - * FILE *sfp The file handle sfp points to the - * currently open file - * FILE * stdin c_library - * FILE * stdout c_library - * FILE *tfp The file handle to the current - * LST file being scanned - * int uflag update listing flag - * - * called functions: - * FILE * afile() lkmain.c - * int fclose() c_library - * char * fgets() c_library - * int fprintf() c_library - * VOID lkulist() lklist.c - * VOID lkexit() lkmain.c - * int strlen() c_library - * - * side effects: - * The input stream is scanned. The .rel files will be - * opened and closed sequentially scanning each in turn. - */ - -int -as_getline() -{ - register int ftype; - register char *fid; - -loop: if (pflag && cfp && cfp->f_type == F_STD) - fprintf(stdout, "ASlink >> "); - - if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) { - if (sfp) { - fclose(sfp); - sfp = NULL; - lkulist(0); - } - if (cfp == NULL) { - cfp = filep; - } else { - cfp = cfp->f_flp; - } - if (cfp) { - ftype = cfp->f_type; - fid = cfp->f_idp; - if (ftype == F_STD) { - sfp = stdin; - } else - if (ftype == F_LNK) { - sfp = afile(fid, "lnk", 0); - } else - if (ftype == F_REL) { - sfp = afile(fid, "rel", 0); - /* if a .cdb file exists then copy it over */ - if (dflag && sfp && dfp && pass == 0) { - FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002 - if (xfp) { - copyfile(dfp,xfp); - fclose(xfp); - } - } - if (uflag && pass != 0) { - SaveLinkedFilePath(fid); //Save the linked path for aomf51 - if ((tfp = afile(fid, "lst", 0)) != NULL) { - if ((rfp = afile(fid, "rst", 1)) == NULL) { - fclose(tfp); - tfp = NULL; - } - } - } - gline = 1; - } else { - fprintf(stderr, "Invalid file type\n"); - lkexit(1); - } - if (sfp == NULL) { - lkexit(1); - } - goto loop; - } else { - filep = NULL; - return(0); - } - } - chop_crlf(ib); - return (1); -} - -/*)Function int more() - * - * The function more() scans the input text line - * skipping white space (SPACES and TABS) and returns a (0) - * if the end of the line or a comment delimeter (;) is found, - * or a (1) if their are additional characters in the line. - * - * local variables: - * int c next character from - * the input text line - * - * global variables: - * none - * - * called functions: - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of getnb() and unget() updates the global pointer ip - * the position in the current input text line - */ - -int -more() -{ - register int c; - - c = getnb(); - unget(c); - return( (c == '\0' || c == ';') ? 0 : 1 ); -} - -/*)Function char endline() - * - * The function endline() scans the input text line - * skipping white space (SPACES and TABS) and returns the next - * character or a (0) if the end of the line is found or a - * comment delimiter (;) is found. - * - * local variables: - * int c next character from - * the input text line - * - * global variables: - * none - * - * called functions: - * char getnb() lklex.c - * - * side effects: - * Use of getnb() updates the global pointer ip the - * position in the current input text line. - */ - -char -endline() -{ - register int c; - - c = getnb(); - return( (c == '\0' || c == ';') ? 0 : c ); -} - -/*)Function VOID chop_crlf(str) - * - * char *str string to chop - * - * The function chop_crlf() removes trailing LF or CR/LF from - * str, if present. - * - * local variables: - * int i string length - * - * global variables: - * none - * - * functions called: - * none - * - * side effects: - * none - */ - -VOID -chop_crlf(str) -char *str; -{ - register int i; - - i = strlen(str); - if (i >= 1 && str[i-1] == '\n') str[i-1] = 0; - if (i >= 2 && str[i-2] == '\r') str[i-2] = 0; -} diff --git a/as/hc08/lklibr.c b/as/hc08/lklibr.c deleted file mode 100644 index 9a36e262..00000000 --- a/as/hc08/lklibr.c +++ /dev/null @@ -1,864 +0,0 @@ -/* lklibr.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * With contributions for the - * object libraries from - * Ken Hornstein - * kenh@cmf.nrl.navy.mil - * - */ - -#define EQ(A,B) !strcmp((A),(B)) -#define MAXLINE 254 /*when using fgets*/ - -#include -#include -#include -#include "aslink.h" - -/*)Module lklibr.c - * - * The module lklibr.c contains the functions which - * (1) specify the path(s) to library files [.LIB] - * (2) specify the library file(s) [.LIB] to search - * (3) search the library files for specific symbols - * and link the module containing this symbol - * - * lklibr.c contains the following functions: - * VOID addpath() - * VOID addlib() - * VOID addfile() - * VOID search() - * VOID fndsym() - * VOID library() - * VOID loadfile() - * - */ - -/*)Function VOID addpath() - * - * The function addpath() creates a linked structure containing - * the paths to various object module library files. - * - * local variables: - * lbpath *lbph pointer to new path structure - * lbpath *lbp temporary pointer - * - * global variables: - * lbpath *lbphead The pointer to the first - * path structure - * - * functions called: - * char getnb() lklex.c - * VOID * new() lksym.c - * int strlen() c_library - * char * strcpy() c_library - * VOID unget() lklex.c - * - * side effects: - * An lbpath structure may be created. - */ - -VOID -addpath() -{ - struct lbpath *lbph, *lbp; - - lbph = (struct lbpath *) new (sizeof(struct lbpath)); - if (lbphead == NULL) { - lbphead = lbph; - } else { - lbp = lbphead; - while (lbp->next) - lbp = lbp->next; - lbp->next = lbph; - } - unget(getnb()); - lbph->path = (char *) new (strlen(ip)+1); - strcpy(lbph->path, ip); -} - -/*)Function VOID addlib() - * - * The function addlib() tests for the existance of a - * library path structure to determine the method of - * adding this library file to the library search structure. - * - * This function calls the function addfile() to actually - * add the library file to the search list. - * - * local variables: - * lbpath *lbph pointer to path structure - * - * global variables: - * lbpath *lbphead The pointer to the first - * path structure - * ip a pointer to the library name - * - * functions called: - * VOID addfile() lklibr.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * The function addfile() may add the file to - * the library search list. - */ - -VOID -addlib() -{ - struct lbpath *lbph; - int foundcount=0; - - unget(getnb()); - - if (lbphead == NULL) - { - foundcount=addfile(NULL, ip); - } - else - { - for (lbph=lbphead; lbph; lbph=lbph->next) - { - foundcount+=addfile(lbph->path, ip); - } - } - if(foundcount == 0) - { - printf("?ASlink-Warning-Couldn't find library '%s'\n", ip); - } -} - -/*)Function int addfile(path,libfil) - * - * char *path library path specification - * char *libfil library file specification - * - * The function addfile() searches for the library file - * by concatenating the path and libfil specifications. - * if the library is found, an lbname structure is created - * and linked to any previously defined structures. This - * linked list is used by the function fndsym() to attempt - * to find any undefined symbols. - * - * The function does not give report an error on invalid - * path / file specifications or if the file is not found. - * - * local variables: - * lbname *lbnh pointer to new name structure - * lbname *lbn temporary pointer - * - * global variables: - * lbname *lbnhead The pointer to the first - * path structure - * - * functions called: - * char getnb() lklex.c - * VOID * new() lksym.c - * int strlen() c_library - * char * strcpy() c_library - * VOID unget() lklex.c - * - * side effects: - * An lbname structure may be created. - * - * return: - * 1: the library was found - * 0: the library was not found - */ - -int addfile(char * path, char * libfil) -{ - FILE *fp; - char *str; - struct lbname *lbnh, *lbn; -#ifdef OTHERSYSTEM - int libfilinc=0; -#endif - - if (path != NULL) - { - str = (char *) new (strlen(path) + strlen(libfil) + 6); - strcpy(str,path); -#ifdef OTHERSYSTEM - if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\')) - { - strcat(str,"/"); - } -#endif - } - else - { - str = (char *) new (strlen(libfil) + 5); - } - -#ifdef OTHERSYSTEM - if ((libfil[0] == '/') || (libfil[0] == '\\')) - { - libfil++; - libfilinc=1; - } -#endif - - strcat(str, libfil); - if(strchr(libfil, FSEPX) == NULL) - { - sprintf(&str[strlen(str)], "%clib", FSEPX); - } - - fp=fopen(str, "r"); - if(fp == NULL) - { - /*Ok, that didn't work. Try with the 'libfil' name only*/ -#ifdef OTHERSYSTEM - if(libfilinc) libfil--; -#endif - fp=fopen(libfil, "r"); - if(fp != NULL) - { - /*Bingo! 'libfil' is the absolute path of the library*/ - strcpy(str, libfil); - path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/ - } - } - - if(path==NULL) - { - /*'path' can not be null since it is needed to find the '.rel' files associated with - the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'. - That way putting 'path' and 'libfil' together will result into the original filepath - as contained in 'str'.*/ - int j; - path = (char *) new (strlen(str) + 1); - strcpy(path, str); - for(j=strlen(path)-1; j>=0; j--) - { - if((path[j] == '/') || (path[j] == '\\')) - { - strcpy(libfil, &path[j+1]); - path[j+1]=0; - break; - } - } - if(j<=0) path[0]=0; - } - - if (fp != NULL) - { - fclose(fp); - lbnh = (struct lbname *) new (sizeof(struct lbname)); - if (lbnhead == NULL) - { - lbnhead = lbnh; - } - else - { - lbn = lbnhead; - while (lbn->next) - lbn = lbn->next; - lbn->next = lbnh; - } - - lbnh->path = path; - lbnh->libfil = (char *) new (strlen(libfil) + 1); - strcpy(lbnh->libfil,libfil); - lbnh->libspc = str; - return 1; - } - else - { - free(str); - return 0; - } -} - -/*)Function VOID search() - * - * The function search() looks through all the symbol tables - * at the end of pass 1. If any undefined symbols are found - * then the function fndsym() is called. Function fndsym() - * searches any specified library files to automagically - * import the object modules containing the needed symbol. - * - * After a symbol is found and imported by the function - * fndsym() the symbol tables are again searched. The - * symbol tables are search until no more symbols can be - * resolved within the library files. This ensures that - * back references from one library module to another are - * also resolved. - * - * local variables: - * int i temporary counter - * sym *sp pointer to a symbol structure - * int symfnd found a symbol flag - * - * global variables: - * sym *symhash[] array of pointers to symbol tables - * - * functions called: - * int fndsym() lklibr.c - * - * side effects: - * If a symbol is found then the library object module - * containing the symbol will be imported and linked. - */ - -VOID -search() -{ - register struct sym *sp; - register int i,symfnd; - - /* - * Look for undefined symbols. Keep - * searching until no more symbols are resolved. - */ - symfnd = 1; - while (symfnd) { - symfnd = 0; - /* - * Look through all the symbols - */ - for (i=0; is_type & S_DEF) == 0) { - if (fndsym(sp->s_id)) { - symfnd++; - } - } - sp = sp->s_sp; - } - } - } -} - -/*Load a .rel file embedded in a sdcclib file*/ -void LoadRel(FILE * libfp, char * ModName) -{ - char str[NINPUT+2]; - int state=0; - - while (fgets(str, NINPUT, libfp) != NULL) - { - str[NINPUT+1] = '\0'; - chop_crlf(str); - switch(state) - { - case 0: - if(EQ(str, "")) - { - fgets(str, NINPUT, libfp); - str[NINPUT+1] = '\0'; - chop_crlf(str); - if(EQ(str, ModName)) state=1; - else - { - printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName); - lkexit(1); - } - } - break; - case 1: - if(EQ(str, "")) state=2; - break; - case 2: - if(EQ(str, "")) return; - ip = str; - link_main(); - break; - } - } -} - -/*Load an .adb file embedded in a sdcclib file. If there is -something between and returns 1, otherwise returns 0. -This way the aomf51 will not have uselless empty modules. */ - -int LoadAdb(FILE * libfp) -{ - char str[MAXLINE+1]; - int state=0; - int ToReturn=0; - - while (fgets(str, MAXLINE, libfp) != NULL) - { - str[NINPUT+1] = '\0'; - chop_crlf(str); - switch(state) - { - case 0: - if(EQ(str, "")) state=1; - break; - case 1: - if(EQ(str, "")) return ToReturn; - fprintf(dfp, "%s\n", str); - ToReturn=1; - break; - } - } - return ToReturn; -} - -/*Check for a symbol in a SDCC library. If found, add the embedded .rel and -.adb files from the library. The library must be created with the SDCC -librarian 'sdcclib' since the linking process depends on the correct file offsets -embedded in the library file.*/ - -int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName) -{ - struct lbfile *lbfh, *lbf; - char ModName[NCPS]=""; - char FLine[MAXLINE+1]; - int state=0; - long IndexOffset=0, FileOffset; - - while(!feof(libfp)) - { - FLine[0]=0; - fgets(FLine, MAXLINE, libfp); - chop_crlf(FLine); - - switch(state) - { - case 0: - if(EQ(FLine, "")) - { - /*The next line has the size of the index*/ - FLine[0]=0; - fgets(FLine, MAXLINE, libfp); - chop_crlf(FLine); - IndexOffset=atol(FLine); - state=1; - } - break; - case 1: - if(EQ(FLine, "")) - { - /*The next line has the name of the module and the offset - of the corresponding embedded file in the library*/ - FLine[0]=0; - fgets(FLine, MAXLINE, libfp); - chop_crlf(FLine); - sscanf(FLine, "%s %ld", ModName, &FileOffset); - state=2; - } - else if(EQ(FLine, "")) - { - /*Reached the end of the index. The symbol is not in this library.*/ - return 0; - } - break; - case 2: - if(EQ(FLine, "")) - { - /*The symbol is not in this module, try the next one*/ - state=1; - } - else - { - /*Check if this is the symbol we are looking for.*/ - if (strncmp(SymName, FLine, NCPS)==0) - { - /*The symbol is in this module.*/ - - /*As in the original library format, it is assumed that the .rel - files reside in the same directory as the lib files.*/ - strcat(DirLib, ModName); - sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX); - - /*If this module has been loaded already don't load it again.*/ - lbf = lbfhead; - while (lbf) - { - if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/ - lbf=lbf->next; - } - - /*Add the embedded file to the list of files to be loaded in - the second pass. That is performed latter by the function - library() below.*/ - lbfh = (struct lbfile *) new (sizeof(struct lbfile)); - if (lbfhead == NULL) - { - lbfhead = lbfh; - } - else - { - lbf = lbfhead; - while (lbf->next) - lbf = lbf->next; - lbf->next = lbfh; - } - - lbfh->libspc = PathLib; - lbfh->filspc = DirLib; - lbfh->relfil = (char *) new (strlen(ModName) + 1); - strcpy(lbfh->relfil, ModName); - /*Library embedded file, so lbfh->offset must be >=0*/ - lbfh->offset = IndexOffset+FileOffset; - - /*Jump to where the .rel begins and load it.*/ - fseek(libfp, lbfh->offset, SEEK_SET); - LoadRel(libfp, ModName); - - /* if cdb information required & .adb file present */ - if (dflag && dfp) - { - if(LoadAdb(libfp)) - SaveLinkedFilePath(DirLib); - } - return 1; /*Found the symbol, so success!*/ - } - } - break; - - default: - return 0; /*It should never reach this point, but just in case...*/ - break; - } - } - - return 0; /*The symbol is not in this library*/ -} - -/*)Function VOID fndsym(name) - * - * char *name symbol name to find - * - * The function fndsym() searches through all combinations of the - * library path specifications (input by the -k option) and the - * library file specifications (input by the -l option) that - * lead to an existing file. - * - * The file specicifation may be formed in one of two ways: - * - * (1) If the library file contained an absolute - * path/file specification then this becomes filspc. - * (i.e. C:\...) - * - * (2) If the library file contains a relative path/file - * specification then the concatenation of the path - * and this file specification becomes filspc. - * (i.e. \...) - * - * The structure lbfile is created for the first library - * object file which contains the definition for the - * specified undefined symbol. - * - * If the library file [.LIB] contains file specifications for - * non existant files, no errors are returned. - * - * local variables: - * char buf[] [.REL] file input line - * char c [.REL] file input character - * FILE *fp file handle for object file - * lbfile *lbf temporary pointer - * lbfile *lbfh pointer to lbfile structure - * FILE *libfp file handle for library file - * lbname *lbnh pointer to lbname structure - * char *path file specification path - * char relfil[] [.REL] file specification - * char *str combined path and file specification - * char symname[] [.REL] file symbol string - * - * global variables: - * lbname *lbnhead The pointer to the first - * name structure - * lbfile *lbfhead The pointer to the first - * file structure - * - * functions called: - * int fclose() c_library - * int fgets() c_library - * FILE *fopen() c_library - * VOID free() c_library - * char getnb() lklex.c - * VOID lkexit() lkmain.c - * VOID loadfile() lklibr.c - * VOID * new() lksym.c - * char * sprintf() c_library - * int sscanf() c_library - * char * strcat() c_library - * char * strchr() c_library - * char * strcpy() c_library - * int strlen() c_library - * int strncmp() c_library - * VOID unget() lklex.c - * - * side effects: - * If the symbol is found then a new lbfile structure - * is created and added to the linked list of lbfile - * structures. The file containing the found symbol - * is linked. - */ - -int -fndsym(name) -char *name; -{ - FILE *libfp, *fp; - struct lbname *lbnh; - struct lbfile *lbfh, *lbf; - char relfil[NINPUT+2]; - char buf[NINPUT+2]; - char symname[NINPUT]; - char *path,*str; - char c; - int result; - - /* - * Search through every library in the linked list "lbnhead". - */ - - for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) - { - if ((libfp = fopen(lbnh->libspc, "r")) == NULL) - { - fprintf(stderr, "Cannot open library file %s\n", - lbnh->libspc); - lkexit(1); - } - path = lbnh->path; - - /* - * Read in a line from the library file. - * This is the relative file specification - * for a .REL file in this library. - */ - - while (fgets(relfil, NINPUT, libfp) != NULL) - { - relfil[NINPUT+1] = '\0'; - chop_crlf(relfil); - if (path != NULL) - { - str = (char *) new (strlen(path)+strlen(relfil)+6); - strcpy(str,path); -#ifdef OTHERSYSTEM - if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\')) - { - strcat(str,"/"); - } -#endif - } - else - { - str = (char *) new (strlen(relfil) + 5); - } - - if(strcmp(relfil, "")==0) - { - result=SdccLib(lbnh->libspc, libfp, str, name); - fclose(libfp); - if(result) return(1); /*Found the symbol*/ - free(str); - /*The symbol is not in the current library, - check the next library in the list*/ - break; - } - - /*From here down is the support for libraries in the original format*/ - if (relfil[0] == '\\') - { - strcat(str,relfil+1); - } - else - { - strcat(str,relfil); - } - - if(strchr(relfil, FSEPX) == NULL) - { - sprintf(&str[strlen(str)], "%crel", FSEPX); - } - - if ((fp = fopen(str, "r")) != NULL) - { - - /* - * Read in the object file. Look for lines that - * begin with "S" and end with "D". These are - * symbol table definitions. If we find one, see - * if it is our symbol. Make sure we only read in - * our object file and don't go into the next one. - */ - - while (fgets(buf, NINPUT, fp) != NULL) - { - buf[NINPUT+1] = '\0'; - chop_crlf(buf); - /* - * Skip everything that's not a symbol record. - */ - if (buf[0] != 'S') continue; - - /* - * When a 'T line' is found terminate file scan. - * All 'S line's preceed 'T line's in .REL files. - */ - if (buf[0] == 'T') break; - - sscanf(buf, "S %s %c", symname, &c); - - /* - * If we find a symbol definition for the - * symbol we're looking for, load in the - * file and add it to lbfhead so it gets - * loaded on pass number 2. - */ - if (strncmp(symname, name, NCPS) == 0 && c == 'D') - { - lbfh = (struct lbfile *) new (sizeof(struct lbfile)); - if (lbfhead == NULL) - { - lbfhead = lbfh; - } - else - { - lbf = lbfhead; - while (lbf->next) - lbf = lbf->next; - lbf->next = lbfh; - } - - lbfh->libspc = lbnh->libspc; - lbfh->filspc = str; - lbfh->relfil = (char *) new (strlen(relfil) + 1); - lbfh->offset = -1; /*Stand alone rel file*/ - strcpy(lbfh->relfil,relfil); - fclose(fp); - fclose(libfp); - - /* if cdb information required & adb file present */ - if (dflag && dfp) - { - FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002 - if (xfp) - { - SaveLinkedFilePath(str); - copyfile(dfp,xfp); - fclose(xfp); - } - } - loadfile(str); - return (1); - } - } - fclose(fp); - } - free(str); - } - fclose(libfp); - } - return(0); -} - -void loadfile_SdccLib(char * libspc, char * module, long offset) -{ - FILE *fp; - - if ((fp = fopen(libspc,"r")) != NULL) - { - fseek(fp, offset, SEEK_SET); - LoadRel(fp, module); - fclose(fp); - } -} - -/*)Function VOID library() - * - * The function library() links all the library object files - * contained in the lbfile structures. - * - * local variables: - * lbfile *lbfh pointer to lbfile structure - * - * global variables: - * lbfile *lbfhead pointer to first lbfile structure - * - * functions called: - * VOID loadfile lklibr.c - * - * side effects: - * Links all files contained in the lbfile structures. - */ - -VOID -library() -{ - struct lbfile *lbfh; - - for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) - { - if(lbfh->offset<0) - { - /*Stand alone rel file (original lib format)*/ - loadfile(lbfh->filspc); - } - else - { - /*rel file embedded in lib (new lib format)*/ - loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset); - } - } -} - -/*)Function VOID loadfile(filspc) - * - * char *filspc library object file specification - * - * The function loadfile() links the library object module. - * - * local variables: - * FILE *fp file handle - * int i input line length - * char str[] file input line - * - * global variables: - * char *ip pointer to linker input string - * - * functions called: - * int fclose() c_library - * int fgets() c_library - * FILE * fopen() c_library - * VOID link_main() lkmain.c - * int strlen() c_library - * - * side effects: - * If file exists it is linked. - */ - -VOID -loadfile(filspc) -char *filspc; -{ - FILE *fp; - char str[NINPUT+2]; - - if ((fp = fopen(filspc,"r")) != NULL) { - while (fgets(str, NINPUT, fp) != NULL) { - str[NINPUT+1] = '\0'; - chop_crlf(str); - ip = str; - link_main(); - } - fclose(fp); - } -} diff --git a/as/hc08/lklist.c b/as/hc08/lklist.c deleted file mode 100644 index 5325ec89..00000000 --- a/as/hc08/lklist.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* lklist.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 28-Oct-97 JLH: - * - lstarea: show s_id as string rather than array [NCPS] - * - lstarea: show a_id as string rather than array [NCPS] - * 31-Oct-97 JLH: add NoICE output file genration in lstarea - * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output - */ - -#include -#include -#include -#include "aslink.h" - -/*)Module lklist.c - * - * The module lklist.c contains the functions which - * output the linker .map file and produce a relocated - * listing .rst file. - * - * lklist.c contains the following functions: - * int dgt() - * VOID lstarea() - * VOID lkulist() - * VOID lkalist() - * VOID lkglist() - * VOID newpag() - * VOID slew() - * - * lklist.c contains no local variables. - */ - -/*)Function VOID slew(fp) - * - * FILE * fp output file handle - * - * The function slew() increments the page line counter. - * If the number of lines exceeds the maximum number of - * lines per page then a page skip and a page header are - * output. - * - * local variables: - * int i loop counter - * - * global variables: - * int lop current line number on page - * int xflag Map file radix type flag - * - * functions called: - * int fprintf() c_library - * VOID newpag() lklist.c - * - * side effects: - * The page line and the page count may be updated. - */ - -VOID -slew(fp) -FILE *fp; -{ - register int i; - - if (lop++ >= NLPP) { - newpag(fp); - if (xflag == 0) { - fprintf(fp, "Hexadecimal\n\n"); - } else - if (xflag == 1) { - fprintf(fp, "Octal\n\n"); - } else - if (xflag == 2) { - fprintf(fp, "Decimal\n\n"); - } - fprintf(fp, "Area Addr Size"); - fprintf(fp, " Decimal Bytes (Attributes)\n"); - for(i=0;i<4;++i) - fprintf(fp, " Value--Global"); - fprintf(fp, "\n\n"); - lop += 6; - } -} - -/*)Function VOID newpag() - * - * The function newpag() outputs a page skip, writes the - * first page header line, sets the line count to 1, and - * increments the page counter. - * - * local variables: - * none - * - * global variables: - * int lop current line number on page - * int page current page number - * - * functions called: - * int fprintf() c_library - * - * side effects: - * The page and line counters are updated. - */ - -VOID -newpag(fp) -FILE *fp; -{ - fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page); - lop = 1; -} - -/* Used for qsort call in lstsym */ -static int _cmpSymByAddr(const void *p1, const void *p2) -{ - struct sym **s1 = (struct sym **)(p1); - struct sym **s2 = (struct sym **)(p2); - int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) - - ((*s2)->s_addr + (*s2)->s_axp->a_addr); - - /* Sort first by address, then by name. */ - if (delta) - { - return delta; - } - return strcmp((*s1)->s_id,(*s2)->s_id); -} - - -#if NCPS-8 - -/* NCPS != 8 */ -/*)Function VOID lstarea(xp) - * - * area * xp pointer to an area structure - * - * The function lstarea() creates the linker map output for - * the area specified by pointer xp. The generated output - * area header includes the area name, starting address, - * size of area, number of words (in decimal), and the - * area attributes. The symbols defined in this area are - * sorted by ascending address and output one per line - * in the selected radix. - * - * local variables: - * areax * oxp pointer to an area extension structure - * int c character value - * int i loop counter - * int j bubble sort update status - * char * ptr pointer to an id string - * int nmsym number of symbols in area - * Addr_T a0 temporary - * Addr_T ai temporary - * Addr_T aj temporary - * sym * sp pointer to a symbol structure - * sym ** p pointer to an array of - * pointers to symbol structures - * - * global variables: - * FILE *mfp Map output file handle - * sym *symhash[NHASH] array of pointers to NHASH - * linked symbol lists - * int xflag Map file radix type flag - * - * functions called: - * int fprintf() c_library - * VOID free() c_library - * char * malloc() c_library - * char putc() c_library - * VOID slew() lklist.c - * - * side effects: - * Map output generated. - */ - -VOID -lstarea(xp) -struct area *xp; -{ - register struct areax *oxp; - register int i; - /* int j; */ - register char *ptr; - int nmsym; - /* Addr_T a0; */ - Addr_T ai, aj; - struct sym *sp; - struct sym **p; - int memPage; - - putc('\n', mfp); - if (xflag == 0) { - fprintf(mfp, "Hexadecimal\n\n"); - } else - if (xflag == 1) { - fprintf(mfp, "Octal\n\n"); - } else - if (xflag == 2) { - fprintf(mfp, "Decimal\n\n"); - } - fprintf(mfp, "Area "); - fprintf(mfp, "Addr Size Decimal %s (Attributes)\n", - (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/ - fprintf(mfp, "-------------------------------- "); - fprintf(mfp, "---- ---- ------- ----- ------------\n"); - /* - * Output Area Header - */ - ptr = &xp->a_id[0]; - fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */ - ai = xp->a_addr; - aj = xp->a_size; - if (xflag == 0) { - fprintf(mfp, " %04X %04X", ai, aj); - } else - if (xflag == 1) { - fprintf(mfp, " %06o %06o", ai, aj); - } else - if (xflag == 2) { - fprintf(mfp, " %05u %05u", ai, aj); - } - fprintf(mfp, " = %6u. %s ", aj, - (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/ - if (xp->a_flag & A_ABS) { - fprintf(mfp, "(ABS"); - } else { - fprintf(mfp, "(REL"); - } - if (xp->a_flag & A_OVR) { - fprintf(mfp, ",OVR"); - } else { - fprintf(mfp, ",CON"); - } - if (xp->a_flag & A_PAG) { - fprintf(mfp, ",PAG"); - } - - memPage = 0x00; - if (xp->a_flag & A_CODE) { - fprintf(mfp, ",CODE"); - memPage = 0x0C; - } - if (xp->a_flag & A_XDATA) { - fprintf(mfp, ",XDATA"); - memPage = 0x0D; - } - if (xp->a_flag & A_BIT) { - fprintf(mfp, ",BIT"); - memPage = 0x0B; - } - fprintf(mfp, ")"); - if (xp->a_flag & A_PAG) { - ai = (ai & 0xFF); - aj = (aj > 256); - if (ai || aj) { fprintf(mfp, " "); } - if (ai) { fprintf(mfp, " Boundary"); } - if (ai & aj) { fprintf(mfp, " /"); } - if (aj) { fprintf(mfp, " Length"); } - if (ai || aj) { fprintf(mfp, " Error"); } - } - - /* - * Find number of symbols in area - */ - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) - ++nmsym; - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - if (nmsym == 0) { - putc('\n', mfp); - return; - } - - /* - * Allocate space for an array of pointers to symbols - * and load array. - */ - if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *))) - == NULL) { - fprintf(mfp, "\nInsufficient space to build Map Segment.\n"); - return; - } - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) { - p[nmsym++] = sp; - } - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - -#if 0 - /* - * Bubble Sort of Addresses in Symbol Table Array - */ - j = 1; - while (j) { - j = 0; - sp = p[0]; - a0 = sp->s_addr + sp->s_axp->a_addr; - for (i=1; is_addr + sp->s_axp->a_addr; - if (a0 > ai) { - j = 1; - p[i] = p[i-1]; - p[i-1] = sp; - } - a0 = ai; - } - } -#else - qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); -#endif - - /* - * Symbol Table Output - */ - - i = 0; - fprintf(mfp, "\n\n"); - fprintf(mfp, " Value Global\n"); - fprintf(mfp, " -------- --------------------------------"); - while (i < nmsym) { - fprintf(mfp, "\n"); - if (memPage != 0) - fprintf(mfp, " %02X:", memPage); - else - fprintf(mfp, " "); - - sp = p[i]; - aj = sp->s_addr + sp->s_axp->a_addr; - if (xflag == 0) { - fprintf(mfp, "%04X ", aj); - } else - if (xflag == 1) { - fprintf(mfp, "%06o ", aj); - } else - if (xflag == 2) { - fprintf(mfp, "%05u ", aj); - } - ptr = &sp->s_id[0]; - fprintf(mfp, "%s", ptr ); - - /* if cdb flag set the output cdb Information - and the symbol has a '$' sign in it then */ - if (dflag && - strchr(ptr,'$')) - fprintf(dfp,"L:%s:%X\n",ptr,aj); - - /* NoICE output of symbol */ - if (jflag) DefineNoICE( ptr, aj, memPage ); - - i++; - } - putc('\n', mfp); - free(p); -} - -#else - -/* NCPS == 8 */ -/*)Function VOID lstarea(xp) - * - * area * xp pointer to an area structure - * - * The function lstarea() creates the linker map output for - * the area specified by pointer xp. The generated output - * area header includes the area name, starting address, - * size of area, number of words (in decimal), and the - * area attributes. The symbols defined in this area are - * sorted by ascending address and output four per line - * in the selected radix. - * - * local variables: - * areax * oxp pointer to an area extension structure - * int c character value - * int i loop counter - * int j bubble sort update status - * char * ptr pointer to an id string - * int nmsym number of symbols in area - * Addr_T a0 temporary - * Addr_T ai temporary - * Addr_T aj temporary - * sym * sp pointer to a symbol structure - * sym ** p pointer to an array of - * pointers to symbol structures - * - * global variables: - * FILE *mfp Map output file handle - * sym *symhash[NHASH] array of pointers to NHASH - * linked symbol lists - * int xflag Map file radix type flag - * - * functions called: - * int fprintf() c_library - * VOID free() c_library - * char * malloc() c_library - * char putc() c_library - * VOID slew() lklist.c - * - * side effects: - * Map output generated. - */ - -VOID -lstarea(xp) -struct area *xp; -{ - register struct areax *oxp; - register c, i, j; - register char *ptr; - int nmsym; - Addr_T a0, ai, aj; - struct sym *sp; - struct sym **p; - int page; - - putc('\n', mfp); - slew(mfp); - /* - * Output Area Header - */ - ptr = &xp->a_id[0]; - while (ptr < &xp->a_id[NCPS]) { - if ((c = *ptr++) != 0) { - putc(c, mfp); - } else { - putc(' ', mfp); - } - } - ai = xp->a_addr; - aj = xp->a_size; - if (xflag == 0) { - fprintf(mfp, " %04X %04X", ai, aj); - } else - if (xflag == 1) { - fprintf(mfp, " %06o %06o", ai, aj); - } else - if (xflag == 2) { - fprintf(mfp, " %05u %05u", ai, aj); - } - fprintf(mfp, " = %6u. bytes ", aj); - if (xp->a_flag & A_ABS) { - fprintf(mfp, "(ABS"); - } else { - fprintf(mfp, "(REL"); - } - if (xp->a_flag & A_OVR) { - fprintf(mfp, ",OVR"); - } else { - fprintf(mfp, ",CON"); - } - if (xp->a_flag & A_PAG) { - fprintf(mfp, ",PAG"); - } - - page = 0x00; - if (xp->a_flag & A_CODE) { - fprintf(mfp, ",CODE"); - memPage = 0x0C; - } - if (xp->a_flag & A_XDATA) { - fprintf(mfp, ",XDATA"); - memPage = 0x0D; - } - if (xp->a_flag & A_BIT) { - fprintf(mfp, ",BIT"); - memPage = 0x0B; - } - fprintf(mfp, ")"); - if (xp->a_flag & A_PAG) { - ai = (ai & 0xFF); - aj = (aj > 256); - if (ai || aj) { fprintf(mfp, " "); } - if (ai) { fprintf(mfp, " Boundary"); } - if (ai & aj) { fprintf(mfp, " /"); } - if (aj) { fprintf(mfp, " Length"); } - if (ai || aj) { fprintf(mfp, " Error"); } - } - - /* - * Find number of symbols in area - */ - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) - ++nmsym; - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - if (nmsym == 0) { - putc('\n', mfp); - slew(mfp); - return; - } - - /* - * Allocate space for an array of pointers to symbols - * and load array. - */ - if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *))) - == NULL) { - fprintf(mfp, "\nInsufficient space to build Map Segment.\n"); - slew(mfp); - return; - } - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) { - p[nmsym++] = sp; - } - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - -#if 0 - /* - * Bubble Sort of Addresses in Symbol Table Array - */ - j = 1; - while (j) { - j = 0; - sp = p[0]; - a0 = sp->s_addr + sp->s_axp->a_addr; - for (i=1; is_addr + sp->s_axp->a_addr; - if (a0 > ai) { - j = 1; - p[i] = p[i-1]; - p[i-1] = sp; - } - a0 = ai; - } - } -#else - qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); -#endif - - /* - * Symbol Table Output - */ - i = 0; - while (i < nmsym) { - fprintf(mfp, "\n"); - slew(mfp); - fprintf(mfp, " "); - sp = p[i]; - aj = sp->s_addr + sp->s_axp->a_addr; - if (xflag == 0) { - fprintf(mfp, " %04X ", aj); - } else - if (xflag == 1) { - fprintf(mfp, "%06o ", aj); - } else - if (xflag == 2) { - fprintf(mfp, " %05u ", aj); - } - ptr = &sp->s_id[0]; - fprintf(mfp, "%s", ptr ); - - /* NoICE output of symbol */ - if (jflag) DefineNoICE( ptr, aj, memPage ); - } - putc('\n', mfp); - free(p); - slew(mfp); -} -#endif - -/*)Function VOID lkulist(i) - * - * int i i # 0 process LST to RST file - * i = 0 copy remainder of LST file - * to RST file and close files - * - * The function lkulist() creates a relocated listing (.rst) - * output file from the ASxxxx assembler listing (.lst) - * files. The .lst file's program address and code bytes - * are changed to reflect the changes made by ASlink as - * the .rel files are combined into a single relocated - * output file. - * - * local variables: - * Addr_T pc current program counter address - * - * global variables: - * int hilo byte order - * int gline get a line from the LST file - * to translate for the RST file - * char rb[] read listing file text line - * FILE *rfp The file handle to the current - * output RST file - * int rtcnt count of data words - * int rtflg[] output the data flag - * Addr_T rtval[] relocated data - * FILE *tfp The file handle to the current - * LST file being scanned - * - * functions called: - * int fclose() c_library - * int fgets() c_library - * int fprintf() c_library - * VOID lkalist() lklist.c - * VOID lkglist() lklist.c - * - * side effects: - * A .rst file is created for each available .lst - * file associated with a .rel file. - */ - -VOID -lkulist(i) -int i; -{ - Addr_T pc; - - /* - * Exit if listing file is not open - */ - if (tfp == NULL) - return; - - /* - * Normal processing of LST to RST - */ - if (i) { - /* - * Evaluate current code address - */ - if (hilo == 0) { - pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF); - } else { - pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF); - } - - /* - * Line with only address - */ - if (rtcnt == 2) { - lkalist(pc); - - /* - * Line with address and code - */ - } else { - for (i=2; i < rtcnt; i++) { - if (rtflg[i]) { - lkglist(pc++, rtval[i] & 0xFF); - } - } - } - - /* - * Copy remainder of LST to RST - */ - } else { - if (gline == 0) - fprintf(rfp, "%s", rb); - - while (fgets(rb, sizeof(rb), tfp) != 0) { - fprintf(rfp, "%s", rb); - } - fclose(tfp); - tfp = NULL; - fclose(rfp); - rfp = NULL; - } -} - -/*)Function VOID lkalist(pc) - * - * int pc current program counter value - * - * The function lkalist() performs the following functions: - * - * (1) if the value of gline = 0 then the current listing - * file line is copied to the relocated listing file output. - * - * (2) the listing file is read line by line and copied to - * the relocated listing file until a valid source - * line number and a program counter value of the correct - * radix is found. The new relocated pc value is substituted - * and the line is written to the RST file. - * - * local variables: - * int i loop counter - * char str[] temporary string - * - * global variables: - * int gcntr data byte counter - * int gline get a line from the LST file - * to translate for the RST file - * char rb[] read listing file text line - * char *rp pointer to listing file text line - * FILE *rfp The file handle to the current - * output RST file - * FILE *tfp The file handle to the current - * LST file being scanned - * - * functions called: - * int dgt() lklist.c - * int fclose() c_library - * int fgets() c_library - * int fprintf() c_library - * int sprintf() c_library - * char * strncpy() c_library - * - * side effects: - * Lines of the LST file are copied to the RST file, - * the last line copied has the code address - * updated to reflect the program relocation. - */ - -VOID -lkalist(pc) -Addr_T pc; -{ - char str[8]; - int i; - - /* - * Exit if listing file is not open - */ -loop: if (tfp == NULL) - return; - - /* - * Copy current LST to RST - */ - if (gline == 0) { - fprintf(rfp, "%s", rb); - gline = 1; - } - - /* - * Clear text line buffer - */ - for (i=0,rp=rb; i -#include -#include -#include "aslink.h" - -#ifdef WIN32T -#include - -void Timer(int action, char * message) -{ - static double start, end, total=0.0; - static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC; - - if(action==0) start=clock()*secs_per_tick; - else if(action==1) - { - end=clock() * secs_per_tick; - printf("%s \t%f seconds.\n", message, (end-start)); - total+=end-start; - } - else - { - printf("Total time: \t%f seconds.\n", total); - total=0.0; - } -} -#endif - -/*)Module lkmain.c - * - * The module lkmain.c contains the functions which - * (1) input the linker options, parameters, and specifications - * (2) perform a two pass link - * (3) produce the appropriate linked data output and/or - * link map file and/or relocated listing files. - * - * lkmain.c contains the following functions: - * FILE * afile(fn,ft,wf) - * VOID bassav() - * VOID gblsav() - * VOID link_main() - * VOID lkexit() - * VOID main(argc,argv) - * VOID map() - * int parse() - * VOID setbas() - * VOID setgbl() - * VOID usage() - * - * lkmain.c contains the following local variables: - * char * usetext[] array of pointers to the - * command option tect lines - * - */ - -/*JCF: Creates some of the default areas so they are allocated in the right order.*/ -void Areas51 (void) -{ - char * rel[]={ - "XH", - "H 7 areas 0 global symbols", - "A _CODE size 0 flags 0", /*Each .rel has one, so...*/ - "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/ - "A REG_BANK_1 size 0 flags 4", - "A REG_BANK_2 size 0 flags 4", - "A REG_BANK_3 size 0 flags 4", - "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/ - "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/ - "" - }; - int j; - - for (j=0; rel[j][0]!=0; j++) - { - ip=rel[j]; - link_main(); - } - - /*Set the start address of the default areas:*/ - for(ap=areap; ap; ap=ap->a_ap) - { - /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr=0x00; ap->a_type=1; } - else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr=0x08; ap->a_type=1; } - else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; } - else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; } - else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; } - } -} - -/*)Function VOID main(argc,argv) - * - * int argc number of command line arguments + 1 - * char * argv[] array of pointers to the command line - * arguments - * - * The function main() evaluates the command line arguments to - * determine if the linker parameters are to input through 'stdin' - * or read from a command file. The functions as_getline() and parse() - * are to input and evaluate the linker parameters. The linking process - * proceeds by making the first pass through each .rel file in the order - * presented to the linker. At the end of the first pass the setbase(), - * lnkarea(), setgbl(), and symdef() functions are called to evaluate - * the base address terms, link all areas, define global variables, - * and look for undefined symbols. Following these routines a linker - * map file may be produced and the linker output files may be opened. - * The second pass through the .rel files will output the linked data - * in one of the four supported formats. - * - * local variables: - * char * p pointer to an argument string - * int c character from argument string - * int i loop counter - * - * global variables: - * text line in ib[] - * lfile *cfp The pointer *cfp points to the - * current lfile structure - * char ctype[] array of character types, one per - * ASCII character - * lfile *filep The pointer *filep points to the - * beginning of a linked list of - * lfile structures. - * head *hp Pointer to the current - * head structure - * char ib[NINPUT] .rel file text line - * char *ip pointer into the .rel file - * lfile *linkp pointer to first lfile structure - * containing an input .rel file - * specification - * int lkerr error flag - * int mflag Map output flag - * int oflag Output file type flag - * FILE *ofp Output file handle - * for word formats - * FILE *ofph Output file handle - * for high byte format - * FILE *ofpl Output file handle - * for low byte format - * int pass linker pass number - * int pflag print linker command file flag - * int radix current number conversion radix - * FILE *sfp The file handle sfp points to the - * currently open file - * lfile *startp asmlnk startup file structure - * FILE * stdin c_library - * FILE * stdout c_library - * - * functions called: - * FILE * afile() lkmain.c - * int fclose() c_library - * int fprintf() c_library - * int as_getline() lklex.c - * VOID library() lklibr.c - * VOID link_main() lkmain.c - * VOID lkexit() lkmain.c - * VOID lnkarea() lkarea.c - * VOID map() lkmain.c - * VOID new() lksym.c - * int parse() lkmain.c - * VOID reloc() lkreloc.c - * VOID search() lklibr.c - * VOID setbas() lkmain.c - * VOID setgbl() lkmain.c - * VOID symdef() lksym.c - * VOID usage() lkmain.c - * - * side effects: - * Completion of main() completes the linking process - * and may produce a map file (.map) and/or a linked - * data files (.ihx or .s19) and/or one or more - * relocated listing files (.rst). - */ - -int -main(argc, argv) -char *argv[]; -{ - register char *p; - register int c, i; - -#ifdef WIN32T - Timer(0, ""); -#endif - - startp = (struct lfile *) new (sizeof (struct lfile)); - - pflag = 1; - for (i=1; if_type = F_STD; - break; - - case 'f': - case 'F': - startp->f_type = F_LNK; - break; - - case 'n': - case 'N': - pflag = 0; - break; - - case 'p': - case 'P': - pflag = 1; - break; - - default: - usage(); - } - } - } else { - if (startp->f_type == F_LNK) { - startp->f_idp = p; - } - } - } - if (startp->f_type == 0) - usage(); - if (startp->f_type == F_LNK && startp->f_idp == NULL) - usage(); - - cfp = NULL; - sfp = NULL; - filep = startp; - while (1) { - ip = ib; - if (as_getline() == 0) - break; - if (pflag && sfp != stdin) - fprintf(stdout, "%s\n", ip); - if (*ip == '\0' || parse()) - break; - } - - if (sfp) { - fclose(sfp); - sfp = NULL; - } - - if (linkp == NULL) - usage(); - - syminit(); - - if (dflag){ - //dfp = afile("temp", "cdb", 1); - SaveLinkedFilePath(linkp->f_idp); //Must be the first one... - dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002 - if (dfp == NULL) - lkexit(1); - } - - for (pass=0; pass<2; ++pass) { - cfp = NULL; - sfp = NULL; - filep = linkp; - hp = NULL; - radix = 10; - - Areas51(); /*JCF: Create the default 8051 areas in the right order*/ - - while (as_getline()) { - ip = ib; - - /* pass any "magic comments" to NoICE output */ - if ((ip[0] == ';') && (ip[1] == '!') && jfp) { - fprintf( jfp, "%s\n", &ip[2] ); - } - link_main(); - } - if (pass == 0) { - /* - * Search libraries for global symbols - */ - search(); - /* - * Set area base addresses. - */ - setbas(); - /* - * Link all area addresses. - */ - lnkarea(); - /* - * Process global definitions. - */ - setgbl(); - /* - * Check for undefined globals. - */ - symdef(stderr); - - /* Open NoICE output file if requested */ - if (jflag) { - jfp = afile(linkp->f_idp, "NOI", 1); - if (jfp == NULL) { - lkexit(1); - } - } - - /* - * Output Link Map if requested, - * or if NoICE output requested (since NoICE - * file is generated in part by map() processing) - */ - if (mflag || jflag) - map(); - - if (sflag) /*JCF: memory usage summary output*/ - if(summary(areap))lkexit(1); - - if (iram_size) - iramcheck(); - - /* - * Open output file - */ - if (oflag == 1) { - ofp = afile(linkp->f_idp, "ihx", 1); - if (ofp == NULL) { - lkexit(1); - } - /* include NoICE command to load hex file */ - if (jfp) fprintf( jfp, "LOAD %s.IHX\n", linkp->f_idp ); - - } else - if (oflag == 2) { - ofp = afile(linkp->f_idp, "S19", 1); - if (ofp == NULL) { - lkexit(1); - } - /* include NoICE command to load hex file */ - if (jfp) fprintf( jfp, "LOAD %s.S19\n", linkp->f_idp ); - } else - if (oflag == 3) { - ofp = afile(linkp->f_idp, "elf", 4); - if (ofp == NULL) { - lkexit(1); - } - } - } else { - /* - * Link in library files - */ - library(); - reloc('E'); - } - } - //JCF: - //CreateAOMF51(); - -#ifdef WIN32T - Timer(1, "Linker execution time"); -#endif - - lkexit(lkerr); - return 0; -} - -/*)Function VOID lkexit(i) - * - * int i exit code - * - * The function lkexit() explicitly closes all open - * files and then terminates the program. - * - * local variables: - * none - * - * global variables: - * FILE * mfp file handle for .map - * FILE * ofp file handle for .ihx/.s19 - * FILE * rfp file hanlde for .rst - * FILE * sfp file handle for .rel - * FILE * tfp file handle for .lst - * - * functions called: - * int fclose() c_library - * VOID exit() c_library - * - * side effects: - * All files closed. Program terminates. - */ - -VOID -lkexit(i) -int i; -{ - if (mfp != NULL) fclose(mfp); - if (jfp != NULL) fclose(jfp); - if (ofp != NULL) fclose(ofp); - if (rfp != NULL) fclose(rfp); - if (sfp != NULL) fclose(sfp); - if (tfp != NULL) fclose(tfp); - if (dfp != NULL) fclose(dfp); - /*if (dfp != NULL) - FILE *xfp = afile(linkp->f_idp,"cdb",1); - dfp = freopen("temp.cdb","r",dfp); - copyfile(xfp,dfp); - fclose(xfp); - fclose(dfp); - remove("temp.cdb"); - }*/ - exit(i); -} - -/*)Function link_main() - * - * The function link_main() evaluates the directives for each line of - * text read from the .rel file(s). The valid directives processed - * are: - * X, D, Q, H, M, A, S, T, R, and P. - * - * local variables: - * int c first non blank character of a line - * - * global variables: - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * int pass linker pass number - * int radix current number conversion radix - * - * functions called: - * char endline() lklex.c - * VOID module() lkhead.c - * VOID newarea() lkarea.c - * VOID newhead() lkhead.c - * sym * newsym() lksym.c - * VOID reloc() lkreloc.c - * - * side effects: - * Head, area, and symbol structures are created and - * the radix is set as the .rel file(s) are read. - */ - -VOID -link_main() -{ - register int c; - - if ((c=endline()) == 0) { return; } - switch (c) { - - case 'O': /*For some important sdcc options*/ - if (pass == 0) - { - if(strlen(sdccopt)==0) - { - strcpy(sdccopt, &ip[1]); - strcpy(sdccopt_module, curr_module); - } - else - { - if(strcmp(sdccopt, &ip[1])!=0) - { - fprintf(stderr, - "?ASlink-Warning-Conflicting sdcc options:\n" - " \"%s\" in module \"%s\" and\n" - " \"%s\" in module \"%s\".\n", - sdccopt, sdccopt_module, &ip[1], curr_module); - lkerr++; - } - } - } - break; - - case 'X': - radix = 16; - break; - - case 'D': - radix = 10; - break; - - case 'Q': - radix = 8; - break; - - case 'H': - if (pass == 0) { - newhead(); - } else { - if (hp == 0) { - hp = headp; - } else { - hp = hp->h_hp; - } - } - sdp.s_area = NULL; - sdp.s_areax = NULL; - sdp.s_addr = 0; - break; - - case 'M': - if (pass == 0) - { - strcpy(curr_module, &ip[1]); - module(); - } - break; - - case 'A': - if (pass == 0) - newarea(); - if (sdp.s_area == NULL) { - sdp.s_area = areap; - sdp.s_areax = areap->a_axp; - sdp.s_addr = 0; - } - break; - - case 'S': - if (pass == 0) - newsym(); - break; - - case 'T': - case 'R': - case 'P': - if (pass == 0) - break; - reloc(c); - break; - - default: - break; - } - if (c == 'X' || c == 'D' || c == 'Q') { - if ((c = get()) == 'H') { - hilo = 1; - } else - if (c == 'L') { - hilo = 0; - } - } -} - - -/*)Function VOID map() - * - * The function map() opens the output map file and calls the various - * routines to - * (1) output the variables in each area, - * (2) list the files processed with module names, - * (3) list the libraries file processed, - * (4) list base address definitions, - * (5) list global variable definitions, and - * (6) list any undefined variables. - * - * local variables: - * int i counter - * head * hdp pointer to head structure - * lbfile *lbfh pointer to library file structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * area *areap The pointer to the first - * area structure of a linked list - * base *basep The pointer to the first - * base structure - * base *bsp Pointer to the current - * base structure - * lfile *filep The pointer *filep points to the - * beginning of a linked list of - * lfile structures. - * globl *globlp The pointer to the first - * globl structure - * globl *gsp Pointer to the current - * globl structure - * head *headp The pointer to the first - * head structure of a linked list - * lbfile *lbfhead The pointer to the first - * lbfile structure of a linked list - * lfile *linkp pointer to first lfile structure - * containing an input REL file - * specification - * int lop current line number on page - * FILE *mfp Map output file handle - * int page current page number - * - * functions called: - * FILE * afile() lkmain.c - * int fprintf() c_library - * VOID lkexit() lkmain.c - * VOID lstarea() lklist.c - * VOID newpag() lklist.c - * VOID symdef() lksym.c - * - * side effects: - * The map file is created. - */ - -VOID -map() -{ - register int i; - register struct head *hdp; - register struct lbfile *lbfh; - - /* - * Open Map File - */ - mfp = afile(linkp->f_idp, "map", 1); - if (mfp == NULL) { - lkexit(1); - } - - /* - * Output Map Area Lists - */ - page = 0; - lop = NLPP; - ap = areap; - while (ap) { - lstarea(ap); - ap = ap->a_ap; - } - /* - * List Linked Files - */ - newpag(mfp); - fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n"); - hdp = headp; - filep = linkp; - while (filep) { - fprintf(mfp, "%-16s", filep->f_idp); - i = 0; - while ((hdp != NULL) && (hdp->h_lfile == filep)) { - if (i % 5) { - fprintf(mfp, ", %8.8s", hdp->m_id); - } else { - if (i) { - fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id); - } else { - fprintf(mfp, " [ %8.8s", hdp->m_id); - } - } - hdp = hdp->h_hp; - i++; - } - if (i) - fprintf(mfp, " ]"); - fprintf(mfp, "\n"); - filep = filep->f_flp; - } - /* - * List Linked Libraries - */ - if (lbfhead != NULL) { - fprintf(mfp, - "\nLibraries Linked [ object file ]\n\n"); - for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) { - fprintf(mfp, "%-32s [ %16.16s ]\n", - lbfh->libspc, lbfh->relfil); - } - fprintf(mfp, "\n"); - } - /* - * List Base Address Definitions - */ - if (basep) { - newpag(mfp); - fprintf(mfp, "\nUser Base Address Definitions\n\n"); - bsp = basep; - while (bsp) { - fprintf(mfp, "%s\n", bsp->b_strp); - bsp = bsp->b_base; - } - } - /* - * List Global Definitions - */ - if (globlp) { - newpag(mfp); - fprintf(mfp, "\nUser Global Definitions\n\n"); - gsp = globlp; - while (gsp) { - fprintf(mfp, "%s\n", gsp->g_strp); - gsp = gsp->g_globl; - } - } - fprintf(mfp, "\n\f"); - symdef(mfp); -} - -/*)Function int parse() - * - * The function parse() evaluates all command line or file input - * linker directives and updates the appropriate variables. - * - * local variables: - * int c character value - * char fid[] file id string - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * lfile *lfp pointer to current lfile structure - * being processed by parse() - * lfile *linkp pointer to first lfile structure - * containing an input REL file - * specification - * int mflag Map output flag - * int oflag Output file type flag - * int pflag print linker command file flag - * FILE * stderr c_library - * int uflag Relocated listing flag - * int xflag Map file radix type flag - * - * Functions called: - * VOID addlib() lklibr.c - * VOID addpath() lklibr.c - * VOID bassav() lkmain.c - * int fprintf() c_library - * VOID gblsav() lkmain.c - * VOID getfid() lklex.c - * char getnb() lklex.c - * VOID lkexit() lkmain.c - * char * strcpy() c_library - * int strlen() c_library - * - * side effects: - * Various linker flags are updated and the linked - * structure lfile is created. - */ - -int -parse() -{ - register int c; - char fid[NINPUT]; - - while ((c = getnb()) != 0) { - if ( c == ';') - return(0); - if ( c == '-') { - while (ctype[c=get()] & LETTER) { - switch(c) { - - case 'i': - case 'I': - oflag = 1; - break; - - case 's': - case 'S': - oflag = 2; - break; - - case 't': - case 'T': - oflag = 3; - break; - - case 'm': - case 'M': - ++mflag; - break; - - case 'y': /*JCF: memory usage summary output*/ - case 'Y': - ++sflag; - break; - - case 'j': - case 'J': - jflag = 1; - break; - - case 'u': - case 'U': - uflag = 1; - break; - case 'r': - case 'R': - rflag = 1; - break; - case 'x': - case 'X': - xflag = 0; - break; - - case 'q': - case 'Q': - xflag = 1; - break; - - case 'd': - case 'D': - xflag = 2; - break; - - case 'e': - case 'E': - return(1); - - case 'n': - case 'N': - pflag = 0; - break; - - case 'p': - case 'P': - pflag = 1; - break; - - case 'b': - case 'B': - bassav(); - return(0); - - case 'g': - case 'G': - gblsav(); - return(0); - - case 'k': - case 'K': - addpath(); - return(0); - - case 'l': - case 'L': - addlib(); - return(0); - - case 'a': - case 'A': - iramsav(); - return(0); - - case 'v': - case 'V': - xramsav(); - return(0); - - case 'w': - case 'W': - codesav(); - return(0); - - case 'z': - case 'Z': - dflag = 1; - return(0); - default: - fprintf(stderr, "Invalid option\n"); - lkexit(1); - } - } - if ( c == ';') - return(0); - } else - if (ctype[c] & ILL) { - fprintf(stderr, "Invalid input"); - lkexit(1); - } else { - if (linkp == NULL) { - linkp = (struct lfile *) - new (sizeof (struct lfile)); - lfp = linkp; - } else { - lfp->f_flp = (struct lfile *) - new (sizeof (struct lfile)); - lfp = lfp->f_flp; - } - getfid(fid, c); - lfp->f_idp = (char *) new (strlen(fid)+1); - strcpy(lfp->f_idp, fid); - lfp->f_type = F_REL; - } - } - return(0); -} - -/*)Function VOID bassav() - * - * The function bassav() creates a linked structure containing - * the base address strings input to the linker. - * - * local variables: - * none - * - * global variables: - * base *basep The pointer to the first - * base structure - * base *bsp Pointer to the current - * base structure - * char *ip pointer into the REL file - * text line in ib[] - * - * functions called: - * char getnb() lklex.c - * VOID * new() lksym.c - * int strlen() c_library - * char * strcpy() c_library - * VOID unget() lklex.c - * - * side effects: - * The basep structure is created. - */ - -VOID -bassav() -{ - if (basep == NULL) { - basep = (struct base *) - new (sizeof (struct base)); - bsp = basep; - } else { - bsp->b_base = (struct base *) - new (sizeof (struct base)); - bsp = bsp->b_base; - } - unget(getnb()); - bsp->b_strp = (char *) new (strlen(ip)+1); - strcpy(bsp->b_strp, ip); -} - -/*)Function VOID setbas() - * - * The function setbas() scans the base address lines in hte - * basep structure, evaluates the arguments, and sets beginning - * address of the specified areas. - * - * local variables: - * int v expression value - * char id[] base id string - * - * global variables: - * area *ap Pointer to the current - * area structure - * area *areap The pointer to the first - * area structure of a linked list - * base *basep The pointer to the first - * base structure - * base *bsp Pointer to the current - * base structure - * char *ip pointer into the REL file - * text line in ib[] - * int lkerr error flag - * - * functions called: - * Addr_T expr() lkeval.c - * int fprintf() c_library - * VOID getid() lklex.c - * char getnb() lklex.c - * int symeq() lksym.c - * - * side effects: - * The base address of an area is set. - */ - -VOID -setbas() -{ - register int v; - char id[NCPS]; - - bsp = basep; - while (bsp) { - ip = bsp->b_strp; - getid(id, -1); - if (getnb() == '=') { - v = expr(0); - for (ap = areap; ap != NULL; ap = ap->a_ap) { - if (symeq(id, ap->a_id)) - break; - } - if (ap == NULL) { - fprintf(stderr, - "ASlink-Warning-No definition of area %s\n", id); - lkerr++; - } else { - ap->a_addr = v; - ap->a_type = 1; /* JLH: value set */ - } - } else { - fprintf(stderr, "ASlink-Warning-No '=' in base expression"); - lkerr++; - } - bsp = bsp->b_base; - } -} - -/*)Function VOID gblsav() - * - * The function gblsav() creates a linked structure containing - * the global variable strings input to the linker. - * - * local variable: - * none - * - * global variables: - * globl *globlp The pointer to the first - * globl structure - * globl *gsp Pointer to the current - * globl structure - * char *ip pointer into the REL file - * text line in ib[] - * int lkerr error flag - * - * functions called: - * char getnb() lklex.c - * VOID * new() lksym.c - * int strlen() c_library - * char * strcpy() c_library - * VOID unget() lklex.c - * - * side effects: - * The globlp structure is created. - */ - -VOID -gblsav() -{ - if (globlp == NULL) { - globlp = (struct globl *) - new (sizeof (struct globl)); - gsp = globlp; - } else { - gsp->g_globl = (struct globl *) - new (sizeof (struct globl)); - gsp = gsp->g_globl; - } - unget(getnb()); - gsp->g_strp = (char *) new (strlen(ip)+1); - strcpy(gsp->g_strp, ip); -} - -/*)Function VOID setgbl() - * - * The function setgbl() scans the global variable lines in hte - * globlp structure, evaluates the arguments, and sets a variable - * to this value. - * - * local variables: - * int v expression value - * char id[] base id string - * sym * sp pointer to a symbol structure - * - * global variables: - * char *ip pointer into the REL file - * text line in ib[] - * globl *globlp The pointer to the first - * globl structure - * globl *gsp Pointer to the current - * globl structure - * FILE * stderr c_library - * int lkerr error flag - * - * functions called: - * Addr_T expr() lkeval.c - * int fprintf() c_library - * VOID getid() lklex.c - * char getnb() lklex.c - * sym * lkpsym() lksym.c - * - * side effects: - * The value of a variable is set. - */ - -VOID -setgbl() -{ - register int v; - register struct sym *sp; - char id[NCPS]; - - gsp = globlp; - while (gsp) { - ip = gsp->g_strp; - getid(id, -1); - if (getnb() == '=') { - v = expr(0); - sp = lkpsym(id, 0); - if (sp == NULL) { - fprintf(stderr, - "No definition of symbol %s\n", id); - lkerr++; - } else { - if (sp->s_flag & S_DEF) { - fprintf(stderr, - "Redefinition of symbol %s\n", id); - lkerr++; - sp->s_axp = NULL; - } - sp->s_addr = v; - sp->s_type |= S_DEF; - } - } else { - fprintf(stderr, "No '=' in global expression"); - lkerr++; - } - gsp = gsp->g_globl; - } -} - -/*)Function FILE * afile(fn,, ft, wf) - * - * char * fn file specification string - * char * ft file type string - * int wf read(0)/write(1) flag - * - * The function afile() opens a file for reading or writing. - * (1) If the file type specification string ft - * is not NULL then a file specification is - * constructed with the file path\name in fn - * and the extension in ft. - * (2) If the file type specification string ft - * is NULL then the file specification is - * constructed from fn. If fn does not have - * a file type then the default .rel file - * type is appended to the file specification. - * - * afile() returns a file handle for the opened file or aborts - * the assembler on an open error. - * - * local variables: - * char fb[] constructed file specification string - * FILE * fp filehandle for opened file - * - * global variables: - * int lkerr error flag - * - * functions called: - * FILE * fopen() c_library - * int fprintf() c_library - * - * side effects: - * File is opened for read or write. - */ - -FILE * -afile(fn, ft, wf) -char *fn; -char *ft; -{ - FILE *fp; - char fb[PATH_MAX]; - char *omode; - int i; - - switch (wf) { - case 0: omode = "r"; break; - case 1: omode = "w"; break; - case 2: omode = "a"; break; - case 3: omode = "rb"; break; - case 4: omode = "wb"; break; - case 5: omode = "ab"; break; - default: omode = "r"; break; - } - - /*Look backward the name path and get rid of the extension, if any*/ - i=strlen(fn); - for(; (fn[i]!='.')&&(fn[i]!='\\')&&(fn[i]!='/')&&(i>0); i--); - if( (fn[i]=='.') && strcmp(ft, "lnk") ) - { - strncpy(fb, fn, i); - fb[i]=0; - } - else - { - strcpy(fb, fn); - } - - /*Add the extension*/ - if (fb[i] != '.') - { - strcat(fb, "."); - strcat(fb, strlen(ft)?ft:"rel"); - } - - fp = fopen(fb, omode); - if (fp==NULL) - { - if (strcmp(ft,"adb"))/*Do not complaint for optional adb files*/ - { - fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open"); - lkerr++; - } - } - return (fp); -} - -/*)Function VOID iramsav() - * - * The function iramsav() stores the size of the chip's internal RAM. - * This is used after linking to check that variable assignment to this - * dataspace didn't overflow into adjoining segments. Variables in the - * DSEG, OSEG, and ISEG are assigned to this dataspace. - * - * local variables: - * none - * - * global variables: - * char *ip pointer into the REL file - * text line in ib[] - * unsigned int size of chip's internal - * iram_size RAM segment - * - * functions called: - * char getnb() lklex.c - * VOID unget() lklex.c - * Addr_T expr() lkeval.c - * - * side effects: - * The iram_size may be modified. - */ - -VOID -iramsav() -{ - unget(getnb()); - if (ip && *ip) - //iram_size = atoi(ip); - iram_size = expr(0); /* evaluate size expression */ - else - iram_size = 128; /* Default is 128 (0x80) bytes */ -} - -/*Similar to iramsav but for xram memory*/ -VOID -xramsav() -{ - unget(getnb()); - if (ip && *ip) - xram_size = expr(0); /* evaluate size expression */ - else - xram_size = rflag?0x1000000:0x10000; -} - -/*Similar to iramsav but for code memory*/ -VOID -codesav() -{ - unget(getnb()); - if (ip && *ip) - code_size = expr(0); /* evaluate size expression */ - else - code_size = rflag?0x1000000:0x10000; -} - - -/*)Function VOID iramcheck() - * - * The function iramcheck() is used at the end of linking to check that - * the internal RAM area wasn't overflowed by too many variable - * assignments. Variables in the DSEG, ISEG, and OSEG are assigned to - * the chip's internal RAM. - * - * local variables: - * none - * - * global variables: - * unsigned int size of chip's internal - * iram_size RAM segment - * struct area linked list of memory - * *areap areas - * - * functions called: - * - * side effects: - */ - -VOID -iramcheck() -{ - register unsigned int last_addr; - register struct area *ap; - - for (ap = areap; ap; ap=ap->a_ap) { - if ((ap->a_size != 0) && - (!strcmp(ap->a_id, "DSEG") || - !strcmp(ap->a_id, "OSEG") || - !strcmp(ap->a_id, "ISEG") - ) - ) - { - last_addr = ap->a_addr + ap->a_size - 1; - if (last_addr >= iram_size) - fprintf(stderr, - "\nWARNING! Segment %s extends past the end\n" - " of internal RAM. Check map file.\n", - ap->a_id); - } - } -} - -char *usetxt[] = { - "Startup:", - " -c Command line input", - " -f file[LNK] File input", - " -p Prompt and echo of file[LNK] to stdout (default)", - " -n No echo of file[LNK] to stdout", -/* "Usage: [-Options] file [file ...]", */ - "Libraries:", - " -k Library path specification, one per -k", - " -l Library file specification, one per -l", - "Relocation:", - " -b area base address = expression", - " -g global symbol = expression", - "Map format:", - " -m Map output generated as file[MAP]", - " -x Hexadecimal (default), -d Decimal, -q Octal", - "Output:", - " -i Intel Hex as file[IHX]", - " -s Motorola S19 as file[S19]", - " -t ELF executable as file[elf]", - " -j Produce NoICE debug as file[NOI]", - " -z Produce SDCdb debug as file[cdb]", -/* "List:", */ - " -u Update listing file(s) with link data as file(s)[.RST]", - "Miscellaneous:\n" - " -a [iram-size] Check for internal RAM overflow", - " -v [xram-size] Check for external RAM overflow", - " -w [code-size] Check for code overflow", - "End:", - " -e or null line terminates input", - 0 -}; - -/*)Function VOID usage() - * - * The function usage() outputs to the stderr device the - * assembler name and version and a list of valid assembler options. - * - * local variables: - * char ** dp pointer to an array of - * text string pointers. - * - * global variables: - * FILE * stderr c_library - * - * functions called: - * int fprintf() c_library - * - * side effects: - * none - */ - -VOID -usage() -{ - register char **dp; - - fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION); - for (dp = usetxt; *dp; dp++) - fprintf(stderr, "%s\n", *dp); - lkexit(1); -} - -/*)Function VOID copyfile() - * - * FILE *dest destination file - * FILE *src source file - * - * function will copy source file to destination file - * - * - * functions called: - * int fgetc() c_library - * int fputc() c_library - * - * side effects: - * none - */ -VOID copyfile (dest,src) -FILE *src,*dest ; -{ - int ch; - while ((ch = fgetc(src)) != EOF) { - - fputc(ch,dest); - } -} diff --git a/as/hc08/lkmem.c b/as/hc08/lkmem.c deleted file mode 100644 index db9a2cd9..00000000 --- a/as/hc08/lkmem.c +++ /dev/null @@ -1,361 +0,0 @@ -/*------------------------------------------------------------------------- - lkmem.c - Create a memory summary file with extension .mem - - Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002) - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --------------------------------------------------------------------------*/ - -#include -#include -#include -#include "aslink.h" -#include "strcmpi.h" - -int summary(struct area * areap) -{ - #define EQ(A,B) !as_strcmpi((A),(B)) - #define MIN_STACK 16 - #define REPORT_ERROR(A, H) \ - {\ - fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \ - fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \ - toreturn=1; \ - } - - #define REPORT_WARNING(A, H) \ - { \ - fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \ - fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \ - } - - char buff[128]; - int j, toreturn=0; - unsigned int Total_Last=0, k; - - struct area * xp; - FILE * of; - - /*Artifacts used for printing*/ - char start[15], end[15], size[15], max[15]; - char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n"; - char line[]="---------------------"; - - typedef struct - { - unsigned long Start; - unsigned long Size; - unsigned long Max; - char Name[NCPS]; - unsigned long flag; - } _Mem; - - unsigned int dram[0x100]; - _Mem Ram[]={ - {0, 0, 0, "REG_BANK_0", 0x0001}, - {0x0, 0, 0, "REG_BANK_1", 0x0002}, - {0x0, 0, 0, "REG_BANK_2", 0x0004}, - {0x0, 0, 0, "REG_BANK_3", 0x0008}, - {0x0, 0, 0, "BSEG_BYTES", 0x0010}, - {0, 0, 256, "UNUSED", 0x0000}, - {0xff, 0, 256, "DATA", 0x0020}, - {0, 0, 256, "TOTAL:", 0x0000} - }; - - _Mem IRam= {0xff, 0, 0, "INDIRECT RAM", 0x0080}; - _Mem Stack={0xff, 0, 1, "STACK", 0x0000}; - _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100}; - _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200}; - -#if 0 - if(rflag) /*For the DS390*/ - { - XRam.Max=0x1000000; /*24 bits*/ - XRam.Start=0xffffff; - Rom.Max=0x1000000; - Rom.Start=0xffffff; - } - - if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/ - { - Ram[5].Max=0x80; - Ram[6].Max=0x80; - Ram[7].Max=0x80; - IRam.Max=0x80; - iram_size=0x100; - } - else if(iram_size<0x80) - { - Ram[5].Max=iram_size; - Ram[6].Max=iram_size; - Ram[7].Max=iram_size; - IRam.Max=0; - } - else - { - Ram[5].Max=0x80; - Ram[6].Max=0x80; - Ram[7].Max=0x80; - IRam.Max=iram_size-0x80; - } -#endif - - for(j=0; j<(int)iram_size; j++) dram[j]=0; - for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/ - - /* Open Memory Summary File*/ - of = afile(linkp->f_idp, "mem", 1); - if (of == NULL) - { - lkexit(1); - } - - xp=areap; - while (xp) - { - /**/ if (EQ(xp->a_id, "REG_BANK_0")) - { - Ram[0].Size=xp->a_size; - } - else if (EQ(xp->a_id, "REG_BANK_1")) - { - Ram[1].Size=xp->a_size; - } - else if (EQ(xp->a_id, "REG_BANK_2")) - { - Ram[2].Size=xp->a_size; - } - else if (EQ(xp->a_id, "REG_BANK_3")) - { - Ram[3].Size=xp->a_size; - } - else if (EQ(xp->a_id, "BSEG_BYTES")) - { - Ram[4].Size=xp->a_size; - } - else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") ) - { - Ram[6].Size+=xp->a_size; - if(xp->a_addra_addr; - } - - else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") || - EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") ) - { - Rom.Size+=xp->a_size; - if(xp->a_addra_addr; - } - - else if (EQ(xp->a_id, "SSEG")) - { - Stack.Size+=xp->a_size; - if(xp->a_addra_addr; - } - - else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) - { - XRam.Size+=xp->a_size; - if(xp->a_addra_addr; - } - - else if (EQ(xp->a_id, "ISEG")) - { - IRam.Size+=xp->a_size; - if(xp->a_addra_addr; - } - xp=xp->a_ap; - } - - for(j=0; j<7; j++) - for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++) - dram[k]|=Ram[j].flag; /*Mark as used*/ - -#if 0 - for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++) - dram[k]|=IRam.flag; /*Mark as used*/ -#endif - - /*Compute the amount of unused memory in direct data Ram. This is the - gap between the last register bank or bit segment and the data segment.*/ - for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--); - Ram[5].Start=k+1; - Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/ - - /*Compute the data Ram totals*/ - for(j=0; j<7; j++) - { - if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start; - Ram[7].Size+=Ram[j].Size; - } - Total_Last=Ram[6].Size+Ram[6].Start-1; - - /*Report the Ram totals*/ - fprintf(of, "Direct Internal RAM:\n"); - fprintf(of, format, "Name", "Start", "End", "Size", "Max"); - - for(j=0; j<8; j++) - { - if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line); - if((j!=5) || (Ram[j].Size>0)) - { - sprintf(start, "0x%02lx", Ram[j].Start); - if(Ram[j].Size==0) - end[0]=0;/*Empty string*/ - else - sprintf(end, "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1); - sprintf(size, "%5lu", Ram[j].Size); - sprintf(max, "%5lu", Ram[j].Max); - fprintf(of, format, Ram[j].Name, start, end, size, max); - } - } - -#if 0 - for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++) - { - if(dram[k]!=Ram[6].flag) - { - sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k); - REPORT_ERROR(buff, 1); - break; - } - } - - - if(Ram[4].Size>Ram[4].Max) - { - k=Ram[4].Size-Ram[4].Max; - sprintf(buff, "Insufficient bit addressable memory. " - "%d byte%s short.\n", k, (k==1)?"":"s"); - REPORT_ERROR(buff, 1); - } - - if(Ram[5].Size!=0) - { - sprintf(buff, "%ld bytes in data memory wasted. " - "SDCC link could use: --data-loc 0x%02lx\n", - Ram[5].Size, Ram[6].Start-Ram[5].Size); - REPORT_WARNING(buff, 1); - } - - if((Ram[6].Start+Ram[6].Size)>Ram[6].Max) - { - k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max; - sprintf(buff, "Insufficient space in data memory. " - "%d byte%s short.\n", k, (k==1)?"":"s"); - REPORT_ERROR(buff, 1); - } -#endif - /*Report the position of the begining of the stack*/ - fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)", - rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1); - -#if 0 - /*Check that the stack pointer is landing in a safe place:*/ - if( (dram[Stack.Start] & 0x8000) == 0x8000 ) - { - fprintf(of, ".\n"); - sprintf(buff, "Stack set to unavailable memory.\n"); - REPORT_ERROR(buff, 1); - } - else if(dram[Stack.Start]) - { - fprintf(of, ".\n"); - sprintf(buff, "Stack overlaps area "); - REPORT_ERROR(buff, 1); - for(j=0; j<7; j++) - { - if(dram[Stack.Start]&Ram[j].flag) - { - sprintf(buff, "'%s'\n", Ram[j].Name); - break; - } - } - if(dram[Stack.Start]&IRam.flag) - { - sprintf(buff, "'%s'\n", IRam.Name); - } - REPORT_ERROR(buff, 0); - } - else - { - for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++); - fprintf(of, " with %d bytes available\n", k); - if (k(IRam.Max+0x80)) - { - sprintf(buff, "Insufficient INDIRECT RAM memory.\n"); - REPORT_ERROR(buff, 1); - } -#endif - if( ((XRam.Start+XRam.Size)>XRam.Max) || - (((int)XRam.Size>xram_size)&&(xram_size>=0)) ) - { - sprintf(buff, "Insufficient EXTERNAL RAM memory.\n"); - REPORT_ERROR(buff, 1); - } - if( ((Rom.Start+Rom.Size)>Rom.Max) || - (((int)Rom.Size>code_size)&&(code_size>=0)) ) - { - sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n"); - REPORT_ERROR(buff, 1); - } - - fclose(of); - return toreturn; -} diff --git a/as/hc08/lknoice.c b/as/hc08/lknoice.c deleted file mode 100644 index 2cd6a91c..00000000 --- a/as/hc08/lknoice.c +++ /dev/null @@ -1,246 +0,0 @@ -/* lknoice.c */ - -/* - * Extensions to CUG 292 linker ASLINK to produce NoICE debug files - * - * 31-Oct-1997 by John Hartman - * 30-Jan-98 JLH add page to DefineNoICE for 8051 - * 2-Feb-98 JLH Allow optional .nest on local vars - C scoping rules... - */ - -#include -#include -#include -#include "aslink.h" -#include "strcmpi.h" - -static void DefineGlobal( char *name, Addr_T value, int page ); -static void DefineScoped( char *name, Addr_T value, int page ); -static void DefineFile( char *name, Addr_T value, int page ); -static void DefineFunction( char *name, Addr_T value, int page ); -static void DefineStaticFunction( char *name, Addr_T value, int page ); -static void DefineEndFunction( Addr_T value, int page ); -static void DefineLine( char *lineString, Addr_T value, int page ); -static void PagedAddress( Addr_T value, int page ); - -/* - * Called from lstarea in lklist.c for each symbol. - * - * Generates appropriate NoICE commands into output file, if any is open - * - */ -void DefineNoICE( char *name, Addr_T value, int page ) -{ - char token1[NCPS]; /* parse for file.function.symbol */ - char token2[NCPS]; - char token3[NCPS]; - // char token4[NCPS]; - char sep1, sep2; - int j, level; - - /* no output if file is not open */ - if (jfp == NULL) return; - - j = sscanf( name, "%[^.]%c%[^.]%c%s", - token1, &sep1, token2, &sep2, token3 ); - switch (j) - { - /* file.function.symbol, or file.function..SPECIAL */ - case 5: - DefineFile( token1, 0, 0 ); - if (token3[0] == '.') - { - if (strcmp( token3, ".FN" ) == 0) - { - /* Global function */ - DefineFunction( token2, value, page ); - } - else if (strcmp( token3, ".SFN" ) == 0) - { - /* Static (file-scope) function */ - DefineStaticFunction( token2, value, page ); - } - else if (strcmp( token3, ".EFN" ) == 0) - { - /* End of function */ - DefineEndFunction( value, page ); - } - } - else - { - /* Function-scope var. */ - DefineFunction( token2, 0, 0 ); - - /* Look for optional level integer */ - j = sscanf( token3, "%[^.]%c%u", token1, &sep1, &level ); - if ((j == 3) && (level != 0)) - { - sprintf( &token1[ strlen(token1) ], "_%u", level ); - } - DefineScoped( token1, value, page ); - } - break; - - /* file.func. is illegal */ - case 4: - break; - - /* either file.symbol or file.line# */ - case 3: - DefineFile( token1, 0, 0 ); - if ((token2[0] >= '0') && (token2[0] <= '9')) - { - /* Line number */ - DefineLine( token2, value, page ); - } - else - { - /* File-scope symbol. (Kill any function) */ - DefineEndFunction( 0, 0 ); - DefineScoped( token2, value, page ); - } - break; - - /* symbol. is illegal */ - case 2: - break; - - /* just a symbol */ - case 1: - DefineGlobal( token1, value, page ); - break; - } -} - -static char currentFile[NCPS]; -static char currentFunction[NCPS]; - -/* - * static function: - * Define "name" as a global symbol - */ -void DefineGlobal( char *name, Addr_T value, int page ) -{ - fprintf( jfp, "DEF %s ", name ); - PagedAddress( value, page ); -} - -/* - * static function: - * Define "name" as a static (scoped) symbol - */ -void DefineScoped( char *name, Addr_T value, int page ) -{ - fprintf( jfp, "DEFS %s ", name ); - PagedAddress( value, page ); -} - -/* - * static function: - * Define "name" as the current file - */ -void DefineFile( char *name, Addr_T value, int page ) -{ - if (as_strcmpi( name, currentFile ) != 0) - { - strcpy( currentFile, name ); - if (value != 0) - { - fprintf( jfp, "FILE %s ", name ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "FILE %s\n", name ); - } - } -} - -/* - * static function: - * Define "name" as the current function - */ -void DefineFunction( char *name, Addr_T value, int page ) -{ - if (as_strcmpi( name, currentFunction ) != 0) - { - strcpy( currentFunction, name ); - if (value != 0) - { - fprintf( jfp, "DEF %s ", name ); - PagedAddress( value, page ); - fprintf( jfp, "FUNC %s ", name ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "FUNC %s\n", name ); - } - } -} - -/* - * static function: - * Define "name" as the current static (scoped) function - */ -void DefineStaticFunction( char *name, Addr_T value, int page ) -{ - if (as_strcmpi( name, currentFunction ) != 0) - { - strcpy( currentFunction, name ); - if (value != 0) - { - fprintf( jfp, "DEFS %s ", name ); - PagedAddress( value, page ); - fprintf( jfp, "SFUNC %s ", name ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "SFUNC %s\n", name ); - } - } -} - -/* - * static function: - * Define the end of the current function - */ -void DefineEndFunction( Addr_T value, int page ) -{ - if (currentFunction[0] != 0) - { - if (value != 0) - { - fprintf( jfp, "ENDF " ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "ENDF\n" ); - } - - currentFunction[0] = 0; - } -} - -/* - * static function: - * Define "lineNumber" as a line in the current file - */ -void DefineLine( char *lineString, Addr_T value, int page ) -{ - int indigit, lineNumber = 0; - - while( (indigit=digit( *lineString++, 10 )) >= 0) - { - lineNumber = 10*lineNumber + indigit; - } - fprintf( jfp, "LINE %u ", lineNumber ); - PagedAddress( value, page ); -} - -void PagedAddress( Addr_T value, int page ) -{ - fprintf( jfp, "%X:0x%X\n", page, value ); -} diff --git a/as/hc08/lkrloc.c b/as/hc08/lkrloc.c deleted file mode 100644 index 954b9c63..00000000 --- a/as/hc08/lkrloc.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* lkrloc.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 29-Oct-97 JLH: - * - errdmp: show s_id as string rather than array [NCPS] - * - relr: add support for 11 bit 8051 addressing - * 02-Apr-98 JLH: don't output empty hex records - */ - -#include -#include -#include "aslink.h" - -/*)Module lkrloc.c - * - * The module lkrloc.c contains the functions which - * perform the relocation calculations. - * - * lkrloc.c contains the following functions: - * Addr_T adb_b() - * Addr_T adb_lo() - * Addr_T adb_hi() - * Addr_T adw_w() - * Addr_T adw_lo() - * Addr_T adw_hi() - * VOID erpdmp() - * VOID errdmp() - * Addr_T evword() - * VOID prntval() - * VOID rele() - * VOID relerr() - * VOID relerp() - * VOID reloc() - * VOID relp() - * VOID relr() - * VOID relt() - * - * lkrloc.c the local variable errmsg[]. - * - */ - -/* Global which holds the upper 16 bits of the last 32 bit area adress - * output. Useful only for iHex mode. - */ -int lastExtendedAddress=-1; - -/* Static variable which holds the index of last processed area. - * Useful only for iHex mode. - */ -static int lastAreaIndex = -1; - -/*)Function VOID reloc(c) - * - * char c process code - * - * The function reloc() calls a particular relocation - * function determined by the process code. - * - * local variable: - * none - * - * global variables: - * int lkerr error flag - * - * called functions: - * int fprintf() c_library - * VOID rele() lkrloc.c - * VOID relp() lkrloc.c - * VOID relr() lkrloc.c - * VOId relt() lkrloc.c - * - * side effects: - * Refer to the called relocation functions. - * - */ - -VOID -reloc(c) -char c; -{ - switch(c) { - - case 'T': - relt(); - break; - - case 'R': - relr(); - break; - - case 'P': - relp(); - break; - - case 'E': - rele(); - break; - - default: - fprintf(stderr, "Undefined Relocation Operation\n"); - lkerr++; - break; - - } -} - - -/*)Function VOID relt() - * - * The function relt() evaluates a T line read by - * the linker. Each byte value read is saved in the - * rtval[] array, rtflg[] is set, and the number of - * evaluations is maintained in rtcnt. - * - * T Line - * - * T xx xx nn nn nn nn nn ... - * - * - * In: "T n0 n1 n2 n3 ... nn" - * - * Out: 0 1 2 .. rtcnt - * +----+----+----+----+----+ - * rtval | n0 | n1 | n2 | .. | nn | - * +----+----+----+----+----+ - * rtflag| 1 | 1 | 1 | 1 | 1 | - * +----+----+----+----+----+ - * - * The T line contains the assembled code output by the assem- - * bler with xx xx being the offset address from the current area - * base address and nn being the assembled instructions and data in - * byte format. - * - * local variable: - * none - * - * global variables: - * int rtcnt number of values evaluated - * int rtflg[] array of evaluation flags - * int rtval[] array of evaluation values - * - * called functions: - * int eval() lkeval.c - * int more() lklex.c - * - * side effects: - * Linker input T line evaluated. - * - */ - -VOID -relt() -{ - rtcnt = 0; - while (more()) { - if (rtcnt < NTXT) { - rtval[rtcnt] = eval(); - rtflg[rtcnt] = 1; - rtcnt++; - } - } -} - -/*)Function VOID relr() - * - * The function relr() evaluates a R line read by - * the linker. The R line data is combined with the - * previous T line data to perform the relocation of - * code and data bytes. The S19 / IHX output and - * translation of the LST files to RST files may be - * performed. - * - * R Line - * - * R 0 0 nn nn n1 n2 xx xx ... - * - * The R line provides the relocation information to the linker. - * The nn nn value is the current area index, i.e. which area the - * current values were assembled. Relocation information is en- - * coded in groups of 4 bytes: - * - * 1. n1 is the relocation mode and object format - * 1. bit 0 word(0x00)/byte(0x01) - * 2. bit 1 relocatable area(0x00)/symbol(0x02) - * 3. bit 2 normal(0x00)/PC relative(0x04) relocation - * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for - * byte data - * 5. bit 4 signed(0x00)/unsigned(0x10) byte data - * 6. bit 5 normal(0x00)/page '0'(0x20) reference - * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference - * - * 2. n2 is a byte index into the corresponding (i.e. pre- - * ceeding) T line data (i.e. a pointer to the data to be - * updated by the relocation). The T line data may be - * 1-byte or 2-byte byte data format or 2-byte word - * format. - * - * 3. xx xx is the area/symbol index for the area/symbol be- - * ing referenced. the corresponding area/symbol is found - * in the header area/symbol lists. - * - * The groups of 4 bytes are repeated for each item requiring relo- - * cation in the preceeding T line. - * - * local variable: - * areax **a pointer to array of area pointers - * int aindex area index - * char *errmsg[] array of pointers to error strings - * int error error code - * int lkerr error flag - * int mode relocation mode - * adrr_t paga paging base area address - * Addr_T pags paging symbol address - * Addr_T pc relocated base address - * Addr_T r PCR relocation value - * Addr_T reli relocation initial value - * Addr_T relv relocation final value - * int rindex symbol / area index - * Addr_T rtbase base code address - * Addr_T rtofst rtval[] index offset - * int rtp index into T data - * sym **s pointer to array of symbol pointers - * - * global variables: - * head *hp pointer to the head structure - * rerr rerr linker error structure - * FILE *stderr standard error device - * - * called functions: - * Addr_T adb_b() lkrloc.c - * Addr_T adb_lo() lkrloc.c - * Addr_T adb_hi() lkrloc.c - * Addr_T adw_w() lkrloc.c - * VOID elf() lkelf.c - * Addr_T evword() lkrloc.c - * int eval() lkeval.c - * int fprintf() c_library - * VOID ihx() lkihx.c - * int lkulist lklist.c - * int more() lklex.c - * VOID relerr() lkrloc.c - * VOID s19() lks19.c - * int symval() lksym.c - * - * side effects: - * The R and T lines are combined to produce - * relocated code and data. Output S19 / IHX - * and relocated listing files may be produced. - * - */ - -VOID -relr() -{ - register int mode; - register Addr_T reli, relv; - int aindex, rindex, rtp, error; - Addr_T r, rtbase, rtofst, paga, pags, pc; - struct areax **a; - struct sym **s; - - /* - * Get area and symbol lists - */ - a = hp->a_list; - s = hp->s_list; - - /* - * Verify Area Mode - */ - if (eval() != (R_WORD | R_AREA) || eval()) { - fprintf(stderr, "R input error\n"); - lkerr++; - } - - /* - * Get area pointer - */ - aindex = evword(); - if (aindex >= hp->h_narea) { - fprintf(stderr, "R area error\n"); - lkerr++; - return; - } - ap = a[aindex]->a_bap; - - /* - * Base values - */ - rtbase = adw_w(0, 0); - rtofst = 2; - - /* - * Relocate address - */ - pc = adw_w(a[aindex]->a_addr, 0); - - #if 0 - printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex, - a[aindex]->a_addr, a[aindex]->a_size, rtbase); - #endif - /* - * Do remaining relocations - */ - while (more()) { - error = 0; - mode = eval(); - - if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK) - { - mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval(); - /* printf("unescaping rmode\n"); */ - } - - rtp = eval(); - rindex = evword(); - - /* - * R_SYM or R_AREA references - */ - if (mode & R_SYM) { - if (rindex >= hp->h_nglob) { - fprintf(stderr, "R symbol error\n"); - lkerr++; - return; - } - reli = symval(s[rindex]); - } else { - if (rindex >= hp->h_narea) { - fprintf(stderr, "R area error\n"); - lkerr++; - return; - } - reli = a[rindex]->a_addr; - } - - /* - * R_PCR addressing - */ - if (mode & R_PCR) { - if (mode & R_BYTE) { - reli -= (pc + (rtp-rtofst) + 1); - } else { - reli -= (pc + (rtp-rtofst) + 2); - } - } - - /* - * R_PAG0 or R_PAG addressing - */ - if (mode & (R_PAG0 | R_PAG)) { - paga = sdp.s_area->a_addr; - pags = sdp.s_addr; - reli -= paga + pags; - } - - /* - * R_BYTE or R_WORD operation - */ - if (mode & R_BYTE) { - if (mode & R_BYT3) - { - /* This is a three byte address, of which - * we will select one byte. - */ - if (mode & R_HIB) - { - /* printf("24 bit address selecting hi byte.\n"); */ - relv = adb_24_hi(reli, rtp); - } - else if (mode & R_MSB) - { - /* Note that in 24 bit mode, R_MSB - * is really the middle byte, not - * the most significant byte. - * - * This is ugly and I can only apologize - * for any confusion. - */ - /* printf("24 bit address selecting middle byte.\n"); */ - relv = adb_24_mid(reli, rtp); - } - else - { - /* printf("24 bit address selecting lo byte.\n"); */ - relv = adb_24_lo(reli, rtp); - } - } - else if (mode & R_BYT2) { - /* This is a two byte address, of - * which we will select one byte. - */ - if (mode & R_MSB) { - relv = adb_hi(reli, rtp); - } else { - relv = adb_lo(reli, rtp); - } - } else { - relv = adb_b(reli, rtp); - } - } else if (IS_R_J11(mode)) { - /* JLH: 11 bit jump destination for 8051. Forms - / two byte instruction with op-code bits - / in the MIDDLE! - / rtp points at 3 byte locus: first two - / will get the instructiion. third one - / has raw op-code. - */ - - /* Calculate absolute destination - / relv must be on same 2K page as pc - */ - relv = adw_w(reli, rtp); - - if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) { - error = 2; - } - - /* Merge MSB (byte 0) with op-code, ignoring - / top 5 bits of address. Then hide the op-code - */ - rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2]; - rtflg[rtp+2] = 0; - rtofst += 1; - } - else if (IS_R_J19(mode)) { - /* 19 bit jump destination for DS80C390. Forms - / three byte instruction with op-code bits - / in the MIDDLE! - / rtp points at 4 byte locus: first three - / will get the instructiion. fourth one - / has raw op-code. - */ - - /* Calculate absolute destination - / relv must be on same 512K page as pc - */ - relv = adw_24(reli, rtp); - - if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) { - error = 2; - } - - /* Merge MSB (byte 0) with op-code, ignoring - / top 5 bits of address. Then hide the op-code - */ - rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3]; - rtflg[rtp+3] = 0; - rtofst += 1; - } - else if (IS_C24(mode)) - { - /* 24 bit address */ - relv = adw_24(reli, rtp); - } - else - { - /* 16 bit address. */ - relv = adw_w(reli, rtp); - } - - /* - * R_BYTE with R_BYT2 offset adjust - */ - if (mode & R_BYTE) { - if (mode & R_BYT2) { - rtofst += 1; - } - } - - /* - * Unsigned Byte Checking - */ - if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF) - error = 1; - - /* - * PCR Relocation Error Checking - */ - if (mode & R_PCR && mode & R_BYTE) { - r = relv & ~0x7F; - if (r != (Addr_T) ~0x7F && r != 0) - error = 2; - } - - /* - * Page Relocation Error Checking - */ - /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags)) - error = 3;*/ - if (mode & R_PAG && (relv & ~0xFF)) - error = 4; - - /* - * Error Processing - */ - if (error) { - rerr.aindex = aindex; - rerr.mode = mode; - rerr.rtbase = rtbase + rtp - rtofst - 1; - rerr.rindex = rindex; - rerr.rval = relv - reli; - relerr(errmsg[error-1]); - } - } - if (uflag != 0) { - lkulist(1); - } - - /* JLH: output only if data (beyond two byte address) */ - if ((oflag == 1) && (rtcnt > 2)) { - // int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff; - - /* Boy, is this a hack: for ABS sections, the - * base address is stored as zero, and the T records - * indicate the offset from zero. - * - * Since T records can only indicate a 16 bit offset, this - * obviously creates a problem for ABS segments located - * above 64K (this is only meaningful in flat24 mode). - * - * However, the size of an ABS area is stored as - * base address + section size (I suspect this is a bug, - * but it's a handy one right now). So the upper 8 bits of - * the 24 bit address are stored in the size record. - * Thus we add it in. - * - * This is another reason why we can't have areas greater - * than 64K yet, even in flat24 mode. - */ - // extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff); - // commented out by jr - - if (lastAreaIndex != aindex) { - lastAreaIndex = aindex; - newArea(); - } -#if 0 - if (extendedAddress != lastExtendedAddress) - { - - if (lastExtendedAddress!=-1) { - printf("output extended linear address record 0x%x 0x%x\n", - extendedAddress, lastExtendedAddress); - } - - if (rflag) - { - ihxEntendedLinearAddress(extendedAddress); - } - else if (extendedAddress) - { - /* Not allowed to generate extended address records, - * but one is called for here... - */ - fprintf(stderr, - "warning: extended linear address encountered; " - "you probably want the -r flag.\n"); - } - lastExtendedAddress = extendedAddress; - } -#endif - ihx(1); - } else - if ((oflag == 2) && (rtcnt > 2)) { - s19(1); - } else - if ((oflag == 3) && (rtcnt > 2)) { - elf(1); - } -} - -char *errmsg[] = { - "Unsigned Byte error", - "Byte PCR relocation error", - "Page0 relocation error", - "Page Mode relocation error" -}; - - -/*)Function VOID relp() - * - * The function relp() evaluates a P line read by - * the linker. The P line data is combined with the - * previous T line data to set the base page address - * and test the paging boundary and length. - * - * P Line - * - * P 0 0 nn nn n1 n2 xx xx - * - * The P line provides the paging information to the linker as - * specified by a .setdp directive. The format of the relocation - * information is identical to that of the R line. The correspond- - * ing T line has the following information: - * T xx xx aa aa bb bb - * - * Where aa aa is the area reference number which specifies the - * selected page area and bb bb is the base address of the page. - * bb bb will require relocation processing if the 'n1 n2 xx xx' is - * specified in the P line. The linker will verify that the base - * address is on a 256 byte boundary and that the page length of an - * area defined with the PAG type is not larger than 256 bytes. - * - * local variable: - * areax **a pointer to array of area pointers - * int aindex area index - * int mode relocation mode - * Addr_T relv relocation value - * int rindex symbol / area index - * int rtp index into T data - * sym **s pointer to array of symbol pointers - * - * global variables: - * head *hp pointer to the head structure - * int lkerr error flag - * sdp sdp base page structure - * FILE *stderr standard error device - * - * called functions: - * Addr_T adw_w() lkrloc.c - * Addr_T evword() lkrloc.c - * int eval() lkeval.c - * int fprintf() c_library - * int more() lklex.c - * int symval() lksym.c - * - * side effects: - * The P and T lines are combined to set - * the base page address and report any - * paging errors. - * - */ - -VOID -relp() -{ - register int aindex, rindex; - int mode, rtp; - Addr_T relv; - struct areax **a; - struct sym **s; - - /* - * Get area and symbol lists - */ - a = hp->a_list; - s = hp->s_list; - - /* - * Verify Area Mode - */ - if (eval() != (R_WORD | R_AREA) || eval()) { - fprintf(stderr, "P input error\n"); - lkerr++; - } - - /* - * Get area pointer - */ - aindex = evword(); - if (aindex >= hp->h_narea) { - fprintf(stderr, "P area error\n"); - lkerr++; - return; - } - - /* - * Do remaining relocations - */ - while (more()) { - mode = eval(); - rtp = eval(); - rindex = evword(); - - /* - * R_SYM or R_AREA references - */ - if (mode & R_SYM) { - if (rindex >= hp->h_nglob) { - fprintf(stderr, "P symbol error\n"); - lkerr++; - return; - } - relv = symval(s[rindex]); - } else { - if (rindex >= hp->h_narea) { - fprintf(stderr, "P area error\n"); - lkerr++; - return; - } - relv = a[rindex]->a_addr; - } - adw_w(relv, rtp); - } - - /* - * Paged values - */ - aindex = adw_w(0,2); - if (aindex >= hp->h_narea) { - fprintf(stderr, "P area error\n"); - lkerr++; - return; - } - sdp.s_areax = a[aindex]; - sdp.s_area = sdp.s_areax->a_bap; - sdp.s_addr = adw_w(0,4); - if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF) - relerp("Page Definition Boundary Error"); -} - -/*)Function VOID rele() - * - * The function rele() closes all open output files - * at the end of the linking process. - * - * local variable: - * none - * - * global variables: - * int oflag output type flag - * int uflag relocation listing flag - * - * called functions: - * VOID elf() lkelf.c - * VOID ihx() lkihx.c - * VOID lkulist() lklist.c - * VOID s19() lks19.c - * - * side effects: - * All open output files are closed. - * - */ - -VOID -rele() -{ - if (uflag != 0) { - lkulist(0); - } - if (oflag == 1) { - ihx(0); - } else - if (oflag == 2) { - s19(0); - } else - if (oflag == 3) { - elf(0); - } -} - -/*)Function Addr_T evword() - * - * The function evword() combines two byte values - * into a single word value. - * - * local variable: - * Addr_T v temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * int eval() lkeval.c - * - * side effects: - * Relocation text line is scanned to combine - * two byte values into a single word value. - * - */ - -Addr_T -evword() -{ - register Addr_T v; - - if (hilo) { - v = (eval() << 8); - v += eval(); - } else { - v = eval(); - v += (eval() << 8); - } - return(v); -} - -/*)Function Addr_T adb_b(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adb_b() adds the value of v to - * the single byte value contained in rtval[i]. - * The new value of rtval[i] is returned. - * - * local variable: - * none - * - * global variables: - * none - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * - */ - -Addr_T -adb_b(v, i) -register Addr_T v; -register int i; -{ - return(rtval[i] += v); -} - -/*)Function Addr_T adb_lo(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adb_lo() adds the value of v to the - * double byte value contained in rtval[i] and rtval[i+1]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The MSB rtflg[] is cleared. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The rtflg[] value corresponding to the - * MSB of the word value is cleared to reflect - * the fact that the LSB is the selected byte. - * - */ - -Addr_T -adb_lo(v, i) -Addr_T v; -int i; -{ - register Addr_T j; - - j = adw_w(v, i); - /* - * Remove Hi byte - */ - if (hilo) { - rtflg[i] = 0; - } else { - rtflg[i+1] = 0; - } - return (j); -} - -/*)Function Addr_T adb_hi(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adb_hi() adds the value of v to the - * double byte value contained in rtval[i] and rtval[i+1]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The LSB rtflg[] is cleared. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The rtflg[] value corresponding to the - * LSB of the word value is cleared to reflect - * the fact that the MSB is the selected byte. - * - */ - -Addr_T -adb_hi(v, i) -Addr_T v; -int i; -{ - register Addr_T j; - - j = adw_w(v, i); - /* - * Remove Lo byte - */ - if (hilo) { - rtflg[i+1] = 0; - } else { - rtflg[i] = 0; - } - return (j); -} - -/*)Function Addr_T adb_24_hi(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adb_24_hi() adds the value of v to the - * 24 bit value contained in rtval[i] - rtval[i+2]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The LSB & middle byte rtflg[] is cleared. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The rtflg[] value corresponding to the - * LSB & middle byte of the word value is cleared to - * reflect the fact that the MSB is the selected byte. - * - */ - -Addr_T -adb_24_hi(Addr_T v, int i) -{ - register Addr_T j; - - j = adw_24(v, i); - - /* Remove the lower two bytes. */ - if (hilo) - { - rtflg[i+2] = 0; - } - else - { - rtflg[i] = 0; - } - rtflg[i+1] = 0; - - return (j); -} - -/*)Function Addr_T adb_24_mid(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adb_24_mid() adds the value of v to the - * 24 bit value contained in rtval[i] - rtval[i+2]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The LSB & MSB byte rtflg[] is cleared. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The rtflg[] value corresponding to the - * LSB & MSB of the 24 bit value is cleared to reflect - * the fact that the middle byte is the selected byte. - * - */ - -Addr_T -adb_24_mid(Addr_T v, int i) -{ - register Addr_T j; - - j = adw_24(v, i); - - /* remove the MSB & LSB. */ - rtflg[i+2] = 0; - rtflg[i] = 0; - - return (j); -} - -/*)Function Addr_T adb_24_lo(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adb_24_lo() adds the value of v to the - * 24 bit value contained in rtval[i] - rtval[i+2]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The MSB & middle byte rtflg[] is cleared. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The rtflg[] value corresponding to the - * MSB & middle byte of the word value is cleared to - * reflect the fact that the LSB is the selected byte. - * - */ - -Addr_T -adb_24_lo(Addr_T v, int i) -{ - register Addr_T j; - - j = adw_24(v, i); - - /* Remove the upper two bytes. */ - if (hilo) - { - rtflg[i] = 0; - } - else - { - rtflg[i+2] = 0; - } - rtflg[i+1] = 0; - - return (j); -} - -/*)Function Addr_T adw_w(v, i) - * - * int v value to add to word - * int i rtval[] index - * - * The function adw_w() adds the value of v to the - * word value contained in rtval[i] and rtval[i+1]. - * The new value of rtval[i] / rtval[i+1] is returned. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The word value of rtval[] is changed. - * - */ - -Addr_T -adw_w(v, i) -register Addr_T v; -register int i; -{ - register Addr_T j; - - if (hilo) { - j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff); - rtval[i] = (j >> 8) & 0xff; - rtval[i+1] = j & 0xff; - } else { - j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8); - rtval[i] = j & 0xff; - rtval[i+1] = (j >> 8) & 0xff; - } - return(j); -} - -/*)Function Addr_T adw_24(v, i) - * - * int v value to add to word - * int i rtval[] index - * - * The function adw_w() adds the value of v to the - * 24 bit value contained in rtval[i] - rtval[i+2]. - * The new value of rtval[i] - rtval[i+2] is returned. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The word value of rtval[] is changed. - * - */ -Addr_T -adw_24(Addr_T v, int i) -{ - register Addr_T j; - - if (hilo) { - j = v + ((rtval[i] & 0xff) << 16) - + ((rtval[i+1] & 0xff) << 8) - + (rtval[i+2] & 0xff); - rtval[i] = (j >> 16) & 0xff; - rtval[i+1] = (j >> 8) & 0xff; - rtval[i+2] = j & 0xff; - } else { - j = v + (rtval[i] & 0xff) - + ((rtval[i+1] & 0xff) << 8) - + ((rtval[i+2] & 0xff) << 16); - rtval[i] = j & 0xff; - rtval[i+1] = (j >> 8) & 0xff; - rtval[i+2] = (j >> 16) & 0xff; - } - return(j); -} - -/*)Function Addr_T adw_lo(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adw_lo() adds the value of v to the - * double byte value contained in rtval[i] and rtval[i+1]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The MSB rtval[] is zeroed. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The MSB of the word value is cleared to reflect - * the fact that the LSB is the selected byte. - * - */ - -Addr_T -adw_lo(v, i) -Addr_T v; -int i; -{ - register Addr_T j; - - j = adw_w(v, i); - /* - * Clear Hi byte - */ - if (hilo) { - rtval[i] = 0; - } else { - rtval[i+1] = 0; - } - return (j); -} - -/*)Function Addr_T adw_hi(v, i) - * - * int v value to add to byte - * int i rtval[] index - * - * The function adw_hi() adds the value of v to the - * double byte value contained in rtval[i] and rtval[i+1]. - * The new value of rtval[i] / rtval[i+1] is returned. - * The MSB and LSB values are interchanged. - * The MSB rtval[] is zeroed. - * - * local variable: - * Addr_T j temporary evaluation variable - * - * global variables: - * hilo byte ordering parameter - * - * called functions: - * none - * - * side effects: - * The value of rtval[] is changed. - * The MSB and LSB values are interchanged and - * then the MSB cleared. - * - */ - -Addr_T -adw_hi(v, i) -Addr_T v; -int i; -{ - register Addr_T j; - - j = adw_w(v, i); - /* - * LSB = MSB, Clear MSB - */ - if (hilo) { - rtval[i+1] = rtval[i]; - rtval[i] = 0; - } else { - rtval[i] = rtval[i+1]; - rtval[i+1] = 0; - } - return (j); -} - -/*)Function VOID relerr(str) - * - * char *str error string - * - * The function relerr() outputs the error string to - * stderr and to the map file (if it is open). - * - * local variable: - * none - * - * global variables: - * FILE *mfp handle for the map file - * - * called functions: - * VOID errdmp() lkrloc.c - * - * side effects: - * Error message inserted into map file. - * - */ - -VOID -relerr(str) -char *str; -{ - errdmp(stderr, str); - if (mfp) - errdmp(mfp, str); -} - -/*)Function VOID errdmp(fptr, str) - * - * FILE *fptr output file handle - * char *str error string - * - * The function errdmp() outputs the error string str - * to the device specified by fptr. Additional information - * is output about the definition and referencing of - * the symbol / area error. - * - * local variable: - * int mode error mode - * int aindex area index - * int lkerr error flag - * int rindex error index - * sym **s pointer to array of symbol pointers - * areax **a pointer to array of area pointers - * areax *raxp error area extension pointer - * - * global variables: - * sdp sdp base page structure - * - * called functions: - * int fprintf() c_library - * VOID prntval() lkrloc.c - * - * side effects: - * Error reported. - * - */ - -VOID -errdmp(fptr, str) -FILE *fptr; -char *str; -{ - int mode, aindex, rindex; - struct sym **s; - struct areax **a; - struct areax *raxp; - - a = hp->a_list; - s = hp->s_list; - - mode = rerr.mode; - aindex = rerr.aindex; - rindex = rerr.rindex; - - /* - * Print Error - */ - fprintf(fptr, "\n?ASlink-Warning-%s", str); - lkerr++; - - /* - * Print symbol if symbol based - */ - if (mode & R_SYM) { - fprintf(fptr, " for symbol %s\n", - &s[rindex]->s_id[0]); - } else { - fprintf(fptr, "\n"); - } - - /* - * Print Ref Info - */ - fprintf(fptr, - " file module area offset\n"); - fprintf(fptr, - " Refby %-8.8s %-8.8s %-8.8s ", - hp->h_lfile->f_idp, - &hp->m_id[0], - &a[aindex]->a_bap->a_id[0]); - prntval(fptr, rerr.rtbase); - - /* - * Print Def Info - */ - if (mode & R_SYM) { - raxp = s[rindex]->s_axp; - } else { - raxp = a[rindex]; - } - fprintf(fptr, - " Defin %-8.8s %-8.8s %-8.8s ", - raxp->a_bhp->h_lfile->f_idp, - &raxp->a_bhp->m_id[0], - &raxp->a_bap->a_id[0]); - if (mode & R_SYM) { - prntval(fptr, s[rindex]->s_addr); - } else { - prntval(fptr, rerr.rval); - } -} - -/*)Function VOID prntval(fptr, v) - * - * FILE *fptr output file handle - * Addr_T v value to output - * - * The function prntval() outputs the value v, in the - * currently selected radix, to the device specified - * by fptr. - * - * local variable: - * none - * - * global variables: - * int xflag current radix - * - * called functions: - * int fprintf() c_library - * - * side effects: - * none - * - */ - -VOID -prntval(fptr, v) -FILE *fptr; -Addr_T v; -{ - if (xflag == 0) { - fprintf(fptr, "%04X\n", v); - } else - if (xflag == 1) { - fprintf(fptr, "%06o\n", v); - } else - if (xflag == 2) { - fprintf(fptr, "%05u\n", v); - } -} - -/*)Function VOID relerp(str) - * - * char *str error string - * - * The function relerp() outputs the paging error string to - * stderr and to the map file (if it is open). - * - * local variable: - * none - * - * global variables: - * FILE *mfp handle for the map file - * - * called functions: - * VOID erpdmp() lkrloc.c - * - * side effects: - * Error message inserted into map file. - * - */ - -VOID -relerp(str) -char *str; -{ - erpdmp(stderr, str); - if (mfp) - erpdmp(mfp, str); -} - -/*)Function VOID erpdmp(fptr, str) - * - * FILE *fptr output file handle - * char *str error string - * - * The function erpdmp() outputs the error string str - * to the device specified by fptr. - * - * local variable: - * head *thp pointer to head structure - * - * global variables: - * int lkerr error flag - * sdp sdp base page structure - * - * called functions: - * int fprintf() c_library - * VOID prntval() lkrloc.c - * - * side effects: - * Error reported. - * - */ - -VOID -erpdmp(fptr, str) -FILE *fptr; -char *str; -{ - register struct head *thp; - - thp = sdp.s_areax->a_bhp; - - /* - * Print Error - */ - fprintf(fptr, "\n?ASlink-Warning-%s\n", str); - lkerr++; - - /* - * Print PgDef Info - */ - fprintf(fptr, - " file module pgarea pgoffset\n"); - fprintf(fptr, - " PgDef %-8.8s %-8.8s %-8.8s ", - thp->h_lfile->f_idp, - &thp->m_id[0], - &sdp.s_area->a_id[0]); - prntval(fptr, sdp.s_area->a_addr + sdp.s_addr); -} diff --git a/as/hc08/lks19.c b/as/hc08/lks19.c deleted file mode 100644 index d50a41ea..00000000 --- a/as/hc08/lks19.c +++ /dev/null @@ -1,124 +0,0 @@ -/* lks19.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*)Module lks19.c - * - * The module lks19.c contains the function to - * output the relocated object code in the - * Motorola S19 format. - * - * lks19.c contains the following function: - * VOID s19(i) - * - * lks19.c contains no local variables. - */ - -/*)S19 Format - * Record Type Field - This field signifies the start of a - * record and identifies the the record - * type as follows: - * - * Ascii S1 - Data Record - * Ascii S9 - End of File Record - * - * Record Length Field - This field specifies the record length - * which includes the address, data, and - * checksum fields. The 8 bit record - * length value is converted to two ascii - * characters, high digit first. - * - * Load Address Field - This field consists of the four ascii - * characters which result from converting - * the the binary value of the address in - * which to begin loading this record. The - * order is as follows: - * - * High digit of high byte of address. - * Low digit of high byte of address. - * High digit of low byte of address. - * Low digit of low byte of address. - * - * In an End of File record this field con- - * sists of either four ascii zeros or the - * program entry address. Currently the - * entry address option is not supported. - * - * Data Field - This field consists of the actual data, - * converted to two ascii characters, high - * digit first. There are no data bytes in - * the End of File record. - * - * Checksum Field - The checksum field is the 8 bit binary - * sum of the record length field, the load - * address field, and the data field. This - * sum is then complemented (1's comple- - * ment) and converted to two ascii - * characters, high digit first. - */ - -/*)Function s19(i) - * - * int i 0 - process data - * 1 - end of data - * - * The function s19() outputs the relocated data - * in the standard Motorola S19 format. - * - * local variables: - * Addr_T chksum byte checksum - * - * global variables: - * int hilo byte order - * FILE * ofp output file handle - * int rtcnt count of data words - * int rtflg[] output the data flag - * Addr_T rtval[] relocated data - * - * functions called: - * int fprintf() c_library - * - * side effects: - * The data is output to the file defined by ofp. - */ - -VOID -s19(i) -{ - register Addr_T chksum; - - if (i) { - if (ap->a_flag & A_NOLOAD) - return; - if (hilo == 0) { - chksum = rtval[0]; - rtval[0] = rtval[1]; - rtval[1] = chksum; - } - for (i = 0, chksum = 1; i < rtcnt; i++) { - if (rtflg[i]) - chksum++; - } - fprintf(ofp, "S1%02X", chksum); - for (i = 0; i < rtcnt ; i++) { - if (rtflg[i]) { - fprintf(ofp, "%02X", rtval[i]); - chksum += rtval[i]; - } - } - fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff); - } else { - fprintf(ofp, "S9030000FC\n"); - } -} diff --git a/as/hc08/lkstore.c b/as/hc08/lkstore.c deleted file mode 100644 index 063e89c4..00000000 --- a/as/hc08/lkstore.c +++ /dev/null @@ -1,50 +0,0 @@ -/* lkstore.c */ - -/* - * Allocated string storage module. - * - * 31-Oct-1997 by John Hartman - */ - -#include -#include -#include -#include "aslink.h" - -/* - * Allocate space for "str", copy str into new space - * Return a pointer to the allocated name, or NULL if out of memory - */ -char *StoreString( char *str ) -{ - /* To avoid wasting memory headers on small allocations, we - / allocate a big chunk and parcel it out as required. - / These static variables remember our hunk - */ - #define STR_STORE_HUNK 2000 - static char *pNextFree = NULL; - static int bytesLeft = 0; - - int length; - char *pStoredString; - - length = strlen( str ) + 1; /* what we need, including null */ - - if (length > bytesLeft) - { - /* no space. Allocate a new hunk. We lose the pointer to any - / old hunk. We don't care, as the names are never deleted. - */ - pNextFree = (char*)new( STR_STORE_HUNK ); - bytesLeft = STR_STORE_HUNK; - } - - /* Copy the name and terminating null into the name store */ - pStoredString = pNextFree; - memcpy( pStoredString, str, length ); - - pNextFree += length; - bytesLeft -= length; - - return pStoredString; -} diff --git a/as/hc08/lksym.c b/as/hc08/lksym.c deleted file mode 100644 index 1ebc49cc..00000000 --- a/as/hc08/lksym.c +++ /dev/null @@ -1,488 +0,0 @@ -/* lksym.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 28-Oct-97 JLH: - * - lkpsym: Use StoreString for sym construction - * - change symeq() to do length-independent string compare - * - change hash() to do length-independent hash calculation - */ - -#include -#include -#if defined(_MSC_VER) -#include -#else -#include -#endif -#include "aslink.h" - -/*)Module lksym.c - * - * The module lksym.c contains the functions that operate - * on the symbol structures. - * - * lksym.c contains the following functions: - * int hash() - * sym * lkpsym() - * VOID * new() - * sym * newsym() - * VOID symdef() - * int symeq() - * VOID syminit() - * VOID symmod() - * Addr_T symval() - * - * lksym.c contains no local/static variables. - */ - -/*)Function VOID syminit() - * - * The function syminit() is called to clear the hashtable. - * - * local variables: - * int h computed hash value - * sym ** spp pointer to an array of - * sym structure pointers - * - * global variables: - * sym * symhash[] array of pointers to NHASH - * linked symbol lists - * - * functions called: - * none - * - * side effects: - * (1) The symbol hash tables are cleared - */ - -VOID -syminit() -{ - // register int h; - struct sym **spp; - - spp = &symhash[0]; - while (spp < &symhash[NHASH]) - *spp++ = NULL; -} - -/*)Function sym * newsym() - * - * The function newsym() is called to evaluate the symbol - * definition/reference directive from the .rel file(s). - * If the symbol is not found in the symbol table a new - * symbol structure is created. Evaluation of the - * directive determines if this is a reference or a definition. - * Multiple definitions of the same variable will be flagged - * as an error if the values are not identical. A symbol - * definition places the symbol value and area extension - * into the symbols data structure. And finally, a pointer - * to the symbol structure is placed into the head structure - * symbol list. Refer to the description of the header, symbol, - * area, and areax structures in lkdata.c for structure and - * linkage details. - * - * local variables: - * int c character from input text - * int i evaluation value - * char id[] symbol name - * int nglob number of symbols in this header - * sym * tsp pointer to symbol structure - * sym ** s list of pointers to symbol structures - * - * global variables: - * areax *axp Pointer to the current - * areax structure - * head *headp The pointer to the first - * head structure of a linked list - * int lkerr error flag - * - * functions called: - * Addr_T eval() lkeval.c - * VOID exit() c_library - * int fprintf() c_library - * char getSid() lklex.c - * char get() lklex.c - * char getnb() lklex.c - * sym * lkpsym() lksym.c - * - * side effects: - * A symbol structure is created and/or modified. - * If structure space allocation fails linker will abort. - * Several severe errors (these are internal errors - * indicating a corrupted .rel file or corrupted - * assembler or linker) will terminated the linker. - */ - -/* - * Find/Create a global symbol entry. - * - * S xxxxxx Defnnnn - * | | | - * | | `-- sp->s_addr - * | `----- sp->s_type - * `------------ sp->s_id - * - */ -struct sym * -newsym() -{ - register unsigned i ; - register unsigned nglob ; - register int c ; - struct sym *tsp; - struct sym **s; - char id[NCPS]; - - getSid(id); // old: getid(id, -1); - tsp = lkpsym(id, 1); - c = getnb();get();get(); - if (c == 'R') { - tsp->s_type |= S_REF; - if (eval()) { - fprintf(stderr, "Non zero S_REF\n"); - lkerr++; - } - } else - if (c == 'D') { - i = eval(); - if (tsp->s_type & S_DEF && tsp->s_addr != i) { - fprintf(stderr, "Multiple definition of %8s\n", id); - lkerr++; - } - tsp->s_type |= S_DEF; - /* - * Set value and area extension link. - */ - tsp->s_addr = i; - tsp->s_axp = axp; - } else { - fprintf(stderr, "Invalid symbol type %c for %8s\n", c, id); - lkexit(1); - } - /* - * Place pointer in header symbol list - */ - if (headp == NULL) { - fprintf(stderr, "No header defined\n"); - lkexit(1); - } - nglob = hp->h_nglob; - s = hp->s_list; - for (i=0; i < nglob ;++i) { - if (s[i] == NULL) { - s[i] = tsp; - return(tsp); - } - } - fprintf(stderr, "Header symbol list overflow\n"); - lkexit(1); - return(0); -} - -/*)Function sym * lkpsym(id,f) - * - * char * id symbol name string - * int f f == 0, lookup only - * f != 0, create if not found - * - * The function lookup() searches the symbol hash tables for - * a symbol name match returning a pointer to the sym structure. - * If the symbol is not found then a sym structure is created, - * initialized, and linked to the appropriate hash table if f != 0. - * A pointer to this new sym structure is returned or a NULL - * pointer is returned if f == 0. - * - * local variables: - * int h computed hash value - * sym * sp pointer to a sym structure - * - * global varaibles: - * sym * symhash[] array of pointers to NHASH - * linked symbol lists - * - * functions called: - * int hash() lksym.c - * VOID * new() lksym.c - * int symeq() lksym.c - * - * side effects: - * If the function new() fails to allocate space - * for the new sym structure the linker terminates. - */ - -struct sym * -lkpsym(id, f) -char *id; -{ - register struct sym *sp; - register int h; - - h = hash(id); - sp = symhash[h]; - while (sp != NULL) { - if (symeq(id, sp->s_id)) - return (sp); - sp = sp->s_sp; - } - if (f == 0) - return (NULL); - sp = (struct sym *) new (sizeof(struct sym)); - sp->s_sp = symhash[h]; - symhash[h] = sp; - sp->s_id = StoreString( id ); /* JLH */ - return (sp); -} - -/*)Function Addr_T symval(tsp) - * - * sym * tsp pointer to a symbol structure - * - * The function symval() returns the value of the - * relocated symbol by adding the variable definition - * value to the areax base address. - * - * local variables: - * Addr_T val relocated address value - * - * global variables: - * none - * - * functions called: - * none - * - * side effects: - * none - */ - -Addr_T -symval(tsp) -register struct sym *tsp; -{ - register Addr_T val; - - val = tsp->s_addr; - if (tsp->s_axp) { - val += tsp->s_axp->a_addr; - } - return(val); -} - -/*)Function VOID symdef(fp) - * - * FILE * fp file handle for output - * - * The function symdef() scans the hashed symbol table - * searching for variables referenced but not defined. - * Undefined variables are linked to the default - * area "_CODE" and reported as referenced by the - * appropriate module. - * - * local variables: - * int i hash table index loop variable - * sym * sp pointer to linked symbol structure - * - * global variables: - * area *areap The pointer to the first - * area structure of a linked list - * sym *symhash[NHASH] array of pointers to NHASH - * linked symbol lists - * - * functions called: - * symmod() lksym.c - * - * side effects: - * Undefined variables have their areas set to "_CODE". - */ - -VOID -symdef(fp) -FILE *fp; -{ - register struct sym *sp; - register int i; - - for (i=0; is_axp == NULL) - sp->s_axp = areap->a_axp; - if ((sp->s_type & S_DEF) == 0) - symmod(fp, sp); - sp = sp->s_sp; - } - } -} - -/*)Function VOID symmod(fp,tsp) - * - * FILE * fp output file handle - * sym * tsp pointer to a symbol structure - * - * The function symmod() scans the header structures - * searching for a reference to the symbol structure - * pointer to by tsp. The function then generates an error - * message whichs names the module having referenced the - * undefined variable. - * - * local variables: - * int i loop counter - * sym ** p pointer to a list of pointers - * to symbol structures - * - * global variables: - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * - * functions called: - * int fprintf() c_library - * - * side effects: - * Error output generated. - */ - -VOID -symmod(fp, tsp) -FILE *fp; -struct sym *tsp; -{ - register int i; - struct sym **p; - - if ((hp = headp) != NULL) { - while(hp) { - p = hp->s_list; - for (i=0; ih_nglob; ++i) { - if (p[i] == tsp) { - fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id); - fprintf(fp, "referenced by module '%s'\n", hp->m_id); - lkerr++; - } - } - hp = hp->h_hp; - } - } -} - -/*)Function int symeq(p1, p2) - * - * char * p1 name string - * char * p2 name string - * - * The function symeq() compares the two name strings for a match. - * The return value is 1 for a match and 0 for no match. - * - * local variables: - * int h loop counter - * - * global variables: - * char ccase[] an array of characters which - * perform the case translation function - * - * functions called: - * none - * - * side effects: - * none - * - */ - -int -symeq(p1, p2) -register char *p1, *p2; -{ -#if CASE_SENSITIVE - return (strcmp( p1, p2 ) == 0); -#else - return (as_strcmpi( p1, p2 ) == 0); -#endif -} - -/*)Function int hash(p) - * - * char * p pointer to string to hash - * - * The function hash() computes a hash code using the sum - * of all characters mod table size algorithm. - * - * local variables: - * int h accumulated character sum - * int n loop counter - * - * global variables: - * char ccase[] an array of characters which - * perform the case translation function - * - * functions called: - * none - * - * side effects: - * none - * - */ - -int -hash(p) -register char *p; -{ - register int h; - - h = 0; - while (*p) { - -#if CASE_SENSITIVE - h += *p++; -#else - h += ccase[*p++]; -#endif - - }; - return (h&HMASK); -} - -/*)Function VOID * new(n) - * - * unsigned int n allocation size in bytes - * - * The function new() allocates n bytes of space and returns - * a pointer to this memory. If no space is available the - * linker is terminated. - * - * local variables: - * char * p a general pointer - * char * q a general pointer - * - * global variables: - * none - * - * functions called: - * int fprintf() c_library - * VOID * malloc() c_library - * - * side effects: - * Memory is allocated, if allocation fails - * the linker is terminated. - */ - -VOID * -new(n) -unsigned int n; -{ - register char *p; - - if ((p = (char *) calloc(n, 1)) == NULL) { - fprintf(stderr, "Out of space!\n"); - lkexit(1); - } - return (p); -} diff --git a/as/link/aslink.h b/as/link/aslink.h index b3d0adfa..23dd808e 100644 --- a/as/link/aslink.h +++ b/as/link/aslink.h @@ -278,8 +278,10 @@ struct area Addr_T a_size; /* Total size of the area */ Addr_T a_unaloc; /* Total number of unallocated bytes, for error reporting */ char a_type; /* Area subtype */ - char a_flag; /* Flag byte */ + int a_flag; /* Flag byte */ char a_id[NCPS]; /* Name */ + char *a_image; /* Something for hc08/lkelf */ + char *a_used; /* Something for hc08/lkelf */ }; /* diff --git a/as/link/hc08/Makefile.aslink b/as/link/hc08/Makefile.aslink new file mode 100644 index 00000000..0aebe56e --- /dev/null +++ b/as/link/hc08/Makefile.aslink @@ -0,0 +1,68 @@ +CC=gcc +LEX=flex +YACC=bison +INCROOT=. +CFLAGS=-ggdb -O2 -I $(INCROOT) +TARGETS=$(SDCCDIR)/bin/aslink +ALLOBJECTS= lkmain.o lkhead.o lkarea.o lkdata.o\ + lkeval.o lklex.o lksym.o lkrloc.o\ + lklibr.o lklist.o lkihx.o lks19.o\ + lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o +all:: $(TARGETS) + +clean:: + rm -f $(TARGETS) $(ALLOBJECTS) + +lkmain.o : lkmain.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmain.o lkmain.c + +lkhead.o : lkhead.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkhead.o lkhead.c + +lkarea.o : lkarea.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkarea.o lkarea.c + +lkdata.o : lkdata.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkdata.o lkdata.c + +lkeval.o : lkeval.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkeval.o lkeval.c + +lklex.o : lklex.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklex.o lklex.c + +lksym.o : lksym.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lksym.o lksym.c + +lkrloc.o : lkrloc.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkrloc.o lkrloc.c + +lklibr.o : lklibr.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklibr.o lklibr.c + +lklist.o : lklist.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklist.o lklist.c + +lkihx.o : lkihx.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkihx.o lkihx.c + +lks19.o : lks19.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lks19.o lks19.c + +lkstore.o : lkstore.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkstore.o lkstore.c + +lknoice.o : lknoice.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lknoice.o lknoice.c + +strcmpi.o : strcmpi.c strcmpi.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o strcmpi.o strcmpi.c + +lkmem.o : lkmem.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmem.o lkmem.c + +lkaomf51.o : lkaomf51.c aslink.h + $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkaomf51.o lkaomf51.c + +$(TARGETS): $(ALLOBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALLOBJECTS) diff --git a/as/link/hc08/Makefile.bcc b/as/link/hc08/Makefile.bcc new file mode 100644 index 00000000..51c73f5d --- /dev/null +++ b/as/link/hc08/Makefile.bcc @@ -0,0 +1,20 @@ +# Makefile for Borland C++ + +PRJDIR = ../.. + +!include $(PRJDIR)/Bcc.inc + +LKOBJECTS = lkmain.obj lkarea.obj lkdata.obj \ + lkrloc.obj \ + lklibr.obj lkihx.obj lks19.obj \ + lkmem.obj lkaomf51.obj \ + ../lkeval.obj ../lkhead.obj ../lklex.obj ../lklist.obj \ + ../lknoice.obj ../lkstore.obj ../lksym.obj \ + ../../strcmpi.obj + +ASLINK = $(PRJDIR)/bin/aslink.exe + +all: $(ASLINK) + +$(ASLINK): $(LKOBJECTS) + $(CC) $(CFLAGS) -e$@ $(LKOBJECTS) diff --git a/as/link/hc08/Makefile.in b/as/link/hc08/Makefile.in new file mode 100644 index 00000000..508e1fb9 --- /dev/null +++ b/as/link/hc08/Makefile.in @@ -0,0 +1,114 @@ +# +# +# + +VERSION = @VERSION@ +VERSIONHI = @VERSIONHI@ +VERSIONLO = @VERSIONLO@ +VERSIONP = @VERSIONP@ + +SHELL = /bin/sh +CC = @CC@ +CPP = @CPP@ +INSTALL = @INSTALL@ +STRIP = @STRIP@ + +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +datadir = @datadir@ +includedir = @includedir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +infodir = @info@ + +EXEEXT = @EXEEXT@ + +VPATH = @srcdir@ + +CPPFLAGS = @CPPFLAGS@ -I$(srcdir)/.. +CFLAGS = @CFLAGS@ -Wall +M_OR_MM = @M_OR_MM@ +LDFLAGS = @LDFLAGS@ + +LKOBJECTS = lkmain.o lkarea.o lkdata.o \ + lkrloc.o \ + lklibr.o lkihx.o lks19.o lkelf.o \ + lkmem.o lkaomf51.o \ + ../lkeval.o ../lkhead.o ../lklex.o ../lklist.o \ + ../lknoice.o ../lkstore.o ../lksym.o \ + ../../strcmpi.o +LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS)) + +ASLINK = $(top_builddir)bin/link-hc08$(EXEEXT) + +transform = @program_transform_name@ + +# Compiling entire program or any subproject +# ------------------------------------------ +all: checkconf $(ASLINK) + +$(ASLINK): $(LKOBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LKOBJECTS) + +# Compiling and installing everything and running test +# ---------------------------------------------------- +install: all installdirs + $(INSTALL) $(ASLINK) `echo $(DESTDIR)$(bindir)/link-hc08$(EXEEXT)|sed '$(transform)'` + $(STRIP) `echo $(DESTDIR)$(bindir)/link-hc08$(EXEEXT)|sed '$(transform)'` + +# Deleting all the installed files +# -------------------------------- +uninstall: + rm -f $(DESTDIR)$(bindir)/link-hc08$(EXEEXT) + + +# Performing self-test +# -------------------- +check: + + +# Performing installation test +# ---------------------------- +installcheck: + + +# Creating installation directories +# --------------------------------- +installdirs: + $(INSTALL) -d $(DESTDIR)$(bindir) + + +# Creating dependencies +# --------------------- +dep: Makefile.dep + +Makefile.dep: $(LKSOURCES) $(srcdir)/../*.h $(top_builddir)*.h $(top_srcdir)/*.h + $(CPP) $(CPPFLAGS) $(M_OR_MM) $(filter %.c,$^) >Makefile.dep + +ifeq "$(findstring $(MAKECMDGOALS),uninstall check installcheck installdirs \ + clean distclean mostlyclean realclean)" "" + include Makefile.dep +endif +include $(srcdir)/clean.mk + +# My rules +# -------- +.c.o: + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + + +# Remaking configuration +# ---------------------- +checkconf: + @if [ -f $(top_builddir)devel ]; then\ + $(MAKE) -f conf.mk srcdir="$(srcdir)" top_builddir="$(top_builddir)" freshconf;\ + fi + +# End of Makefile diff --git a/as/link/hc08/aslink.mak b/as/link/hc08/aslink.mak new file mode 100644 index 00000000..300803d9 --- /dev/null +++ b/as/link/hc08/aslink.mak @@ -0,0 +1,263 @@ +ORIGIN = Symantec C++ +ORIGIN_VER = Version 7.00 +VERSION = RELEASE + +!IFDEF SUB_DEBUG +DEBUG = $(SUB_DEBUG) +NDEBUG = !$(SUB_DEBUG) +!ELSE +DEBUG = 0 +NDEBUG = 1 +!ENDIF + +PROJ = ASLINK +APPTYPE = DOS EXE +PROJTYPE = EXE + +CC = SC +CPP = SPP +MAKE = SMAKE +RC = RCC +HC = HC31 +ASM = SC +DISASM = OBJ2ASM +LNK = LINK +DLLS = + +HEADERS = ..\linksrc\aslink.h + +DEFFILE = ASLINK.DEF + +!IF $(DEBUG) +OUTPUTDIR = . +CREATEOUTPUTDIR = +TARGETDIR = . +CREATETARGETDIR = + +LIBS = + +CFLAGS = -A -Jm -J -ms -o+time -S -2 -a2 -c +LFLAGS = /PACKF +DEFINES = -D_DEBUG=1 +!ELSE +OUTPUTDIR = . +CREATEOUTPUTDIR = +TARGETDIR = . +CREATETARGETDIR = + +LIBS = + +CFLAGS = -A -Jm -J -ms -o+time -S -2 -a2 -c +LFLAGS = /PACKF +DEFINES = +!ENDIF + +HFLAGS = $(CFLAGS) +MFLAGS = MASTERPROJ=$(PROJ) +LIBFLAGS = /C +RESFLAGS = +DEBUGGERFLAGS = -LOADSYMBOLS +AFLAGS = $(CFLAGS) +HELPFLAGS = + +MODEL = S + +PAR = PROJS BATS OBJS + +RCDEFINES = + +LIBDIRS = + +INCLUDES = -Ic:\asxxxx\linksrc + +INCLUDEDOBJS = + +OBJS = $(OUTPUTDIR)\lkarea.OBJ $(OUTPUTDIR)\lkdata.OBJ $(OUTPUTDIR)\lkeval.OBJ \ + $(OUTPUTDIR)\lkhead.OBJ $(OUTPUTDIR)\lkihx.OBJ $(OUTPUTDIR)\lklex.OBJ $(OUTPUTDIR)\lklibr.OBJ \ + $(OUTPUTDIR)\lklist.OBJ $(OUTPUTDIR)\lkmain.OBJ $(OUTPUTDIR)\lkrloc.OBJ $(OUTPUTDIR)\lks19.OBJ \ + $(OUTPUTDIR)\lksym.OBJ + +RCFILES = + +RESFILES = + +SYMS = + +HELPFILES = + +BATS = + +.SUFFIXES: .C .CP .CPP .CXX .CC .H .HPP .HXX .COM .EXE .DLL .LIB .RTF .DLG .ASM .RES .RC .OBJ + +.C.OBJ: + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.c + +.CPP.OBJ: + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cpp + +.CXX.OBJ: + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cxx + +.CC.OBJ: + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cc + +.CP.OBJ: + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cp + +.H.SYM: + $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.h + +.HPP.SYM: + $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hpp + +.HXX.SYM: + $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hxx + +.C.EXP: + $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.c -o$*.lst + +.CPP.EXP: + $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cpp -o$*.lst + +.CXX.EXP: + $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cxx -o$*.lst + +.CP.EXP: + $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cp -o$*.lst + +.CC.EXP: + $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cc -o$*.lst + +.ASM.EXP: + $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.asm -o$*.lst + +.OBJ.COD: + $(DISASM) $*.OBJ >$*.cod + +.OBJ.EXE: + $(LNK) $(LFLAGS) @$(PROJ).LNK + +.RTF.HLP: + $(HC) $(HELPFLAGS) $*.HPJ + +.ASM.OBJ: + $(ASM) $(AFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.asm + +.RC.RES: + $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $*.rc -o$*.res + +.DLG.RES: + echo ^#include "windows.h" >$$$*.rc + echo ^IF EXIST "$*.h" >>$$$*.rc + echo ^#include "$*.h" >>$$$*.rc + echo ^#include "$*.dlg" >>$$$*.rc + $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $$$*.rc + -del $*.res + -ren $$$*.res $*.res + + + +all: createdir $(PRECOMPILE) $(SYMS) $(OBJS) $(INCLUDEDOBJS) $(POSTCOMPILE) $(TARGETDIR)\$(PROJ).$(PROJTYPE) $(POSTLINK) _done + +createdir: + $(CREATEOUTPUTDIR) + $(CREATETARGETDIR) + +$(TARGETDIR)\$(PROJ).$(PROJTYPE): $(OBJS) $(INCLUDEDOBJS) $(RCFILES) $(RESFILES) $(HELPFILES) + $(LNK) $(LFLAGS) @$(PROJ).LNK; + -del $(TARGETDIR)\$(PROJ).$(PROJTYPE) + -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE) + -echo $(TARGETDIR)\$(PROJ).$(PROJTYPE) built + +_done: + -echo $(PROJ).$(PROJTYPE) done + +buildall: clean all + + +clean: + -del $(TARGETDIR)\$$SCW$$.$(PROJTYPE) + -del $(TARGETDIR)\$(PROJ).CLE + -del $(OUTPUTDIR)\SCPH.SYM + -del $(OBJS) + +cleanres: + +res: cleanres $(RCFILES) all + + +link: + $(LNK) $(LFLAGS) @$(PROJ).LNK; + -del $(TARGETDIR)\$(PROJ).$(PROJTYPE) + -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE) + + + + +!IF EXIST (ASLINK.dpd) +!INCLUDE ASLINK.dpd +!ENDIF + + + +$(OUTPUTDIR)\lkarea.OBJ: ..\linksrc\lkarea.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkarea.obj ..\linksrc\lkarea.c + + + +$(OUTPUTDIR)\lkdata.OBJ: ..\linksrc\lkdata.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkdata.obj ..\linksrc\lkdata.c + + + +$(OUTPUTDIR)\lkeval.OBJ: ..\linksrc\lkeval.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkeval.obj ..\linksrc\lkeval.c + + + +$(OUTPUTDIR)\lkhead.OBJ: ..\linksrc\lkhead.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkhead.obj ..\linksrc\lkhead.c + + + +$(OUTPUTDIR)\lkihx.OBJ: ..\linksrc\lkihx.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkihx.obj ..\linksrc\lkihx.c + + + +$(OUTPUTDIR)\lklex.OBJ: ..\linksrc\lklex.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklex.obj ..\linksrc\lklex.c + + + +$(OUTPUTDIR)\lklibr.OBJ: ..\linksrc\lklibr.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklibr.obj ..\linksrc\lklibr.c + + + +$(OUTPUTDIR)\lklist.OBJ: ..\linksrc\lklist.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklist.obj ..\linksrc\lklist.c + + + +$(OUTPUTDIR)\lkmain.OBJ: ..\linksrc\lkmain.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkmain.obj ..\linksrc\lkmain.c + + + +$(OUTPUTDIR)\lkrloc.OBJ: ..\linksrc\lkrloc.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkrloc.obj ..\linksrc\lkrloc.c + + + +$(OUTPUTDIR)\lks19.OBJ: ..\linksrc\lks19.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lks19.obj ..\linksrc\lks19.c + + + +$(OUTPUTDIR)\lksym.OBJ: ..\linksrc\lksym.c + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lksym.obj ..\linksrc\lksym.c + + + + diff --git a/as/link/hc08/clean.mk b/as/link/hc08/clean.mk new file mode 100644 index 00000000..2ecd3c76 --- /dev/null +++ b/as/link/hc08/clean.mk @@ -0,0 +1,25 @@ +# Deleting all files created by building the program +# -------------------------------------------------- +include $(top_builddir)Makefile.common + +clean: + rm -f *core *[%~] *.[oa] + rm -f .[a-z]*~ + rm -f $(top_builddir)bin/link-hc08$(EXEEXT) link-hc08$(EXEEXT) + + +# Deleting all files created by configuring or building the program +# ----------------------------------------------------------------- +distclean: clean + rm -f Makefile *.dep + + +# Like clean but some files may still exist +# ----------------------------------------- +mostlyclean: clean + + +# Deleting everything that can reconstructed by this Makefile. It deletes +# everything deleted by distclean plus files created by bison, etc. +# ----------------------------------------------------------------------- +realclean: distclean diff --git a/as/link/hc08/conf.mk b/as/link/hc08/conf.mk new file mode 100644 index 00000000..ac65f24e --- /dev/null +++ b/as/link/hc08/conf.mk @@ -0,0 +1,10 @@ +# +# Makefile targets to remake configuration +# + +freshconf: Makefile + +Makefile: $(srcdir)/Makefile.in $(top_srcdir)/configure.in + cd $(top_builddir) && $(SHELL) ./config.status + +# End of conf.mk diff --git a/as/link/hc08/link_hc08.dsp b/as/link/hc08/link_hc08.dsp new file mode 100644 index 00000000..ca05142d --- /dev/null +++ b/as/link/hc08/link_hc08.dsp @@ -0,0 +1,174 @@ +# Microsoft Developer Studio Project File - Name="link_hc08" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=link_hc08 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "link_hc08.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "link_hc08.mak" CFG="link_hc08 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "link_hc08 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "link_hc08 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "link_hc08 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "hc08\Release" +# PROP BASE Intermediate_Dir "hc08\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\link-hc08.exe" + +!ELSEIF "$(CFG)" == "link_hc08 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "hc08\Debug" +# PROP BASE Intermediate_Dir "hc08\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\link-hc08.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "link_hc08 - Win32 Release" +# Name "link_hc08 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\lkaomf51.c +# End Source File +# Begin Source File + +SOURCE=.\lkarea.c +# End Source File +# Begin Source File + +SOURCE=.\lkdata.c +# End Source File +# Begin Source File + +SOURCE=.\lkelf.c +# End Source File +# Begin Source File + +SOURCE=..\lkeval.c +# End Source File +# Begin Source File + +SOURCE=..\lkhead.c +# End Source File +# Begin Source File + +SOURCE=.\lkihx.c +# End Source File +# Begin Source File + +SOURCE=..\lklex.c +# End Source File +# Begin Source File + +SOURCE=.\lklibr.c +# End Source File +# Begin Source File + +SOURCE=..\lklist.c +# End Source File +# Begin Source File + +SOURCE=.\lkmain.c +# End Source File +# Begin Source File + +SOURCE=.\lkmem.c +# End Source File +# Begin Source File + +SOURCE=..\lknoice.c +# End Source File +# Begin Source File + +SOURCE=.\lkrloc.c +# End Source File +# Begin Source File + +SOURCE=.\lks19.c +# End Source File +# Begin Source File + +SOURCE=..\lkstore.c +# End Source File +# Begin Source File + +SOURCE=..\lksym.c +# End Source File +# Begin Source File + +SOURCE=..\..\strcmpi.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\aslink.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\sdcc_vc.h +# End Source File +# End Group +# End Target +# End Project diff --git a/as/link/hc08/lkaomf51.c b/as/link/hc08/lkaomf51.c new file mode 100644 index 00000000..f81a96a9 --- /dev/null +++ b/as/link/hc08/lkaomf51.c @@ -0,0 +1,980 @@ +/*------------------------------------------------------------------------- + lkaomf51.c - Create an absolute object memory format 51 file + + Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002) + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +-------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "aslink.h" + +#define EQ(A,B) !strcmp((A),(B)) +#define MEMSIZE 0x10000 +//#define DODUMP 1 + +typedef struct +{ + char PathName[PATH_MAX]; + char ModuleName[PATH_MAX]; +} _infn; + +int numin=0; +_infn * infn=NULL; + +char ihxFileName[PATH_MAX]; +char aomf51FileName[PATH_MAX]; + +typedef struct +{ + char name[0x100]; + int FileNameNumber; + int Procedure;//If the symbol belongs to a function + int Static; //If the symbol is only public on its file + int Address; + int UsageType; +} _symbol; + +int numsym=0; +_symbol * symbol=NULL; + +typedef struct +{ + char name[0x100]; + int FileNameNumber; + int BeginAdd; + int EndAdd; +} _procedure; + +int numproc=0; +_procedure * procedure=NULL; + +typedef struct +{ + int Number; + int Address; + int Procedure; + int FileNameNumber; +} _linenum; + +int numlinenum=0; +_linenum * linenum=NULL; +#if 0 +typedef struct +{ + char * name; + int usage; +} +_UsageType; + +_UsageType UsageType[]= +{ + {"CSEG", 0}, + {"GSINIT", 0}, + {"GSFINAL", 0}, + {"HOME", 0}, + {"XINIT", 0}, + {"XSEG", 1}, + {"XISEG", 1}, + {"REG_BANK_0", 2}, + {"REG_BANK_1", 2}, + {"REG_BANK_2", 2}, + {"REG_BANK_3", 2}, + {"DSEG", 2}, + {"OSEG", 2}, + {"SSEG", 2}, + {"ISEG", 3}, + {"BSEG", 4}, + {"", 5} /*A typeless number?*/ +}; +#endif +char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"}; +int AddNumber; +unsigned char * ihxBuff=NULL; +FILE * aomf51out; +int GlobalChkSum=0; +int HexSize, HexBegin=0x10000; + + +void GetName(char * filepath, char * name) +{ + int j, k; + for(j=strlen(filepath); j>0; j--) + if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break; + for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++) + name[k]=filepath[j]; + name[k]=0; +} + +void SaveLinkedFilePath(char * filepath) +{ + int j; + + if((dflag) && (!rflag)) + { + infn=realloc(infn, sizeof(_infn)*(numin+1)); + + strcpy(infn[numin].PathName, filepath); + j=strlen(infn[numin].PathName); + + /*If there is an extension remove it*/ + if(j>=4) + { + if(EQ(&infn[numin].PathName[j-4], ".rel")) + { + infn[numin].PathName[j-4]=0; + } + } + + /*Get the module name=filename, no drive, no dir, no ext*/ + GetName(infn[numin].PathName, infn[numin].ModuleName); + //printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName); + + /*Check if this filename is already in*/ + for(j=0; j=0)?procedure[symbol[j].Procedure].name:"GLOBAL", + symbol[j].Address, + k<6?UsageTypeName[k]:"???"); + } + + fprintf(DumpFile,"\nPROCEDURES:\n"); + for(j=0; j %s\n", + linenum[j].Number, + linenum[j].Address, + infn[linenum[j].FileNameNumber].PathName, + (linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know"); + } + + fclose(DumpFile); +} +#endif + +void OutputAOEMF51(void) +{ + int i, j, k, recsize; + char MHRname[0x100], Mname[0x100]; + + strcpy(aomf51FileName, infn[0].PathName); + + aomf51out=fopen(aomf51FileName, "wb"); + if(aomf51out==NULL) + { + printf("Couldn't create file %s\n", aomf51FileName); + return; + } + + GetName(infn[0].PathName, MHRname); + GlobalChkSum=0; + + /*Module header record*/ + OutputByte(0x02);/*REC TYPE*/ + OutputWord((strlen(MHRname)+1)+3);/*Record Length*/ + OutputName(MHRname);/*Module Name*/ + OutputByte(0xff);/*TRN ID: RL51?*/ + OutputByte(0x00); + OutputChkSum(); + + for(j=0; j2) /*If there are any symbols*/ + { + OutputByte(0x12); /*REC TYPE*/ + OutputWord(recsize);/*Record Length*/ + OutputByte(0x01); /*DEF TYPE: Public symbols*/ + for(k=0; k2) /*If there are any symbols*/ + { + OutputByte(0x12); /*REC TYPE*/ + OutputWord(recsize);/*Record Length*/ + OutputByte(0x00); /*DEF TYPE: Local symbols*/ + for(k=0; k2) /*If there are any symbols*/ + { + OutputByte(0x12); /*REC TYPE*/ + OutputWord(recsize);/*Record Length*/ + OutputByte(0x00); /*DEF TYPE: Local symbols*/ + for(i=0; i2) /*If there are any line numbers*/ + { + OutputByte(0x12); /*REC TYPE*/ + OutputWord(recsize);/*Record Length*/ + OutputByte(0x03); /*DEF TYPE: Line numbers*/ + for(i=0; i|L}$$$(),
,," + char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s"; + char c; + char scope[0x100]; + char name[0x100]; + char level[0x100]; + char block[0x100]; + char Bfmt[]="%[^)] %c %c %c %c %d %c %d"; + char TypeInfo[0x100]; + char AddressSpace; + int OnStack; + int StackOffset; + int Address, CLine; + + if(numin==0) return; + + if (dfp != NULL) + { + fclose(dfp); + dfp=NULL; + } + + /*Build the source filename*/ + strcpy(SourceName, infn[0].PathName); + strcat(SourceName, ".cdb"); + CDBin=fopen(SourceName, "r"); + if(CDBin==NULL) + { + printf("Couldn't open file '%s'\n", SourceName); + lkexit(1); + } + + CurrentModule=0; /*Set the active module as the first one*/ + while(!feof(CDBin)) + { + fgets(buff, sizeof(buff)-1, CDBin); + + if(!feof(CDBin)) switch(buff[0]) + { + /*Example: "M:adq"*/ + case 'M': + sscanf(&buff[2], "%s", name); + for(j=0; j(),
,,*/ + sscanf(block, Bfmt, + TypeInfo, &c, &c, + &AddressSpace, &c, + &OnStack, &c, + &StackOffset); + + i=-1; k=-1; + switch(scope[2]) + { + case 'G': /*Global symbol*/ + break; + case 'L': /*Local symbol of a procedure*/ + for(j=0; j=procedure[k].BeginAdd) && + (linenum[j].Address<=procedure[k].EndAdd) && + (linenum[j].FileNameNumber==procedure[k].FileNameNumber) ) + { + linenum[j].Procedure=k; + } + } + } + + fclose(CDBin); +} + +int hex2dec (unsigned char hex_digit) +{ + if (isdigit(hex_digit)) + return hex_digit-'0'; + else + return toupper(hex_digit)-'A'+10; +} + +unsigned char GetByte(char * buffer) +{ + return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]); +} + +unsigned short GetWord(char * buffer) +{ + return hex2dec(buffer[0])*0x1000+ + hex2dec(buffer[1])*0x100+ + hex2dec(buffer[2])*0x10+ + hex2dec(buffer[3]); +} + +int ReadHexFile(int * Begin) +{ + char buffer[1024]; + FILE * filein; + int j; + unsigned char linesize, recordtype, rchksum, value; + unsigned short address; + int MaxAddress=0; + int chksum; + + /*If the hexfile is already open, close it*/ + if(ofp!=NULL) + { + fclose(ofp); + ofp=NULL; + } + + strcpy(ihxFileName, infn[0].PathName); + strcat(ihxFileName, ".ihx"); + + if ( (filein=fopen(ihxFileName, "r")) == NULL ) + { + printf("Error: Can't open file `%s`.\r\n", ihxFileName); + return 0; + } + + ihxBuff=calloc(MEMSIZE, sizeof(unsigned char)); + if(ihxBuff==NULL) + { + printf("Insufficient memory\n"); + fclose(filein); + return -1; + } + + for(j=0; j +#include +#include "aslink.h" + +/*)Module lkarea.c + * + * The module lkarea.c contains the functions which + * create and link together all area definitions read + * from the .rel file(s). + * + * lkarea.c contains the following functions: + * VOID lnkarea() + * VOID lnksect() + * VOID lkparea() + * VOID newarea() + * + * lkarea.c contains no global variables. + */ + +/*)Function VOID newarea() + * + * The function newarea() creates and/or modifies area + * and areax structures for each A directive read from + * the .rel file(s). The function lkparea() is called + * to find the area structure associated with this name. + * If the area does not yet exist then a new area + * structure is created and linked to any existing + * linked area structures. The area flags are copied + * into the area flag variable. For each occurence of + * an A directive an areax structure is created and + * linked to the areax structures associated with this + * area. The size of this area section is placed into + * the areax structure. The flag value for all subsequent + * area definitions for the same area are compared and + * flagged as an error if they are not identical. + * The areax structure created for every occurence of + * an A directive is loaded with a pointer to the base + * area structure and a pointer to the associated + * head structure. And finally, a pointer to this + * areax structure is loaded into the list of areax + * structures in the head structure. Refer to lkdata.c + * for details of the structures and their linkage. + * + * local variables: + * areax **halp pointer to an array of pointers + * int i counter, loop variable, value + * char id[] id string + * int narea number of areas in this head structure + * areax * taxp pointer to an areax structure + * to areax structures + * + * global variables: + * area *ap Pointer to the current + * area structure + * areax *axp Pointer to the current + * areax structure + * head *hp Pointer to the current + * head structure + * int lkerr error flag + * + * functions called: + * Addr_T eval() lkeval.c + * VOID exit() c_library + * int fprintf() c_library + * VOID getid() lklex.c + * VOID lkparea() lkarea.c + * VOID skip() lklex.c + * + * side effects: + * The area and areax structures are created and + * linked with the appropriate head structures. + * Failure to allocate area or areax structure + * space will terminate the linker. Other internal + * errors most likely caused by corrupted .rel + * files will also terminate the linker. + */ + +/* + * Create an area entry. + * + * A xxxxxx size nnnn flags mm + * | | | + * | | `-- ap->a_flag + * | `------------- axp->a_size + * `------------------------- ap->a_id + * + */ +VOID +newarea() +{ + register int i, narea; + struct areax *taxp; + struct areax **halp; + char id[NCPS]; + + /* + * Create Area entry + */ + getid(id, -1); + lkparea(id); + /* + * Evaluate area size + */ + skip(-1); + axp->a_size = eval(); + /* + * Evaluate flags + */ + skip(-1); + i = 0; + taxp = ap->a_axp; + while (taxp->a_axp) { + ++i; + taxp = taxp->a_axp; + } + if (i == 0) { + ap->a_flag = eval(); + } else { + i = eval(); +/* if (i && (ap->a_flag != i)) { */ +/* fprintf(stderr, "Conflicting flags in area %8s\n", id); */ +/* lkerr++; */ +/* } */ + } + /* + * Evaluate area address + */ + skip(-1); + axp->a_addr = eval(); + /* + * Place pointer in header area list + */ + if (headp == NULL) { + fprintf(stderr, "No header defined\n"); + lkexit(1); + } + narea = hp->h_narea; + halp = hp->a_list; + for (i=0; i < narea ;++i) { + if (halp[i] == NULL) { + halp[i] = taxp; + return; + } + } + fprintf(stderr, "Header area list overflow\n"); + lkexit(1); +} + +/*)Function VOID lkparea(id) + * + * char * id pointer to the area name string + * + * The function lkparea() searches the linked area structures + * for a name match. If the name is not found then an area + * structure is created. An areax structure is created and + * appended to the areax structures linked to the area structure. + * The associated base area and head structure pointers are + * loaded into the areax structure. + * + * local variables: + * area * tap pointer to an area structure + * areax * taxp pointer to an areax structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * area *areap The pointer to the first + * area structure of a linked list + * areax *axp Pointer to the current + * areax structure + * + * functions called: + * VOID * new() lksym() + * char * strcpy() c_library + * int symeq() lksym.c + * + * side effects: + * Area and/or areax structures are created. + * Failure to allocate space for created structures + * will terminate the linker. + */ + +VOID +lkparea(char *id) +{ + register struct area *tap; + register struct areax *taxp; + + ap = areap; + axp = (struct areax *) new (sizeof(struct areax)); + axp->a_addr = -1; /* default: no address yet */ + while (ap) { + if (symeq(id, ap->a_id)) { + taxp = ap->a_axp; + while (taxp->a_axp) + taxp = taxp->a_axp; + taxp->a_axp = axp; + axp->a_bap = ap; + axp->a_bhp = hp; + return; + } + ap = ap->a_ap; + } + ap = (struct area *) new (sizeof(struct area)); + if (areap == NULL) { + areap = ap; + } else { + tap = areap; + while (tap->a_ap) + tap = tap->a_ap; + tap->a_ap = ap; + } + ap->a_axp = axp; + axp->a_bap = ap; + axp->a_bhp = hp; + strncpy(ap->a_id, id, NCPS); + ap->a_addr = 0; +} + +/*)Function VOID lnkarea() + * + * The function lnkarea() resolves all area addresses. + * The function evaluates each area structure (and all + * the associated areax structures) in sequence. The + * linking process supports four (4) possible area types: + * + * ABS/OVR - All sections (each individual areax + * section) starts at the identical base + * area address overlaying all other + * areax sections for this area. The + * size of the area is largest of the area + * sections. + * + * ABS/CON - All sections (each individual areax + * section) are concatenated with the + * first section starting at the base + * area address. The size of the area + * is the sum of the section sizes. + * + * NOTE: Multiple absolute (ABS) areas are + * never concatenated with each other, + * thus absolute area A and absolute area + * B will overlay each other if they begin + * at the same location (the default is + * always address 0 for absolute areas). + * + * REL/OVR - All sections (each individual areax + * section) starts at the identical base + * area address overlaying all other + * areax sections for this area. The + * size of the area is largest of the area + * sections. + * + * REL/CON - All sections (each individual areax + * section) are concatenated with the + * first section starting at the base + * area address. The size of the area + * is the sum of the section sizes. + * + * NOTE: Relocatable (REL) areas are always concatenated + * with each other, thus relocatable area B + * (defined after area A) will follow + * relocatable area A independent of the + * starting address of area A. Within a + * specific area each areax section may be + * overlayed or concatenated with other + * areax sections. + * + * + * If a base address for an area is specified then the + * area will start at that address. Any relocatable + * areas defined subsequently will be concatenated to the + * previous relocatable area if it does not have a base + * address specified. + * + * The names s_ and l_ are created to + * define the starting address and length of each area. + * + * local variables: + * Addr_T rloc ;current relocation address + * char temp[] ;temporary string + * struct symbol *sp ;symbol structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * area *areap The pointer to the first + * area structure of a linked list + * + * functions called: + * int fprintf() c_library + * VOID lnksect() lkarea.c + * symbol *lkpsym() lksym.c + * char * strncpy() c_library + * int symeq() lksym.c + * + * side effects: + * All area and areax addresses and sizes are + * determined and saved in their respective + * structures. + */ + +unsigned long codemap[2048]; +Addr_T lnksect(struct area *tap); +/* + * Resolve all area addresses. + */ +VOID +lnkarea() +{ + Addr_T rloc[4] = {0, 0, 0, 0}; + Addr_T gs_size = 0; + int locIndex; + char temp[NCPS]; + struct sym *sp; + /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/ + struct area *ta[5]; + int j; + struct area *abs_ap = NULL; + struct area *gs0_ap = NULL; + + memset(codemap, 0, sizeof(codemap)); + + /* first sort all absolute areas to the front */ + ap = areap; + /* no need to check first area, it's in front anyway */ + while (ap && ap->a_ap) + { + if (ap->a_ap->a_flag & A_ABS) + {/* next area is absolute, move it to front, + reversed sequence is no problem for absolutes */ + abs_ap = ap->a_ap; + ap->a_ap = abs_ap->a_ap; + abs_ap->a_ap = areap; + areap = abs_ap; + } + else + { + ap = ap->a_ap; + } + } + + /* next accumulate all GSINITx/GSFINAL area sizes + into GSINIT so they stay together */ + ap = areap; + while (ap) + { + if (!strncmp(ap->a_id, "GS", 2)) + {/* GSxxxxx area */ + if (ap->a_size == 0) + { + axp = ap->a_axp; + while (axp) + { + ap->a_size += axp->a_size; + axp = axp->a_axp; + } + } + gs_size += ap->a_size; + if (!strcmp(ap->a_id, "GSINIT0")) + {/* GSINIT0 area */ + gs0_ap = ap; + } + } + ap = ap->a_ap; + } + if (gs0_ap) + gs0_ap->a_size = gs_size; + + ap = areap; + while (ap) { + if (ap->a_flag & A_ABS) { + /* + * Absolute sections + */ + lnksect(ap); + } else { + /* Determine memory space */ + locIndex = 0; + #if 0 + if (ap->a_flag & A_CODE) { + locIndex = 1; + } + if (ap->a_flag & A_XDATA) { + locIndex = 2; + } + if (ap->a_flag & A_BIT) { + locIndex = 3; + } + #endif + /* + * Relocatable sections + */ + if (ap->a_type == 0) { /* JLH */ + if (ap->a_flag & A_NOLOAD) { + locIndex = 2; + ap->a_addr = 0; + } else { + ap->a_addr = rloc[ locIndex ]; + } + ap->a_type = 1; + } + + rloc[ locIndex ] = lnksect(ap); + } + + /* + * Create symbols called: + * s_ the start address of the area + * l_ the length of the area + */ + + if (! symeq(ap->a_id, _abs_)) + { + strncpy(temp+2,ap->a_id,NCPS-2); + *(temp+1) = '_'; + + *temp = 's'; + sp = lkpsym(temp, 1); + sp->s_addr = ap->a_addr ; + /* sp->s_axp = ap->a_axp; JLH: was NULL; */ + sp->s_type |= S_DEF; + + *temp = 'l'; + sp = lkpsym(temp, 1); + sp->s_addr = ap->a_size; + sp->s_axp = NULL; + sp->s_type |= S_DEF; + + } + + /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG + to compute the byte size of BSEG_BYTES: */ + if (!strcmp(ap->a_id, "BSEG")) { + ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/ + } + else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap; + else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap; + else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap; + else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap; + else if (!strcmp(ap->a_id, "BSEG_BYTES")) + { + ta[4]=ap; + for(j=4; j>1; j--) + { + /*If upper register banks are not used roll back the relocation counter*/ + if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) ) + { + rloc[0]-=8; + } + else break; + } + } + ap = ap->a_ap; + } +} + +static +Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map) +{ + int i, j, k; + unsigned long mask, b; + + while (1) + { + Addr_T a = start; + i = start >> 5; + j = (start + size) >> 5; + mask = -(1 << (start & 0x1F)); + + while (i < j) + { + if (map[i] & mask) + { + k = 32; + for (b=0x80000000; b!=0; b>>=1, k--) + { + if (map[i] & b) + break; + } + start = a + k; + break; + } + i++; + mask = 0xFFFFFFFF; + a += 32; + } + if (start > a) + continue; + + mask &= (1 << ((start + size) & 0x1F)) - 1; + if (map[i] & mask) + { + k = 32; + for (b=0x80000000; b!=0; b>>=1, k--) + { + if (map[i] & b) + break; + } + start = (a & ~0x1F) + k; + } + if (start <= a) + break; + } + return start; +} + +static +Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map) +{ + int i, j; + unsigned long mask; + Addr_T a = start; + i = start >> 5; + j = (start + size) >> 5; + mask = -(1 << (start & 0x1F)); + + while (i < j) + { + if (map[i] & mask) + { + fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id); + } + map[i++] |= mask; + mask = 0xFFFFFFFF; + a += 32; + } + mask &= (1 << ((start + size) & 0x1F)) - 1; + if (map[i] & mask) + { + fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id); + } + map[i] |= mask; + return start; +} + +/*)Function VOID lnksect() + * + * area * tap pointer to an area structure + * + * The function lnksect() is the function called by + * lnkarea() to resolve the areax addresses. Refer + * to the function lnkarea() for more detail. Pageing + * boundary and length errors will be reported by this + * function. + * + * local variables: + * Addr_T size size of area + * Addr_T addr address of area + * areax * taxp pointer to an areax structure + * + * global variables: + * int lkerr error flag + * + * functions called: + * none + * + * side effects: + * All area and areax addresses and sizes area determined + * and linked into the structures. + */ + +Addr_T lnksect(struct area *tap) +{ + register Addr_T size, addr; + register struct areax *taxp; + + size = 0; + addr = tap->a_addr; + + if ((tap->a_flag&A_PAG) && (addr & 0xFF)) { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id); + lkerr++; + } + + taxp = tap->a_axp; + if (tap->a_flag&A_OVR) { + /* + * Overlayed sections + */ + while (taxp) { + taxp->a_addr = addr; + if (taxp->a_size > size) + size = taxp->a_size; + taxp = taxp->a_axp; + } + } else if (tap->a_flag & A_ABS) { + /* + * Absolute sections + */ + while (taxp) { + allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap); + taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */ + size += taxp->a_size; + taxp = taxp->a_axp; + } + } else { + /* + * Concatenated sections + */ + if (tap->a_size) { + addr = find_empty_space(addr, tap->a_size, codemap); + } + while (taxp) { + //find next unused address now + if (taxp->a_size) + { + addr = find_empty_space(addr, taxp->a_size, codemap); + allocate_space(addr, taxp->a_size, tap->a_id, codemap); + } + taxp->a_addr = addr; + addr += taxp->a_size; + size += taxp->a_size; + taxp = taxp->a_axp; + } + } + tap->a_size = size; + + if ((tap->a_flag&A_PAG) && (size > 256)) { + fprintf(stderr, + "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id); + lkerr++; + } + + return addr; +} diff --git a/as/link/hc08/lkdata.c b/as/link/hc08/lkdata.c new file mode 100644 index 00000000..022ad65c --- /dev/null +++ b/as/link/hc08/lkdata.c @@ -0,0 +1,491 @@ +/* lkdata.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + * + * 28-Oct-97 JLH: + * - change s_id from [NCPS] to pointer (comment) + * 31-Oct-97 JLH: + * - add jflag and jfp for NoICE output + */ + +#include +#include +#include "aslink.h" + +/*)Module lkdata.c + * + * The module lkdata contains the global variables + * and structures used in the linker aslink. + */ + +/* + * Definitions for all Global Variables + */ + +char *_abs_ = { ". .ABS." }; + +int lkerr; /* Linker error flag + */ +char *ip; /* Pointer into the REL file text line in ib[] + */ +char ib[NINPUT]; /* REL file text line + */ +char *rp; /* pointer into the LST file + * text line in rb[] + */ +char rb[NINPUT]; /* LST file text line being + * address relocated + */ + +char sdccopt[NINPUT]=""; +char sdccopt_module[NINPUT]=""; +char curr_module[NINPUT]=""; + +int dflag; /* Debug information output flag + */ +int oflag; /* Output file type flag + */ +int mflag; /* Map output flag + */ +int sflag; /* JCF: Memory usage output flag + */ +int aflag; /* Overlapping area warning flag + */ +int jflag; /* NoICE output flag + */ +int xflag; /* Map file radix type flag + */ +int pflag; /* print linker command file flag + */ +int uflag; /* Listing relocation flag + */ +int rflag; /* Extended linear address record flag. + */ +int radix; /* current number conversion radix: + * 2 (binary), 8 (octal), 10 (decimal), + * 16 (hexadecimal) + */ +int line; /* current line number + */ +int page; /* current page number + */ +int lop; /* current line number on page + */ +int pass; /* linker pass number + */ +int rtcnt; /* count of elements in the + * rtval[] and rtflg[] arrays + */ +Addr_T rtval[NTXT]; /* data associated with relocation + */ +int rtflg[NTXT]; /* indicates if rtval[] value is + * to be sent to the output file. + * (always set in this linker) + */ +int hilo; /* REL file byte ordering + */ +int gline; /* LST file relocation active + * for current line + */ +int gcntr; /* LST file relocation active + * counter + */ +Addr_T iram_size; /* internal ram size + */ +long xram_size=-1; /* external ram size + */ +long code_size=-1; /* code size + */ + +/* + * The structure lfile contains a pointer to a + * file specification string, the file type, and + * a link to the next lfile structure. + * + * struct lfile + * { + * struct lfile *f_flp; lfile link + * int f_type; File type + * char *f_idp; Pointer to file spec + * }; + */ +struct lfile *filep; /* The pointers (lfile *) filep, + * (lfile *) cfp, and (FILE *) sfp + * are used in conjunction with + * the routine lk_getline() to read + * asmlnk commands from + * (1) the standard input or + * (2) or a command file + * and to read the REL files + * sequentially as defined by the + * asmlnk input commands. + * + * The pointer *filep points to the + * beginning of a linked list of + * lfile structures. + */ +struct lfile *cfp; /* The pointer *cfp points to the + * current lfile structure + */ +struct lfile *startp;/* asmlnk startup file structure + */ +struct lfile *linkp; /* pointer to first lfile structure + * containing an input REL file + * specification + */ +struct lfile *lfp; /* pointer to current lfile structure + * being processed by parse() + */ +FILE *ofp; /* Output file handle + * for word formats + */ +FILE *mfp; /* Map output file handle + */ +FILE *jfp; /* NoICE output file handle + */ +FILE *rfp; /* File handle for output + * address relocated ASxxxx + * listing file + */ +FILE *sfp; /* The file handle sfp points to the + * currently open file + */ +FILE *tfp; /* File handle for input + * ASxxxx listing file + */ +FILE *dfp = NULL ; /* + * File handle for debug + * information output file + */ +/* + * The structures of head, area, areax, and sym are created + * as the REL files are read during the first pass of the + * linker. The struct head is created upon encountering a + * H directive in the REL file. The structure contains a + * link to a link file structure (struct lfile) which describes + * the file containing the H directive, the number of data/code + * areas contained in this header segment, the number of + * symbols referenced/defined in this header segment, a pointer + * to an array of pointers to areax structures (struct areax) + * created as each A directive is read, and a pointer to an + * array of pointers to symbol structures (struct sym) for + * all referenced/defined symbols. As H directives are read + * from the REL files a linked list of head structures is + * created by placing a link to the new head structure + * in the previous head structure. + * + * struct head + * { + * struct head *h_hp; Header link + * struct lfile *h_lfile; Associated file + * int h_narea; # of areas + * struct areax **a_list; Area list + * int h_nglob; # of global symbols + * struct sym **s_list; Global symbol list + * char m_id[NCPS]; Module name + * }; + */ +struct head *headp; /* The pointer to the first + * head structure of a linked list + */ +struct head *hp; /* Pointer to the current + * head structure + */ + +/* + * A structure area is created for each 'unique' data/code + * area definition found as the REL files are read. The + * struct area contains the name of the area, a flag byte + * which contains the area attributes (REL/CON/OVR/ABS), + * an area subtype (not used in this assembler), and the + * area base address and total size which will be filled + * in at the end of the first pass through the REL files. + * As A directives are read from the REL files a linked + * list of unique area structures is created by placing a + * link to the new area structure in the previous area structure. + * + * struct area + * { + * struct area *a_ap; Area link + * struct areax *a_axp; Area extension link + * Addr_T a_addr; Beginning address of area + * Addr_T a_size; Total size of the area + * char a_type; Area subtype + * char a_flag; Flag byte + * char a_id[NCPS]; Name + * }; + */ +struct area *areap; /* The pointer to the first + * area structure of a linked list + */ +struct area *ap; /* Pointer to the current + * area structure + */ + +/* + * An areax structure is created for every A directive found + * while reading the REL files. The struct areax contains a + * link to the 'unique' area structure referenced by the A + * directive and to the head structure this area segment is + * a part of. The size of this area segment as read from the + * A directive is placed in the areax structure. The beginning + * address of this segment will be filled in at the end of the + * first pass through the REL files. As A directives are read + * from the REL files a linked list of areax structures is + * created for each unique area. The final areax linked + * list has at its head the 'unique' area structure linked + * to the linked areax structures (one areax structure for + * each A directive for this area). + * + * struct areax + * { + * struct areax *a_axp; Area extension link + * struct area *a_bap; Base area link + * struct head *a_bhp; Base header link + * Addr_T a_addr; Beginning address of section + * Addr_T a_size; Size of the area in section + * }; + */ +struct areax *axp; /* Pointer to the current + * areax structure + */ + +/* + * A sym structure is created for every unique symbol + * referenced/defined while reading the REL files. The + * struct sym contains the symbol's name, a flag value + * (not used in this linker), a symbol type denoting + * referenced/defined, and an address which is loaded + * with the relative address within the area in which + * the symbol was defined. The sym structure also + * contains a link to the area where the symbol was defined. + * The sym structures are linked into linked lists using + * the symbol link element. + * + * struct sym + * { + * struct sym *s_sp; Symbol link + * struct areax *s_axp; Symbol area link + * char s_type; Symbol subtype + * char s_flag; Flag byte + * Addr_T s_addr; Address + * char *s_id; Name (JLH) + * }; + */ +struct sym *symhash[NHASH]; /* array of pointers to NHASH + * linked symbol lists + */ +/* + * The struct base contains a pointer to a + * base definition string and a link to the next + * base structure. + * + * struct base + * { + * struct base *b_base; Base link + * char *b_strp; String pointer + * }; + */ +struct base *basep; /* The pointer to the first + * base structure + */ +struct base *bsp; /* Pointer to the current + * base structure + */ + +/* + * The struct globl contains a pointer to a + * global definition string and a link to the next + * global structure. + * + * struct globl + * { + * struct globl *g_globl; Global link + * char *g_strp; String pointer + * }; + */ +struct globl *globlp;/* The pointer to the first + * globl structure + */ +struct globl *gsp; /* Pointer to the current + * globl structure + */ + +/* + * A structure sdp is created for each 'unique' paged + * area definition found as the REL files are read. + * As P directives are read from the REL files a linked + * list of unique sdp structures is created by placing a + * link to the new sdp structure in the previous area structure. + * + * struct sdp + * { + * struct area *s_area; Paged Area link + * struct areax *s_areax; Paged Area Extension Link + * Addr_T s_addr; Page address offset + * }; + */ +struct sdp sdp; /* Base Page Structure */ + +/* + * The structure rerr is loaded with the information + * required to report an error during the linking + * process. The structure contains an index value + * which selects the areax structure from the header + * areax structure list, a mode value which selects + * symbol or area relocation, the base address in the + * area section, an area/symbol list index value, and + * an area/symbol offset value. + * + * struct rerr + * { + * int aindex; Linking area + * int mode; Relocation mode + * Addr_T rtbase; Base address in section + * int rindex; Area/Symbol reloaction index + * Addr_T rval; Area/Symbol offset value + * }; + */ +struct rerr rerr; /* Structure containing the + * linker error information + */ + +/* + * The structure lbpath is created for each library + * path specification input by the -k option. The + * lbpath structures are linked into a list using + * the next link element. + * + * struct lbpath { + * struct lbpath *next; + * char *path; + * }; + */ +struct lbpath *lbphead; /* pointer to the first + * library path structure + */ + +/* + * The structure lbname is created for all combinations of the + * library path specifications (input by the -k option) and the + * library file specifications (input by the -l option) that + * lead to an existing file. The element path points to + * the path string, element libfil points to the library + * file string, and the element libspc is the concatenation + * of the valid path and libfil strings. + * + * The lbpath structures are linked into a list + * using the next link element. + * + * Each library file contains a list of object files + * that are contained in the particular library. e.g.: + * + * \iolib\termio + * \inilib\termio + * + * Only one specification per line is allowed. + * + * struct lbname { + * struct lbname *next; + * char *path; + * char *libfil; + * char *libspc; + * }; + */ +struct lbname *lbnhead; /* pointer to the first + * library name structure + */ + +/* + * The function fndsym() searches through all combinations of the + * library path specifications (input by the -k option) and the + * library file specifications (input by the -l option) that + * lead to an existing file for a symbol definition. + * + * The structure lbfile is created for the first library + * object file which contains the definition for the + * specified undefined symbol. + * + * The element libspc points to the library file path specification + * and element relfil points to the object file specification string. + * The element filspc is the complete path/file specification for + * the library file to be imported into the linker. The + * file specicifation may be formed in one of two ways: + * + * (1) If the library file contained an absolute + * path/file specification then this becomes filspc. + * (i.e. C:\...) + * + * (2) If the library file contains a relative path/file + * specification then the concatenation of the path + * and this file specification becomes filspc. + * (i.e. \...) + * + * The lbpath structures are linked into a list + * using the next link element. + * + * struct lbfile { + * struct lbfile *next; + * char *libspc; + * char *relfil; + * char *filspc; + * }; + */ +struct lbfile *lbfhead; /* pointer to the first + * library file structure + */ + +/* + * array of character types, one per + * ASCII character + */ +unsigned char ctype[128] = { +/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, +/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL, +/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, +/*CAN*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, +/*SPC*/ SPACE, ETC, ETC, ETC, LETTER, BINOP, BINOP, ETC, +/*(*/ ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, BINOP, +/*0*/ DGT2, DGT2, DGT8, DGT8, DGT8, DGT8, DGT8, DGT8, +/*8*/ DGT10, DGT10, ETC, ETC, BINOP, ETC, BINOP, ETC, +/*@*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER, +/*H*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, +/*P*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, +/*X*/ LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER, +/*`*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER, +/*h*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, +/*p*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, +/*x*/ LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC +}; + +/* + * an array of characters which + * perform the case translation function + */ +#if CASE_SENSITIVE +#else +char ccase[128] = { +/*NUL*/ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', +/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', +/*DLE*/ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', +/*CAN*/ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', +/*SPC*/ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', +/*(*/ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', +/*0*/ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', +/*8*/ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', +/*@*/ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', +/*H*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', +/*P*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', +/*X*/ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', +/*`*/ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', +/*h*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', +/*p*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', +/*x*/ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177' +}; +#endif diff --git a/as/link/hc08/lkelf.c b/as/link/hc08/lkelf.c new file mode 100644 index 00000000..3cc602fd --- /dev/null +++ b/as/link/hc08/lkelf.c @@ -0,0 +1,784 @@ +/*------------------------------------------------------------------------- + lkelf.c - Create an executable ELF/DWARF file + + Written By - Erik Petrich, epetrich@users.sourceforge.net (2004) + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +-------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "aslink.h" + +#ifdef _WIN32 +# ifdef __MINGW32__ /* GCC MINGW32 depends on configure */ +# include "sdccconf.h" +# else +# include "sdcc_vc.h" +# endif +#else /* Assume Un*x style system */ +# include "sdccconf.h" +#endif + +static int execStartMSB; +static int execStartLSB; +static char execStartMSBfound; +static char execStartLSBfound; + +typedef TYPE_UDWORD Elf32_Addr; +typedef TYPE_WORD Elf32_Half; +typedef TYPE_UDWORD Elf32_Off; +typedef TYPE_DWORD Elf32_Sword; +typedef TYPE_UDWORD Elf32_Word; + +enum +{ + EI_MAG0 = 0, + EI_MAG1, + EI_MAG2, + EI_MAG3, + EI_CLASS, + EI_DATA, + EI_VERSION, + EI_PAD, + EI_NIDENT = 16 +}; + +enum +{ + ELFMAG0 = 0x7f, + ELFMAG1 = 'E', + ELFMAG2 = 'L', + ELFMAG3 = 'F' +}; + +enum +{ + ET_NONE = 0, + ET_REL, + ET_EXEC, + ET_DYN, + ET_CORE +}; + +/* These e_machine values are from "Motorola 8- and 16-bit Embedded */ +/* Application Binary Interface (M8/16EABI)" version 2.0 */ +enum +{ + EM_NONE = 0, + EM_68HC05 = 72, + EM_68HC08 = 71, + EM_68HC11 = 70, + EM_68HC12 = 53, + EM_68HC16 = 69 +}; + +enum +{ + EV_NONE = 0, + EV_CURRENT +}; + +enum +{ + ELFCLASSNONE = 0, + ELFCLASS32, + ELFCLASS64 +}; + +enum +{ + ELFDATANONE = 0, + ELFDATA2LSB, + ELFDATA2MSB +}; + +enum +{ + SHT_NULL = 0, + SHT_PROGBITS, + SHT_SYMTAB, + SHT_STRTAB, + SHT_RELA, + SHT_HASH, + SHT_DYNAMIC, + SHT_NOTE, + SHT_NOBITS, + SHT_REL, + SHT_SHLIB, + SHT_DYNSYM +}; + +enum +{ + SHF_WRITE = (1 << 0), + SHF_ALLOC = (1 << 1), + SHF_EXECINSTR = (1 << 2), +}; + +enum +{ + PT_NULL = 0, + PT_LOAD +}; + +enum +{ + PF_X = (1 << 0), + PF_W = (1 << 1), + PF_R = (1 << 2) +}; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct strtabString +{ + char * string; + struct strtabString * prev; + struct strtabString * next; + Elf32_Word index; +} strtabString; + +typedef struct +{ + strtabString * first; + strtabString * last; +} strtabList; + +static strtabList shstrtab; + + +typedef struct listEntry +{ + void * item; + struct listEntry * prev; + struct listEntry * next; +} listEntry; + +typedef struct +{ + listEntry * first; + listEntry * last; + int count; +} listHeader; + + + +static void +listAdd (listHeader * lhp, void * item) +{ + listEntry * lep; + + lep = new (sizeof (*lep)); + lep->item = item; + lep->prev = lhp->last; + if (lep->prev) + lep->prev->next = lep; + + lhp->last = lep; + if (!lhp->first) + lhp->first = lep; + + lhp->count++; +} + +static listHeader * +listNew (void) +{ + listHeader * lhp; + + lhp = new (sizeof (*lhp)); + + return lhp; +} + + +#if 0 +static Elf32_Word +strtabFind (strtabList * strtab, char * str) +{ + strtabString * sp; + sp = strtab->first; + + while (sp) + { + if (!strcmp (str, sp->string)) + return sp->index; + sp = sp->next; + } + + return 0; +} +#endif + +/*-------------------------------------------------------------------*/ +/* strtabFindOrAdd - Finds a string in a string table or adds the */ +/* string if it does not already exist. Returns the offset of the */ +/* string in the table. */ +/*-------------------------------------------------------------------*/ +static Elf32_Word +strtabFindOrAdd (strtabList * strtab, char * str) +{ + strtabString * sp; + sp = strtab->first; + + while (sp) + { + if (!strcmp (str, sp->string)) + return sp->index; + sp = sp->next; + } + + sp = new (sizeof(*sp)); + if (strtab->last) + sp->index = strtab->last->index + 1 + strlen (strtab->last->string); + else + sp->index = 1; + sp->string = new (1+strlen (str)); + strcpy (sp->string, str); + + sp->prev = strtab->last; + if (sp->prev) + sp->prev->next = sp; + strtab->last = sp; + if (!strtab->first) + strtab->first = sp; + + return sp->index; +} + +/*-------------------------------------------------------------------*/ +/* fputElfStrtab - writes a string table to a file */ +/*-------------------------------------------------------------------*/ +static void +fputElfStrtab (strtabList *strtab, FILE *fp) +{ + strtabString * sp; + + fputc (0, fp); /* index 0 must be the null character */ + + sp = strtab->first; + while (sp) + { + fputs (sp->string, fp); + fputc (0, fp); + sp = sp->next; + } +} + +/*-------------------------------------------------------------------*/ +/* fputElf32_Word - writes an Elf32_Word value to a file */ +/*-------------------------------------------------------------------*/ +static void +fputElf32_Word (Elf32_Word x, FILE *fp) +{ + if (hilo == 0) + { + fputc (x & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + fputc ((x >> 16) & 0xff, fp); + fputc ((x >> 24) & 0xff, fp); + } + else + { + fputc ((x >> 24) & 0xff, fp); + fputc ((x >> 16) & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + fputc (x & 0xff, fp); + } +} + +/*-------------------------------------------------------------------*/ +/* fputElf32_Off - writes an Elf32_Off value to a file */ +/*-------------------------------------------------------------------*/ +static void +fputElf32_Off (Elf32_Off x, FILE *fp) +{ + if (hilo == 0) + { + fputc (x & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + fputc ((x >> 16) & 0xff, fp); + fputc ((x >> 24) & 0xff, fp); + } + else + { + fputc ((x >> 24) & 0xff, fp); + fputc ((x >> 16) & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + fputc (x & 0xff, fp); + } +} + +/*-------------------------------------------------------------------*/ +/* fputElf32_Addr - writes an Elf32_Addr value to a file */ +/*-------------------------------------------------------------------*/ +static void +fputElf32_Addr (Elf32_Addr x, FILE *fp) +{ + if (hilo == 0) + { + fputc (x & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + fputc ((x >> 16) & 0xff, fp); + fputc ((x >> 24) & 0xff, fp); + } + else + { + fputc ((x >> 24) & 0xff, fp); + fputc ((x >> 16) & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + fputc (x & 0xff, fp); + } +} + +/*-------------------------------------------------------------------*/ +/* fputElf32_Half - writes an Elf32_Half value to a file */ +/*-------------------------------------------------------------------*/ +static void +fputElf32_Half (Elf32_Half x, FILE *fp) +{ + if (hilo == 0) + { + fputc (x & 0xff, fp); + fputc ((x >> 8) & 0xff, fp); + } + else + { + fputc ((x >> 8) & 0xff, fp); + fputc (x & 0xff, fp); + } +} + +/*------------------------------------------------------------------------*/ +/* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */ +/*------------------------------------------------------------------------*/ +static void +fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp) +{ + int i; + + for (i=0; ie_ident[i], fp); + + fputElf32_Half (ehdr->e_type, fp); + fputElf32_Half (ehdr->e_machine, fp); + fputElf32_Word (ehdr->e_version, fp); + fputElf32_Addr (ehdr->e_entry, fp); + fputElf32_Off (ehdr->e_phoff, fp); + fputElf32_Off (ehdr->e_shoff, fp); + fputElf32_Word (ehdr->e_flags, fp); + fputElf32_Half (ehdr->e_ehsize, fp); + fputElf32_Half (ehdr->e_phentsize, fp); + fputElf32_Half (ehdr->e_phnum, fp); + fputElf32_Half (ehdr->e_shentsize, fp); + fputElf32_Half (ehdr->e_shnum, fp); + fputElf32_Half (ehdr->e_shstrndx, fp); +} + +/*-------------------------------------------------------------------------*/ +/* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */ +/*-------------------------------------------------------------------------*/ +static void +fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp) +{ + fputElf32_Word (shdr->sh_name, fp); + fputElf32_Word (shdr->sh_type, fp); + fputElf32_Word (shdr->sh_flags, fp); + fputElf32_Addr (shdr->sh_addr, fp); + fputElf32_Off (shdr->sh_offset, fp); + fputElf32_Word (shdr->sh_size, fp); + fputElf32_Word (shdr->sh_link, fp); + fputElf32_Word (shdr->sh_info, fp); + fputElf32_Word (shdr->sh_addralign, fp); + fputElf32_Word (shdr->sh_entsize, fp); +} + +/*-------------------------------------------------------------------------*/ +/* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */ +/*-------------------------------------------------------------------------*/ +static void +fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp) +{ + fputElf32_Word (phdr->p_type, fp); + fputElf32_Off (phdr->p_offset, fp); + fputElf32_Addr (phdr->p_vaddr, fp); + fputElf32_Addr (phdr->p_paddr, fp); + fputElf32_Word (phdr->p_filesz, fp); + fputElf32_Word (phdr->p_memsz, fp); + fputElf32_Word (phdr->p_flags, fp); + fputElf32_Word (phdr->p_align, fp); +} + + +/*--------------------------------------------------------------------------*/ +/* elfGenerateAbs - generates segments and sections for an absolute area. */ +/* This is a little more complicated than a relative area since it may */ +/* contain noncontiguous regions. */ +/*--------------------------------------------------------------------------*/ +static void +elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections) +{ + Elf32_Addr ofs; + Elf32_Addr addr; + Elf32_Word size; + Elf32_Phdr * phdrp; + Elf32_Shdr * shdrp; + + if (!ap->a_image) + { + return; + } + + ofs = 0; + for (;;) + { + /* Find the start of a contiguously */ + /* used region within this area */ + while (ofs < ap->a_size && !ap->a_used[ofs]) + ofs++; + if (ofs >= ap->a_size) + return; + + /* Find the end of the region */ + addr = ap->a_addr + ofs; + while (ofs < ap->a_size && ap->a_used[ofs]) + ofs++; + size = ap->a_addr + ofs - addr; + + /* create a segment header for this region if loadable */ + if (!(ap->a_flag & A_NOLOAD)) + { + phdrp = new (sizeof (*phdrp)); + phdrp->p_type = PT_LOAD; + phdrp->p_offset = ftell (ofp); + phdrp->p_vaddr = addr; + phdrp->p_paddr = addr; + phdrp->p_filesz = size; + phdrp->p_memsz = size; + phdrp->p_flags = PF_R; + if (ap->a_flag & A_CODE) + phdrp->p_flags |= PF_X; + phdrp->p_align = 1; + listAdd (segments, phdrp); + } + + /* create a section header for this region */ + shdrp = new (sizeof (*shdrp)); + shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id); + shdrp->sh_type = SHT_PROGBITS; + shdrp->sh_flags = 0; + if (!(ap->a_flag & A_NOLOAD)) + shdrp->sh_flags |= SHF_ALLOC; + if (ap->a_flag & A_CODE) + shdrp->sh_flags |= SHF_EXECINSTR; + shdrp->sh_addr = addr; + shdrp->sh_offset = ftell (ofp); + shdrp->sh_size = size; + shdrp->sh_link = 0; + shdrp->sh_info = 0; + shdrp->sh_addralign = 0; + shdrp->sh_entsize = 0; + listAdd (sections, shdrp); + + fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp); + } +} + +/*--------------------------------------------------------------------------*/ +/* elfGenerateRel - generates a segment and section for a relative area. */ +/*--------------------------------------------------------------------------*/ +static void +elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections) +{ + Elf32_Phdr * phdrp; + Elf32_Shdr * shdrp; + + if (!ap->a_image) + { + return; + } + + /* create a segment header for this area if loadable */ + if (!(ap->a_flag & A_NOLOAD)) + { + phdrp = new (sizeof (*phdrp)); + phdrp->p_type = PT_LOAD; + phdrp->p_offset = ftell (ofp); + phdrp->p_vaddr = ap->a_addr; + phdrp->p_paddr = ap->a_addr; + phdrp->p_filesz = ap->a_size; + phdrp->p_memsz = ap->a_size; + phdrp->p_flags = PF_R; + if (ap->a_flag & A_CODE) + phdrp->p_flags |= PF_X; + phdrp->p_align = 1; + listAdd (segments, phdrp); + } + + /* create a section header for this area */ + shdrp = new (sizeof (*shdrp)); + shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id); + shdrp->sh_type = SHT_PROGBITS; + shdrp->sh_flags = 0; + if (!(ap->a_flag & A_NOLOAD)) + shdrp->sh_flags |= SHF_ALLOC; + if (ap->a_flag & A_CODE) + shdrp->sh_flags |= SHF_EXECINSTR; + shdrp->sh_addr = ap->a_addr; + shdrp->sh_offset = ftell (ofp); + shdrp->sh_size = ap->a_size; + shdrp->sh_link = 0; + shdrp->sh_info = 0; + shdrp->sh_addralign = 0; + shdrp->sh_entsize = 0; + listAdd (sections, shdrp); + + fwrite (ap->a_image, 1, ap->a_size, ofp); +} + +/*--------------------------------------------------------------------------*/ +/* elfGenerate - generates the complete ELF file */ +/*--------------------------------------------------------------------------*/ +static void +elfGenerate (void) +{ + listHeader * sections = listNew(); + listHeader * segments = listNew(); + struct area *ap; + Elf32_Ehdr ehdr; + Elf32_Shdr * shdrp; + Elf32_Phdr * phdrp; + listEntry * lep; + int i; + Elf32_Word shstrtabName; + + /* create the null section header for index 0 */ + shdrp = new (sizeof (*shdrp)); + shdrp->sh_name = 0; + shdrp->sh_type = SHT_NULL; + shdrp->sh_flags = 0; + shdrp->sh_addr = 0; + shdrp->sh_offset = 0; + shdrp->sh_size = 0; + shdrp->sh_link = 0; + shdrp->sh_info = 0; + shdrp->sh_addralign = 0; + shdrp->sh_entsize = 0; + listAdd (sections, shdrp); + + /* Initialize the ELF header */ + for (i=0; ia_size) + { + if (ap->a_flag & A_ABS) + elfGenerateAbs (ap, segments, sections); + else + elfGenerateRel (ap, segments, sections); + } + ap = ap->a_ap; + } + + /* Create the string table section after the other sections */ + shdrp = new (sizeof (*shdrp)); + shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab"); + shdrp->sh_type = SHT_STRTAB; + shdrp->sh_flags = 0; + shdrp->sh_addr = 0; + shdrp->sh_offset = ftell (ofp); + shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1; + shdrp->sh_link = 0; + shdrp->sh_info = 0; + shdrp->sh_addralign = 0; + shdrp->sh_entsize = 0; + listAdd (sections, shdrp); + fputElfStrtab (&shstrtab, ofp); + + /* Find the index of the section string table */ + /* header and save it in the ELF header */ + ehdr.e_shstrndx = 0; + shstrtabName = shdrp->sh_name; + lep = sections->first; + while (lep) + { + shdrp = lep->item; + if (shdrp->sh_name == shstrtabName) + break; + ehdr.e_shstrndx++; + lep = lep->next; + } + + /* Write out the segment headers */ + ehdr.e_phnum = segments->count; + ehdr.e_phoff = ftell (ofp); + lep = segments->first; + while (lep) + { + phdrp = lep->item; + fputElf32_Phdr (phdrp, ofp); + lep = lep->next; + } + + /* Write out the section headers */ + ehdr.e_shnum = sections->count; + ehdr.e_shoff = ftell (ofp); + lep = sections->first; + while (lep) + { + shdrp = lep->item; + fputElf32_Shdr (shdrp, ofp); + lep = lep->next; + } + + /* All the values in the ELF header have now been computed; write */ + /* over the placeholder header with the final values */ + fseek (ofp, 0, SEEK_SET); + fputElf32_Ehdr (&ehdr, ofp); + fseek (ofp, 0, SEEK_END); +} + +/*--------------------------------------------------------------------------*/ +/* elf - incrementally called by the linker core to generate ELF file data. */ +/* The parameter is nonzero when there is data available and zero when */ +/* the linker is finished. */ +/*--------------------------------------------------------------------------*/ +void +elf (int i) +{ + Addr_T address; + + /* Buffer the data until we have it all */ + if (i) + { + if (hilo == 0) + address = rtval[0] + (rtval[1] << 8); /* little endian order */ + else + address = rtval[1] + (rtval[0] << 8); /* big endian order */ + + /* If this area doesn't have an image buffer, create one */ + if (!ap->a_image) + { + ap->a_image = new (ap->a_size); + if (ap->a_flag & A_ABS) + ap->a_used = new (ap->a_size); + } + + /* Copy the data into the image buffer */ + for (i = 2; i < rtcnt ; i++) + { + if (rtflg[i]) + { + ap->a_image[address-ap->a_addr] = rtval[i]; + if (ap->a_used) + ap->a_used[address-ap->a_addr] = 1; + + /* Make note of the reset vector */ + if (!(ap->a_flag & A_NOLOAD)) + { + if (address == 0xfffe) + { + execStartMSB = rtval[i]; + execStartMSBfound = 1; + } + if (address == 0xffff) + { + execStartLSB = rtval[i]; + execStartLSBfound = 1; + } + } + address++; + } + } + } + else + elfGenerate(); +} diff --git a/as/link/hc08/lkihx.c b/as/link/hc08/lkihx.c new file mode 100644 index 00000000..28c2f500 --- /dev/null +++ b/as/link/hc08/lkihx.c @@ -0,0 +1,262 @@ +/* lkihx.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include "aslink.h" + +/*)Module lkihx.c + * + * The module lkihx.c contains the function to + * output the relocated object code in the + * Intel Hex format. + * + * lkihx.c contains the following functions: + * VOID hexRecord(addr, rtvalIndex) + * VOID ihx(i) + * VOID ihxEntendedLinearAddress(a) + * + * local variables: hexPageOverrun, lastHexAddr + */ + +/*Intel Hex Format + * Record Mark Field - This field signifies the start of a + * record, and consists of an ascii colon + * (:). + * + * Record Length Field - This field consists of two ascii + * characters which indicate the number of + * data bytes in this record. The + * characters are the result of converting + * the number of bytes in binary to two + * ascii characters, high digit first. An + * End of File record contains two ascii + * zeros in this field. + * + * Load Address Field - This field consists of the four ascii + * characters which result from converting + * the the binary value of the address in + * which to begin loading this record. The + * order is as follows: + * + * High digit of high byte of address. + * Low digit of high byte of address. + * High digit of low byte of address. + * Low digit of low byte of address. + * + * In an End of File record this field con- + * sists of either four ascii zeros or the + * program entry address. Currently the + * entry address option is not supported. + * + * Record Type Field - This field identifies the record type, + * which is either 0 for data records or 1 + * for an End of File record. It consists + * of two ascii characters, with the high + * digit of the record type first, followed + * by the low digit of the record type. + * + * Data Field - This field consists of the actual data, + * converted to two ascii characters, high + * digit first. There are no data bytes in + * the End of File record. + * + * Checksum Field - The checksum field is the 8 bit binary + * sum of the record length field, the load + * address field, the record type field, + * and the data field. This sum is then + * negated (2's complement) and converted + * to two ascii characters, high digit + * first. + */ + +/* Static variable which holds the count of hex page overruns + * (crossings of the 64kB boundary). Cleared at explicit extended + * address output. + */ +static int hexPageOverrun = 0; + +/* Global which holds the last (16 bit) address of hex record. + * Cleared at begin of new area or when the extended address is output. + */ +unsigned int lastHexAddr = 0; + + +/*)Function hexRecord(addr, rtvalIndex) + * + * unsigned addr starting address of hex record + * int rtvalIndex starting index into the rtval[] array + * + * The function hexRecord() outputs the relocated data + * in the standard Intel Hex format (with inserting + * the extended address record if necessary). + * + * local variables: + * Addr_T chksum byte checksum + * int i index for loops + * int overrun temporary storage for hexPageOverrun + * int bytes counter for bytes written + * + * global variables: + * FILE * ofp output file handle + * int rtcnt count of data words + * int rtflg[] output the data flag + * Addr_T rtval[] relocated data + * + * functions called: + * int fprintf() c_library + * ihxEntendedLinearAddress() lkihx.c + * hexRecord() lkihx.c (recursion) + * + * side effects: + * hexPageOverrun is eventually incremented, + * lastHexAddr is updated + */ + +VOID +hexRecord(unsigned addr, int rtvalIndex) +{ + Addr_T chksum; + int i, overrun, bytes; + + for (i = rtvalIndex, chksum = 0; i < rtcnt; i++) { + if (rtflg[i]) { + if (addr + ++chksum > 0xffff) + break; + } + } + if (chksum == 0) + return; // nothing to output + + if (lastHexAddr > addr) { + overrun = hexPageOverrun + 1; + ihxEntendedLinearAddress(lastExtendedAddress + overrun); + hexPageOverrun = overrun; + hexRecord(addr, rtvalIndex); + return; + } + + lastHexAddr = addr; + fprintf(ofp, ":%02X%04X00", chksum, addr); + chksum += (addr >> 8) + (addr & 0xff); + for (i = rtvalIndex, bytes = 0; i < rtcnt; i++) { + if (rtflg[i]) { + fprintf(ofp, "%02X", rtval[i]); + chksum += rtval[i]; +#if 0 + if (addr + ++bytes > 0xffff) { + if (rflag) { + fprintf(ofp, "%02X\n", (0-chksum) & 0xff); + overrun = hexPageOverrun + 1; + ihxEntendedLinearAddress(lastExtendedAddress + overrun); + hexPageOverrun = overrun; + hexRecord(0, i + 1); + return; + } else { + fprintf(stderr, + "warning: extended linear address encountered; " + "you probably want the -r flag.\n"); + } + } +#endif + } + } + fprintf(ofp, "%02X\n", (0-chksum) & 0xff); +} + +/*)Function ihx(i) + * + * int i 0 - process data + * 1 - end of data + * + * The function ihx() calls the hexRecord() function for processing data + * or writes the End of Data record to the file defined by ofp. + * + * local variables: + * Addr_T n auxiliary variable + * + * global variables: + * int hilo byte order + * FILE * ofp output file handle + * Addr_T rtval[] relocated data + * + * functions called: + * VOID hexRecord() lkihx.c + * int fprintf() c_library + * + * side effects: + * The sequence of rtval[0], rtval[1] is eventually changed. + */ + +VOID +ihx(i) +{ + Addr_T n; + if (i) { + if (ap->a_flag & A_NOLOAD) + return; + if (hilo == 0) { + n = rtval[0]; + rtval[0] = rtval[1]; + rtval[1] = n; + } + hexRecord((rtval[0]<<8) + rtval[1], 2); + } else { + fprintf(ofp, ":00000001FF\n"); + } +} + +/*)Function newArea(i) + * The function newArea() is called when processing of new area is started. + * It resets the value of lastHexAddr. + */ + +VOID +newArea() +{ + lastHexAddr = 0; +} + +/*)Function ihxEntendedLinearAddress(i) + * + * Addr_T i 16 bit extended linear address. + * + * The function ihxEntendedLinearAddress() writes an extended + * linear address record (type 04) to the output file. + * + * local variables: + * Addr_T chksum byte checksum + * + * global variables: + * FILE * ofp output file handle + * + * functions called: + * int fprintf() c_library + * + * side effects: + * The data is output to the file defined by ofp. + * hexPageOverrun and lastHexAddr is cleared + */ +VOID +ihxEntendedLinearAddress(Addr_T a) +{ + Addr_T chksum; + + /* The checksum is the complement of the bytes in the + * record: the 2 is record length, 4 is the extended linear + * address record type, plus the two address bytes. + */ + chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff); + + fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (0-chksum) & 0xff); + hexPageOverrun = 0; + lastHexAddr = 0; +} diff --git a/as/link/hc08/lklibr.c b/as/link/hc08/lklibr.c new file mode 100644 index 00000000..f7614d28 --- /dev/null +++ b/as/link/hc08/lklibr.c @@ -0,0 +1,865 @@ +/* lklibr.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + * + * With contributions for the + * object libraries from + * Ken Hornstein + * kenh@cmf.nrl.navy.mil + * + */ + +#define EQ(A,B) !strcmp((A),(B)) +#define MAXLINE 254 /*when using fgets*/ + +#include +#include +#include +#include "aslink.h" + +/*)Module lklibr.c + * + * The module lklibr.c contains the functions which + * (1) specify the path(s) to library files [.LIB] + * (2) specify the library file(s) [.LIB] to search + * (3) search the library files for specific symbols + * and link the module containing this symbol + * + * lklibr.c contains the following functions: + * VOID addpath() + * VOID addlib() + * VOID addfile() + * VOID search() + * VOID fndsym() + * VOID library() + * VOID loadfile() + * + */ + +/*)Function VOID addpath() + * + * The function addpath() creates a linked structure containing + * the paths to various object module library files. + * + * local variables: + * lbpath *lbph pointer to new path structure + * lbpath *lbp temporary pointer + * + * global variables: + * lbpath *lbphead The pointer to the first + * path structure + * + * functions called: + * char getnb() lklex.c + * VOID * new() lksym.c + * int strlen() c_library + * char * strcpy() c_library + * VOID unget() lklex.c + * + * side effects: + * An lbpath structure may be created. + */ + +VOID +addpath() +{ + struct lbpath *lbph, *lbp; + + lbph = (struct lbpath *) new (sizeof(struct lbpath)); + if (lbphead == NULL) { + lbphead = lbph; + } else { + lbp = lbphead; + while (lbp->next) + lbp = lbp->next; + lbp->next = lbph; + } + unget(getnb()); + lbph->path = (char *) new (strlen(ip)+1); + strcpy(lbph->path, ip); +} + +/*)Function VOID addlib() + * + * The function addlib() tests for the existance of a + * library path structure to determine the method of + * adding this library file to the library search structure. + * + * This function calls the function addfile() to actually + * add the library file to the search list. + * + * local variables: + * lbpath *lbph pointer to path structure + * + * global variables: + * lbpath *lbphead The pointer to the first + * path structure + * ip a pointer to the library name + * + * functions called: + * VOID addfile() lklibr.c + * char getnb() lklex.c + * VOID unget() lklex.c + * + * side effects: + * The function addfile() may add the file to + * the library search list. + */ + +VOID +addlib() +{ + struct lbpath *lbph; + int foundcount=0; + + unget(getnb()); + + if (lbphead == NULL) + { + foundcount=addfile(NULL, ip); + } + else + { + for (lbph=lbphead; lbph; lbph=lbph->next) + { + foundcount+=addfile(lbph->path, ip); + } + } + if(foundcount == 0) + { + fprintf(stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip); + } +} + +/*)Function int addfile(path,libfil) + * + * char *path library path specification + * char *libfil library file specification + * + * The function addfile() searches for the library file + * by concatenating the path and libfil specifications. + * if the library is found, an lbname structure is created + * and linked to any previously defined structures. This + * linked list is used by the function fndsym() to attempt + * to find any undefined symbols. + * + * The function does not give report an error on invalid + * path / file specifications or if the file is not found. + * + * local variables: + * lbname *lbnh pointer to new name structure + * lbname *lbn temporary pointer + * + * global variables: + * lbname *lbnhead The pointer to the first + * path structure + * + * functions called: + * char getnb() lklex.c + * VOID * new() lksym.c + * int strlen() c_library + * char * strcpy() c_library + * VOID unget() lklex.c + * + * side effects: + * An lbname structure may be created. + * + * return: + * 1: the library was found + * 0: the library was not found + */ + +int addfile(char * path, char * libfil) +{ + FILE *fp; + char *str; + struct lbname *lbnh, *lbn; +#ifdef OTHERSYSTEM + int libfilinc=0; +#endif + + if (path != NULL) + { + str = (char *) new (strlen(path) + strlen(libfil) + 6); + strcpy(str,path); +#ifdef OTHERSYSTEM + if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\')) + { + strcat(str,"/"); + } +#endif + } + else + { + str = (char *) new (strlen(libfil) + 5); + } + +#ifdef OTHERSYSTEM + if ((libfil[0] == '/') || (libfil[0] == '\\')) + { + libfil++; + libfilinc=1; + } +#endif + + strcat(str, libfil); + if(strchr(libfil, FSEPX) == NULL) + { + sprintf(&str[strlen(str)], "%clib", FSEPX); + } + + fp=fopen(str, "r"); + if(fp == NULL) + { + /*Ok, that didn't work. Try with the 'libfil' name only*/ +#ifdef OTHERSYSTEM + if(libfilinc) libfil--; +#endif + fp=fopen(libfil, "r"); + if(fp != NULL) + { + /*Bingo! 'libfil' is the absolute path of the library*/ + strcpy(str, libfil); + path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/ + } + } + + if(path==NULL) + { + /*'path' can not be null since it is needed to find the '.rel' files associated with + the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'. + That way putting 'path' and 'libfil' together will result into the original filepath + as contained in 'str'.*/ + int j; + path = (char *) new (strlen(str) + 1); + strcpy(path, str); + for(j=strlen(path)-1; j>=0; j--) + { + if((path[j] == '/') || (path[j] == '\\')) + { + strcpy(libfil, &path[j+1]); + path[j+1]=0; + break; + } + } + if(j<=0) path[0]=0; + } + + if (fp != NULL) + { + fclose(fp); + lbnh = (struct lbname *) new (sizeof(struct lbname)); + if (lbnhead == NULL) + { + lbnhead = lbnh; + } + else + { + lbn = lbnhead; + while (lbn->next) + lbn = lbn->next; + lbn->next = lbnh; + } + + lbnh->path = path; + lbnh->libfil = (char *) new (strlen(libfil) + 1); + strcpy(lbnh->libfil,libfil); + lbnh->libspc = str; + return 1; + } + else + { + free(str); + return 0; + } +} + +/*)Function VOID search() + * + * The function search() looks through all the symbol tables + * at the end of pass 1. If any undefined symbols are found + * then the function fndsym() is called. Function fndsym() + * searches any specified library files to automagically + * import the object modules containing the needed symbol. + * + * After a symbol is found and imported by the function + * fndsym() the symbol tables are again searched. The + * symbol tables are search until no more symbols can be + * resolved within the library files. This ensures that + * back references from one library module to another are + * also resolved. + * + * local variables: + * int i temporary counter + * sym *sp pointer to a symbol structure + * int symfnd found a symbol flag + * + * global variables: + * sym *symhash[] array of pointers to symbol tables + * + * functions called: + * int fndsym() lklibr.c + * + * side effects: + * If a symbol is found then the library object module + * containing the symbol will be imported and linked. + */ + +VOID +search() +{ + register struct sym *sp; + register int i,symfnd; + + /* + * Look for undefined symbols. Keep + * searching until no more symbols are resolved. + */ + symfnd = 1; + while (symfnd) { + symfnd = 0; + /* + * Look through all the symbols + */ + for (i=0; is_type & S_DEF) == 0) { + if (fndsym(sp->s_id)) { + symfnd++; + } + } + sp = sp->s_sp; + } + } + } +} + +/*Load a .rel file embedded in a sdcclib file*/ +void LoadRel(FILE * libfp, char * ModName) +{ + char str[NINPUT+2]; + int state=0; + + while (fgets(str, NINPUT, libfp) != NULL) + { + str[NINPUT+1] = '\0'; + chop_crlf(str); + switch(state) + { + case 0: + if(EQ(str, "")) + { + fgets(str, NINPUT, libfp); + str[NINPUT+1] = '\0'; + chop_crlf(str); + if(EQ(str, ModName)) state=1; + else + { + fprintf(stderr, "?ASlink-Error-Bad offset in library file str=%s, Modname=%s\n", + str, ModName); + lkexit(1); + } + } + break; + case 1: + if(EQ(str, "")) state=2; + break; + case 2: + if(EQ(str, "")) return; + ip = str; + link_main(); + break; + } + } +} + +/*Load an .adb file embedded in a sdcclib file. If there is +something between and returns 1, otherwise returns 0. +This way the aomf51 will not have uselless empty modules. */ + +int LoadAdb(FILE * libfp) +{ + char str[MAXLINE+1]; + int state=0; + int ToReturn=0; + + while (fgets(str, MAXLINE, libfp) != NULL) + { + str[NINPUT+1] = '\0'; + chop_crlf(str); + switch(state) + { + case 0: + if(EQ(str, "")) state=1; + break; + case 1: + if(EQ(str, "")) return ToReturn; + fprintf(dfp, "%s\n", str); + ToReturn=1; + break; + } + } + return ToReturn; +} + +/*Check for a symbol in a SDCC library. If found, add the embedded .rel and +.adb files from the library. The library must be created with the SDCC +librarian 'sdcclib' since the linking process depends on the correct file offsets +embedded in the library file.*/ + +int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName) +{ + struct lbfile *lbfh, *lbf; + char ModName[NCPS]=""; + char FLine[MAXLINE+1]; + int state=0; + long IndexOffset=0, FileOffset; + + while(!feof(libfp)) + { + FLine[0]=0; + fgets(FLine, MAXLINE, libfp); + chop_crlf(FLine); + + switch(state) + { + case 0: + if(EQ(FLine, "")) + { + /*The next line has the size of the index*/ + FLine[0]=0; + fgets(FLine, MAXLINE, libfp); + chop_crlf(FLine); + IndexOffset=atol(FLine); + state=1; + } + break; + case 1: + if(EQ(FLine, "")) + { + /*The next line has the name of the module and the offset + of the corresponding embedded file in the library*/ + FLine[0]=0; + fgets(FLine, MAXLINE, libfp); + chop_crlf(FLine); + sscanf(FLine, "%s %ld", ModName, &FileOffset); + state=2; + } + else if(EQ(FLine, "")) + { + /*Reached the end of the index. The symbol is not in this library.*/ + return 0; + } + break; + case 2: + if(EQ(FLine, "")) + { + /*The symbol is not in this module, try the next one*/ + state=1; + } + else + { + /*Check if this is the symbol we are looking for.*/ + if (strncmp(SymName, FLine, NCPS)==0) + { + /*The symbol is in this module.*/ + + /*As in the original library format, it is assumed that the .rel + files reside in the same directory as the lib files.*/ + strcat(DirLib, ModName); + sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX); + + /*If this module has been loaded already don't load it again.*/ + lbf = lbfhead; + while (lbf) + { + if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/ + lbf=lbf->next; + } + + /*Add the embedded file to the list of files to be loaded in + the second pass. That is performed latter by the function + library() below.*/ + lbfh = (struct lbfile *) new (sizeof(struct lbfile)); + if (lbfhead == NULL) + { + lbfhead = lbfh; + } + else + { + lbf = lbfhead; + while (lbf->next) + lbf = lbf->next; + lbf->next = lbfh; + } + + lbfh->libspc = PathLib; + lbfh->filspc = DirLib; + lbfh->relfil = (char *) new (strlen(ModName) + 1); + strcpy(lbfh->relfil, ModName); + /*Library embedded file, so lbfh->offset must be >=0*/ + lbfh->offset = IndexOffset+FileOffset; + + /*Jump to where the .rel begins and load it.*/ + fseek(libfp, lbfh->offset, SEEK_SET); + LoadRel(libfp, ModName); + + /* if cdb information required & .adb file present */ + if (dflag && dfp) + { + if(LoadAdb(libfp)) + SaveLinkedFilePath(DirLib); + } + return 1; /*Found the symbol, so success!*/ + } + } + break; + + default: + return 0; /*It should never reach this point, but just in case...*/ + break; + } + } + + return 0; /*The symbol is not in this library*/ +} + +/*)Function VOID fndsym(name) + * + * char *name symbol name to find + * + * The function fndsym() searches through all combinations of the + * library path specifications (input by the -k option) and the + * library file specifications (input by the -l option) that + * lead to an existing file. + * + * The file specicifation may be formed in one of two ways: + * + * (1) If the library file contained an absolute + * path/file specification then this becomes filspc. + * (i.e. C:\...) + * + * (2) If the library file contains a relative path/file + * specification then the concatenation of the path + * and this file specification becomes filspc. + * (i.e. \...) + * + * The structure lbfile is created for the first library + * object file which contains the definition for the + * specified undefined symbol. + * + * If the library file [.LIB] contains file specifications for + * non existant files, no errors are returned. + * + * local variables: + * char buf[] [.REL] file input line + * char c [.REL] file input character + * FILE *fp file handle for object file + * lbfile *lbf temporary pointer + * lbfile *lbfh pointer to lbfile structure + * FILE *libfp file handle for library file + * lbname *lbnh pointer to lbname structure + * char *path file specification path + * char relfil[] [.REL] file specification + * char *str combined path and file specification + * char symname[] [.REL] file symbol string + * + * global variables: + * lbname *lbnhead The pointer to the first + * name structure + * lbfile *lbfhead The pointer to the first + * file structure + * + * functions called: + * int fclose() c_library + * int fgets() c_library + * FILE *fopen() c_library + * VOID free() c_library + * char getnb() lklex.c + * VOID lkexit() lkmain.c + * VOID loadfile() lklibr.c + * VOID * new() lksym.c + * char * sprintf() c_library + * int sscanf() c_library + * char * strcat() c_library + * char * strchr() c_library + * char * strcpy() c_library + * int strlen() c_library + * int strncmp() c_library + * VOID unget() lklex.c + * + * side effects: + * If the symbol is found then a new lbfile structure + * is created and added to the linked list of lbfile + * structures. The file containing the found symbol + * is linked. + */ + +int +fndsym(name) +char *name; +{ + FILE *libfp, *fp; + struct lbname *lbnh; + struct lbfile *lbfh, *lbf; + char relfil[NINPUT+2]; + char buf[NINPUT+2]; + char symname[NINPUT]; + char *path,*str; + char c; + int result; + + /* + * Search through every library in the linked list "lbnhead". + */ + + for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) + { + if ((libfp = fopen(lbnh->libspc, "r")) == NULL) + { + fprintf(stderr, "ASlink-Error-Cannot open library file %s\n", + lbnh->libspc); + lkexit(1); + } + path = lbnh->path; + + /* + * Read in a line from the library file. + * This is the relative file specification + * for a .REL file in this library. + */ + + while (fgets(relfil, NINPUT, libfp) != NULL) + { + relfil[NINPUT+1] = '\0'; + chop_crlf(relfil); + if (path != NULL) + { + str = (char *) new (strlen(path)+strlen(relfil)+6); + strcpy(str,path); +#ifdef OTHERSYSTEM + if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\')) + { + strcat(str,"/"); + } +#endif + } + else + { + str = (char *) new (strlen(relfil) + 5); + } + + if(strcmp(relfil, "")==0) + { + result=SdccLib(lbnh->libspc, libfp, str, name); + fclose(libfp); + if(result) return(1); /*Found the symbol*/ + free(str); + /*The symbol is not in the current library, + check the next library in the list*/ + break; + } + + /*From here down is the support for libraries in the original format*/ + if (relfil[0] == '\\') + { + strcat(str,relfil+1); + } + else + { + strcat(str,relfil); + } + + if(strchr(relfil, FSEPX) == NULL) + { + sprintf(&str[strlen(str)], "%crel", FSEPX); + } + + if ((fp = fopen(str, "r")) != NULL) + { + + /* + * Read in the object file. Look for lines that + * begin with "S" and end with "D". These are + * symbol table definitions. If we find one, see + * if it is our symbol. Make sure we only read in + * our object file and don't go into the next one. + */ + + while (fgets(buf, NINPUT, fp) != NULL) + { + buf[NINPUT+1] = '\0'; + chop_crlf(buf); + /* + * Skip everything that's not a symbol record. + */ + if (buf[0] != 'S') continue; + + /* + * When a 'T line' is found terminate file scan. + * All 'S line's preceed 'T line's in .REL files. + */ + if (buf[0] == 'T') break; + + sscanf(buf, "S %s %c", symname, &c); + + /* + * If we find a symbol definition for the + * symbol we're looking for, load in the + * file and add it to lbfhead so it gets + * loaded on pass number 2. + */ + if (strncmp(symname, name, NCPS) == 0 && c == 'D') + { + lbfh = (struct lbfile *) new (sizeof(struct lbfile)); + if (lbfhead == NULL) + { + lbfhead = lbfh; + } + else + { + lbf = lbfhead; + while (lbf->next) + lbf = lbf->next; + lbf->next = lbfh; + } + + lbfh->libspc = lbnh->libspc; + lbfh->filspc = str; + lbfh->relfil = (char *) new (strlen(relfil) + 1); + lbfh->offset = -1; /*Stand alone rel file*/ + strcpy(lbfh->relfil,relfil); + fclose(fp); + fclose(libfp); + + /* if cdb information required & adb file present */ + if (dflag && dfp) + { + FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002 + if (xfp) + { + SaveLinkedFilePath(str); + copyfile(dfp,xfp); + fclose(xfp); + } + } + loadfile(str); + return (1); + } + } + fclose(fp); + } + free(str); + } + fclose(libfp); + } + return(0); +} + +void loadfile_SdccLib(char * libspc, char * module, long offset) +{ + FILE *fp; + + if ((fp = fopen(libspc,"r")) != NULL) + { + fseek(fp, offset, SEEK_SET); + LoadRel(fp, module); + fclose(fp); + } +} + +/*)Function VOID library() + * + * The function library() links all the library object files + * contained in the lbfile structures. + * + * local variables: + * lbfile *lbfh pointer to lbfile structure + * + * global variables: + * lbfile *lbfhead pointer to first lbfile structure + * + * functions called: + * VOID loadfile lklibr.c + * + * side effects: + * Links all files contained in the lbfile structures. + */ + +VOID +library() +{ + struct lbfile *lbfh; + + for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) + { + if(lbfh->offset<0) + { + /*Stand alone rel file (original lib format)*/ + loadfile(lbfh->filspc); + } + else + { + /*rel file embedded in lib (new lib format)*/ + loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset); + } + } +} + +/*)Function VOID loadfile(filspc) + * + * char *filspc library object file specification + * + * The function loadfile() links the library object module. + * + * local variables: + * FILE *fp file handle + * int i input line length + * char str[] file input line + * + * global variables: + * char *ip pointer to linker input string + * + * functions called: + * int fclose() c_library + * int fgets() c_library + * FILE * fopen() c_library + * VOID link_main() lkmain.c + * int strlen() c_library + * + * side effects: + * If file exists it is linked. + */ + +VOID +loadfile(filspc) +char *filspc; +{ + FILE *fp; + char str[NINPUT+2]; + + if ((fp = fopen(filspc,"r")) != NULL) { + while (fgets(str, NINPUT, fp) != NULL) { + str[NINPUT+1] = '\0'; + chop_crlf(str); + ip = str; + link_main(); + } + fclose(fp); + } +} diff --git a/as/link/hc08/lkmain.c b/as/link/hc08/lkmain.c new file mode 100644 index 00000000..9b37da68 --- /dev/null +++ b/as/link/hc08/lkmain.c @@ -0,0 +1,1397 @@ +/* lkmain.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + * + * 31-Oct-97 JLH: + * - add jflag and jfp to control NoICE output file genration + * 3-Nov-97 JLH: + * - use a_type == 0 as "virgin area" flag: set == 1 if -b + */ + +#include +#include +#include +#include "aslink.h" + +#ifdef WIN32T +#include + +void Timer(int action, char * message) +{ + static double start, end, total=0.0; + static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC; + + if(action==0) start=clock()*secs_per_tick; + else if(action==1) + { + end=clock() * secs_per_tick; + printf("%s \t%f seconds.\n", message, (end-start)); + total+=end-start; + } + else + { + printf("Total time: \t%f seconds.\n", total); + total=0.0; + } +} +#endif + +/*)Module lkmain.c + * + * The module lkmain.c contains the functions which + * (1) input the linker options, parameters, and specifications + * (2) perform a two pass link + * (3) produce the appropriate linked data output and/or + * link map file and/or relocated listing files. + * + * lkmain.c contains the following functions: + * FILE * afile(fn,ft,wf) + * VOID bassav() + * VOID gblsav() + * VOID link_main() + * VOID lkexit() + * VOID main(argc,argv) + * VOID map() + * int parse() + * VOID setbas() + * VOID setgbl() + * VOID usage() + * + * lkmain.c contains the following local variables: + * char * usetext[] array of pointers to the + * command option tect lines + * + */ + +/*JCF: Creates some of the default areas so they are allocated in the right order.*/ +void Areas51 (void) +{ + char * rel[]={ + "XH", + "H 7 areas 0 global symbols", + "A _CODE size 0 flags 0", /*Each .rel has one, so...*/ + "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/ + "A REG_BANK_1 size 0 flags 4", + "A REG_BANK_2 size 0 flags 4", + "A REG_BANK_3 size 0 flags 4", + "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/ + "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/ + "" + }; + int j; + + for (j=0; rel[j][0]!=0; j++) + { + ip=rel[j]; + link_main(); + } + + /*Set the start address of the default areas:*/ + for(ap=areap; ap; ap=ap->a_ap) + { + /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr=0x00; ap->a_type=1; } + else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr=0x08; ap->a_type=1; } + else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; } + else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; } + else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; } + } +} + +/*)Function VOID main(argc,argv) + * + * int argc number of command line arguments + 1 + * char * argv[] array of pointers to the command line + * arguments + * + * The function main() evaluates the command line arguments to + * determine if the linker parameters are to input through 'stdin' + * or read from a command file. The functions lk_getline() and parse() + * are to input and evaluate the linker parameters. The linking process + * proceeds by making the first pass through each .rel file in the order + * presented to the linker. At the end of the first pass the setbase(), + * lnkarea(), setgbl(), and symdef() functions are called to evaluate + * the base address terms, link all areas, define global variables, + * and look for undefined symbols. Following these routines a linker + * map file may be produced and the linker output files may be opened. + * The second pass through the .rel files will output the linked data + * in one of the four supported formats. + * + * local variables: + * char * p pointer to an argument string + * int c character from argument string + * int i loop counter + * + * global variables: + * text line in ib[] + * lfile *cfp The pointer *cfp points to the + * current lfile structure + * char ctype[] array of character types, one per + * ASCII character + * lfile *filep The pointer *filep points to the + * beginning of a linked list of + * lfile structures. + * head *hp Pointer to the current + * head structure + * char ib[NINPUT] .rel file text line + * char *ip pointer into the .rel file + * lfile *linkp pointer to first lfile structure + * containing an input .rel file + * specification + * int lkerr error flag + * int mflag Map output flag + * int oflag Output file type flag + * FILE *ofp Output file handle + * for word formats + * FILE *ofph Output file handle + * for high byte format + * FILE *ofpl Output file handle + * for low byte format + * int pass linker pass number + * int pflag print linker command file flag + * int radix current number conversion radix + * FILE *sfp The file handle sfp points to the + * currently open file + * lfile *startp asmlnk startup file structure + * FILE * stdin c_library + * FILE * stdout c_library + * + * functions called: + * FILE * afile() lkmain.c + * int fclose() c_library + * int fprintf() c_library + * int lk_getline() lklex.c + * VOID library() lklibr.c + * VOID link_main() lkmain.c + * VOID lkexit() lkmain.c + * VOID lnkarea() lkarea.c + * VOID map() lkmain.c + * VOID new() lksym.c + * int parse() lkmain.c + * VOID reloc() lkreloc.c + * VOID search() lklibr.c + * VOID setbas() lkmain.c + * VOID setgbl() lkmain.c + * VOID symdef() lksym.c + * VOID usage() lkmain.c + * + * side effects: + * Completion of main() completes the linking process + * and may produce a map file (.map) and/or a linked + * data files (.ihx or .s19) and/or one or more + * relocated listing files (.rst). + */ + +int +main(int argc, char *argv[]) +{ + register char *p; + register int c, i; + +#ifdef WIN32T + Timer(0, ""); +#endif + + startp = (struct lfile *) new (sizeof (struct lfile)); + + pflag = 1; + for (i=1; if_type = F_STD; + break; + + case 'f': + case 'F': + startp->f_type = F_LNK; + break; + + case 'n': + case 'N': + pflag = 0; + break; + + case 'p': + case 'P': + pflag = 1; + break; + + default: + usage(); + } + } + } else { + if (startp->f_type == F_LNK) { + startp->f_idp = p; + } + } + } + if (startp->f_type == 0) + usage(); + if (startp->f_type == F_LNK && startp->f_idp == NULL) + usage(); + + cfp = NULL; + sfp = NULL; + filep = startp; + while (1) { + ip = ib; + if (lk_getline() == 0) + break; + if (pflag && sfp != stdin) + fprintf(stdout, "%s\n", ip); + if (*ip == '\0' || parse()) + break; + } + + if (sfp) { + fclose(sfp); + sfp = NULL; + } + + if (linkp == NULL) + usage(); + + syminit(); + + if (dflag){ + //dfp = afile("temp", "cdb", 1); + SaveLinkedFilePath(linkp->f_idp); //Must be the first one... + dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002 + if (dfp == NULL) + lkexit(1); + } + + for (pass=0; pass<2; ++pass) { + cfp = NULL; + sfp = NULL; + filep = linkp; + hp = NULL; + radix = 10; + + Areas51(); /*JCF: Create the default 8051 areas in the right order*/ + + while (lk_getline()) { + ip = ib; + + /* pass any "magic comments" to NoICE output */ + if ((ip[0] == ';') && (ip[1] == '!') && jfp) { + fprintf( jfp, "%s\n", &ip[2] ); + } + link_main(); + } + if (pass == 0) { + /* + * Search libraries for global symbols + */ + search(); + /* + * Set area base addresses. + */ + setbas(); + /* + * Link all area addresses. + */ + lnkarea(); + /* + * Process global definitions. + */ + setgbl(); + /* + * Check for undefined globals. + */ + symdef(stderr); + + /* Open NoICE output file if requested */ + if (jflag) { + jfp = afile(linkp->f_idp, "NOI", 1); + if (jfp == NULL) { + lkexit(1); + } + } + + /* + * Output Link Map if requested, + * or if NoICE output requested (since NoICE + * file is generated in part by map() processing) + */ + if (mflag || jflag) + map(); + + if (sflag) /*JCF: memory usage summary output*/ + if(summary(areap))lkexit(1); + + if (iram_size) + iramcheck(); + + /* + * Open output file + */ + if (oflag == 1) { + ofp = afile(linkp->f_idp, "ihx", 1); + if (ofp == NULL) { + lkexit(1); + } + /* include NoICE command to load hex file */ + if (jfp) fprintf( jfp, "LOAD %s.IHX\n", linkp->f_idp ); + + } else + if (oflag == 2) { + ofp = afile(linkp->f_idp, "S19", 1); + if (ofp == NULL) { + lkexit(1); + } + /* include NoICE command to load hex file */ + if (jfp) fprintf( jfp, "LOAD %s.S19\n", linkp->f_idp ); + } else + if (oflag == 3) { + ofp = afile(linkp->f_idp, "elf", 4); + if (ofp == NULL) { + lkexit(1); + } + } + } else { + /* + * Link in library files + */ + library(); + reloc('E'); + } + } + //JCF: + //CreateAOMF51(); + +#ifdef WIN32T + Timer(1, "Linker execution time"); +#endif + + lkexit(lkerr); + return 0; +} + +/*)Function VOID lkexit(i) + * + * int i exit code + * + * The function lkexit() explicitly closes all open + * files and then terminates the program. + * + * local variables: + * none + * + * global variables: + * FILE * mfp file handle for .map + * FILE * ofp file handle for .ihx/.s19 + * FILE * rfp file hanlde for .rst + * FILE * sfp file handle for .rel + * FILE * tfp file handle for .lst + * + * functions called: + * int fclose() c_library + * VOID exit() c_library + * + * side effects: + * All files closed. Program terminates. + */ + +VOID +lkexit(int i) +{ + if (mfp != NULL) fclose(mfp); + if (jfp != NULL) fclose(jfp); + if (ofp != NULL) fclose(ofp); + if (rfp != NULL) fclose(rfp); + if (sfp != NULL) fclose(sfp); + if (tfp != NULL) fclose(tfp); + if (dfp != NULL) fclose(dfp); + /*if (dfp != NULL) + FILE *xfp = afile(linkp->f_idp,"cdb",1); + dfp = freopen("temp.cdb","r",dfp); + copyfile(xfp,dfp); + fclose(xfp); + fclose(dfp); + remove("temp.cdb"); + }*/ + exit(i); +} + +/*)Function link_main() + * + * The function link_main() evaluates the directives for each line of + * text read from the .rel file(s). The valid directives processed + * are: + * X, D, Q, H, M, A, S, T, R, and P. + * + * local variables: + * int c first non blank character of a line + * + * global variables: + * head *headp The pointer to the first + * head structure of a linked list + * head *hp Pointer to the current + * head structure + * int pass linker pass number + * int radix current number conversion radix + * + * functions called: + * char endline() lklex.c + * VOID module() lkhead.c + * VOID newarea() lkarea.c + * VOID newhead() lkhead.c + * sym * newsym() lksym.c + * VOID reloc() lkreloc.c + * + * side effects: + * Head, area, and symbol structures are created and + * the radix is set as the .rel file(s) are read. + */ + +VOID +link_main() +{ + register char c; + + if ((c=endline()) == 0) { return; } + switch (c) { + + case 'O': /*For some important sdcc options*/ + if (pass == 0) + { + if(strlen(sdccopt)==0) + { + strcpy(sdccopt, &ip[1]); + strcpy(sdccopt_module, curr_module); + } + else + { + if(strcmp(sdccopt, &ip[1])!=0) + { + fprintf(stderr, + "?ASlink-Warning-Conflicting sdcc options:\n" + " \"%s\" in module \"%s\" and\n" + " \"%s\" in module \"%s\".\n", + sdccopt, sdccopt_module, &ip[1], curr_module); + lkerr++; + } + } + } + break; + + case 'X': + radix = 16; + break; + + case 'D': + radix = 10; + break; + + case 'Q': + radix = 8; + break; + + case 'H': + if (pass == 0) { + newhead(); + } else { + if (hp == 0) { + hp = headp; + } else { + hp = hp->h_hp; + } + } + sdp.s_area = NULL; + sdp.s_areax = NULL; + sdp.s_addr = 0; + break; + + case 'M': + if (pass == 0) + { + strcpy(curr_module, &ip[1]); + module(); + } + break; + + case 'A': + if (pass == 0) + newarea(); + if (sdp.s_area == NULL) { + sdp.s_area = areap; + sdp.s_areax = areap->a_axp; + sdp.s_addr = 0; + } + break; + + case 'S': + if (pass == 0) + newsym(); + break; + + case 'T': + case 'R': + case 'P': + if (pass == 0) + break; + reloc(c); + break; + + default: + break; + } + if (c == 'X' || c == 'D' || c == 'Q') { + if ((c = get()) == 'H') { + hilo = 1; + } else + if (c == 'L') { + hilo = 0; + } + } +} + + +/*)Function VOID map() + * + * The function map() opens the output map file and calls the various + * routines to + * (1) output the variables in each area, + * (2) list the files processed with module names, + * (3) list the libraries file processed, + * (4) list base address definitions, + * (5) list global variable definitions, and + * (6) list any undefined variables. + * + * local variables: + * int i counter + * head * hdp pointer to head structure + * lbfile *lbfh pointer to library file structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * area *areap The pointer to the first + * area structure of a linked list + * base *basep The pointer to the first + * base structure + * base *bsp Pointer to the current + * base structure + * lfile *filep The pointer *filep points to the + * beginning of a linked list of + * lfile structures. + * globl *globlp The pointer to the first + * globl structure + * globl *gsp Pointer to the current + * globl structure + * head *headp The pointer to the first + * head structure of a linked list + * lbfile *lbfhead The pointer to the first + * lbfile structure of a linked list + * lfile *linkp pointer to first lfile structure + * containing an input REL file + * specification + * int lop current line number on page + * FILE *mfp Map output file handle + * int page current page number + * + * functions called: + * FILE * afile() lkmain.c + * int fprintf() c_library + * VOID lkexit() lkmain.c + * VOID lstarea() lklist.c + * VOID newpag() lklist.c + * VOID symdef() lksym.c + * + * side effects: + * The map file is created. + */ + +VOID +map() +{ + register int i; + register struct head *hdp; + register struct lbfile *lbfh; + + /* + * Open Map File + */ + mfp = afile(linkp->f_idp, "map", 1); + if (mfp == NULL) { + lkexit(1); + } + + /* + * Output Map Area Lists + */ + page = 0; + lop = NLPP; + ap = areap; + while (ap) { + lstarea(ap); + ap = ap->a_ap; + } + /* + * List Linked Files + */ + newpag(mfp); + fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n"); + hdp = headp; + filep = linkp; + while (filep) { + fprintf(mfp, "%-16s", filep->f_idp); + i = 0; + while ((hdp != NULL) && (hdp->h_lfile == filep)) { + if (i % 5) { + fprintf(mfp, ", %8.8s", hdp->m_id); + } else { + if (i) { + fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id); + } else { + fprintf(mfp, " [ %8.8s", hdp->m_id); + } + } + hdp = hdp->h_hp; + i++; + } + if (i) + fprintf(mfp, " ]"); + fprintf(mfp, "\n"); + filep = filep->f_flp; + } + /* + * List Linked Libraries + */ + if (lbfhead != NULL) { + fprintf(mfp, + "\nLibraries Linked [ object file ]\n\n"); + for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) { + fprintf(mfp, "%-32s [ %16.16s ]\n", + lbfh->libspc, lbfh->relfil); + } + fprintf(mfp, "\n"); + } + /* + * List Base Address Definitions + */ + if (basep) { + newpag(mfp); + fprintf(mfp, "\nUser Base Address Definitions\n\n"); + bsp = basep; + while (bsp) { + fprintf(mfp, "%s\n", bsp->b_strp); + bsp = bsp->b_base; + } + } + /* + * List Global Definitions + */ + if (globlp) { + newpag(mfp); + fprintf(mfp, "\nUser Global Definitions\n\n"); + gsp = globlp; + while (gsp) { + fprintf(mfp, "%s\n", gsp->g_strp); + gsp = gsp->g_globl; + } + } + fprintf(mfp, "\n\f"); + symdef(mfp); +} + +/*)Function int parse() + * + * The function parse() evaluates all command line or file input + * linker directives and updates the appropriate variables. + * + * local variables: + * int c character value + * char fid[] file id string + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * lfile *lfp pointer to current lfile structure + * being processed by parse() + * lfile *linkp pointer to first lfile structure + * containing an input REL file + * specification + * int mflag Map output flag + * int oflag Output file type flag + * int pflag print linker command file flag + * FILE * stderr c_library + * int uflag Relocated listing flag + * int xflag Map file radix type flag + * + * Functions called: + * VOID addlib() lklibr.c + * VOID addpath() lklibr.c + * VOID bassav() lkmain.c + * int fprintf() c_library + * VOID gblsav() lkmain.c + * VOID getfid() lklex.c + * char getnb() lklex.c + * VOID lkexit() lkmain.c + * char * strcpy() c_library + * int strlen() c_library + * + * side effects: + * Various linker flags are updated and the linked + * structure lfile is created. + */ + +int +parse() +{ + register int c; + char fid[NINPUT]; + + while ((c = getnb()) != 0) { + if ( c == ';') + return(0); + if ( c == '-') { + while (ctype[c=get()] & LETTER) { + switch(c) { + + case 'i': + case 'I': + oflag = 1; + break; + + case 's': + case 'S': + oflag = 2; + break; + + case 't': + case 'T': + oflag = 3; + break; + + case 'm': + case 'M': + ++mflag; + break; + + case 'y': /*JCF: memory usage summary output*/ + case 'Y': + ++sflag; + break; + + case 'j': + case 'J': + jflag = 1; + break; + + case 'u': + case 'U': + uflag = 1; + break; + case 'r': + case 'R': + rflag = 1; + break; + case 'x': + case 'X': + xflag = 0; + break; + + case 'q': + case 'Q': + xflag = 1; + break; + + case 'd': + case 'D': + xflag = 2; + break; + + case 'e': + case 'E': + return(1); + + case 'n': + case 'N': + pflag = 0; + break; + + case 'p': + case 'P': + pflag = 1; + break; + + case 'b': + case 'B': + bassav(); + return(0); + + case 'g': + case 'G': + gblsav(); + return(0); + + case 'k': + case 'K': + addpath(); + return(0); + + case 'l': + case 'L': + addlib(); + return(0); + + case 'a': + case 'A': + iramsav(); + return(0); + + case 'v': + case 'V': + xramsav(); + return(0); + + case 'w': + case 'W': + codesav(); + return(0); + + case 'z': + case 'Z': + dflag = 1; + return(0); + default: + fprintf(stderr, "Invalid option\n"); + lkexit(1); + } + } + if ( c == ';') + return(0); + } else + if (ctype[c] & ILL) { + fprintf(stderr, "Invalid input"); + lkexit(1); + } else { + if (linkp == NULL) { + linkp = (struct lfile *) + new (sizeof (struct lfile)); + lfp = linkp; + } else { + lfp->f_flp = (struct lfile *) + new (sizeof (struct lfile)); + lfp = lfp->f_flp; + } + getfid(fid, c); + lfp->f_idp = (char *) new (strlen(fid)+1); + strcpy(lfp->f_idp, fid); + lfp->f_type = F_REL; + } + } + return(0); +} + +/*)Function VOID bassav() + * + * The function bassav() creates a linked structure containing + * the base address strings input to the linker. + * + * local variables: + * none + * + * global variables: + * base *basep The pointer to the first + * base structure + * base *bsp Pointer to the current + * base structure + * char *ip pointer into the REL file + * text line in ib[] + * + * functions called: + * char getnb() lklex.c + * VOID * new() lksym.c + * int strlen() c_library + * char * strcpy() c_library + * VOID unget() lklex.c + * + * side effects: + * The basep structure is created. + */ + +VOID +bassav() +{ + if (basep == NULL) { + basep = (struct base *) + new (sizeof (struct base)); + bsp = basep; + } else { + bsp->b_base = (struct base *) + new (sizeof (struct base)); + bsp = bsp->b_base; + } + unget(getnb()); + bsp->b_strp = (char *) new (strlen(ip)+1); + strcpy(bsp->b_strp, ip); +} + +/*)Function VOID setbas() + * + * The function setbas() scans the base address lines in the + * basep structure, evaluates the arguments, and sets beginning + * address of the specified areas. + * + * local variables: + * int v expression value + * char id[] base id string + * + * global variables: + * area *ap Pointer to the current + * area structure + * area *areap The pointer to the first + * area structure of a linked list + * base *basep The pointer to the first + * base structure + * base *bsp Pointer to the current + * base structure + * char *ip pointer into the REL file + * text line in ib[] + * int lkerr error flag + * + * functions called: + * Addr_T expr() lkeval.c + * int fprintf() c_library + * VOID getid() lklex.c + * char getnb() lklex.c + * int symeq() lksym.c + * + * side effects: + * The base address of an area is set. + */ + +VOID +setbas() +{ + register int v; + char id[NCPS]; + + bsp = basep; + while (bsp) { + ip = bsp->b_strp; + getid(id, -1); + if (getnb() == '=') { + v = expr(0); + for (ap = areap; ap != NULL; ap = ap->a_ap) { + if (symeq(id, ap->a_id)) + break; + } + if (ap == NULL) { + fprintf(stderr, + "ASlink-Warning-No definition of area %s\n", id); + lkerr++; + } else { + ap->a_addr = v; + ap->a_type = 1; /* JLH: value set */ + } + } else { + fprintf(stderr, "ASlink-Warning-No '=' in base expression"); + lkerr++; + } + bsp = bsp->b_base; + } +} + +/*)Function VOID gblsav() + * + * The function gblsav() creates a linked structure containing + * the global variable strings input to the linker. + * + * local variable: + * none + * + * global variables: + * globl *globlp The pointer to the first + * globl structure + * globl *gsp Pointer to the current + * globl structure + * char *ip pointer into the REL file + * text line in ib[] + * int lkerr error flag + * + * functions called: + * char getnb() lklex.c + * VOID * new() lksym.c + * int strlen() c_library + * char * strcpy() c_library + * VOID unget() lklex.c + * + * side effects: + * The globlp structure is created. + */ + +VOID +gblsav() +{ + if (globlp == NULL) { + globlp = (struct globl *) + new (sizeof (struct globl)); + gsp = globlp; + } else { + gsp->g_globl = (struct globl *) + new (sizeof (struct globl)); + gsp = gsp->g_globl; + } + unget(getnb()); + gsp->g_strp = (char *) new (strlen(ip)+1); + strcpy(gsp->g_strp, ip); +} + +/*)Function VOID setgbl() + * + * The function setgbl() scans the global variable lines in the + * globlp structure, evaluates the arguments, and sets a variable + * to this value. + * + * local variables: + * int v expression value + * char id[] base id string + * sym * sp pointer to a symbol structure + * + * global variables: + * char *ip pointer into the REL file + * text line in ib[] + * globl *globlp The pointer to the first + * globl structure + * globl *gsp Pointer to the current + * globl structure + * FILE * stderr c_library + * int lkerr error flag + * + * functions called: + * Addr_T expr() lkeval.c + * int fprintf() c_library + * VOID getid() lklex.c + * char getnb() lklex.c + * sym * lkpsym() lksym.c + * + * side effects: + * The value of a variable is set. + */ + +VOID +setgbl() +{ + register int v; + register struct sym *sp; + char id[NCPS]; + + gsp = globlp; + while (gsp) { + ip = gsp->g_strp; + getid(id, -1); + if (getnb() == '=') { + v = expr(0); + sp = lkpsym(id, 0); + if (sp == NULL) { + fprintf(stderr, + "No definition of symbol %s\n", id); + lkerr++; + } else { + if (sp->s_flag & S_DEF) { + fprintf(stderr, + "Redefinition of symbol %s\n", id); + lkerr++; + sp->s_axp = NULL; + } + sp->s_addr = v; + sp->s_type |= S_DEF; + } + } else { + fprintf(stderr, "No '=' in global expression"); + lkerr++; + } + gsp = gsp->g_globl; + } +} + +/*)Function FILE * afile(fn,, ft, wf) + * + * char * fn file specification string + * char * ft file type string + * int wf read(0)/write(1) flag + * + * The function afile() opens a file for reading or writing. + * (1) If the file type specification string ft + * is not NULL then a file specification is + * constructed with the file path\name in fn + * and the extension in ft. + * (2) If the file type specification string ft + * is NULL then the file specification is + * constructed from fn. If fn does not have + * a file type then the default .rel file + * type is appended to the file specification. + * + * afile() returns a file handle for the opened file or aborts + * the assembler on an open error. + * + * local variables: + * char fb[] constructed file specification string + * FILE * fp filehandle for opened file + * + * global variables: + * int lkerr error flag + * + * functions called: + * FILE * fopen() c_library + * int fprintf() c_library + * + * side effects: + * File is opened for read or write. + */ + +FILE * +afile(char *fn, char *ft, int wf) +{ + FILE *fp; + char fb[PATH_MAX]; + char *omode; + int i; + + switch (wf) { + case 0: omode = "r"; break; + case 1: omode = "w"; break; + case 2: omode = "a"; break; + case 3: omode = "rb"; break; + case 4: omode = "wb"; break; + case 5: omode = "ab"; break; + default: omode = "r"; break; + } + + /*Look backward the name path and get rid of the extension, if any*/ + i=strlen(fn); + for(; (fn[i]!='.')&&(fn[i]!='\\')&&(fn[i]!='/')&&(i>0); i--); + if( (fn[i]=='.') && strcmp(ft, "lnk") ) + { + strncpy(fb, fn, i); + fb[i]=0; + } + else + { + strcpy(fb, fn); + } + + /*Add the extension*/ + if (fb[i] != '.') + { + strcat(fb, "."); + strcat(fb, strlen(ft)?ft:"rel"); + } + + fp = fopen(fb, omode); + if (fp==NULL) + { + if (strcmp(ft,"adb"))/*Do not complaint for optional adb files*/ + { + fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open"); + lkerr++; + } + } + return (fp); +} + +/*)Function VOID iramsav() + * + * The function iramsav() stores the size of the chip's internal RAM. + * This is used after linking to check that variable assignment to this + * dataspace didn't overflow into adjoining segments. Variables in the + * DSEG, OSEG, and ISEG are assigned to this dataspace. + * + * local variables: + * none + * + * global variables: + * char *ip pointer into the REL file + * text line in ib[] + * unsigned int size of chip's internal + * iram_size RAM segment + * + * functions called: + * char getnb() lklex.c + * VOID unget() lklex.c + * Addr_T expr() lkeval.c + * + * side effects: + * The iram_size may be modified. + */ + +VOID +iramsav() +{ + unget(getnb()); + if (ip && *ip) + iram_size = expr(0); /* evaluate size expression */ + else + iram_size = 128; /* Default is 128 (0x80) bytes */ +} + +/*Similar to iramsav but for xram memory*/ +VOID +xramsav() +{ + unget(getnb()); + if (ip && *ip) + xram_size = expr(0); /* evaluate size expression */ + else + xram_size = rflag?0x1000000:0x10000; +} + +/*Similar to iramsav but for code memory*/ +VOID +codesav() +{ + unget(getnb()); + if (ip && *ip) + code_size = expr(0); /* evaluate size expression */ + else + code_size = rflag?0x1000000:0x10000; +} + + +/*)Function VOID iramcheck() + * + * The function iramcheck() is used at the end of linking to check that + * the internal RAM area wasn't overflowed by too many variable + * assignments. Variables in the DSEG, ISEG, and OSEG are assigned to + * the chip's internal RAM. + * + * local variables: + * none + * + * global variables: + * unsigned int size of chip's internal + * iram_size RAM segment + * struct area linked list of memory + * *areap areas + * + * functions called: + * + * side effects: + */ + +VOID +iramcheck() +{ + register unsigned int last_addr; + register struct area *ap; + + for (ap = areap; ap; ap=ap->a_ap) { + if ((ap->a_size != 0) && + (!strcmp(ap->a_id, "DSEG") || + !strcmp(ap->a_id, "OSEG") || + !strcmp(ap->a_id, "ISEG") + ) + ) + { + last_addr = ap->a_addr + ap->a_size - 1; + if (last_addr >= iram_size) + fprintf(stderr, + "\nWARNING! Segment %s extends past the end\n" + " of internal RAM. Check map file.\n", + ap->a_id); + } + } +} + +char *usetxt[] = { + "Startup:", + " -c Command line input", + " -f file[LNK] File input", + " -p Prompt and echo of file[LNK] to stdout (default)", + " -n No echo of file[LNK] to stdout", +/* "Usage: [-Options] file [file ...]", */ + "Libraries:", + " -k Library path specification, one per -k", + " -l Library file specification, one per -l", + "Relocation:", + " -b area base address = expression", + " -g global symbol = expression", + "Map format:", + " -m Map output generated as file[MAP]", + " -x Hexadecimal (default), -d Decimal, -q Octal", + "Output:", + " -i Intel Hex as file[IHX]", + " -s Motorola S19 as file[S19]", + " -t ELF executable as file[elf]", + " -j Produce NoICE debug as file[NOI]", + " -z Produce SDCdb debug as file[cdb]", +/* "List:", */ + " -u Update listing file(s) with link data as file(s)[.RST]", + "Miscellaneous:\n" + " -a [iram-size] Check for internal RAM overflow", + " -v [xram-size] Check for external RAM overflow", + " -w [code-size] Check for code overflow", + "End:", + " -e or null line terminates input", + 0 +}; + +/*)Function VOID usage() + * + * The function usage() outputs to the stderr device the + * assembler name and version and a list of valid assembler options. + * + * local variables: + * char ** dp pointer to an array of + * text string pointers. + * + * global variables: + * FILE * stderr c_library + * + * functions called: + * int fprintf() c_library + * + * side effects: + * none + */ + +VOID +usage() +{ + register char **dp; + + fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION); + for (dp = usetxt; *dp; dp++) + fprintf(stderr, "%s\n", *dp); + lkexit(1); +} + +/*)Function VOID copyfile() + * + * FILE *dest destination file + * FILE *src source file + * + * function will copy source file to destination file + * + * + * functions called: + * int fgetc() c_library + * int fputc() c_library + * + * side effects: + * none + */ +VOID copyfile (dest,src) +FILE *src,*dest ; +{ + int ch; + while ((ch = fgetc(src)) != EOF) { + + fputc(ch,dest); + } +} diff --git a/as/link/hc08/lkmem.c b/as/link/hc08/lkmem.c new file mode 100644 index 00000000..e250f95d --- /dev/null +++ b/as/link/hc08/lkmem.c @@ -0,0 +1,360 @@ +/*------------------------------------------------------------------------- + lkmem.c - Create a memory summary file with extension .mem + + Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002) + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +-------------------------------------------------------------------------*/ + +#include +#include +#include +#include "aslink.h" + +int summary(struct area * areap) +{ + #define EQ(A,B) !as_strcmpi((A),(B)) + #define MIN_STACK 16 + #define REPORT_ERROR(A, H) \ + {\ + fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \ + fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \ + toreturn=1; \ + } + + #define REPORT_WARNING(A, H) \ + { \ + fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \ + fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \ + } + + char buff[128]; + int j, toreturn=0; + unsigned int Total_Last=0, k; + + struct area * xp; + FILE * of; + + /*Artifacts used for printing*/ + char start[15], end[15], size[15], max[15]; + char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n"; + char line[]="---------------------"; + + typedef struct + { + unsigned long Start; + unsigned long Size; + unsigned long Max; + char Name[NCPS]; + unsigned long flag; + } _Mem; + + unsigned int dram[0x100]; + _Mem Ram[]={ + {0, 0, 0, "REG_BANK_0", 0x0001}, + {0x0, 0, 0, "REG_BANK_1", 0x0002}, + {0x0, 0, 0, "REG_BANK_2", 0x0004}, + {0x0, 0, 0, "REG_BANK_3", 0x0008}, + {0x0, 0, 0, "BSEG_BYTES", 0x0010}, + {0, 0, 256, "UNUSED", 0x0000}, + {0xff, 0, 256, "DATA", 0x0020}, + {0, 0, 256, "TOTAL:", 0x0000} + }; + + _Mem IRam= {0xff, 0, 0, "INDIRECT RAM", 0x0080}; + _Mem Stack={0xff, 0, 1, "STACK", 0x0000}; + _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100}; + _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200}; + +#if 0 + if(rflag) /*For the DS390*/ + { + XRam.Max=0x1000000; /*24 bits*/ + XRam.Start=0xffffff; + Rom.Max=0x1000000; + Rom.Start=0xffffff; + } + + if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/ + { + Ram[5].Max=0x80; + Ram[6].Max=0x80; + Ram[7].Max=0x80; + IRam.Max=0x80; + iram_size=0x100; + } + else if(iram_size<0x80) + { + Ram[5].Max=iram_size; + Ram[6].Max=iram_size; + Ram[7].Max=iram_size; + IRam.Max=0; + } + else + { + Ram[5].Max=0x80; + Ram[6].Max=0x80; + Ram[7].Max=0x80; + IRam.Max=iram_size-0x80; + } +#endif + + for(j=0; j<(int)iram_size; j++) dram[j]=0; + for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/ + + /* Open Memory Summary File*/ + of = afile(linkp->f_idp, "mem", 1); + if (of == NULL) + { + lkexit(1); + } + + xp=areap; + while (xp) + { + /**/ if (EQ(xp->a_id, "REG_BANK_0")) + { + Ram[0].Size=xp->a_size; + } + else if (EQ(xp->a_id, "REG_BANK_1")) + { + Ram[1].Size=xp->a_size; + } + else if (EQ(xp->a_id, "REG_BANK_2")) + { + Ram[2].Size=xp->a_size; + } + else if (EQ(xp->a_id, "REG_BANK_3")) + { + Ram[3].Size=xp->a_size; + } + else if (EQ(xp->a_id, "BSEG_BYTES")) + { + Ram[4].Size=xp->a_size; + } + else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") ) + { + Ram[6].Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") || + EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") ) + { + Rom.Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else if (EQ(xp->a_id, "SSEG")) + { + Stack.Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) + { + XRam.Size+=xp->a_size; + if(xp->a_addra_addr; + } + + else if (EQ(xp->a_id, "ISEG")) + { + IRam.Size+=xp->a_size; + if(xp->a_addra_addr; + } + xp=xp->a_ap; + } + + for(j=0; j<7; j++) + for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++) + dram[k]|=Ram[j].flag; /*Mark as used*/ + +#if 0 + for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++) + dram[k]|=IRam.flag; /*Mark as used*/ +#endif + + /*Compute the amount of unused memory in direct data Ram. This is the + gap between the last register bank or bit segment and the data segment.*/ + for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--); + Ram[5].Start=k+1; + Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/ + + /*Compute the data Ram totals*/ + for(j=0; j<7; j++) + { + if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start; + Ram[7].Size+=Ram[j].Size; + } + Total_Last=Ram[6].Size+Ram[6].Start-1; + + /*Report the Ram totals*/ + fprintf(of, "Direct Internal RAM:\n"); + fprintf(of, format, "Name", "Start", "End", "Size", "Max"); + + for(j=0; j<8; j++) + { + if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line); + if((j!=5) || (Ram[j].Size>0)) + { + sprintf(start, "0x%02lx", Ram[j].Start); + if(Ram[j].Size==0) + end[0]=0;/*Empty string*/ + else + sprintf(end, "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1); + sprintf(size, "%5lu", Ram[j].Size); + sprintf(max, "%5lu", Ram[j].Max); + fprintf(of, format, Ram[j].Name, start, end, size, max); + } + } + +#if 0 + for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++) + { + if(dram[k]!=Ram[6].flag) + { + sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k); + REPORT_ERROR(buff, 1); + break; + } + } + + + if(Ram[4].Size>Ram[4].Max) + { + k=Ram[4].Size-Ram[4].Max; + sprintf(buff, "Insufficient bit addressable memory. " + "%d byte%s short.\n", k, (k==1)?"":"s"); + REPORT_ERROR(buff, 1); + } + + if(Ram[5].Size!=0) + { + sprintf(buff, "%ld bytes in data memory wasted. " + "SDCC link could use: --data-loc 0x%02lx\n", + Ram[5].Size, Ram[6].Start-Ram[5].Size); + REPORT_WARNING(buff, 1); + } + + if((Ram[6].Start+Ram[6].Size)>Ram[6].Max) + { + k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max; + sprintf(buff, "Insufficient space in data memory. " + "%d byte%s short.\n", k, (k==1)?"":"s"); + REPORT_ERROR(buff, 1); + } +#endif + /*Report the position of the beginning of the stack*/ + fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)", + rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1); + +#if 0 + /*Check that the stack pointer is landing in a safe place:*/ + if( (dram[Stack.Start] & 0x8000) == 0x8000 ) + { + fprintf(of, ".\n"); + sprintf(buff, "Stack set to unavailable memory.\n"); + REPORT_ERROR(buff, 1); + } + else if(dram[Stack.Start]) + { + fprintf(of, ".\n"); + sprintf(buff, "Stack overlaps area "); + REPORT_ERROR(buff, 1); + for(j=0; j<7; j++) + { + if(dram[Stack.Start]&Ram[j].flag) + { + sprintf(buff, "'%s'\n", Ram[j].Name); + break; + } + } + if(dram[Stack.Start]&IRam.flag) + { + sprintf(buff, "'%s'\n", IRam.Name); + } + REPORT_ERROR(buff, 0); + } + else + { + for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++); + fprintf(of, " with %d bytes available\n", k); + if (k(IRam.Max+0x80)) + { + sprintf(buff, "Insufficient INDIRECT RAM memory.\n"); + REPORT_ERROR(buff, 1); + } +#endif + if( ((XRam.Start+XRam.Size)>XRam.Max) || + (((int)XRam.Size>xram_size)&&(xram_size>=0)) ) + { + sprintf(buff, "Insufficient EXTERNAL RAM memory.\n"); + REPORT_ERROR(buff, 1); + } + if( ((Rom.Start+Rom.Size)>Rom.Max) || + (((int)Rom.Size>code_size)&&(code_size>=0)) ) + { + sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n"); + REPORT_ERROR(buff, 1); + } + + fclose(of); + return toreturn; +} diff --git a/as/link/hc08/lkrloc.c b/as/link/hc08/lkrloc.c new file mode 100644 index 00000000..7aaf0c58 --- /dev/null +++ b/as/link/hc08/lkrloc.c @@ -0,0 +1,1438 @@ +/* lkrloc.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + * + * 29-Oct-97 JLH: + * - errdmp: show s_id as string rather than array [NCPS] + * - relr: add support for 11 bit 8051 addressing + * 02-Apr-98 JLH: don't output empty hex records + */ + +#include +#include +#include "aslink.h" + +/*)Module lkrloc.c + * + * The module lkrloc.c contains the functions which + * perform the relocation calculations. + * + * lkrloc.c contains the following functions: + * Addr_T adb_b() + * Addr_T adb_lo() + * Addr_T adb_hi() + * Addr_T adw_w() + * Addr_T adw_lo() + * Addr_T adw_hi() + * VOID erpdmp() + * VOID errdmp() + * Addr_T evword() + * VOID prntval() + * VOID rele() + * VOID relerr() + * VOID relerp() + * VOID reloc() + * VOID relp() + * VOID relr() + * VOID relt() + * + * lkrloc.c the local variable errmsg[]. + * + */ + +/* Global which holds the upper 16 bits of the last 32 bit area adress + * output. Useful only for iHex mode. + */ +int lastExtendedAddress=-1; + +/* Static variable which holds the index of last processed area. + * Useful only for iHex mode. + */ +static int lastAreaIndex = -1; + +/*)Function VOID reloc(c) + * + * char c process code + * + * The function reloc() calls a particular relocation + * function determined by the process code. + * + * local variable: + * none + * + * global variables: + * int lkerr error flag + * + * called functions: + * int fprintf() c_library + * VOID rele() lkrloc.c + * VOID relp() lkrloc.c + * VOID relr() lkrloc.c + * VOId relt() lkrloc.c + * + * side effects: + * Refer to the called relocation functions. + * + */ + +VOID reloc(char c) +{ + switch(c) { + + case 'T': + relt(); + break; + + case 'R': + relr(); + break; + + case 'P': + relp(); + break; + + case 'E': + rele(); + break; + + default: + fprintf(stderr, "Undefined Relocation Operation\n"); + lkerr++; + break; + + } +} + + +/*)Function VOID relt() + * + * The function relt() evaluates a T line read by + * the linker. Each byte value read is saved in the + * rtval[] array, rtflg[] is set, and the number of + * evaluations is maintained in rtcnt. + * + * T Line + * + * T xx xx nn nn nn nn nn ... + * + * + * In: "T n0 n1 n2 n3 ... nn" + * + * Out: 0 1 2 .. rtcnt + * +----+----+----+----+----+ + * rtval | n0 | n1 | n2 | .. | nn | + * +----+----+----+----+----+ + * rtflag| 1 | 1 | 1 | 1 | 1 | + * +----+----+----+----+----+ + * + * The T line contains the assembled code output by the assem- + * bler with xx xx being the offset address from the current area + * base address and nn being the assembled instructions and data in + * byte format. + * + * local variable: + * none + * + * global variables: + * int rtcnt number of values evaluated + * int rtflg[] array of evaluation flags + * int rtval[] array of evaluation values + * + * called functions: + * int eval() lkeval.c + * int more() lklex.c + * + * side effects: + * Linker input T line evaluated. + * + */ + +VOID relt(VOID) +{ + rtcnt = 0; + while (more()) { + if (rtcnt < NTXT) { + rtval[rtcnt] = eval(); + rtflg[rtcnt] = 1; + rtcnt++; + } + } +} + +/*)Function VOID relr() + * + * The function relr() evaluates a R line read by + * the linker. The R line data is combined with the + * previous T line data to perform the relocation of + * code and data bytes. The S19 / IHX output and + * translation of the LST files to RST files may be + * performed. + * + * R Line + * + * R 0 0 nn nn n1 n2 xx xx ... + * + * The R line provides the relocation information to the linker. + * The nn nn value is the current area index, i.e. which area the + * current values were assembled. Relocation information is en- + * coded in groups of 4 bytes: + * + * 1. n1 is the relocation mode and object format + * 1. bit 0 word(0x00)/byte(0x01) + * 2. bit 1 relocatable area(0x00)/symbol(0x02) + * 3. bit 2 normal(0x00)/PC relative(0x04) relocation + * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for + * byte data + * 5. bit 4 signed(0x00)/unsigned(0x10) byte data + * 6. bit 5 normal(0x00)/page '0'(0x20) reference + * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference + * + * 2. n2 is a byte index into the corresponding (i.e. pre- + * ceeding) T line data (i.e. a pointer to the data to be + * updated by the relocation). The T line data may be + * 1-byte or 2-byte byte data format or 2-byte word + * format. + * + * 3. xx xx is the area/symbol index for the area/symbol be- + * ing referenced. the corresponding area/symbol is found + * in the header area/symbol lists. + * + * The groups of 4 bytes are repeated for each item requiring relo- + * cation in the preceeding T line. + * + * local variable: + * areax **a pointer to array of area pointers + * int aindex area index + * char *errmsg[] array of pointers to error strings + * int error error code + * int lkerr error flag + * int mode relocation mode + * adrr_t paga paging base area address + * Addr_T pags paging symbol address + * Addr_T pc relocated base address + * Addr_T r PCR relocation value + * Addr_T reli relocation initial value + * Addr_T relv relocation final value + * int rindex symbol / area index + * Addr_T rtbase base code address + * Addr_T rtofst rtval[] index offset + * int rtp index into T data + * sym **s pointer to array of symbol pointers + * + * global variables: + * head *hp pointer to the head structure + * rerr rerr linker error structure + * FILE *stderr standard error device + * + * called functions: + * Addr_T adb_b() lkrloc.c + * Addr_T adb_lo() lkrloc.c + * Addr_T adb_hi() lkrloc.c + * Addr_T adw_w() lkrloc.c + * VOID elf() lkelf.c + * Addr_T evword() lkrloc.c + * int eval() lkeval.c + * int fprintf() c_library + * VOID ihx() lkihx.c + * int lkulist lklist.c + * int more() lklex.c + * VOID relerr() lkrloc.c + * VOID s19() lks19.c + * int symval() lksym.c + * + * side effects: + * The R and T lines are combined to produce + * relocated code and data. Output S19 / IHX + * and relocated listing files may be produced. + * + */ + +VOID relr(VOID) +{ + register int mode; + register Addr_T reli, relv; + int aindex, rindex, rtp, error; + Addr_T r, rtbase, rtofst, paga, pags, pc; + struct areax **a; + struct sym **s; + + /* + * Get area and symbol lists + */ + a = hp->a_list; + s = hp->s_list; + + /* + * Verify Area Mode + */ + if (eval() != (R_WORD | R_AREA) || eval()) { + fprintf(stderr, "R input error\n"); + lkerr++; + } + + /* + * Get area pointer + */ + aindex = evword(); + if (aindex >= hp->h_narea) { + fprintf(stderr, "R area error\n"); + lkerr++; + return; + } + ap = a[aindex]->a_bap; + + /* + * Base values + */ + rtbase = adw_w(0, 0); + rtofst = 2; + + /* + * Relocate address + */ + pc = adw_w(a[aindex]->a_addr, 0); + + #if 0 + printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex, + a[aindex]->a_addr, a[aindex]->a_size, rtbase); + #endif + /* + * Do remaining relocations + */ + while (more()) { + error = 0; + mode = eval(); + + if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK) + { + mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval(); + /* printf("unescaping rmode\n"); */ + } + + rtp = eval(); + rindex = evword(); + + /* + * R_SYM or R_AREA references + */ + if (mode & R_SYM) { + if (rindex >= hp->h_nglob) { + fprintf(stderr, "R symbol error\n"); + lkerr++; + return; + } + reli = symval(s[rindex]); + } else { + if (rindex >= hp->h_narea) { + fprintf(stderr, "R area error\n"); + lkerr++; + return; + } + reli = a[rindex]->a_addr; + } + + /* + * R_PCR addressing + */ + if (mode & R_PCR) { + if (mode & R_BYTE) { + reli -= (pc + (rtp-rtofst) + 1); + } else { + reli -= (pc + (rtp-rtofst) + 2); + } + } + + /* + * R_PAG0 or R_PAG addressing + */ + if (mode & (R_PAG0 | R_PAG)) { + paga = sdp.s_area->a_addr; + pags = sdp.s_addr; + reli -= paga + pags; + } + + /* + * R_BYTE or R_WORD operation + */ + if (mode & R_BYTE) { + if (mode & R_BYT3) + { + /* This is a three byte address, of which + * we will select one byte. + */ + if (mode & R_HIB) + { + /* printf("24 bit address selecting hi byte.\n"); */ + relv = adb_24_hi(reli, rtp); + } + else if (mode & R_MSB) + { + /* Note that in 24 bit mode, R_MSB + * is really the middle byte, not + * the most significant byte. + * + * This is ugly and I can only apologize + * for any confusion. + */ + /* printf("24 bit address selecting middle byte.\n"); */ + relv = adb_24_mid(reli, rtp); + } + else + { + /* printf("24 bit address selecting lo byte.\n"); */ + relv = adb_24_lo(reli, rtp); + } + } + else if (mode & R_BYT2) { + /* This is a two byte address, of + * which we will select one byte. + */ + if (mode & R_MSB) { + relv = adb_hi(reli, rtp); + } else { + relv = adb_lo(reli, rtp); + } + } else { + relv = adb_b(reli, rtp); + } + } else if (IS_R_J11(mode)) { + /* JLH: 11 bit jump destination for 8051. Forms + / two byte instruction with op-code bits + / in the MIDDLE! + / rtp points at 3 byte locus: first two + / will get the instructiion. third one + / has raw op-code. + */ + + /* Calculate absolute destination + / relv must be on same 2K page as pc + */ + relv = adw_w(reli, rtp); + + if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) { + error = 2; + } + + /* Merge MSB (byte 0) with op-code, ignoring + / top 5 bits of address. Then hide the op-code + */ + rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2]; + rtflg[rtp+2] = 0; + rtofst += 1; + } + else if (IS_R_J19(mode)) { + /* 19 bit jump destination for DS80C390. Forms + / three byte instruction with op-code bits + / in the MIDDLE! + / rtp points at 4 byte locus: first three + / will get the instructiion. fourth one + / has raw op-code. + */ + + /* Calculate absolute destination + / relv must be on same 512K page as pc + */ + relv = adw_24(reli, rtp); + + if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) { + error = 2; + } + + /* Merge MSB (byte 0) with op-code, ignoring + / top 5 bits of address. Then hide the op-code + */ + rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3]; + rtflg[rtp+3] = 0; + rtofst += 1; + } + else if (IS_C24(mode)) + { + /* 24 bit address */ + relv = adw_24(reli, rtp); + } + else + { + /* 16 bit address. */ + relv = adw_w(reli, rtp); + } + + /* + * R_BYTE with R_BYT2 offset adjust + */ + if (mode & R_BYTE) { + if (mode & R_BYT2) { + rtofst += 1; + } + } + + /* + * Unsigned Byte Checking + */ + if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF) + error = 1; + + /* + * PCR Relocation Error Checking + */ + if (mode & R_PCR && mode & R_BYTE) { + r = relv & ~0x7F; + if (r != (Addr_T) ~0x7F && r != 0) + error = 2; + } + + /* + * Page Relocation Error Checking + */ + /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags)) + error = 3;*/ + if (mode & R_PAG && (relv & ~0xFF)) + error = 4; + + /* + * Error Processing + */ + if (error) { + rerr.aindex = aindex; + rerr.mode = mode; + rerr.rtbase = rtbase + rtp - rtofst - 1; + rerr.rindex = rindex; + rerr.rval = relv - reli; + relerr(errmsg[error-1]); + } + } + if (uflag != 0) { + lkulist(1); + } + + /* JLH: output only if data (beyond two byte address) */ + if ((oflag == 1) && (rtcnt > 2)) { + // int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff; + + /* Boy, is this a hack: for ABS sections, the + * base address is stored as zero, and the T records + * indicate the offset from zero. + * + * Since T records can only indicate a 16 bit offset, this + * obviously creates a problem for ABS segments located + * above 64K (this is only meaningful in flat24 mode). + * + * However, the size of an ABS area is stored as + * base address + section size (I suspect this is a bug, + * but it's a handy one right now). So the upper 8 bits of + * the 24 bit address are stored in the size record. + * Thus we add it in. + * + * This is another reason why we can't have areas greater + * than 64K yet, even in flat24 mode. + */ + // extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff); + // commented out by jr + + if (lastAreaIndex != aindex) { + lastAreaIndex = aindex; + newArea(); + } +#if 0 + if (extendedAddress != lastExtendedAddress) + { + + if (lastExtendedAddress!=-1) { + printf("output extended linear address record 0x%x 0x%x\n", + extendedAddress, lastExtendedAddress); + } + + if (rflag) + { + ihxEntendedLinearAddress(extendedAddress); + } + else if (extendedAddress) + { + /* Not allowed to generate extended address records, + * but one is called for here... + */ + fprintf(stderr, + "warning: extended linear address encountered; " + "you probably want the -r flag.\n"); + } + lastExtendedAddress = extendedAddress; + } +#endif + ihx(1); + } else + if ((oflag == 2) && (rtcnt > 2)) { + s19(1); + } else + if ((oflag == 3) && (rtcnt > 2)) { + elf(1); + } +} + +char *errmsg[] = { + "Unsigned Byte error", + "Byte PCR relocation error", + "Page0 relocation error", + "Page Mode relocation error" +}; + + +/*)Function VOID relp() + * + * The function relp() evaluates a P line read by + * the linker. The P line data is combined with the + * previous T line data to set the base page address + * and test the paging boundary and length. + * + * P Line + * + * P 0 0 nn nn n1 n2 xx xx + * + * The P line provides the paging information to the linker as + * specified by a .setdp directive. The format of the relocation + * information is identical to that of the R line. The correspond- + * ing T line has the following information: + * T xx xx aa aa bb bb + * + * Where aa aa is the area reference number which specifies the + * selected page area and bb bb is the base address of the page. + * bb bb will require relocation processing if the 'n1 n2 xx xx' is + * specified in the P line. The linker will verify that the base + * address is on a 256 byte boundary and that the page length of an + * area defined with the PAG type is not larger than 256 bytes. + * + * local variable: + * areax **a pointer to array of area pointers + * int aindex area index + * int mode relocation mode + * Addr_T relv relocation value + * int rindex symbol / area index + * int rtp index into T data + * sym **s pointer to array of symbol pointers + * + * global variables: + * head *hp pointer to the head structure + * int lkerr error flag + * sdp sdp base page structure + * FILE *stderr standard error device + * + * called functions: + * Addr_T adw_w() lkrloc.c + * Addr_T evword() lkrloc.c + * int eval() lkeval.c + * int fprintf() c_library + * int more() lklex.c + * int symval() lksym.c + * + * side effects: + * The P and T lines are combined to set + * the base page address and report any + * paging errors. + * + */ + +VOID relp(VOID) +{ + register int aindex, rindex; + int mode, rtp; + Addr_T relv; + struct areax **a; + struct sym **s; + + /* + * Get area and symbol lists + */ + a = hp->a_list; + s = hp->s_list; + + /* + * Verify Area Mode + */ + if (eval() != (R_WORD | R_AREA) || eval()) { + fprintf(stderr, "P input error\n"); + lkerr++; + } + + /* + * Get area pointer + */ + aindex = evword(); + if (aindex >= hp->h_narea) { + fprintf(stderr, "P area error\n"); + lkerr++; + return; + } + + /* + * Do remaining relocations + */ + while (more()) { + mode = eval(); + rtp = eval(); + rindex = evword(); + + /* + * R_SYM or R_AREA references + */ + if (mode & R_SYM) { + if (rindex >= hp->h_nglob) { + fprintf(stderr, "P symbol error\n"); + lkerr++; + return; + } + relv = symval(s[rindex]); + } else { + if (rindex >= hp->h_narea) { + fprintf(stderr, "P area error\n"); + lkerr++; + return; + } + relv = a[rindex]->a_addr; + } + adw_w(relv, rtp); + } + + /* + * Paged values + */ + aindex = adw_w(0,2); + if (aindex >= hp->h_narea) { + fprintf(stderr, "P area error\n"); + lkerr++; + return; + } + sdp.s_areax = a[aindex]; + sdp.s_area = sdp.s_areax->a_bap; + sdp.s_addr = adw_w(0,4); + if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF) + relerp("Page Definition Boundary Error"); +} + +/*)Function VOID rele() + * + * The function rele() closes all open output files + * at the end of the linking process. + * + * local variable: + * none + * + * global variables: + * int oflag output type flag + * int uflag relocation listing flag + * + * called functions: + * VOID elf() lkelf.c + * VOID ihx() lkihx.c + * VOID lkulist() lklist.c + * VOID s19() lks19.c + * + * side effects: + * All open output files are closed. + * + */ + +VOID rele(VOID) +{ + if (uflag != 0) { + lkulist(0); + } + if (oflag == 1) { + ihx(0); + } else + if (oflag == 2) { + s19(0); + } else + if (oflag == 3) { + elf(0); + } +} + +/*)Function Addr_T evword() + * + * The function evword() combines two byte values + * into a single word value. + * + * local variable: + * Addr_T v temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * int eval() lkeval.c + * + * side effects: + * Relocation text line is scanned to combine + * two byte values into a single word value. + * + */ + +Addr_T evword(VOID) +{ + register Addr_T v; + + if (hilo) { + v = (eval() << 8); + v += eval(); + } else { + v = eval(); + v += (eval() << 8); + } + return(v); +} + +/*)Function Addr_T adb_b(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_b() adds the value of v to + * the single byte value contained in rtval[i]. + * The new value of rtval[i] is returned. + * + * local variable: + * none + * + * global variables: + * none + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * + */ + +Addr_T adb_b(register Addr_T v, register int i) +{ + return(rtval[i] += v); +} + +/*)Function Addr_T adb_lo(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_lo() adds the value of v to the + * double byte value contained in rtval[i] and rtval[i+1]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The MSB rtflg[] is cleared. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * MSB of the word value is cleared to reflect + * the fact that the LSB is the selected byte. + * + */ + +Addr_T adb_lo(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_w(v, i); + /* + * Remove Hi byte + */ + if (hilo) { + rtflg[i] = 0; + } else { + rtflg[i+1] = 0; + } + return (j); +} + +/*)Function Addr_T adb_hi(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_hi() adds the value of v to the + * double byte value contained in rtval[i] and rtval[i+1]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The LSB rtflg[] is cleared. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * LSB of the word value is cleared to reflect + * the fact that the MSB is the selected byte. + * + */ + +Addr_T adb_hi(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_w(v, i); + /* + * Remove Lo byte + */ + if (hilo) { + rtflg[i+1] = 0; + } else { + rtflg[i] = 0; + } + return (j); +} + +/*)Function Addr_T adb_24_hi(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_24_hi() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The LSB & middle byte rtflg[] is cleared. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * LSB & middle byte of the word value is cleared to + * reflect the fact that the MSB is the selected byte. + * + */ + +Addr_T adb_24_hi(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_24(v, i); + + /* Remove the lower two bytes. */ + if (hilo) + { + rtflg[i+2] = 0; + } + else + { + rtflg[i] = 0; + } + rtflg[i+1] = 0; + + return (j); +} + +/*)Function Addr_T adb_24_mid(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_24_mid() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The LSB & MSB byte rtflg[] is cleared. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * LSB & MSB of the 24 bit value is cleared to reflect + * the fact that the middle byte is the selected byte. + * + */ + +Addr_T adb_24_mid(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_24(v, i); + + /* remove the MSB & LSB. */ + rtflg[i+2] = 0; + rtflg[i] = 0; + + return (j); +} + +/*)Function Addr_T adb_24_lo(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_24_lo() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The MSB & middle byte rtflg[] is cleared. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * MSB & middle byte of the word value is cleared to + * reflect the fact that the LSB is the selected byte. + * + */ + +Addr_T adb_24_lo(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_24(v, i); + + /* Remove the upper two bytes. */ + if (hilo) + { + rtflg[i] = 0; + } + else + { + rtflg[i+2] = 0; + } + rtflg[i+1] = 0; + + return (j); +} + +/*)Function Addr_T adw_w(v, i) + * + * int v value to add to word + * int i rtval[] index + * + * The function adw_w() adds the value of v to the + * word value contained in rtval[i] and rtval[i+1]. + * The new value of rtval[i] / rtval[i+1] is returned. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The word value of rtval[] is changed. + * + */ + +Addr_T adw_w(register Addr_T v, register int i) +{ + register Addr_T j; + + if (hilo) { + j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff); + rtval[i] = (j >> 8) & 0xff; + rtval[i+1] = j & 0xff; + } else { + j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8); + rtval[i] = j & 0xff; + rtval[i+1] = (j >> 8) & 0xff; + } + return(j); +} + +/*)Function Addr_T adw_24(v, i) + * + * int v value to add to word + * int i rtval[] index + * + * The function adw_w() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] - rtval[i+2] is returned. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The word value of rtval[] is changed. + * + */ +Addr_T adw_24(Addr_T v, int i) +{ + register Addr_T j; + + if (hilo) { + j = v + ((rtval[i] & 0xff) << 16) + + ((rtval[i+1] & 0xff) << 8) + + (rtval[i+2] & 0xff); + rtval[i] = (j >> 16) & 0xff; + rtval[i+1] = (j >> 8) & 0xff; + rtval[i+2] = j & 0xff; + } else { + j = v + (rtval[i] & 0xff) + + ((rtval[i+1] & 0xff) << 8) + + ((rtval[i+2] & 0xff) << 16); + rtval[i] = j & 0xff; + rtval[i+1] = (j >> 8) & 0xff; + rtval[i+2] = (j >> 16) & 0xff; + } + return(j); +} + +/*)Function Addr_T adw_lo(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adw_lo() adds the value of v to the + * double byte value contained in rtval[i] and rtval[i+1]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The MSB rtval[] is zeroed. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The MSB of the word value is cleared to reflect + * the fact that the LSB is the selected byte. + * + */ + +Addr_T adw_lo(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_w(v, i); + /* + * Clear Hi byte + */ + if (hilo) { + rtval[i] = 0; + } else { + rtval[i+1] = 0; + } + return (j); +} + +/*)Function Addr_T adw_hi(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adw_hi() adds the value of v to the + * double byte value contained in rtval[i] and rtval[i+1]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The MSB and LSB values are interchanged. + * The MSB rtval[] is zeroed. + * + * local variable: + * Addr_T j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The MSB and LSB values are interchanged and + * then the MSB cleared. + * + */ + +Addr_T adw_hi(Addr_T v, int i) +{ + register Addr_T j; + + j = adw_w(v, i); + /* + * LSB = MSB, Clear MSB + */ + if (hilo) { + rtval[i+1] = rtval[i]; + rtval[i] = 0; + } else { + rtval[i] = rtval[i+1]; + rtval[i+1] = 0; + } + return (j); +} + +/*)Function VOID relerr(str) + * + * char *str error string + * + * The function relerr() outputs the error string to + * stderr and to the map file (if it is open). + * + * local variable: + * none + * + * global variables: + * FILE *mfp handle for the map file + * + * called functions: + * VOID errdmp() lkrloc.c + * + * side effects: + * Error message inserted into map file. + * + */ + +VOID relerr(char *str) +{ + errdmp(stderr, str); + if (mfp) + errdmp(mfp, str); +} + +/*)Function VOID errdmp(fptr, str) + * + * FILE *fptr output file handle + * char *str error string + * + * The function errdmp() outputs the error string str + * to the device specified by fptr. Additional information + * is output about the definition and referencing of + * the symbol / area error. + * + * local variable: + * int mode error mode + * int aindex area index + * int lkerr error flag + * int rindex error index + * sym **s pointer to array of symbol pointers + * areax **a pointer to array of area pointers + * areax *raxp error area extension pointer + * + * global variables: + * sdp sdp base page structure + * + * called functions: + * int fprintf() c_library + * VOID prntval() lkrloc.c + * + * side effects: + * Error reported. + * + */ + +VOID errdmp(FILE *fptr, char *str) +{ + int mode, aindex, rindex; + struct sym **s; + struct areax **a; + struct areax *raxp; + + a = hp->a_list; + s = hp->s_list; + + mode = rerr.mode; + aindex = rerr.aindex; + rindex = rerr.rindex; + + /* + * Print Error + */ + fprintf(fptr, "\n?ASlink-Warning-%s", str); + lkerr++; + + /* + * Print symbol if symbol based + */ + if (mode & R_SYM) { + fprintf(fptr, " for symbol %s\n", + &s[rindex]->s_id[0]); + } else { + fprintf(fptr, "\n"); + } + + /* + * Print Ref Info + */ + fprintf(fptr, + " file module area offset\n"); + fprintf(fptr, + " Refby %-8.8s %-8.8s %-8.8s ", + hp->h_lfile->f_idp, + &hp->m_id[0], + &a[aindex]->a_bap->a_id[0]); + prntval(fptr, rerr.rtbase); + + /* + * Print Def Info + */ + if (mode & R_SYM) { + raxp = s[rindex]->s_axp; + } else { + raxp = a[rindex]; + } + fprintf(fptr, + " Defin %-8.8s %-8.8s %-8.8s ", + raxp->a_bhp->h_lfile->f_idp, + &raxp->a_bhp->m_id[0], + &raxp->a_bap->a_id[0]); + if (mode & R_SYM) { + prntval(fptr, s[rindex]->s_addr); + } else { + prntval(fptr, rerr.rval); + } +} + +/*)Function VOID prntval(fptr, v) + * + * FILE *fptr output file handle + * Addr_T v value to output + * + * The function prntval() outputs the value v, in the + * currently selected radix, to the device specified + * by fptr. + * + * local variable: + * none + * + * global variables: + * int xflag current radix + * + * called functions: + * int fprintf() c_library + * + * side effects: + * none + * + */ + +VOID prntval(FILE *fptr, Addr_T v) +{ + if (xflag == 0) { + fprintf(fptr, "%04X\n", v); + } else + if (xflag == 1) { + fprintf(fptr, "%06o\n", v); + } else + if (xflag == 2) { + fprintf(fptr, "%05u\n", v); + } +} + +/*)Function VOID relerp(str) + * + * char *str error string + * + * The function relerp() outputs the paging error string to + * stderr and to the map file (if it is open). + * + * local variable: + * none + * + * global variables: + * FILE *mfp handle for the map file + * + * called functions: + * VOID erpdmp() lkrloc.c + * + * side effects: + * Error message inserted into map file. + * + */ + +VOID relerp(char *str) +{ + erpdmp(stderr, str); + if (mfp) + erpdmp(mfp, str); +} + +/*)Function VOID erpdmp(fptr, str) + * + * FILE *fptr output file handle + * char *str error string + * + * The function erpdmp() outputs the error string str + * to the device specified by fptr. + * + * local variable: + * head *thp pointer to head structure + * + * global variables: + * int lkerr error flag + * sdp sdp base page structure + * + * called functions: + * int fprintf() c_library + * VOID prntval() lkrloc.c + * + * side effects: + * Error reported. + * + */ + +VOID erpdmp(FILE *fptr, char *str) +{ + register struct head *thp; + + thp = sdp.s_areax->a_bhp; + + /* + * Print Error + */ + fprintf(fptr, "\n?ASlink-Warning-%s\n", str); + lkerr++; + + /* + * Print PgDef Info + */ + fprintf(fptr, + " file module pgarea pgoffset\n"); + fprintf(fptr, + " PgDef %-8.8s %-8.8s %-8.8s ", + thp->h_lfile->f_idp, + &thp->m_id[0], + &sdp.s_area->a_id[0]); + prntval(fptr, sdp.s_area->a_addr + sdp.s_addr); +} diff --git a/as/link/hc08/lks19.c b/as/link/hc08/lks19.c new file mode 100644 index 00000000..d50a41ea --- /dev/null +++ b/as/link/hc08/lks19.c @@ -0,0 +1,124 @@ +/* lks19.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include "aslink.h" + +/*)Module lks19.c + * + * The module lks19.c contains the function to + * output the relocated object code in the + * Motorola S19 format. + * + * lks19.c contains the following function: + * VOID s19(i) + * + * lks19.c contains no local variables. + */ + +/*)S19 Format + * Record Type Field - This field signifies the start of a + * record and identifies the the record + * type as follows: + * + * Ascii S1 - Data Record + * Ascii S9 - End of File Record + * + * Record Length Field - This field specifies the record length + * which includes the address, data, and + * checksum fields. The 8 bit record + * length value is converted to two ascii + * characters, high digit first. + * + * Load Address Field - This field consists of the four ascii + * characters which result from converting + * the the binary value of the address in + * which to begin loading this record. The + * order is as follows: + * + * High digit of high byte of address. + * Low digit of high byte of address. + * High digit of low byte of address. + * Low digit of low byte of address. + * + * In an End of File record this field con- + * sists of either four ascii zeros or the + * program entry address. Currently the + * entry address option is not supported. + * + * Data Field - This field consists of the actual data, + * converted to two ascii characters, high + * digit first. There are no data bytes in + * the End of File record. + * + * Checksum Field - The checksum field is the 8 bit binary + * sum of the record length field, the load + * address field, and the data field. This + * sum is then complemented (1's comple- + * ment) and converted to two ascii + * characters, high digit first. + */ + +/*)Function s19(i) + * + * int i 0 - process data + * 1 - end of data + * + * The function s19() outputs the relocated data + * in the standard Motorola S19 format. + * + * local variables: + * Addr_T chksum byte checksum + * + * global variables: + * int hilo byte order + * FILE * ofp output file handle + * int rtcnt count of data words + * int rtflg[] output the data flag + * Addr_T rtval[] relocated data + * + * functions called: + * int fprintf() c_library + * + * side effects: + * The data is output to the file defined by ofp. + */ + +VOID +s19(i) +{ + register Addr_T chksum; + + if (i) { + if (ap->a_flag & A_NOLOAD) + return; + if (hilo == 0) { + chksum = rtval[0]; + rtval[0] = rtval[1]; + rtval[1] = chksum; + } + for (i = 0, chksum = 1; i < rtcnt; i++) { + if (rtflg[i]) + chksum++; + } + fprintf(ofp, "S1%02X", chksum); + for (i = 0; i < rtcnt ; i++) { + if (rtflg[i]) { + fprintf(ofp, "%02X", rtval[i]); + chksum += rtval[i]; + } + } + fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff); + } else { + fprintf(ofp, "S9030000FC\n"); + } +} diff --git a/as/link/lkeval.c b/as/link/lkeval.c new file mode 100644 index 00000000..90df0031 --- /dev/null +++ b/as/link/lkeval.c @@ -0,0 +1,396 @@ +/* lkeval.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include "aslink.h" + +/*)Module lkeval.c + * + * The module lkeval.c contains the routines to evaluate + * arithmetic/numerical expressions. The functions in + * lkeval.c perform a recursive evaluation of the arithmetic + * expression read from the input text line. + * The expression may include binary/unary operators, brackets, + * symbols, labels, and constants in hexadecimal, decimal, octal + * and binary. Arithmetic operations are prioritized and + * evaluated by normal arithmetic conventions. + * + * lkeval.c contains the following functions: + * int digit() + * Addr_T eval() + * Addr_T expr() + * int oprio() + * Addr_T term() + * + * lkeval.c contains no local/static variables + */ + +/*)Function Addr_T eval() + * + * The function eval() evaluates a character string to a + * numerical value. + * + * local variables: + * int c character from input string + * int v value of character in current radix + * Addr_T n evaluation value + * + * global variables: + * int radix current number conversion radix + * + * functions called: + * int digit() lkeval.c + * char get() lklex.c + * char getnb() lklex.c + * VOID unget() lklex.c + * + * side effects: + * Input test is scanned and evaluated to a + * numerical value. + */ + +Addr_T +eval() +{ + register int c, v; + register Addr_T n; + + c = getnb(); + n = 0; + while ((v = digit(c, radix)) >= 0) { + n = n*radix + v; + c = get(); + } + unget(c); + return(n); +} + +/*)Function Addr_T expr(n) + * + * int n a firewall priority; all top + * level calls (from the user) + * should be made with n set to 0. + * + * The function expr() evaluates an expression and + * returns the value. + * + * local variables: + * int c current input text character + * int p current operator priority + * Addr_T v value returned by term() + * Addr_T ve value returned by a + * recursive call to expr() + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * int lkerr error flag + * FILE * stderr c_library + * + * functions called: + * VOID expr() lkeval.c + * int fprintf() c_library + * int getnb() lklex.c + * int oprio() lkeval.c + * VOID term() lkeval.c + * VOID unget() lklex.c + * + * + * side effects: + * An expression is evaluated by scanning the input + * text string. + */ + +Addr_T +expr (n) +{ + register int c, p; + register Addr_T v, ve; + + v = term(); + while (ctype[c = getnb()] & BINOP) { + if ((p = oprio(c)) <= n) + break; + if ((c == '>' || c == '<') && c != get()) { + fprintf(stderr, "Invalid expression"); + lkerr++; + return(v); + } + ve = expr(p); + if (c == '+') { + v += ve; + } else + if (c == '-') { + v -= ve; + } else { + switch (c) { + + case '*': + v *= ve; + break; + + case '/': + v /= ve; + break; + + case '&': + v &= ve; + break; + + case '|': + v |= ve; + break; + + case '%': + v %= ve; + break; + + case '^': + v ^= ve; + break; + + case '<': + v <<= ve; + break; + + case '>': + v >>= ve; + break; + } + } + } + unget(c); + return(v); +} + +/*)Function Addr_T term() + * + * The function term() evaluates a single constant + * or symbol value prefaced by any unary operator + * ( +, -, ~, ', ", >, or < ). + * + * local variables: + * int c current character + * char id[] symbol name + * int n value of digit in current radix + * int r current evaluation radix + * sym * sp pointer to a sym structure + * Addr_T v evaluation value + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * int lkerr error flag + * + * functions called: + * int digit() lkeval.c + * VOID expr() lkeval.c + * int fprintf() c_library + * int get() lklex.c + * VOID getid() lklex.c + * int getmap() lklex.c + * int getnb() lklex.c + * sym * lkpsym() lksym.c + * Addr_T symval() lksym.c + * VOID unget() lklex.c + * + * side effects: + * An arithmetic term is evaluated by scanning input text. + */ + +Addr_T +term() +{ + register int c, r, n; + register Addr_T v; + struct sym *sp; + char id[NCPS]; + + c = getnb(); + if (c == '#') { c = getnb(); } + if (c == '(') { + v = expr(0); + if (getnb() != ')') { + fprintf(stderr, "Missing delimiter"); + lkerr++; + } + return(v); + } + if (c == '-') { + return(0-expr(100)); + } + if (c == '~') { + return(~expr(100)); + } + if (c == '\'') { + return(getmap(-1)&0377); + } + if (c == '\"') { + if (hilo) { + v = (getmap(-1)&0377)<<8; + v |= getmap(-1)&0377; + } else { + v = getmap(-1)&0377; + v |= (getmap(-1)&0377)<<8; + } + return(v); + } + if (c == '>' || c == '<') { + v = expr(100); + if (c == '>') + v >>= 8; + return(v&0377); + } + if (ctype[c] & DIGIT) { + r = 10; + if (c == '0') { + c = get(); + switch (c) { + case 'b': + case 'B': + r = 2; + c = get(); + break; + case '@': + case 'o': + case 'O': + case 'q': + case 'Q': + r = 8; + c = get(); + break; + case 'd': + case 'D': + r = 10; + c = get(); + break; + case 'h': + case 'H': + case 'x': + case 'X': + r = 16; + c = get(); + break; + default: + break; + } + } + v = 0; + while ((n = digit(c, r)) >= 0) { + v = r*v + n; + c = get(); + } + unget(c); + return(v); + } + if (ctype[c] & LETTER) { + getid(id, c); + if ((sp = lkpsym(id, 0)) == NULL) { + fprintf(stderr, "Undefined symbol %8s\n", id); + lkerr++; + return(0); + } else { + return(symval(sp)); + } + } + return(0); +} + +/*)Function int digit(c, r) + * + * int c digit character + * int r current radix + * + * The function digit() returns the value of c + * in the current radix r. If the c value is not + * a number of the current radix then a -1 is returned. + * + * local variables: + * none + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * + * functions called: + * none + * + * side effects: + * none + */ + +int +digit(c, r) +register int c, r; +{ + if (r == 16) { + if (ctype[c] & RAD16) { + if (c >= 'A' && c <= 'F') + return (c - 'A' + 10); + if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + return (c - '0'); + } + } else + if (r == 10) { + if (ctype[c] & RAD10) + return (c - '0'); + } else + if (r == 8) { + if (ctype[c] & RAD8) + return (c - '0'); + } else + if (r == 2) { + if (ctype[c] & RAD2) + return (c - '0'); + } + return (-1); +} + +/*)Function int oprio(c) + * + * int c operator character + * + * The function oprio() returns a relative priority + * for all valid unary and binary operators. + * + * local variables: + * none + * + * global variables: + * none + * + * functions called: + * none + * + * side effects: + * none + */ + +int +oprio(c) +register int c; +{ + if (c == '*' || c == '/' || c == '%') + return (10); + if (c == '+' || c == '-') + return (7); + if (c == '<' || c == '>') + return (5); + if (c == '^') + return (4); + if (c == '&') + return (3); + if (c == '|') + return (1); + return (0); +} diff --git a/as/link/lkhead.c b/as/link/lkhead.c new file mode 100644 index 00000000..b9c5541a --- /dev/null +++ b/as/link/lkhead.c @@ -0,0 +1,154 @@ +/* lkhead.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include "aslink.h" + +/*Module lkhead.c + * + * The module lkhead.c contains the function newhead() which + * creates a head structure and the function module() which + * loads the module name into the current head structure. + * + * lkhead.c contains the following functions: + * VOID newhead() + * VOID module() + * + * lkhead.c contains no local variables. + */ + +/*)Function VOID newhead() + * + * The function newhead() creates a head structure. All head + * structures are linked to form a linked list of head structures + * with the current head structure at the tail of the list. + * + * local variables: + * int i evaluation value + * head * thp temporary pointer + * to a header structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * lfile *cfp The pointer *cfp points to the + * current lfile structure + * head *headp The pointer to the first + * head structure of a linked list + * head *hp Pointer to the current + * head structure + * + * functions called: + * Addr_T expr() lkeval.c + * VOID * new() lksym.c + * VOID lkparea() lkarea.c + * + * side effects: + * A new head structure is created and linked to any + * existing linked head structure. The head structure + * parameters of file handle, number of areas, and number + * of global symbols are loaded into the structure. + * The default area "_abs_" is created when the first + * head structure is created and an areax structure is + * created for every head structure called. + */ + +/* + * Create a new header entry. + * + * H n areas n global symbols + * | | + * | `---- hp->h_nglob + * `------------ hp->h_narea + * + */ +VOID +newhead() +{ + register int i; + struct head *thp; + + hp = (struct head *) new (sizeof(struct head)); + if (headp == NULL) { + headp = hp; + } else { + thp = headp; + while (thp->h_hp) + thp = thp->h_hp; + thp->h_hp = hp; + } + /* + * Set file pointer + */ + hp->h_lfile = cfp; + /* + * Evaluate and build Area pointer list + */ + i = hp->h_narea = eval(); + if (i) + hp->a_list = (struct areax **) new (i*sizeof(struct areax *)); + /* + * Evaluate and build Global symbol pointer list + */ + skip(-1); + i = hp->h_nglob = eval(); + if (i) + hp->s_list = (struct sym **) new (i*sizeof(struct sym *)); + /* + * Setup Absolute DEF linkage. + */ + lkparea(_abs_); + ap->a_flag = A_ABS; + axp->a_addr = 0; +} + +/*)Function VOID module() + * + * The function module() copies the module name into + * the current head structure. + * + * local variables: + * char id[] module id string + * + * global variables: + * head *headp The pointer to the first + * head structure of a linked list + * head *hp Pointer to the current + * head structure + * int lkerr error flag + * FILE * stderr c_library + * + * functions called: + * int fprintf() c_library + * VOID getid() lklex.c + * char * strncpy() c_library + * + * side effects: + * The module name is copied into the head structure. + */ + +/* + * Module Name + */ +VOID +module() +{ + char id[NCPS]; + + if (headp) { + getid(id, -1); + strncpy(hp->m_id, id, NCPS); + } else { + fprintf(stderr, "No header defined\n"); + lkerr++; + } +} diff --git a/as/link/lklex.c b/as/link/lklex.c new file mode 100644 index 00000000..73093ce9 --- /dev/null +++ b/as/link/lklex.c @@ -0,0 +1,639 @@ +/* lklex.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include "aslink.h" + +/*)Module lklex.c + * + * The module lklex.c contains the general lexical analysis + * functions used to scan the text lines from the .rel files. + * + * lklex.c contains the fllowing functions: + * char endline() + * char get() + * VOID getfid() + * VOID getid() + * VOID getSid() + * int lk_getline() + * int getmap() + * char getnb() + * int more() + * VOID skip() + * VOID unget() + * + * lklex.c contains no local variables. + */ + +/*)Function VOID getid(id,c) + * + * char * id a pointer to a string of + * maximum length NCPS + * int c mode flag + * >=0 this is first character to + * copy to the string buffer + * <0 skip white space + * + * The function getid() scans the current input text line + * from the current position copying the next LETTER | DIGIT string + * into the external string buffer (id). The string ends when a non + * LETTER or DIGIT character is found. The maximum number of + * characters copied is NCPS. If the input string is larger than + * NCPS characters then the string is truncated, if the input string + * is shorter than NCPS characters then the string is NULL filled. + * If the mode argument (c) is >=0 then (c) is the first character + * copied to the string buffer, if (c) is <0 then intervening white + * space (SPACES and TABS) are skipped. + * + * local variables: + * char * p pointer to external string buffer + * int c current character value + * + * global variables: + * char ctype[] a character array which defines the + * type of character being processed. + * This index is the character + * being processed. + * + * called functions: + * char get() lklex.c + * char getnb() lklex.c + * VOID unget() lklex.c + * + * side effects: + * use of getnb(), get(), and unget() updates the + * global pointer ip the position in the current + * input text line. + */ + +VOID +getid(id, c) +register int c; +char *id; +{ + register char *p; + + if (c < 0) { + c = getnb(); + } + p = id; + do { + if (p < &id[NCPS]) + *p++ = c; + } while (ctype[c=get()] & (LETTER|DIGIT)); + unget(c); + while (p < &id[NCPS]) + *p++ = 0; +} + +/*)Function VOID getSid (char *id) + * + * char * id a pointer to a string of + * maximum length NCPS + * + * getSid is derived from getid. It is called from newsym() + * in lksym.c, when an S-record has to be scanned. getSid accepts + * much more characters than getid, which is necessary for SDCC. + * + * The function getSid() scans the current input text line + * from the current position copying the next string + * into the external string buffer (id). The string ends when a space + * character (space, tab, \0) is found. The maximum number of + * characters copied is NCPS. If the input string is larger than + * NCPS characters then the string is truncated, if the input string + * is shorter than NCPS characters then the string is NULL filled. + * Intervening white space (SPACES and TABS) are skipped. + * + * local variables: + * char * p pointer to external string buffer + * int c current character value + * + * global variables: + * char ctype[] a character array which defines the + * type of character being processed. + * This index is the character + * being processed. + * + * called functions: + * char get() lklex.c + * char getnb() lklex.c + * VOID unget() lklex.c + * + * side effects: + * use of getnb(), get(), and unget() updates the + * global pointer ip the position in the current + * input text line. + */ + +VOID +getSid (char *id) +{ + register int c; + register char *p; + + c = getnb(); + p = id; + do { + if (p < &id[NCPS]) + *p++ = c; + c = get(); + } while (c != '\0' && c != ' ' && c != '\t'); + unget(c); + while (p < &id[NCPS]) + *p++ = 0; +} + +/*)Function VOID getfid(fid,c) + * + * char * str a pointer to a string of + * maximum length PATH_MAX + * int c this is first character to + * copy to the string buffer + * + * The function getfid() scans the current input text line from + * the current position copying the next string into the external + * string buffer (str). The string ends when end of line is found. + * Trailing spacers are removed. The maximum number of characters + * copied is PATH_MAX. If the input string is larger than PATH_MAX + * characters then the string is truncated. The string is NULL + * terminated. + * + * local variables: + * char * p pointer to external string buffer + * int c current character value + * + * global variables: + * char ctype[] a character array which defines the + * type of character being processed. + * This index is the character + * being processed. + * + * called functions: + * char get() lklex.c + * + * side effects: + * use of get() updates the global pointer ip + * the position in the current input text line. + */ + +VOID +getfid(str, c) +register int c; +char *str; +{ + register char *p; + + p = str; + do + { + if (p < &str[PATH_MAX-1]) + *p++ = c; + c = get(); + if (c == ';') + while (c) + c = get(); + } while (c); + /* trim trailing spaces */ + --p; + while (p >= str && ctype[(int)*p] == SPACE) + --p; + /* terminate the string */ + *(++p) = '\0'; +} + +/*)Function char getnb() + * + * The function getnb() scans the current input text + * line returning the first character not a SPACE or TAB. + * + * local variables: + * int c current character from input + * + * global variables: + * none + * + * called functions: + * char get() lklex.c + * + * side effects: + * use of get() updates the global pointer ip, the position + * in the current input text line + */ + +char +getnb() +{ + register int c; + + while ((c=get())==' ' || c=='\t') + ; + return (c); +} + +/*)Function VOID skip() + * + * The function skip() scans the input text skipping all + * letters and digits. + * + * local variables: + * none + * + * global variables: + * char ctype[] array of character types, one per + * ASCII character + * + * functions called: + * char get() lklex.c + * char getnb() lklex.c + * VOID unget() lklex.c + * + * side effects: + * Input letters and digits are skipped. + */ + +VOID +skip(c) +register int c; +{ + if (c < 0) + c = getnb(); + while (ctype[c=get()] & (LETTER|DIGIT)) { ; } + unget(c); +} + +/*)Function char get() + * + * The function get() returns the next character in the + * input text line, at the end of the line a + * NULL character is returned. + * + * local variables: + * int c current character from + * input text line + * + * global variables: + * char * ip pointer into the current + * input text line + * + * called functions: + * none + * + * side effects: + * updates ip to the next character position in the + * input text line. If ip is at the end of the + * line, ip is not updated. + */ + +char +get() +{ + register int c; + + if ((c = *ip) != 0) + ++ip; + return (c); +} + +/*)Function VOID unget(c) + * + * int c value of last character + * read from input text line + * + * If (c) is not a NULL character then the global pointer ip + * is updated to point to the preceeding character in the + * input text line. + * + * NOTE: This function does not push the character (c) + * back into the input text line, only + * the pointer ip is changed. + * + * local variables: + * int c last character read + * from input text line + * + * global variables: + * char * ip position into the current + * input text line + * + * called functions: + * none + * + * side effects: + * ip decremented by 1 character position + */ + +VOID +unget(c) +{ + if (c != 0) + --ip; +} + +/*)Function int getmap(d) + * + * int d value to compare with the + * input text line character + * + * The function getmap() converts the 'C' style characters \b, \f, + * \n, \r, and \t to their equivalent ascii values and also + * converts 'C' style octal constants '\123' to their equivalent + * numeric values. If the first character is equivalent to (d) then + * a (-1) is returned, if the end of the line is detected then + * a 'q' error terminates the parse for this line, or if the first + * character is not a \ then the character value is returned. + * + * local variables: + * int c value of character + * from input text line + * int n looping counter + * int v current value of numeric conversion + * + * global variables: + * none + * + * called functions: + * char get() lklex.c + * VOID unget() lklex.c + * + * side effects: + * use of get() updates the global pointer ip the position + * in the current input text line + */ + +int +getmap(d) +{ + register int c, n, v; + + if ((c = get()) == '\0') + return (-1); + if (c == d) + return (-1); + if (c == '\\') { + c = get(); + switch (c) { + + case 'b': + c = '\b'; + break; + + case 'f': + c = '\f'; + break; + + case 'n': + c = '\n'; + break; + + case 'r': + c = '\r'; + break; + + case 't': + c = '\t'; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + n = 0; + v = 0; + while (++n<=3 && c>='0' && c<='7') { + v = (v<<3) + c - '0'; + c = get(); + } + unget(c); + c = v; + break; + } + } + return (c); +} + +/*)Function int lk_getline() + * + * The function lk_getline() reads a line of input text from a + * .rel source text file, a .lnk command file or from stdin. + * Lines of text are processed from a single .lnk file or + * multiple .rel files until all files have been read. + * The input text line is copied into the global string ib[] + * and converted to a NULL terminated string. The function + * lk_getline() returns a (1) after succesfully reading a line + * or a (0) if all files have been read. + * This function also opens each input .lst file and output + * .rst file as each .rel file is processed. + * + * local variables: + * int i string length + * int ftype file type + * char * fid file name + * + * global variables: + * lfile *cfp The pointer *cfp points to the + * current lfile structure + * lfile *filep The pointer *filep points to the + * beginning of a linked list of + * lfile structures. + * int gline get a line from the LST file + * to translate for the RST file + * char ib[NINPUT] REL file text line + * int pass linker pass number + * int pflag print linker command file flag + * FILE *rfp The file handle to the current + * output RST file + * FILE *sfp The file handle sfp points to the + * currently open file + * FILE * stdin c_library + * FILE * stdout c_library + * FILE *tfp The file handle to the current + * LST file being scanned + * int uflag update listing flag + * + * called functions: + * FILE * afile() lkmain.c + * int fclose() c_library + * char * fgets() c_library + * int fprintf() c_library + * VOID lkulist() lklist.c + * VOID lkexit() lkmain.c + * int strlen() c_library + * + * side effects: + * The input stream is scanned. The .rel files will be + * opened and closed sequentially scanning each in turn. + */ + +int +lk_getline() +{ + register int ftype; + register char *fid; + +loop: if (pflag && cfp && cfp->f_type == F_STD) + fprintf(stdout, "ASlink >> "); + + if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) { + if (sfp) { + fclose(sfp); + sfp = NULL; + lkulist(0); + } + if (cfp == NULL) { + cfp = filep; + } else { + cfp = cfp->f_flp; + } + if (cfp) { + ftype = cfp->f_type; + fid = cfp->f_idp; + if (ftype == F_STD) { + sfp = stdin; + } else + if (ftype == F_LNK) { + sfp = afile(fid, "lnk", 0); + } else + if (ftype == F_REL) { + sfp = afile(fid, "rel", 0); + /* if a .cdb file exists then copy it over */ + if (dflag && sfp && dfp && pass == 0) { + FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002 + if (xfp) { + copyfile(dfp,xfp); + fclose(xfp); + } + } + if (uflag && pass != 0) { + SaveLinkedFilePath(fid); //Save the linked path for aomf51 + if ((tfp = afile(fid, "lst", 0)) != NULL) { + if ((rfp = afile(fid, "rst", 1)) == NULL) { + fclose(tfp); + tfp = NULL; + } + } + } + gline = 1; + } else { + fprintf(stderr, "Invalid file type\n"); + lkexit(1); + } + if (sfp == NULL) { + lkexit(1); + } + goto loop; + } else { + filep = NULL; + return(0); + } + } + chop_crlf(ib); + return (1); +} + +/*)Function int more() + * + * The function more() scans the input text line + * skipping white space (SPACES and TABS) and returns a (0) + * if the end of the line or a comment delimeter (;) is found, + * or a (1) if their are additional characters in the line. + * + * local variables: + * int c next character from + * the input text line + * + * global variables: + * none + * + * called functions: + * char getnb() lklex.c + * VOID unget() lklex.c + * + * side effects: + * use of getnb() and unget() updates the global pointer ip + * the position in the current input text line + */ + +int +more() +{ + register int c; + + c = getnb(); + unget(c); + return( (c == '\0' || c == ';') ? 0 : 1 ); +} + +/*)Function char endline() + * + * The function endline() scans the input text line + * skipping white space (SPACES and TABS) and returns the next + * character or a (0) if the end of the line is found or a + * comment delimiter (;) is found. + * + * local variables: + * int c next character from + * the input text line + * + * global variables: + * none + * + * called functions: + * char getnb() lklex.c + * + * side effects: + * Use of getnb() updates the global pointer ip the + * position in the current input text line. + */ + +char +endline() +{ + register int c; + + c = getnb(); + return( (c == '\0' || c == ';') ? 0 : c ); +} + +/*)Function VOID chop_crlf(str) + * + * char *str string to chop + * + * The function chop_crlf() removes trailing LF or CR/LF from + * str, if present. + * + * local variables: + * int i string length + * + * global variables: + * none + * + * functions called: + * none + * + * side effects: + * none + */ + +VOID +chop_crlf(str) +char *str; +{ + register int i; + + i = strlen(str); + if (i >= 1 && str[i-1] == '\n') str[i-1] = 0; + if (i >= 2 && str[i-2] == '\r') str[i-2] = 0; +} diff --git a/as/link/lklist.c b/as/link/lklist.c new file mode 100644 index 00000000..5325ec89 --- /dev/null +++ b/as/link/lklist.c @@ -0,0 +1,1099 @@ +/* lklist.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + * + * 28-Oct-97 JLH: + * - lstarea: show s_id as string rather than array [NCPS] + * - lstarea: show a_id as string rather than array [NCPS] + * 31-Oct-97 JLH: add NoICE output file genration in lstarea + * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output + */ + +#include +#include +#include +#include "aslink.h" + +/*)Module lklist.c + * + * The module lklist.c contains the functions which + * output the linker .map file and produce a relocated + * listing .rst file. + * + * lklist.c contains the following functions: + * int dgt() + * VOID lstarea() + * VOID lkulist() + * VOID lkalist() + * VOID lkglist() + * VOID newpag() + * VOID slew() + * + * lklist.c contains no local variables. + */ + +/*)Function VOID slew(fp) + * + * FILE * fp output file handle + * + * The function slew() increments the page line counter. + * If the number of lines exceeds the maximum number of + * lines per page then a page skip and a page header are + * output. + * + * local variables: + * int i loop counter + * + * global variables: + * int lop current line number on page + * int xflag Map file radix type flag + * + * functions called: + * int fprintf() c_library + * VOID newpag() lklist.c + * + * side effects: + * The page line and the page count may be updated. + */ + +VOID +slew(fp) +FILE *fp; +{ + register int i; + + if (lop++ >= NLPP) { + newpag(fp); + if (xflag == 0) { + fprintf(fp, "Hexadecimal\n\n"); + } else + if (xflag == 1) { + fprintf(fp, "Octal\n\n"); + } else + if (xflag == 2) { + fprintf(fp, "Decimal\n\n"); + } + fprintf(fp, "Area Addr Size"); + fprintf(fp, " Decimal Bytes (Attributes)\n"); + for(i=0;i<4;++i) + fprintf(fp, " Value--Global"); + fprintf(fp, "\n\n"); + lop += 6; + } +} + +/*)Function VOID newpag() + * + * The function newpag() outputs a page skip, writes the + * first page header line, sets the line count to 1, and + * increments the page counter. + * + * local variables: + * none + * + * global variables: + * int lop current line number on page + * int page current page number + * + * functions called: + * int fprintf() c_library + * + * side effects: + * The page and line counters are updated. + */ + +VOID +newpag(fp) +FILE *fp; +{ + fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page); + lop = 1; +} + +/* Used for qsort call in lstsym */ +static int _cmpSymByAddr(const void *p1, const void *p2) +{ + struct sym **s1 = (struct sym **)(p1); + struct sym **s2 = (struct sym **)(p2); + int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) - + ((*s2)->s_addr + (*s2)->s_axp->a_addr); + + /* Sort first by address, then by name. */ + if (delta) + { + return delta; + } + return strcmp((*s1)->s_id,(*s2)->s_id); +} + + +#if NCPS-8 + +/* NCPS != 8 */ +/*)Function VOID lstarea(xp) + * + * area * xp pointer to an area structure + * + * The function lstarea() creates the linker map output for + * the area specified by pointer xp. The generated output + * area header includes the area name, starting address, + * size of area, number of words (in decimal), and the + * area attributes. The symbols defined in this area are + * sorted by ascending address and output one per line + * in the selected radix. + * + * local variables: + * areax * oxp pointer to an area extension structure + * int c character value + * int i loop counter + * int j bubble sort update status + * char * ptr pointer to an id string + * int nmsym number of symbols in area + * Addr_T a0 temporary + * Addr_T ai temporary + * Addr_T aj temporary + * sym * sp pointer to a symbol structure + * sym ** p pointer to an array of + * pointers to symbol structures + * + * global variables: + * FILE *mfp Map output file handle + * sym *symhash[NHASH] array of pointers to NHASH + * linked symbol lists + * int xflag Map file radix type flag + * + * functions called: + * int fprintf() c_library + * VOID free() c_library + * char * malloc() c_library + * char putc() c_library + * VOID slew() lklist.c + * + * side effects: + * Map output generated. + */ + +VOID +lstarea(xp) +struct area *xp; +{ + register struct areax *oxp; + register int i; + /* int j; */ + register char *ptr; + int nmsym; + /* Addr_T a0; */ + Addr_T ai, aj; + struct sym *sp; + struct sym **p; + int memPage; + + putc('\n', mfp); + if (xflag == 0) { + fprintf(mfp, "Hexadecimal\n\n"); + } else + if (xflag == 1) { + fprintf(mfp, "Octal\n\n"); + } else + if (xflag == 2) { + fprintf(mfp, "Decimal\n\n"); + } + fprintf(mfp, "Area "); + fprintf(mfp, "Addr Size Decimal %s (Attributes)\n", + (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/ + fprintf(mfp, "-------------------------------- "); + fprintf(mfp, "---- ---- ------- ----- ------------\n"); + /* + * Output Area Header + */ + ptr = &xp->a_id[0]; + fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */ + ai = xp->a_addr; + aj = xp->a_size; + if (xflag == 0) { + fprintf(mfp, " %04X %04X", ai, aj); + } else + if (xflag == 1) { + fprintf(mfp, " %06o %06o", ai, aj); + } else + if (xflag == 2) { + fprintf(mfp, " %05u %05u", ai, aj); + } + fprintf(mfp, " = %6u. %s ", aj, + (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/ + if (xp->a_flag & A_ABS) { + fprintf(mfp, "(ABS"); + } else { + fprintf(mfp, "(REL"); + } + if (xp->a_flag & A_OVR) { + fprintf(mfp, ",OVR"); + } else { + fprintf(mfp, ",CON"); + } + if (xp->a_flag & A_PAG) { + fprintf(mfp, ",PAG"); + } + + memPage = 0x00; + if (xp->a_flag & A_CODE) { + fprintf(mfp, ",CODE"); + memPage = 0x0C; + } + if (xp->a_flag & A_XDATA) { + fprintf(mfp, ",XDATA"); + memPage = 0x0D; + } + if (xp->a_flag & A_BIT) { + fprintf(mfp, ",BIT"); + memPage = 0x0B; + } + fprintf(mfp, ")"); + if (xp->a_flag & A_PAG) { + ai = (ai & 0xFF); + aj = (aj > 256); + if (ai || aj) { fprintf(mfp, " "); } + if (ai) { fprintf(mfp, " Boundary"); } + if (ai & aj) { fprintf(mfp, " /"); } + if (aj) { fprintf(mfp, " Length"); } + if (ai || aj) { fprintf(mfp, " Error"); } + } + + /* + * Find number of symbols in area + */ + nmsym = 0; + oxp = xp->a_axp; + while (oxp) { + for (i=0; is_axp) + ++nmsym; + sp = sp->s_sp; + } + } + oxp = oxp->a_axp; + } + if (nmsym == 0) { + putc('\n', mfp); + return; + } + + /* + * Allocate space for an array of pointers to symbols + * and load array. + */ + if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *))) + == NULL) { + fprintf(mfp, "\nInsufficient space to build Map Segment.\n"); + return; + } + nmsym = 0; + oxp = xp->a_axp; + while (oxp) { + for (i=0; is_axp) { + p[nmsym++] = sp; + } + sp = sp->s_sp; + } + } + oxp = oxp->a_axp; + } + +#if 0 + /* + * Bubble Sort of Addresses in Symbol Table Array + */ + j = 1; + while (j) { + j = 0; + sp = p[0]; + a0 = sp->s_addr + sp->s_axp->a_addr; + for (i=1; is_addr + sp->s_axp->a_addr; + if (a0 > ai) { + j = 1; + p[i] = p[i-1]; + p[i-1] = sp; + } + a0 = ai; + } + } +#else + qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); +#endif + + /* + * Symbol Table Output + */ + + i = 0; + fprintf(mfp, "\n\n"); + fprintf(mfp, " Value Global\n"); + fprintf(mfp, " -------- --------------------------------"); + while (i < nmsym) { + fprintf(mfp, "\n"); + if (memPage != 0) + fprintf(mfp, " %02X:", memPage); + else + fprintf(mfp, " "); + + sp = p[i]; + aj = sp->s_addr + sp->s_axp->a_addr; + if (xflag == 0) { + fprintf(mfp, "%04X ", aj); + } else + if (xflag == 1) { + fprintf(mfp, "%06o ", aj); + } else + if (xflag == 2) { + fprintf(mfp, "%05u ", aj); + } + ptr = &sp->s_id[0]; + fprintf(mfp, "%s", ptr ); + + /* if cdb flag set the output cdb Information + and the symbol has a '$' sign in it then */ + if (dflag && + strchr(ptr,'$')) + fprintf(dfp,"L:%s:%X\n",ptr,aj); + + /* NoICE output of symbol */ + if (jflag) DefineNoICE( ptr, aj, memPage ); + + i++; + } + putc('\n', mfp); + free(p); +} + +#else + +/* NCPS == 8 */ +/*)Function VOID lstarea(xp) + * + * area * xp pointer to an area structure + * + * The function lstarea() creates the linker map output for + * the area specified by pointer xp. The generated output + * area header includes the area name, starting address, + * size of area, number of words (in decimal), and the + * area attributes. The symbols defined in this area are + * sorted by ascending address and output four per line + * in the selected radix. + * + * local variables: + * areax * oxp pointer to an area extension structure + * int c character value + * int i loop counter + * int j bubble sort update status + * char * ptr pointer to an id string + * int nmsym number of symbols in area + * Addr_T a0 temporary + * Addr_T ai temporary + * Addr_T aj temporary + * sym * sp pointer to a symbol structure + * sym ** p pointer to an array of + * pointers to symbol structures + * + * global variables: + * FILE *mfp Map output file handle + * sym *symhash[NHASH] array of pointers to NHASH + * linked symbol lists + * int xflag Map file radix type flag + * + * functions called: + * int fprintf() c_library + * VOID free() c_library + * char * malloc() c_library + * char putc() c_library + * VOID slew() lklist.c + * + * side effects: + * Map output generated. + */ + +VOID +lstarea(xp) +struct area *xp; +{ + register struct areax *oxp; + register c, i, j; + register char *ptr; + int nmsym; + Addr_T a0, ai, aj; + struct sym *sp; + struct sym **p; + int page; + + putc('\n', mfp); + slew(mfp); + /* + * Output Area Header + */ + ptr = &xp->a_id[0]; + while (ptr < &xp->a_id[NCPS]) { + if ((c = *ptr++) != 0) { + putc(c, mfp); + } else { + putc(' ', mfp); + } + } + ai = xp->a_addr; + aj = xp->a_size; + if (xflag == 0) { + fprintf(mfp, " %04X %04X", ai, aj); + } else + if (xflag == 1) { + fprintf(mfp, " %06o %06o", ai, aj); + } else + if (xflag == 2) { + fprintf(mfp, " %05u %05u", ai, aj); + } + fprintf(mfp, " = %6u. bytes ", aj); + if (xp->a_flag & A_ABS) { + fprintf(mfp, "(ABS"); + } else { + fprintf(mfp, "(REL"); + } + if (xp->a_flag & A_OVR) { + fprintf(mfp, ",OVR"); + } else { + fprintf(mfp, ",CON"); + } + if (xp->a_flag & A_PAG) { + fprintf(mfp, ",PAG"); + } + + page = 0x00; + if (xp->a_flag & A_CODE) { + fprintf(mfp, ",CODE"); + memPage = 0x0C; + } + if (xp->a_flag & A_XDATA) { + fprintf(mfp, ",XDATA"); + memPage = 0x0D; + } + if (xp->a_flag & A_BIT) { + fprintf(mfp, ",BIT"); + memPage = 0x0B; + } + fprintf(mfp, ")"); + if (xp->a_flag & A_PAG) { + ai = (ai & 0xFF); + aj = (aj > 256); + if (ai || aj) { fprintf(mfp, " "); } + if (ai) { fprintf(mfp, " Boundary"); } + if (ai & aj) { fprintf(mfp, " /"); } + if (aj) { fprintf(mfp, " Length"); } + if (ai || aj) { fprintf(mfp, " Error"); } + } + + /* + * Find number of symbols in area + */ + nmsym = 0; + oxp = xp->a_axp; + while (oxp) { + for (i=0; is_axp) + ++nmsym; + sp = sp->s_sp; + } + } + oxp = oxp->a_axp; + } + if (nmsym == 0) { + putc('\n', mfp); + slew(mfp); + return; + } + + /* + * Allocate space for an array of pointers to symbols + * and load array. + */ + if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *))) + == NULL) { + fprintf(mfp, "\nInsufficient space to build Map Segment.\n"); + slew(mfp); + return; + } + nmsym = 0; + oxp = xp->a_axp; + while (oxp) { + for (i=0; is_axp) { + p[nmsym++] = sp; + } + sp = sp->s_sp; + } + } + oxp = oxp->a_axp; + } + +#if 0 + /* + * Bubble Sort of Addresses in Symbol Table Array + */ + j = 1; + while (j) { + j = 0; + sp = p[0]; + a0 = sp->s_addr + sp->s_axp->a_addr; + for (i=1; is_addr + sp->s_axp->a_addr; + if (a0 > ai) { + j = 1; + p[i] = p[i-1]; + p[i-1] = sp; + } + a0 = ai; + } + } +#else + qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); +#endif + + /* + * Symbol Table Output + */ + i = 0; + while (i < nmsym) { + fprintf(mfp, "\n"); + slew(mfp); + fprintf(mfp, " "); + sp = p[i]; + aj = sp->s_addr + sp->s_axp->a_addr; + if (xflag == 0) { + fprintf(mfp, " %04X ", aj); + } else + if (xflag == 1) { + fprintf(mfp, "%06o ", aj); + } else + if (xflag == 2) { + fprintf(mfp, " %05u ", aj); + } + ptr = &sp->s_id[0]; + fprintf(mfp, "%s", ptr ); + + /* NoICE output of symbol */ + if (jflag) DefineNoICE( ptr, aj, memPage ); + } + putc('\n', mfp); + free(p); + slew(mfp); +} +#endif + +/*)Function VOID lkulist(i) + * + * int i i # 0 process LST to RST file + * i = 0 copy remainder of LST file + * to RST file and close files + * + * The function lkulist() creates a relocated listing (.rst) + * output file from the ASxxxx assembler listing (.lst) + * files. The .lst file's program address and code bytes + * are changed to reflect the changes made by ASlink as + * the .rel files are combined into a single relocated + * output file. + * + * local variables: + * Addr_T pc current program counter address + * + * global variables: + * int hilo byte order + * int gline get a line from the LST file + * to translate for the RST file + * char rb[] read listing file text line + * FILE *rfp The file handle to the current + * output RST file + * int rtcnt count of data words + * int rtflg[] output the data flag + * Addr_T rtval[] relocated data + * FILE *tfp The file handle to the current + * LST file being scanned + * + * functions called: + * int fclose() c_library + * int fgets() c_library + * int fprintf() c_library + * VOID lkalist() lklist.c + * VOID lkglist() lklist.c + * + * side effects: + * A .rst file is created for each available .lst + * file associated with a .rel file. + */ + +VOID +lkulist(i) +int i; +{ + Addr_T pc; + + /* + * Exit if listing file is not open + */ + if (tfp == NULL) + return; + + /* + * Normal processing of LST to RST + */ + if (i) { + /* + * Evaluate current code address + */ + if (hilo == 0) { + pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF); + } else { + pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF); + } + + /* + * Line with only address + */ + if (rtcnt == 2) { + lkalist(pc); + + /* + * Line with address and code + */ + } else { + for (i=2; i < rtcnt; i++) { + if (rtflg[i]) { + lkglist(pc++, rtval[i] & 0xFF); + } + } + } + + /* + * Copy remainder of LST to RST + */ + } else { + if (gline == 0) + fprintf(rfp, "%s", rb); + + while (fgets(rb, sizeof(rb), tfp) != 0) { + fprintf(rfp, "%s", rb); + } + fclose(tfp); + tfp = NULL; + fclose(rfp); + rfp = NULL; + } +} + +/*)Function VOID lkalist(pc) + * + * int pc current program counter value + * + * The function lkalist() performs the following functions: + * + * (1) if the value of gline = 0 then the current listing + * file line is copied to the relocated listing file output. + * + * (2) the listing file is read line by line and copied to + * the relocated listing file until a valid source + * line number and a program counter value of the correct + * radix is found. The new relocated pc value is substituted + * and the line is written to the RST file. + * + * local variables: + * int i loop counter + * char str[] temporary string + * + * global variables: + * int gcntr data byte counter + * int gline get a line from the LST file + * to translate for the RST file + * char rb[] read listing file text line + * char *rp pointer to listing file text line + * FILE *rfp The file handle to the current + * output RST file + * FILE *tfp The file handle to the current + * LST file being scanned + * + * functions called: + * int dgt() lklist.c + * int fclose() c_library + * int fgets() c_library + * int fprintf() c_library + * int sprintf() c_library + * char * strncpy() c_library + * + * side effects: + * Lines of the LST file are copied to the RST file, + * the last line copied has the code address + * updated to reflect the program relocation. + */ + +VOID +lkalist(pc) +Addr_T pc; +{ + char str[8]; + int i; + + /* + * Exit if listing file is not open + */ +loop: if (tfp == NULL) + return; + + /* + * Copy current LST to RST + */ + if (gline == 0) { + fprintf(rfp, "%s", rb); + gline = 1; + } + + /* + * Clear text line buffer + */ + for (i=0,rp=rb; i +#include +#include +#include "aslink.h" + +static void DefineGlobal( char *name, Addr_T value, int page ); +static void DefineScoped( char *name, Addr_T value, int page ); +static void DefineFile( char *name, Addr_T value, int page ); +static void DefineFunction( char *name, Addr_T value, int page ); +static void DefineStaticFunction( char *name, Addr_T value, int page ); +static void DefineEndFunction( Addr_T value, int page ); +static void DefineLine( char *lineString, Addr_T value, int page ); +static void PagedAddress( Addr_T value, int page ); + +/* + * Called from lstarea in lklist.c for each symbol. + * + * Generates appropriate NoICE commands into output file, if any is open + * + */ +void DefineNoICE( char *name, Addr_T value, int page ) +{ + char token1[NCPS]; /* parse for file.function.symbol */ + char token2[NCPS]; + char token3[NCPS]; + // char token4[NCPS]; + char sep1, sep2; + int j, level; + + /* no output if file is not open */ + if (jfp == NULL) return; + + j = sscanf( name, "%[^.]%c%[^.]%c%s", + token1, &sep1, token2, &sep2, token3 ); + switch (j) + { + /* file.function.symbol, or file.function..SPECIAL */ + case 5: + DefineFile( token1, 0, 0 ); + if (token3[0] == '.') + { + if (strcmp( token3, ".FN" ) == 0) + { + /* Global function */ + DefineFunction( token2, value, page ); + } + else if (strcmp( token3, ".SFN" ) == 0) + { + /* Static (file-scope) function */ + DefineStaticFunction( token2, value, page ); + } + else if (strcmp( token3, ".EFN" ) == 0) + { + /* End of function */ + DefineEndFunction( value, page ); + } + } + else + { + /* Function-scope var. */ + DefineFunction( token2, 0, 0 ); + + /* Look for optional level integer */ + j = sscanf( token3, "%[^.]%c%u", token1, &sep1, &level ); + if ((j == 3) && (level != 0)) + { + sprintf( &token1[ strlen(token1) ], "_%u", level ); + } + DefineScoped( token1, value, page ); + } + break; + + /* file.func. is illegal */ + case 4: + break; + + /* either file.symbol or file.line# */ + case 3: + DefineFile( token1, 0, 0 ); + if ((token2[0] >= '0') && (token2[0] <= '9')) + { + /* Line number */ + DefineLine( token2, value, page ); + } + else + { + /* File-scope symbol. (Kill any function) */ + DefineEndFunction( 0, 0 ); + DefineScoped( token2, value, page ); + } + break; + + /* symbol. is illegal */ + case 2: + break; + + /* just a symbol */ + case 1: + DefineGlobal( token1, value, page ); + break; + } +} + +static char currentFile[NCPS]; +static char currentFunction[NCPS]; + +/* + * static function: + * Define "name" as a global symbol + */ +void DefineGlobal( char *name, Addr_T value, int page ) +{ + fprintf( jfp, "DEF %s ", name ); + PagedAddress( value, page ); +} + +/* + * static function: + * Define "name" as a static (scoped) symbol + */ +void DefineScoped( char *name, Addr_T value, int page ) +{ + fprintf( jfp, "DEFS %s ", name ); + PagedAddress( value, page ); +} + +/* + * static function: + * Define "name" as the current file + */ +void DefineFile( char *name, Addr_T value, int page ) +{ + if (as_strcmpi( name, currentFile ) != 0) + { + strcpy( currentFile, name ); + if (value != 0) + { + fprintf( jfp, "FILE %s ", name ); + PagedAddress( value, page ); + } + else + { + fprintf( jfp, "FILE %s\n", name ); + } + } +} + +/* + * static function: + * Define "name" as the current function + */ +void DefineFunction( char *name, Addr_T value, int page ) +{ + if (as_strcmpi( name, currentFunction ) != 0) + { + strcpy( currentFunction, name ); + if (value != 0) + { + fprintf( jfp, "DEF %s ", name ); + PagedAddress( value, page ); + fprintf( jfp, "FUNC %s ", name ); + PagedAddress( value, page ); + } + else + { + fprintf( jfp, "FUNC %s\n", name ); + } + } +} + +/* + * static function: + * Define "name" as the current static (scoped) function + */ +void DefineStaticFunction( char *name, Addr_T value, int page ) +{ + if (as_strcmpi( name, currentFunction ) != 0) + { + strcpy( currentFunction, name ); + if (value != 0) + { + fprintf( jfp, "DEFS %s ", name ); + PagedAddress( value, page ); + fprintf( jfp, "SFUNC %s ", name ); + PagedAddress( value, page ); + } + else + { + fprintf( jfp, "SFUNC %s\n", name ); + } + } +} + +/* + * static function: + * Define the end of the current function + */ +void DefineEndFunction( Addr_T value, int page ) +{ + if (currentFunction[0] != 0) + { + if (value != 0) + { + fprintf( jfp, "ENDF " ); + PagedAddress( value, page ); + } + else + { + fprintf( jfp, "ENDF\n" ); + } + + currentFunction[0] = 0; + } +} + +/* + * static function: + * Define "lineNumber" as a line in the current file + */ +void DefineLine( char *lineString, Addr_T value, int page ) +{ + int indigit, lineNumber = 0; + + while( (indigit=digit( *lineString++, 10 )) >= 0) + { + lineNumber = 10*lineNumber + indigit; + } + fprintf( jfp, "LINE %u ", lineNumber ); + PagedAddress( value, page ); +} + +void PagedAddress( Addr_T value, int page ) +{ + fprintf( jfp, "%X:0x%X\n", page, value ); +} diff --git a/as/link/lksym.c b/as/link/lksym.c new file mode 100644 index 00000000..526e7189 --- /dev/null +++ b/as/link/lksym.c @@ -0,0 +1,484 @@ +/* lksym.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + * + * 28-Oct-97 JLH: + * - lkpsym: Use StoreString for sym construction + * - change symeq() to do length-independent string compare + * - change hash() to do length-independent hash calculation + */ + +#include +#include +#include +#include "aslink.h" + +/*)Module lksym.c + * + * The module lksym.c contains the functions that operate + * on the symbol structures. + * + * lksym.c contains the following functions: + * int hash() + * sym * lkpsym() + * VOID * new() + * sym * newsym() + * VOID symdef() + * int symeq() + * VOID syminit() + * VOID symmod() + * Addr_T symval() + * + * lksym.c contains no local/static variables. + */ + +/*)Function VOID syminit() + * + * The function syminit() is called to clear the hashtable. + * + * local variables: + * int h computed hash value + * sym ** spp pointer to an array of + * sym structure pointers + * + * global variables: + * sym * symhash[] array of pointers to NHASH + * linked symbol lists + * + * functions called: + * none + * + * side effects: + * (1) The symbol hash tables are cleared + */ + +VOID +syminit() +{ + // register int h; + struct sym **spp; + + spp = &symhash[0]; + while (spp < &symhash[NHASH]) + *spp++ = NULL; +} + +/*)Function sym * newsym() + * + * The function newsym() is called to evaluate the symbol + * definition/reference directive from the .rel file(s). + * If the symbol is not found in the symbol table a new + * symbol structure is created. Evaluation of the + * directive determines if this is a reference or a definition. + * Multiple definitions of the same variable will be flagged + * as an error if the values are not identical. A symbol + * definition places the symbol value and area extension + * into the symbols data structure. And finally, a pointer + * to the symbol structure is placed into the head structure + * symbol list. Refer to the description of the header, symbol, + * area, and areax structures in lkdata.c for structure and + * linkage details. + * + * local variables: + * int c character from input text + * int i evaluation value + * char id[] symbol name + * int nglob number of symbols in this header + * sym * tsp pointer to symbol structure + * sym ** s list of pointers to symbol structures + * + * global variables: + * areax *axp Pointer to the current + * areax structure + * head *headp The pointer to the first + * head structure of a linked list + * int lkerr error flag + * + * functions called: + * Addr_T eval() lkeval.c + * VOID exit() c_library + * int fprintf() c_library + * char getSid() lklex.c + * char get() lklex.c + * char getnb() lklex.c + * sym * lkpsym() lksym.c + * + * side effects: + * A symbol structure is created and/or modified. + * If structure space allocation fails linker will abort. + * Several severe errors (these are internal errors + * indicating a corrupted .rel file or corrupted + * assembler or linker) will terminated the linker. + */ + +/* + * Find/Create a global symbol entry. + * + * S xxxxxx Defnnnn + * | | | + * | | `-- sp->s_addr + * | `----- sp->s_type + * `------------ sp->s_id + * + */ +struct sym * +newsym() +{ + register unsigned i ; + register unsigned nglob ; + register int c ; + struct sym *tsp; + struct sym **s; + char id[NCPS]; + + getSid(id); // old: getid(id, -1); + tsp = lkpsym(id, 1); + c = getnb();get();get(); + if (c == 'R') { + tsp->s_type |= S_REF; + if (eval()) { + fprintf(stderr, "Non zero S_REF\n"); + lkerr++; + } + } else + if (c == 'D') { + i = eval(); + if (tsp->s_type & S_DEF && tsp->s_addr != i) { + fprintf(stderr, "Multiple definition of %8s\n", id); + lkerr++; + } + tsp->s_type |= S_DEF; + /* + * Set value and area extension link. + */ + tsp->s_addr = i; + tsp->s_axp = axp; + } else { + fprintf(stderr, "Invalid symbol type %c for %8s\n", c, id); + lkexit(1); + } + /* + * Place pointer in header symbol list + */ + if (headp == NULL) { + fprintf(stderr, "No header defined\n"); + lkexit(1); + } + nglob = hp->h_nglob; + s = hp->s_list; + for (i=0; i < nglob ;++i) { + if (s[i] == NULL) { + s[i] = tsp; + return(tsp); + } + } + fprintf(stderr, "Header symbol list overflow\n"); + lkexit(1); + return(0); +} + +/*)Function sym * lkpsym(id,f) + * + * char * id symbol name string + * int f f == 0, lookup only + * f != 0, create if not found + * + * The function lookup() searches the symbol hash tables for + * a symbol name match returning a pointer to the sym structure. + * If the symbol is not found then a sym structure is created, + * initialized, and linked to the appropriate hash table if f != 0. + * A pointer to this new sym structure is returned or a NULL + * pointer is returned if f == 0. + * + * local variables: + * int h computed hash value + * sym * sp pointer to a sym structure + * + * global varaibles: + * sym * symhash[] array of pointers to NHASH + * linked symbol lists + * + * functions called: + * int hash() lksym.c + * VOID * new() lksym.c + * int symeq() lksym.c + * + * side effects: + * If the function new() fails to allocate space + * for the new sym structure the linker terminates. + */ + +struct sym * +lkpsym(id, f) +char *id; +{ + register struct sym *sp; + register int h; + + h = hash(id); + sp = symhash[h]; + while (sp != NULL) { + if (symeq(id, sp->s_id)) + return (sp); + sp = sp->s_sp; + } + if (f == 0) + return (NULL); + sp = (struct sym *) new (sizeof(struct sym)); + sp->s_sp = symhash[h]; + symhash[h] = sp; + sp->s_id = StoreString( id ); /* JLH */ + return (sp); +} + +/*)Function Addr_T symval(tsp) + * + * sym * tsp pointer to a symbol structure + * + * The function symval() returns the value of the + * relocated symbol by adding the variable definition + * value to the areax base address. + * + * local variables: + * Addr_T val relocated address value + * + * global variables: + * none + * + * functions called: + * none + * + * side effects: + * none + */ + +Addr_T +symval(tsp) +register struct sym *tsp; +{ + register Addr_T val; + + val = tsp->s_addr; + if (tsp->s_axp) { + val += tsp->s_axp->a_addr; + } + return(val); +} + +/*)Function VOID symdef(fp) + * + * FILE * fp file handle for output + * + * The function symdef() scans the hashed symbol table + * searching for variables referenced but not defined. + * Undefined variables are linked to the default + * area "_CODE" and reported as referenced by the + * appropriate module. + * + * local variables: + * int i hash table index loop variable + * sym * sp pointer to linked symbol structure + * + * global variables: + * area *areap The pointer to the first + * area structure of a linked list + * sym *symhash[NHASH] array of pointers to NHASH + * linked symbol lists + * + * functions called: + * symmod() lksym.c + * + * side effects: + * Undefined variables have their areas set to "_CODE". + */ + +VOID +symdef(fp) +FILE *fp; +{ + register struct sym *sp; + register int i; + + for (i=0; is_axp == NULL) + sp->s_axp = areap->a_axp; + if ((sp->s_type & S_DEF) == 0) + symmod(fp, sp); + sp = sp->s_sp; + } + } +} + +/*)Function VOID symmod(fp,tsp) + * + * FILE * fp output file handle + * sym * tsp pointer to a symbol structure + * + * The function symmod() scans the header structures + * searching for a reference to the symbol structure + * pointer to by tsp. The function then generates an error + * message whichs names the module having referenced the + * undefined variable. + * + * local variables: + * int i loop counter + * sym ** p pointer to a list of pointers + * to symbol structures + * + * global variables: + * head *headp The pointer to the first + * head structure of a linked list + * head *hp Pointer to the current + * head structure + * int lkerr error flag + * + * functions called: + * int fprintf() c_library + * + * side effects: + * Error output generated. + */ + +VOID +symmod(fp, tsp) +FILE *fp; +struct sym *tsp; +{ + register int i; + struct sym **p; + + if ((hp = headp) != NULL) { + while(hp) { + p = hp->s_list; + for (i=0; ih_nglob; ++i) { + if (p[i] == tsp) { + fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id); + fprintf(fp, "referenced by module '%s'\n", hp->m_id); + lkerr++; + } + } + hp = hp->h_hp; + } + } +} + +/*)Function int symeq(p1, p2) + * + * char * p1 name string + * char * p2 name string + * + * The function symeq() compares the two name strings for a match. + * The return value is 1 for a match and 0 for no match. + * + * local variables: + * int h loop counter + * + * global variables: + * char ccase[] an array of characters which + * perform the case translation function + * + * functions called: + * none + * + * side effects: + * none + * + */ + +int +symeq(p1, p2) +register char *p1, *p2; +{ +#if CASE_SENSITIVE + return (strcmp( p1, p2 ) == 0); +#else + return (as_strcmpi( p1, p2 ) == 0); +#endif +} + +/*)Function int hash(p) + * + * char * p pointer to string to hash + * + * The function hash() computes a hash code using the sum + * of all characters mod table size algorithm. + * + * local variables: + * int h accumulated character sum + * int n loop counter + * + * global variables: + * char ccase[] an array of characters which + * perform the case translation function + * + * functions called: + * none + * + * side effects: + * none + * + */ + +int +hash(p) +register char *p; +{ + register int h; + + h = 0; + while (*p) { + +#if CASE_SENSITIVE + h += *p++; +#else + h += ccase[*p++]; +#endif + + }; + return (h&HMASK); +} + +/*)Function VOID * new(n) + * + * unsigned int n allocation size in bytes + * + * The function new() allocates n bytes of space and returns + * a pointer to this memory. If no space is available the + * linker is terminated. + * + * local variables: + * char * p a general pointer + * char * q a general pointer + * + * global variables: + * none + * + * functions called: + * int fprintf() c_library + * VOID * malloc() c_library + * + * side effects: + * Memory is allocated, if allocation fails + * the linker is terminated. + */ + +VOID * +new(n) +unsigned int n; +{ + register char *p; + + if ((p = (char *) calloc(n, 1)) == NULL) { + fprintf(stderr, "Out of space!\n"); + lkexit(1); + } + return (p); +} diff --git a/as/link/mcs51/Makefile.in b/as/link/mcs51/Makefile.in index 1d11f188..071cd958 100644 --- a/as/link/mcs51/Makefile.in +++ b/as/link/mcs51/Makefile.in @@ -37,12 +37,13 @@ CFLAGS = @CFLAGS@ -Wall -DINDEXLIB M_OR_MM = @M_OR_MM@ LDFLAGS = @LDFLAGS@ -LKOBJECTS = lkmain.o lkhead.o lkarea.o lkdata.o \ - lkeval.o lklex.o lksym.o lkrloc.o \ - lklibr.o lklist.o lkihx.o lks19.o \ - lknoice.o lkmem.o lkaomf51.o \ - ../lkstore.o \ - strcmpi.o +LKOBJECTS = lkmain.o lkarea.o lkdata.o \ + lkrloc.o \ + lklibr.o lkihx.o lks19.o \ + lkmem.o lkaomf51.o \ + ../lkeval.o ../lkhead.o ../lklex.o ../lklist.o \ + ../lknoice.o ../lkstore.o ../lksym.o \ + ../../strcmpi.o LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS)) ASLINK = $(top_builddir)bin/aslink$(EXEEXT) diff --git a/as/link/mcs51/aslink.dsp b/as/link/mcs51/aslink.dsp index 9d49a88d..b1c68f33 100644 --- a/as/link/mcs51/aslink.dsp +++ b/as/link/mcs51/aslink.dsp @@ -7,19 +7,19 @@ CFG=aslink - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "aslink.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "aslink.mak" CFG="aslink - Win32 Release" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "aslink - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "aslink - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -55,19 +55,19 @@ LINK32=link.exe !ELSEIF "$(CFG)" == "aslink - Win32 Release" # PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "mcs51\Release" # PROP BASE Intermediate_Dir "mcs51\Release" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 +# PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c -# ADD CPP /nologo /ML /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -77,7 +77,7 @@ LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\aslink.exe" /pdbtype:sept # ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\aslink.exe" /pdbtype:sept -!ENDIF +!ENDIF # Begin Target @@ -100,11 +100,11 @@ SOURCE=.\lkdata.c # End Source File # Begin Source File -SOURCE=.\lkeval.c +SOURCE=..\lkeval.c # End Source File # Begin Source File -SOURCE=.\lkhead.c +SOURCE=..\lkhead.c # End Source File # Begin Source File @@ -112,7 +112,7 @@ SOURCE=.\lkihx.c # End Source File # Begin Source File -SOURCE=.\lklex.c +SOURCE=..\lklex.c # End Source File # Begin Source File @@ -120,7 +120,7 @@ SOURCE=.\lklibr.c # End Source File # Begin Source File -SOURCE=.\lklist.c +SOURCE=..\lklist.c # End Source File # Begin Source File @@ -132,7 +132,7 @@ SOURCE=.\lkmem.c # End Source File # Begin Source File -SOURCE=.\lknoice.c +SOURCE=..\lknoice.c # End Source File # Begin Source File @@ -148,11 +148,11 @@ SOURCE=..\lkstore.c # End Source File # Begin Source File -SOURCE=.\lksym.c +SOURCE=..\lksym.c # End Source File # Begin Source File -SOURCE=.\strcmpi.c +SOURCE=..\..\strcmpi.c # End Source File # End Group # Begin Group "Header Files" @@ -160,11 +160,7 @@ SOURCE=.\strcmpi.c # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File -SOURCE=..\alloc.h -# End Source File -# Begin Source File - -SOURCE=.\aslink.h +SOURCE=..\aslink.h # End Source File # End Group # End Target diff --git a/as/link/mcs51/lkeval.c b/as/link/mcs51/lkeval.c deleted file mode 100644 index 90df0031..00000000 --- a/as/link/mcs51/lkeval.c +++ /dev/null @@ -1,396 +0,0 @@ -/* lkeval.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*)Module lkeval.c - * - * The module lkeval.c contains the routines to evaluate - * arithmetic/numerical expressions. The functions in - * lkeval.c perform a recursive evaluation of the arithmetic - * expression read from the input text line. - * The expression may include binary/unary operators, brackets, - * symbols, labels, and constants in hexadecimal, decimal, octal - * and binary. Arithmetic operations are prioritized and - * evaluated by normal arithmetic conventions. - * - * lkeval.c contains the following functions: - * int digit() - * Addr_T eval() - * Addr_T expr() - * int oprio() - * Addr_T term() - * - * lkeval.c contains no local/static variables - */ - -/*)Function Addr_T eval() - * - * The function eval() evaluates a character string to a - * numerical value. - * - * local variables: - * int c character from input string - * int v value of character in current radix - * Addr_T n evaluation value - * - * global variables: - * int radix current number conversion radix - * - * functions called: - * int digit() lkeval.c - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * Input test is scanned and evaluated to a - * numerical value. - */ - -Addr_T -eval() -{ - register int c, v; - register Addr_T n; - - c = getnb(); - n = 0; - while ((v = digit(c, radix)) >= 0) { - n = n*radix + v; - c = get(); - } - unget(c); - return(n); -} - -/*)Function Addr_T expr(n) - * - * int n a firewall priority; all top - * level calls (from the user) - * should be made with n set to 0. - * - * The function expr() evaluates an expression and - * returns the value. - * - * local variables: - * int c current input text character - * int p current operator priority - * Addr_T v value returned by term() - * Addr_T ve value returned by a - * recursive call to expr() - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * int lkerr error flag - * FILE * stderr c_library - * - * functions called: - * VOID expr() lkeval.c - * int fprintf() c_library - * int getnb() lklex.c - * int oprio() lkeval.c - * VOID term() lkeval.c - * VOID unget() lklex.c - * - * - * side effects: - * An expression is evaluated by scanning the input - * text string. - */ - -Addr_T -expr (n) -{ - register int c, p; - register Addr_T v, ve; - - v = term(); - while (ctype[c = getnb()] & BINOP) { - if ((p = oprio(c)) <= n) - break; - if ((c == '>' || c == '<') && c != get()) { - fprintf(stderr, "Invalid expression"); - lkerr++; - return(v); - } - ve = expr(p); - if (c == '+') { - v += ve; - } else - if (c == '-') { - v -= ve; - } else { - switch (c) { - - case '*': - v *= ve; - break; - - case '/': - v /= ve; - break; - - case '&': - v &= ve; - break; - - case '|': - v |= ve; - break; - - case '%': - v %= ve; - break; - - case '^': - v ^= ve; - break; - - case '<': - v <<= ve; - break; - - case '>': - v >>= ve; - break; - } - } - } - unget(c); - return(v); -} - -/*)Function Addr_T term() - * - * The function term() evaluates a single constant - * or symbol value prefaced by any unary operator - * ( +, -, ~, ', ", >, or < ). - * - * local variables: - * int c current character - * char id[] symbol name - * int n value of digit in current radix - * int r current evaluation radix - * sym * sp pointer to a sym structure - * Addr_T v evaluation value - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * int lkerr error flag - * - * functions called: - * int digit() lkeval.c - * VOID expr() lkeval.c - * int fprintf() c_library - * int get() lklex.c - * VOID getid() lklex.c - * int getmap() lklex.c - * int getnb() lklex.c - * sym * lkpsym() lksym.c - * Addr_T symval() lksym.c - * VOID unget() lklex.c - * - * side effects: - * An arithmetic term is evaluated by scanning input text. - */ - -Addr_T -term() -{ - register int c, r, n; - register Addr_T v; - struct sym *sp; - char id[NCPS]; - - c = getnb(); - if (c == '#') { c = getnb(); } - if (c == '(') { - v = expr(0); - if (getnb() != ')') { - fprintf(stderr, "Missing delimiter"); - lkerr++; - } - return(v); - } - if (c == '-') { - return(0-expr(100)); - } - if (c == '~') { - return(~expr(100)); - } - if (c == '\'') { - return(getmap(-1)&0377); - } - if (c == '\"') { - if (hilo) { - v = (getmap(-1)&0377)<<8; - v |= getmap(-1)&0377; - } else { - v = getmap(-1)&0377; - v |= (getmap(-1)&0377)<<8; - } - return(v); - } - if (c == '>' || c == '<') { - v = expr(100); - if (c == '>') - v >>= 8; - return(v&0377); - } - if (ctype[c] & DIGIT) { - r = 10; - if (c == '0') { - c = get(); - switch (c) { - case 'b': - case 'B': - r = 2; - c = get(); - break; - case '@': - case 'o': - case 'O': - case 'q': - case 'Q': - r = 8; - c = get(); - break; - case 'd': - case 'D': - r = 10; - c = get(); - break; - case 'h': - case 'H': - case 'x': - case 'X': - r = 16; - c = get(); - break; - default: - break; - } - } - v = 0; - while ((n = digit(c, r)) >= 0) { - v = r*v + n; - c = get(); - } - unget(c); - return(v); - } - if (ctype[c] & LETTER) { - getid(id, c); - if ((sp = lkpsym(id, 0)) == NULL) { - fprintf(stderr, "Undefined symbol %8s\n", id); - lkerr++; - return(0); - } else { - return(symval(sp)); - } - } - return(0); -} - -/*)Function int digit(c, r) - * - * int c digit character - * int r current radix - * - * The function digit() returns the value of c - * in the current radix r. If the c value is not - * a number of the current radix then a -1 is returned. - * - * local variables: - * none - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * - * functions called: - * none - * - * side effects: - * none - */ - -int -digit(c, r) -register int c, r; -{ - if (r == 16) { - if (ctype[c] & RAD16) { - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - return (c - '0'); - } - } else - if (r == 10) { - if (ctype[c] & RAD10) - return (c - '0'); - } else - if (r == 8) { - if (ctype[c] & RAD8) - return (c - '0'); - } else - if (r == 2) { - if (ctype[c] & RAD2) - return (c - '0'); - } - return (-1); -} - -/*)Function int oprio(c) - * - * int c operator character - * - * The function oprio() returns a relative priority - * for all valid unary and binary operators. - * - * local variables: - * none - * - * global variables: - * none - * - * functions called: - * none - * - * side effects: - * none - */ - -int -oprio(c) -register int c; -{ - if (c == '*' || c == '/' || c == '%') - return (10); - if (c == '+' || c == '-') - return (7); - if (c == '<' || c == '>') - return (5); - if (c == '^') - return (4); - if (c == '&') - return (3); - if (c == '|') - return (1); - return (0); -} diff --git a/as/link/mcs51/lkhead.c b/as/link/mcs51/lkhead.c deleted file mode 100644 index 41a5198c..00000000 --- a/as/link/mcs51/lkhead.c +++ /dev/null @@ -1,153 +0,0 @@ -/* lkhead.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*Module lkhead.c - * - * The module lkhead.c contains the function newhead() which - * creates a head structure and the function module() which - * loads the module name into the current head structure. - * - * lkhead.c contains the following functions: - * VOID newhead() - * VOID module() - * - * lkhead.c contains no local variables. - */ - -/*)Function VOID newhead() - * - * The function newhead() creates a head structure. All head - * structures are linked to form a linked list of head structures - * with the current head structure at the tail of the list. - * - * local variables: - * int i evaluation value - * head * thp temporary pointer - * to a header structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * lfile *cfp The pointer *cfp points to the - * current lfile structure - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * - * functions called: - * Addr_T expr() lkeval.c - * VOID * new() lksym.c - * VOID lkparea() lkarea.c - * - * side effects: - * A new head structure is created and linked to any - * existing linked head structure. The head structure - * parameters of file handle, number of areas, and number - * of global symbols are loaded into the structure. - * The default area "_abs_" is created when the first - * head structure is created and an areax structure is - * created for every head structure called. - */ - -/* - * Create a new header entry. - * - * H n areas n global symbols - * | | - * | `---- hp->h_nglob - * `------------ hp->h_narea - * - */ -VOID -newhead() -{ - register int i; - struct head *thp; - - hp = (struct head *) new (sizeof(struct head)); - if (headp == NULL) { - headp = hp; - } else { - thp = headp; - while (thp->h_hp) - thp = thp->h_hp; - thp->h_hp = hp; - } - /* - * Set file pointer - */ - hp->h_lfile = cfp; - /* - * Evaluate and build Area pointer list - */ - i = hp->h_narea = eval(); - if (i) - hp->a_list = (struct areax **) new (i*sizeof(struct areax *)); - /* - * Evaluate and build Global symbol pointer list - */ - skip(-1); - i = hp->h_nglob = eval(); - if (i) - hp->s_list = (struct sym **) new (i*sizeof(struct sym *)); - /* - * Setup Absolute DEF linkage. - */ - lkparea(_abs_); - ap->a_flag = A_ABS; -} - -/*)Function VOID module() - * - * The function module() copies the module name into - * the current head structure. - * - * local variables: - * char id[] module id string - * - * global variables: - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * FILE * stderr c_library - * - * functions called: - * int fprintf() c_library - * VOID getid() lklex.c - * char * strncpy() c_library - * - * side effects: - * The module name is copied into the head structure. - */ - -/* - * Module Name - */ -VOID -module() -{ - char id[NCPS]; - - if (headp) { - getid(id, -1); - strncpy(hp->m_id, id, NCPS); - } else { - fprintf(stderr, "No header defined\n"); - lkerr++; - } -} diff --git a/as/link/mcs51/lklex.c b/as/link/mcs51/lklex.c deleted file mode 100644 index 73093ce9..00000000 --- a/as/link/mcs51/lklex.c +++ /dev/null @@ -1,639 +0,0 @@ -/* lklex.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include "aslink.h" - -/*)Module lklex.c - * - * The module lklex.c contains the general lexical analysis - * functions used to scan the text lines from the .rel files. - * - * lklex.c contains the fllowing functions: - * char endline() - * char get() - * VOID getfid() - * VOID getid() - * VOID getSid() - * int lk_getline() - * int getmap() - * char getnb() - * int more() - * VOID skip() - * VOID unget() - * - * lklex.c contains no local variables. - */ - -/*)Function VOID getid(id,c) - * - * char * id a pointer to a string of - * maximum length NCPS - * int c mode flag - * >=0 this is first character to - * copy to the string buffer - * <0 skip white space - * - * The function getid() scans the current input text line - * from the current position copying the next LETTER | DIGIT string - * into the external string buffer (id). The string ends when a non - * LETTER or DIGIT character is found. The maximum number of - * characters copied is NCPS. If the input string is larger than - * NCPS characters then the string is truncated, if the input string - * is shorter than NCPS characters then the string is NULL filled. - * If the mode argument (c) is >=0 then (c) is the first character - * copied to the string buffer, if (c) is <0 then intervening white - * space (SPACES and TABS) are skipped. - * - * local variables: - * char * p pointer to external string buffer - * int c current character value - * - * global variables: - * char ctype[] a character array which defines the - * type of character being processed. - * This index is the character - * being processed. - * - * called functions: - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of getnb(), get(), and unget() updates the - * global pointer ip the position in the current - * input text line. - */ - -VOID -getid(id, c) -register int c; -char *id; -{ - register char *p; - - if (c < 0) { - c = getnb(); - } - p = id; - do { - if (p < &id[NCPS]) - *p++ = c; - } while (ctype[c=get()] & (LETTER|DIGIT)); - unget(c); - while (p < &id[NCPS]) - *p++ = 0; -} - -/*)Function VOID getSid (char *id) - * - * char * id a pointer to a string of - * maximum length NCPS - * - * getSid is derived from getid. It is called from newsym() - * in lksym.c, when an S-record has to be scanned. getSid accepts - * much more characters than getid, which is necessary for SDCC. - * - * The function getSid() scans the current input text line - * from the current position copying the next string - * into the external string buffer (id). The string ends when a space - * character (space, tab, \0) is found. The maximum number of - * characters copied is NCPS. If the input string is larger than - * NCPS characters then the string is truncated, if the input string - * is shorter than NCPS characters then the string is NULL filled. - * Intervening white space (SPACES and TABS) are skipped. - * - * local variables: - * char * p pointer to external string buffer - * int c current character value - * - * global variables: - * char ctype[] a character array which defines the - * type of character being processed. - * This index is the character - * being processed. - * - * called functions: - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of getnb(), get(), and unget() updates the - * global pointer ip the position in the current - * input text line. - */ - -VOID -getSid (char *id) -{ - register int c; - register char *p; - - c = getnb(); - p = id; - do { - if (p < &id[NCPS]) - *p++ = c; - c = get(); - } while (c != '\0' && c != ' ' && c != '\t'); - unget(c); - while (p < &id[NCPS]) - *p++ = 0; -} - -/*)Function VOID getfid(fid,c) - * - * char * str a pointer to a string of - * maximum length PATH_MAX - * int c this is first character to - * copy to the string buffer - * - * The function getfid() scans the current input text line from - * the current position copying the next string into the external - * string buffer (str). The string ends when end of line is found. - * Trailing spacers are removed. The maximum number of characters - * copied is PATH_MAX. If the input string is larger than PATH_MAX - * characters then the string is truncated. The string is NULL - * terminated. - * - * local variables: - * char * p pointer to external string buffer - * int c current character value - * - * global variables: - * char ctype[] a character array which defines the - * type of character being processed. - * This index is the character - * being processed. - * - * called functions: - * char get() lklex.c - * - * side effects: - * use of get() updates the global pointer ip - * the position in the current input text line. - */ - -VOID -getfid(str, c) -register int c; -char *str; -{ - register char *p; - - p = str; - do - { - if (p < &str[PATH_MAX-1]) - *p++ = c; - c = get(); - if (c == ';') - while (c) - c = get(); - } while (c); - /* trim trailing spaces */ - --p; - while (p >= str && ctype[(int)*p] == SPACE) - --p; - /* terminate the string */ - *(++p) = '\0'; -} - -/*)Function char getnb() - * - * The function getnb() scans the current input text - * line returning the first character not a SPACE or TAB. - * - * local variables: - * int c current character from input - * - * global variables: - * none - * - * called functions: - * char get() lklex.c - * - * side effects: - * use of get() updates the global pointer ip, the position - * in the current input text line - */ - -char -getnb() -{ - register int c; - - while ((c=get())==' ' || c=='\t') - ; - return (c); -} - -/*)Function VOID skip() - * - * The function skip() scans the input text skipping all - * letters and digits. - * - * local variables: - * none - * - * global variables: - * char ctype[] array of character types, one per - * ASCII character - * - * functions called: - * char get() lklex.c - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * Input letters and digits are skipped. - */ - -VOID -skip(c) -register int c; -{ - if (c < 0) - c = getnb(); - while (ctype[c=get()] & (LETTER|DIGIT)) { ; } - unget(c); -} - -/*)Function char get() - * - * The function get() returns the next character in the - * input text line, at the end of the line a - * NULL character is returned. - * - * local variables: - * int c current character from - * input text line - * - * global variables: - * char * ip pointer into the current - * input text line - * - * called functions: - * none - * - * side effects: - * updates ip to the next character position in the - * input text line. If ip is at the end of the - * line, ip is not updated. - */ - -char -get() -{ - register int c; - - if ((c = *ip) != 0) - ++ip; - return (c); -} - -/*)Function VOID unget(c) - * - * int c value of last character - * read from input text line - * - * If (c) is not a NULL character then the global pointer ip - * is updated to point to the preceeding character in the - * input text line. - * - * NOTE: This function does not push the character (c) - * back into the input text line, only - * the pointer ip is changed. - * - * local variables: - * int c last character read - * from input text line - * - * global variables: - * char * ip position into the current - * input text line - * - * called functions: - * none - * - * side effects: - * ip decremented by 1 character position - */ - -VOID -unget(c) -{ - if (c != 0) - --ip; -} - -/*)Function int getmap(d) - * - * int d value to compare with the - * input text line character - * - * The function getmap() converts the 'C' style characters \b, \f, - * \n, \r, and \t to their equivalent ascii values and also - * converts 'C' style octal constants '\123' to their equivalent - * numeric values. If the first character is equivalent to (d) then - * a (-1) is returned, if the end of the line is detected then - * a 'q' error terminates the parse for this line, or if the first - * character is not a \ then the character value is returned. - * - * local variables: - * int c value of character - * from input text line - * int n looping counter - * int v current value of numeric conversion - * - * global variables: - * none - * - * called functions: - * char get() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of get() updates the global pointer ip the position - * in the current input text line - */ - -int -getmap(d) -{ - register int c, n, v; - - if ((c = get()) == '\0') - return (-1); - if (c == d) - return (-1); - if (c == '\\') { - c = get(); - switch (c) { - - case 'b': - c = '\b'; - break; - - case 'f': - c = '\f'; - break; - - case 'n': - c = '\n'; - break; - - case 'r': - c = '\r'; - break; - - case 't': - c = '\t'; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - n = 0; - v = 0; - while (++n<=3 && c>='0' && c<='7') { - v = (v<<3) + c - '0'; - c = get(); - } - unget(c); - c = v; - break; - } - } - return (c); -} - -/*)Function int lk_getline() - * - * The function lk_getline() reads a line of input text from a - * .rel source text file, a .lnk command file or from stdin. - * Lines of text are processed from a single .lnk file or - * multiple .rel files until all files have been read. - * The input text line is copied into the global string ib[] - * and converted to a NULL terminated string. The function - * lk_getline() returns a (1) after succesfully reading a line - * or a (0) if all files have been read. - * This function also opens each input .lst file and output - * .rst file as each .rel file is processed. - * - * local variables: - * int i string length - * int ftype file type - * char * fid file name - * - * global variables: - * lfile *cfp The pointer *cfp points to the - * current lfile structure - * lfile *filep The pointer *filep points to the - * beginning of a linked list of - * lfile structures. - * int gline get a line from the LST file - * to translate for the RST file - * char ib[NINPUT] REL file text line - * int pass linker pass number - * int pflag print linker command file flag - * FILE *rfp The file handle to the current - * output RST file - * FILE *sfp The file handle sfp points to the - * currently open file - * FILE * stdin c_library - * FILE * stdout c_library - * FILE *tfp The file handle to the current - * LST file being scanned - * int uflag update listing flag - * - * called functions: - * FILE * afile() lkmain.c - * int fclose() c_library - * char * fgets() c_library - * int fprintf() c_library - * VOID lkulist() lklist.c - * VOID lkexit() lkmain.c - * int strlen() c_library - * - * side effects: - * The input stream is scanned. The .rel files will be - * opened and closed sequentially scanning each in turn. - */ - -int -lk_getline() -{ - register int ftype; - register char *fid; - -loop: if (pflag && cfp && cfp->f_type == F_STD) - fprintf(stdout, "ASlink >> "); - - if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) { - if (sfp) { - fclose(sfp); - sfp = NULL; - lkulist(0); - } - if (cfp == NULL) { - cfp = filep; - } else { - cfp = cfp->f_flp; - } - if (cfp) { - ftype = cfp->f_type; - fid = cfp->f_idp; - if (ftype == F_STD) { - sfp = stdin; - } else - if (ftype == F_LNK) { - sfp = afile(fid, "lnk", 0); - } else - if (ftype == F_REL) { - sfp = afile(fid, "rel", 0); - /* if a .cdb file exists then copy it over */ - if (dflag && sfp && dfp && pass == 0) { - FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002 - if (xfp) { - copyfile(dfp,xfp); - fclose(xfp); - } - } - if (uflag && pass != 0) { - SaveLinkedFilePath(fid); //Save the linked path for aomf51 - if ((tfp = afile(fid, "lst", 0)) != NULL) { - if ((rfp = afile(fid, "rst", 1)) == NULL) { - fclose(tfp); - tfp = NULL; - } - } - } - gline = 1; - } else { - fprintf(stderr, "Invalid file type\n"); - lkexit(1); - } - if (sfp == NULL) { - lkexit(1); - } - goto loop; - } else { - filep = NULL; - return(0); - } - } - chop_crlf(ib); - return (1); -} - -/*)Function int more() - * - * The function more() scans the input text line - * skipping white space (SPACES and TABS) and returns a (0) - * if the end of the line or a comment delimeter (;) is found, - * or a (1) if their are additional characters in the line. - * - * local variables: - * int c next character from - * the input text line - * - * global variables: - * none - * - * called functions: - * char getnb() lklex.c - * VOID unget() lklex.c - * - * side effects: - * use of getnb() and unget() updates the global pointer ip - * the position in the current input text line - */ - -int -more() -{ - register int c; - - c = getnb(); - unget(c); - return( (c == '\0' || c == ';') ? 0 : 1 ); -} - -/*)Function char endline() - * - * The function endline() scans the input text line - * skipping white space (SPACES and TABS) and returns the next - * character or a (0) if the end of the line is found or a - * comment delimiter (;) is found. - * - * local variables: - * int c next character from - * the input text line - * - * global variables: - * none - * - * called functions: - * char getnb() lklex.c - * - * side effects: - * Use of getnb() updates the global pointer ip the - * position in the current input text line. - */ - -char -endline() -{ - register int c; - - c = getnb(); - return( (c == '\0' || c == ';') ? 0 : c ); -} - -/*)Function VOID chop_crlf(str) - * - * char *str string to chop - * - * The function chop_crlf() removes trailing LF or CR/LF from - * str, if present. - * - * local variables: - * int i string length - * - * global variables: - * none - * - * functions called: - * none - * - * side effects: - * none - */ - -VOID -chop_crlf(str) -char *str; -{ - register int i; - - i = strlen(str); - if (i >= 1 && str[i-1] == '\n') str[i-1] = 0; - if (i >= 2 && str[i-2] == '\r') str[i-2] = 0; -} diff --git a/as/link/mcs51/lklist.c b/as/link/mcs51/lklist.c deleted file mode 100644 index 5325ec89..00000000 --- a/as/link/mcs51/lklist.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* lklist.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 28-Oct-97 JLH: - * - lstarea: show s_id as string rather than array [NCPS] - * - lstarea: show a_id as string rather than array [NCPS] - * 31-Oct-97 JLH: add NoICE output file genration in lstarea - * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output - */ - -#include -#include -#include -#include "aslink.h" - -/*)Module lklist.c - * - * The module lklist.c contains the functions which - * output the linker .map file and produce a relocated - * listing .rst file. - * - * lklist.c contains the following functions: - * int dgt() - * VOID lstarea() - * VOID lkulist() - * VOID lkalist() - * VOID lkglist() - * VOID newpag() - * VOID slew() - * - * lklist.c contains no local variables. - */ - -/*)Function VOID slew(fp) - * - * FILE * fp output file handle - * - * The function slew() increments the page line counter. - * If the number of lines exceeds the maximum number of - * lines per page then a page skip and a page header are - * output. - * - * local variables: - * int i loop counter - * - * global variables: - * int lop current line number on page - * int xflag Map file radix type flag - * - * functions called: - * int fprintf() c_library - * VOID newpag() lklist.c - * - * side effects: - * The page line and the page count may be updated. - */ - -VOID -slew(fp) -FILE *fp; -{ - register int i; - - if (lop++ >= NLPP) { - newpag(fp); - if (xflag == 0) { - fprintf(fp, "Hexadecimal\n\n"); - } else - if (xflag == 1) { - fprintf(fp, "Octal\n\n"); - } else - if (xflag == 2) { - fprintf(fp, "Decimal\n\n"); - } - fprintf(fp, "Area Addr Size"); - fprintf(fp, " Decimal Bytes (Attributes)\n"); - for(i=0;i<4;++i) - fprintf(fp, " Value--Global"); - fprintf(fp, "\n\n"); - lop += 6; - } -} - -/*)Function VOID newpag() - * - * The function newpag() outputs a page skip, writes the - * first page header line, sets the line count to 1, and - * increments the page counter. - * - * local variables: - * none - * - * global variables: - * int lop current line number on page - * int page current page number - * - * functions called: - * int fprintf() c_library - * - * side effects: - * The page and line counters are updated. - */ - -VOID -newpag(fp) -FILE *fp; -{ - fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page); - lop = 1; -} - -/* Used for qsort call in lstsym */ -static int _cmpSymByAddr(const void *p1, const void *p2) -{ - struct sym **s1 = (struct sym **)(p1); - struct sym **s2 = (struct sym **)(p2); - int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) - - ((*s2)->s_addr + (*s2)->s_axp->a_addr); - - /* Sort first by address, then by name. */ - if (delta) - { - return delta; - } - return strcmp((*s1)->s_id,(*s2)->s_id); -} - - -#if NCPS-8 - -/* NCPS != 8 */ -/*)Function VOID lstarea(xp) - * - * area * xp pointer to an area structure - * - * The function lstarea() creates the linker map output for - * the area specified by pointer xp. The generated output - * area header includes the area name, starting address, - * size of area, number of words (in decimal), and the - * area attributes. The symbols defined in this area are - * sorted by ascending address and output one per line - * in the selected radix. - * - * local variables: - * areax * oxp pointer to an area extension structure - * int c character value - * int i loop counter - * int j bubble sort update status - * char * ptr pointer to an id string - * int nmsym number of symbols in area - * Addr_T a0 temporary - * Addr_T ai temporary - * Addr_T aj temporary - * sym * sp pointer to a symbol structure - * sym ** p pointer to an array of - * pointers to symbol structures - * - * global variables: - * FILE *mfp Map output file handle - * sym *symhash[NHASH] array of pointers to NHASH - * linked symbol lists - * int xflag Map file radix type flag - * - * functions called: - * int fprintf() c_library - * VOID free() c_library - * char * malloc() c_library - * char putc() c_library - * VOID slew() lklist.c - * - * side effects: - * Map output generated. - */ - -VOID -lstarea(xp) -struct area *xp; -{ - register struct areax *oxp; - register int i; - /* int j; */ - register char *ptr; - int nmsym; - /* Addr_T a0; */ - Addr_T ai, aj; - struct sym *sp; - struct sym **p; - int memPage; - - putc('\n', mfp); - if (xflag == 0) { - fprintf(mfp, "Hexadecimal\n\n"); - } else - if (xflag == 1) { - fprintf(mfp, "Octal\n\n"); - } else - if (xflag == 2) { - fprintf(mfp, "Decimal\n\n"); - } - fprintf(mfp, "Area "); - fprintf(mfp, "Addr Size Decimal %s (Attributes)\n", - (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/ - fprintf(mfp, "-------------------------------- "); - fprintf(mfp, "---- ---- ------- ----- ------------\n"); - /* - * Output Area Header - */ - ptr = &xp->a_id[0]; - fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */ - ai = xp->a_addr; - aj = xp->a_size; - if (xflag == 0) { - fprintf(mfp, " %04X %04X", ai, aj); - } else - if (xflag == 1) { - fprintf(mfp, " %06o %06o", ai, aj); - } else - if (xflag == 2) { - fprintf(mfp, " %05u %05u", ai, aj); - } - fprintf(mfp, " = %6u. %s ", aj, - (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/ - if (xp->a_flag & A_ABS) { - fprintf(mfp, "(ABS"); - } else { - fprintf(mfp, "(REL"); - } - if (xp->a_flag & A_OVR) { - fprintf(mfp, ",OVR"); - } else { - fprintf(mfp, ",CON"); - } - if (xp->a_flag & A_PAG) { - fprintf(mfp, ",PAG"); - } - - memPage = 0x00; - if (xp->a_flag & A_CODE) { - fprintf(mfp, ",CODE"); - memPage = 0x0C; - } - if (xp->a_flag & A_XDATA) { - fprintf(mfp, ",XDATA"); - memPage = 0x0D; - } - if (xp->a_flag & A_BIT) { - fprintf(mfp, ",BIT"); - memPage = 0x0B; - } - fprintf(mfp, ")"); - if (xp->a_flag & A_PAG) { - ai = (ai & 0xFF); - aj = (aj > 256); - if (ai || aj) { fprintf(mfp, " "); } - if (ai) { fprintf(mfp, " Boundary"); } - if (ai & aj) { fprintf(mfp, " /"); } - if (aj) { fprintf(mfp, " Length"); } - if (ai || aj) { fprintf(mfp, " Error"); } - } - - /* - * Find number of symbols in area - */ - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) - ++nmsym; - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - if (nmsym == 0) { - putc('\n', mfp); - return; - } - - /* - * Allocate space for an array of pointers to symbols - * and load array. - */ - if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *))) - == NULL) { - fprintf(mfp, "\nInsufficient space to build Map Segment.\n"); - return; - } - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) { - p[nmsym++] = sp; - } - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - -#if 0 - /* - * Bubble Sort of Addresses in Symbol Table Array - */ - j = 1; - while (j) { - j = 0; - sp = p[0]; - a0 = sp->s_addr + sp->s_axp->a_addr; - for (i=1; is_addr + sp->s_axp->a_addr; - if (a0 > ai) { - j = 1; - p[i] = p[i-1]; - p[i-1] = sp; - } - a0 = ai; - } - } -#else - qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); -#endif - - /* - * Symbol Table Output - */ - - i = 0; - fprintf(mfp, "\n\n"); - fprintf(mfp, " Value Global\n"); - fprintf(mfp, " -------- --------------------------------"); - while (i < nmsym) { - fprintf(mfp, "\n"); - if (memPage != 0) - fprintf(mfp, " %02X:", memPage); - else - fprintf(mfp, " "); - - sp = p[i]; - aj = sp->s_addr + sp->s_axp->a_addr; - if (xflag == 0) { - fprintf(mfp, "%04X ", aj); - } else - if (xflag == 1) { - fprintf(mfp, "%06o ", aj); - } else - if (xflag == 2) { - fprintf(mfp, "%05u ", aj); - } - ptr = &sp->s_id[0]; - fprintf(mfp, "%s", ptr ); - - /* if cdb flag set the output cdb Information - and the symbol has a '$' sign in it then */ - if (dflag && - strchr(ptr,'$')) - fprintf(dfp,"L:%s:%X\n",ptr,aj); - - /* NoICE output of symbol */ - if (jflag) DefineNoICE( ptr, aj, memPage ); - - i++; - } - putc('\n', mfp); - free(p); -} - -#else - -/* NCPS == 8 */ -/*)Function VOID lstarea(xp) - * - * area * xp pointer to an area structure - * - * The function lstarea() creates the linker map output for - * the area specified by pointer xp. The generated output - * area header includes the area name, starting address, - * size of area, number of words (in decimal), and the - * area attributes. The symbols defined in this area are - * sorted by ascending address and output four per line - * in the selected radix. - * - * local variables: - * areax * oxp pointer to an area extension structure - * int c character value - * int i loop counter - * int j bubble sort update status - * char * ptr pointer to an id string - * int nmsym number of symbols in area - * Addr_T a0 temporary - * Addr_T ai temporary - * Addr_T aj temporary - * sym * sp pointer to a symbol structure - * sym ** p pointer to an array of - * pointers to symbol structures - * - * global variables: - * FILE *mfp Map output file handle - * sym *symhash[NHASH] array of pointers to NHASH - * linked symbol lists - * int xflag Map file radix type flag - * - * functions called: - * int fprintf() c_library - * VOID free() c_library - * char * malloc() c_library - * char putc() c_library - * VOID slew() lklist.c - * - * side effects: - * Map output generated. - */ - -VOID -lstarea(xp) -struct area *xp; -{ - register struct areax *oxp; - register c, i, j; - register char *ptr; - int nmsym; - Addr_T a0, ai, aj; - struct sym *sp; - struct sym **p; - int page; - - putc('\n', mfp); - slew(mfp); - /* - * Output Area Header - */ - ptr = &xp->a_id[0]; - while (ptr < &xp->a_id[NCPS]) { - if ((c = *ptr++) != 0) { - putc(c, mfp); - } else { - putc(' ', mfp); - } - } - ai = xp->a_addr; - aj = xp->a_size; - if (xflag == 0) { - fprintf(mfp, " %04X %04X", ai, aj); - } else - if (xflag == 1) { - fprintf(mfp, " %06o %06o", ai, aj); - } else - if (xflag == 2) { - fprintf(mfp, " %05u %05u", ai, aj); - } - fprintf(mfp, " = %6u. bytes ", aj); - if (xp->a_flag & A_ABS) { - fprintf(mfp, "(ABS"); - } else { - fprintf(mfp, "(REL"); - } - if (xp->a_flag & A_OVR) { - fprintf(mfp, ",OVR"); - } else { - fprintf(mfp, ",CON"); - } - if (xp->a_flag & A_PAG) { - fprintf(mfp, ",PAG"); - } - - page = 0x00; - if (xp->a_flag & A_CODE) { - fprintf(mfp, ",CODE"); - memPage = 0x0C; - } - if (xp->a_flag & A_XDATA) { - fprintf(mfp, ",XDATA"); - memPage = 0x0D; - } - if (xp->a_flag & A_BIT) { - fprintf(mfp, ",BIT"); - memPage = 0x0B; - } - fprintf(mfp, ")"); - if (xp->a_flag & A_PAG) { - ai = (ai & 0xFF); - aj = (aj > 256); - if (ai || aj) { fprintf(mfp, " "); } - if (ai) { fprintf(mfp, " Boundary"); } - if (ai & aj) { fprintf(mfp, " /"); } - if (aj) { fprintf(mfp, " Length"); } - if (ai || aj) { fprintf(mfp, " Error"); } - } - - /* - * Find number of symbols in area - */ - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) - ++nmsym; - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - if (nmsym == 0) { - putc('\n', mfp); - slew(mfp); - return; - } - - /* - * Allocate space for an array of pointers to symbols - * and load array. - */ - if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *))) - == NULL) { - fprintf(mfp, "\nInsufficient space to build Map Segment.\n"); - slew(mfp); - return; - } - nmsym = 0; - oxp = xp->a_axp; - while (oxp) { - for (i=0; is_axp) { - p[nmsym++] = sp; - } - sp = sp->s_sp; - } - } - oxp = oxp->a_axp; - } - -#if 0 - /* - * Bubble Sort of Addresses in Symbol Table Array - */ - j = 1; - while (j) { - j = 0; - sp = p[0]; - a0 = sp->s_addr + sp->s_axp->a_addr; - for (i=1; is_addr + sp->s_axp->a_addr; - if (a0 > ai) { - j = 1; - p[i] = p[i-1]; - p[i-1] = sp; - } - a0 = ai; - } - } -#else - qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); -#endif - - /* - * Symbol Table Output - */ - i = 0; - while (i < nmsym) { - fprintf(mfp, "\n"); - slew(mfp); - fprintf(mfp, " "); - sp = p[i]; - aj = sp->s_addr + sp->s_axp->a_addr; - if (xflag == 0) { - fprintf(mfp, " %04X ", aj); - } else - if (xflag == 1) { - fprintf(mfp, "%06o ", aj); - } else - if (xflag == 2) { - fprintf(mfp, " %05u ", aj); - } - ptr = &sp->s_id[0]; - fprintf(mfp, "%s", ptr ); - - /* NoICE output of symbol */ - if (jflag) DefineNoICE( ptr, aj, memPage ); - } - putc('\n', mfp); - free(p); - slew(mfp); -} -#endif - -/*)Function VOID lkulist(i) - * - * int i i # 0 process LST to RST file - * i = 0 copy remainder of LST file - * to RST file and close files - * - * The function lkulist() creates a relocated listing (.rst) - * output file from the ASxxxx assembler listing (.lst) - * files. The .lst file's program address and code bytes - * are changed to reflect the changes made by ASlink as - * the .rel files are combined into a single relocated - * output file. - * - * local variables: - * Addr_T pc current program counter address - * - * global variables: - * int hilo byte order - * int gline get a line from the LST file - * to translate for the RST file - * char rb[] read listing file text line - * FILE *rfp The file handle to the current - * output RST file - * int rtcnt count of data words - * int rtflg[] output the data flag - * Addr_T rtval[] relocated data - * FILE *tfp The file handle to the current - * LST file being scanned - * - * functions called: - * int fclose() c_library - * int fgets() c_library - * int fprintf() c_library - * VOID lkalist() lklist.c - * VOID lkglist() lklist.c - * - * side effects: - * A .rst file is created for each available .lst - * file associated with a .rel file. - */ - -VOID -lkulist(i) -int i; -{ - Addr_T pc; - - /* - * Exit if listing file is not open - */ - if (tfp == NULL) - return; - - /* - * Normal processing of LST to RST - */ - if (i) { - /* - * Evaluate current code address - */ - if (hilo == 0) { - pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF); - } else { - pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF); - } - - /* - * Line with only address - */ - if (rtcnt == 2) { - lkalist(pc); - - /* - * Line with address and code - */ - } else { - for (i=2; i < rtcnt; i++) { - if (rtflg[i]) { - lkglist(pc++, rtval[i] & 0xFF); - } - } - } - - /* - * Copy remainder of LST to RST - */ - } else { - if (gline == 0) - fprintf(rfp, "%s", rb); - - while (fgets(rb, sizeof(rb), tfp) != 0) { - fprintf(rfp, "%s", rb); - } - fclose(tfp); - tfp = NULL; - fclose(rfp); - rfp = NULL; - } -} - -/*)Function VOID lkalist(pc) - * - * int pc current program counter value - * - * The function lkalist() performs the following functions: - * - * (1) if the value of gline = 0 then the current listing - * file line is copied to the relocated listing file output. - * - * (2) the listing file is read line by line and copied to - * the relocated listing file until a valid source - * line number and a program counter value of the correct - * radix is found. The new relocated pc value is substituted - * and the line is written to the RST file. - * - * local variables: - * int i loop counter - * char str[] temporary string - * - * global variables: - * int gcntr data byte counter - * int gline get a line from the LST file - * to translate for the RST file - * char rb[] read listing file text line - * char *rp pointer to listing file text line - * FILE *rfp The file handle to the current - * output RST file - * FILE *tfp The file handle to the current - * LST file being scanned - * - * functions called: - * int dgt() lklist.c - * int fclose() c_library - * int fgets() c_library - * int fprintf() c_library - * int sprintf() c_library - * char * strncpy() c_library - * - * side effects: - * Lines of the LST file are copied to the RST file, - * the last line copied has the code address - * updated to reflect the program relocation. - */ - -VOID -lkalist(pc) -Addr_T pc; -{ - char str[8]; - int i; - - /* - * Exit if listing file is not open - */ -loop: if (tfp == NULL) - return; - - /* - * Copy current LST to RST - */ - if (gline == 0) { - fprintf(rfp, "%s", rb); - gline = 1; - } - - /* - * Clear text line buffer - */ - for (i=0,rp=rb; i -#include -#include -#include "aslink.h" - -static void DefineGlobal( char *name, Addr_T value, int page ); -static void DefineScoped( char *name, Addr_T value, int page ); -static void DefineFile( char *name, Addr_T value, int page ); -static void DefineFunction( char *name, Addr_T value, int page ); -static void DefineStaticFunction( char *name, Addr_T value, int page ); -static void DefineEndFunction( Addr_T value, int page ); -static void DefineLine( char *lineString, Addr_T value, int page ); -static void PagedAddress( Addr_T value, int page ); - -/* - * Called from lstarea in lklist.c for each symbol. - * - * Generates appropriate NoICE commands into output file, if any is open - * - */ -void DefineNoICE( char *name, Addr_T value, int page ) -{ - char token1[NCPS]; /* parse for file.function.symbol */ - char token2[NCPS]; - char token3[NCPS]; - // char token4[NCPS]; - char sep1, sep2; - int j, level; - - /* no output if file is not open */ - if (jfp == NULL) return; - - j = sscanf( name, "%[^.]%c%[^.]%c%s", - token1, &sep1, token2, &sep2, token3 ); - switch (j) - { - /* file.function.symbol, or file.function..SPECIAL */ - case 5: - DefineFile( token1, 0, 0 ); - if (token3[0] == '.') - { - if (strcmp( token3, ".FN" ) == 0) - { - /* Global function */ - DefineFunction( token2, value, page ); - } - else if (strcmp( token3, ".SFN" ) == 0) - { - /* Static (file-scope) function */ - DefineStaticFunction( token2, value, page ); - } - else if (strcmp( token3, ".EFN" ) == 0) - { - /* End of function */ - DefineEndFunction( value, page ); - } - } - else - { - /* Function-scope var. */ - DefineFunction( token2, 0, 0 ); - - /* Look for optional level integer */ - j = sscanf( token3, "%[^.]%c%u", token1, &sep1, &level ); - if ((j == 3) && (level != 0)) - { - sprintf( &token1[ strlen(token1) ], "_%u", level ); - } - DefineScoped( token1, value, page ); - } - break; - - /* file.func. is illegal */ - case 4: - break; - - /* either file.symbol or file.line# */ - case 3: - DefineFile( token1, 0, 0 ); - if ((token2[0] >= '0') && (token2[0] <= '9')) - { - /* Line number */ - DefineLine( token2, value, page ); - } - else - { - /* File-scope symbol. (Kill any function) */ - DefineEndFunction( 0, 0 ); - DefineScoped( token2, value, page ); - } - break; - - /* symbol. is illegal */ - case 2: - break; - - /* just a symbol */ - case 1: - DefineGlobal( token1, value, page ); - break; - } -} - -static char currentFile[NCPS]; -static char currentFunction[NCPS]; - -/* - * static function: - * Define "name" as a global symbol - */ -void DefineGlobal( char *name, Addr_T value, int page ) -{ - fprintf( jfp, "DEF %s ", name ); - PagedAddress( value, page ); -} - -/* - * static function: - * Define "name" as a static (scoped) symbol - */ -void DefineScoped( char *name, Addr_T value, int page ) -{ - fprintf( jfp, "DEFS %s ", name ); - PagedAddress( value, page ); -} - -/* - * static function: - * Define "name" as the current file - */ -void DefineFile( char *name, Addr_T value, int page ) -{ - if (as_strcmpi( name, currentFile ) != 0) - { - strcpy( currentFile, name ); - if (value != 0) - { - fprintf( jfp, "FILE %s ", name ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "FILE %s\n", name ); - } - } -} - -/* - * static function: - * Define "name" as the current function - */ -void DefineFunction( char *name, Addr_T value, int page ) -{ - if (as_strcmpi( name, currentFunction ) != 0) - { - strcpy( currentFunction, name ); - if (value != 0) - { - fprintf( jfp, "DEF %s ", name ); - PagedAddress( value, page ); - fprintf( jfp, "FUNC %s ", name ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "FUNC %s\n", name ); - } - } -} - -/* - * static function: - * Define "name" as the current static (scoped) function - */ -void DefineStaticFunction( char *name, Addr_T value, int page ) -{ - if (as_strcmpi( name, currentFunction ) != 0) - { - strcpy( currentFunction, name ); - if (value != 0) - { - fprintf( jfp, "DEFS %s ", name ); - PagedAddress( value, page ); - fprintf( jfp, "SFUNC %s ", name ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "SFUNC %s\n", name ); - } - } -} - -/* - * static function: - * Define the end of the current function - */ -void DefineEndFunction( Addr_T value, int page ) -{ - if (currentFunction[0] != 0) - { - if (value != 0) - { - fprintf( jfp, "ENDF " ); - PagedAddress( value, page ); - } - else - { - fprintf( jfp, "ENDF\n" ); - } - - currentFunction[0] = 0; - } -} - -/* - * static function: - * Define "lineNumber" as a line in the current file - */ -void DefineLine( char *lineString, Addr_T value, int page ) -{ - int indigit, lineNumber = 0; - - while( (indigit=digit( *lineString++, 10 )) >= 0) - { - lineNumber = 10*lineNumber + indigit; - } - fprintf( jfp, "LINE %u ", lineNumber ); - PagedAddress( value, page ); -} - -void PagedAddress( Addr_T value, int page ) -{ - fprintf( jfp, "%X:0x%X\n", page, value ); -} diff --git a/as/link/mcs51/lksym.c b/as/link/mcs51/lksym.c deleted file mode 100644 index 526e7189..00000000 --- a/as/link/mcs51/lksym.c +++ /dev/null @@ -1,484 +0,0 @@ -/* lksym.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - * - * 28-Oct-97 JLH: - * - lkpsym: Use StoreString for sym construction - * - change symeq() to do length-independent string compare - * - change hash() to do length-independent hash calculation - */ - -#include -#include -#include -#include "aslink.h" - -/*)Module lksym.c - * - * The module lksym.c contains the functions that operate - * on the symbol structures. - * - * lksym.c contains the following functions: - * int hash() - * sym * lkpsym() - * VOID * new() - * sym * newsym() - * VOID symdef() - * int symeq() - * VOID syminit() - * VOID symmod() - * Addr_T symval() - * - * lksym.c contains no local/static variables. - */ - -/*)Function VOID syminit() - * - * The function syminit() is called to clear the hashtable. - * - * local variables: - * int h computed hash value - * sym ** spp pointer to an array of - * sym structure pointers - * - * global variables: - * sym * symhash[] array of pointers to NHASH - * linked symbol lists - * - * functions called: - * none - * - * side effects: - * (1) The symbol hash tables are cleared - */ - -VOID -syminit() -{ - // register int h; - struct sym **spp; - - spp = &symhash[0]; - while (spp < &symhash[NHASH]) - *spp++ = NULL; -} - -/*)Function sym * newsym() - * - * The function newsym() is called to evaluate the symbol - * definition/reference directive from the .rel file(s). - * If the symbol is not found in the symbol table a new - * symbol structure is created. Evaluation of the - * directive determines if this is a reference or a definition. - * Multiple definitions of the same variable will be flagged - * as an error if the values are not identical. A symbol - * definition places the symbol value and area extension - * into the symbols data structure. And finally, a pointer - * to the symbol structure is placed into the head structure - * symbol list. Refer to the description of the header, symbol, - * area, and areax structures in lkdata.c for structure and - * linkage details. - * - * local variables: - * int c character from input text - * int i evaluation value - * char id[] symbol name - * int nglob number of symbols in this header - * sym * tsp pointer to symbol structure - * sym ** s list of pointers to symbol structures - * - * global variables: - * areax *axp Pointer to the current - * areax structure - * head *headp The pointer to the first - * head structure of a linked list - * int lkerr error flag - * - * functions called: - * Addr_T eval() lkeval.c - * VOID exit() c_library - * int fprintf() c_library - * char getSid() lklex.c - * char get() lklex.c - * char getnb() lklex.c - * sym * lkpsym() lksym.c - * - * side effects: - * A symbol structure is created and/or modified. - * If structure space allocation fails linker will abort. - * Several severe errors (these are internal errors - * indicating a corrupted .rel file or corrupted - * assembler or linker) will terminated the linker. - */ - -/* - * Find/Create a global symbol entry. - * - * S xxxxxx Defnnnn - * | | | - * | | `-- sp->s_addr - * | `----- sp->s_type - * `------------ sp->s_id - * - */ -struct sym * -newsym() -{ - register unsigned i ; - register unsigned nglob ; - register int c ; - struct sym *tsp; - struct sym **s; - char id[NCPS]; - - getSid(id); // old: getid(id, -1); - tsp = lkpsym(id, 1); - c = getnb();get();get(); - if (c == 'R') { - tsp->s_type |= S_REF; - if (eval()) { - fprintf(stderr, "Non zero S_REF\n"); - lkerr++; - } - } else - if (c == 'D') { - i = eval(); - if (tsp->s_type & S_DEF && tsp->s_addr != i) { - fprintf(stderr, "Multiple definition of %8s\n", id); - lkerr++; - } - tsp->s_type |= S_DEF; - /* - * Set value and area extension link. - */ - tsp->s_addr = i; - tsp->s_axp = axp; - } else { - fprintf(stderr, "Invalid symbol type %c for %8s\n", c, id); - lkexit(1); - } - /* - * Place pointer in header symbol list - */ - if (headp == NULL) { - fprintf(stderr, "No header defined\n"); - lkexit(1); - } - nglob = hp->h_nglob; - s = hp->s_list; - for (i=0; i < nglob ;++i) { - if (s[i] == NULL) { - s[i] = tsp; - return(tsp); - } - } - fprintf(stderr, "Header symbol list overflow\n"); - lkexit(1); - return(0); -} - -/*)Function sym * lkpsym(id,f) - * - * char * id symbol name string - * int f f == 0, lookup only - * f != 0, create if not found - * - * The function lookup() searches the symbol hash tables for - * a symbol name match returning a pointer to the sym structure. - * If the symbol is not found then a sym structure is created, - * initialized, and linked to the appropriate hash table if f != 0. - * A pointer to this new sym structure is returned or a NULL - * pointer is returned if f == 0. - * - * local variables: - * int h computed hash value - * sym * sp pointer to a sym structure - * - * global varaibles: - * sym * symhash[] array of pointers to NHASH - * linked symbol lists - * - * functions called: - * int hash() lksym.c - * VOID * new() lksym.c - * int symeq() lksym.c - * - * side effects: - * If the function new() fails to allocate space - * for the new sym structure the linker terminates. - */ - -struct sym * -lkpsym(id, f) -char *id; -{ - register struct sym *sp; - register int h; - - h = hash(id); - sp = symhash[h]; - while (sp != NULL) { - if (symeq(id, sp->s_id)) - return (sp); - sp = sp->s_sp; - } - if (f == 0) - return (NULL); - sp = (struct sym *) new (sizeof(struct sym)); - sp->s_sp = symhash[h]; - symhash[h] = sp; - sp->s_id = StoreString( id ); /* JLH */ - return (sp); -} - -/*)Function Addr_T symval(tsp) - * - * sym * tsp pointer to a symbol structure - * - * The function symval() returns the value of the - * relocated symbol by adding the variable definition - * value to the areax base address. - * - * local variables: - * Addr_T val relocated address value - * - * global variables: - * none - * - * functions called: - * none - * - * side effects: - * none - */ - -Addr_T -symval(tsp) -register struct sym *tsp; -{ - register Addr_T val; - - val = tsp->s_addr; - if (tsp->s_axp) { - val += tsp->s_axp->a_addr; - } - return(val); -} - -/*)Function VOID symdef(fp) - * - * FILE * fp file handle for output - * - * The function symdef() scans the hashed symbol table - * searching for variables referenced but not defined. - * Undefined variables are linked to the default - * area "_CODE" and reported as referenced by the - * appropriate module. - * - * local variables: - * int i hash table index loop variable - * sym * sp pointer to linked symbol structure - * - * global variables: - * area *areap The pointer to the first - * area structure of a linked list - * sym *symhash[NHASH] array of pointers to NHASH - * linked symbol lists - * - * functions called: - * symmod() lksym.c - * - * side effects: - * Undefined variables have their areas set to "_CODE". - */ - -VOID -symdef(fp) -FILE *fp; -{ - register struct sym *sp; - register int i; - - for (i=0; is_axp == NULL) - sp->s_axp = areap->a_axp; - if ((sp->s_type & S_DEF) == 0) - symmod(fp, sp); - sp = sp->s_sp; - } - } -} - -/*)Function VOID symmod(fp,tsp) - * - * FILE * fp output file handle - * sym * tsp pointer to a symbol structure - * - * The function symmod() scans the header structures - * searching for a reference to the symbol structure - * pointer to by tsp. The function then generates an error - * message whichs names the module having referenced the - * undefined variable. - * - * local variables: - * int i loop counter - * sym ** p pointer to a list of pointers - * to symbol structures - * - * global variables: - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * - * functions called: - * int fprintf() c_library - * - * side effects: - * Error output generated. - */ - -VOID -symmod(fp, tsp) -FILE *fp; -struct sym *tsp; -{ - register int i; - struct sym **p; - - if ((hp = headp) != NULL) { - while(hp) { - p = hp->s_list; - for (i=0; ih_nglob; ++i) { - if (p[i] == tsp) { - fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id); - fprintf(fp, "referenced by module '%s'\n", hp->m_id); - lkerr++; - } - } - hp = hp->h_hp; - } - } -} - -/*)Function int symeq(p1, p2) - * - * char * p1 name string - * char * p2 name string - * - * The function symeq() compares the two name strings for a match. - * The return value is 1 for a match and 0 for no match. - * - * local variables: - * int h loop counter - * - * global variables: - * char ccase[] an array of characters which - * perform the case translation function - * - * functions called: - * none - * - * side effects: - * none - * - */ - -int -symeq(p1, p2) -register char *p1, *p2; -{ -#if CASE_SENSITIVE - return (strcmp( p1, p2 ) == 0); -#else - return (as_strcmpi( p1, p2 ) == 0); -#endif -} - -/*)Function int hash(p) - * - * char * p pointer to string to hash - * - * The function hash() computes a hash code using the sum - * of all characters mod table size algorithm. - * - * local variables: - * int h accumulated character sum - * int n loop counter - * - * global variables: - * char ccase[] an array of characters which - * perform the case translation function - * - * functions called: - * none - * - * side effects: - * none - * - */ - -int -hash(p) -register char *p; -{ - register int h; - - h = 0; - while (*p) { - -#if CASE_SENSITIVE - h += *p++; -#else - h += ccase[*p++]; -#endif - - }; - return (h&HMASK); -} - -/*)Function VOID * new(n) - * - * unsigned int n allocation size in bytes - * - * The function new() allocates n bytes of space and returns - * a pointer to this memory. If no space is available the - * linker is terminated. - * - * local variables: - * char * p a general pointer - * char * q a general pointer - * - * global variables: - * none - * - * functions called: - * int fprintf() c_library - * VOID * malloc() c_library - * - * side effects: - * Memory is allocated, if allocation fails - * the linker is terminated. - */ - -VOID * -new(n) -unsigned int n; -{ - register char *p; - - if ((p = (char *) calloc(n, 1)) == NULL) { - fprintf(stderr, "Out of space!\n"); - lkexit(1); - } - return (p); -} diff --git a/as/link/mcs51/strcmpi.c b/as/link/mcs51/strcmpi.c deleted file mode 100644 index 434529ce..00000000 --- a/as/link/mcs51/strcmpi.c +++ /dev/null @@ -1,35 +0,0 @@ -/* strcmpi.c */ - -/* - * Compare two strings ignoring case. - * - * Taken from GLIBC 2.2.5. Original code is copyrighted "Free - * Software Foundation" and published under the GNU Lesser General - * Public License. - * - */ - -#include -#include "strcmpi.h" - -int as_strcmpi (const char *s1, const char *s2) -{ - const unsigned char *p1 = (const unsigned char *) s1; - const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - c1 = tolower (*p1++); - c2 = tolower (*p2++); - if (c1 == '\0') - break; - } - while (c1 == c2); - - return c1 - c2; -} - diff --git a/as/link/mcs51/strcmpi.h b/as/link/mcs51/strcmpi.h deleted file mode 100644 index 63c35c43..00000000 --- a/as/link/mcs51/strcmpi.h +++ /dev/null @@ -1,3 +0,0 @@ -/* strcmpi.h */ - -int as_strcmpi (const char *s1, const char *s2); diff --git a/as/mcs51/asm.h b/as/mcs51/asm.h index 5490613c..7b9c1f6f 100644 --- a/as/mcs51/asm.h +++ b/as/mcs51/asm.h @@ -89,6 +89,20 @@ #endif #endif +#ifdef _WIN32 /* WIN32 native */ + +# define NATIVE_WIN32 1 +# ifdef __MINGW32__ /* GCC MINGW32 depends on configure */ +# include "../../sdccconf.h" +# else +# include "../../sdcc_vc.h" +# define PATH_MAX _MAX_PATH +# endif + +#else /* Assume Un*x style system */ +# include "../../sdccconf.h" +#endif + /* * Assembler definitions. */ diff --git a/as/strcmpi.c b/as/strcmpi.c new file mode 100644 index 00000000..8c5ad454 --- /dev/null +++ b/as/strcmpi.c @@ -0,0 +1,34 @@ +/* strcmpi.c */ + +/* + * Compare two strings ignoring case. + * + * Taken from GLIBC 2.2.5. Original code is copyrighted "Free + * Software Foundation" and published under the GNU Lesser General + * Public License. + * + */ + +#include + +int as_strcmpi (const char *s1, const char *s2) +{ + const unsigned char *p1 = (const unsigned char *) s1; + const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + c1 = tolower (*p1++); + c2 = tolower (*p2++); + if (c1 == '\0') + break; + } + while (c1 == c2); + + return c1 - c2; +} + diff --git a/configure b/configure index ae83b810..4ea48196 100755 --- a/configure +++ b/configure @@ -7321,7 +7321,7 @@ if test $OPT_DISABLE_DS400 = 0; then fi if test $OPT_DISABLE_HC08 = 0; then - ac_config_files="$ac_config_files src/hc08/Makefile as/hc08/Makefile" + ac_config_files="$ac_config_files src/hc08/Makefile as/hc08/Makefile as/link/hc08/Makefile" test $OPT_DISABLE_DEVICE_LIB = 0 && ac_config_files="$ac_config_files device/lib/hc08/Makefile" @@ -7900,6 +7900,7 @@ do "device/lib/ds400/Makefile" ) CONFIG_FILES="$CONFIG_FILES device/lib/ds400/Makefile" ;; "src/hc08/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/hc08/Makefile" ;; "as/hc08/Makefile" ) CONFIG_FILES="$CONFIG_FILES as/hc08/Makefile" ;; + "as/link/hc08/Makefile" ) CONFIG_FILES="$CONFIG_FILES as/link/hc08/Makefile" ;; "device/lib/hc08/Makefile" ) CONFIG_FILES="$CONFIG_FILES device/lib/hc08/Makefile" ;; "src/mcs51/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/mcs51/Makefile" ;; "as/mcs51/Makefile" ) CONFIG_FILES="$CONFIG_FILES as/mcs51/Makefile" ;; diff --git a/configure.in b/configure.in index a6a969b6..25ef046b 100755 --- a/configure.in +++ b/configure.in @@ -641,7 +641,8 @@ fi if test $OPT_DISABLE_HC08 = 0; then AC_CONFIG_FILES([src/hc08/Makefile - as/hc08/Makefile]) + as/hc08/Makefile] + as/link/hc08/Makefile]) test $OPT_DISABLE_DEVICE_LIB = 0 && AC_CONFIG_FILES([device/lib/hc08/Makefile]) fi diff --git a/sdcc.dsw b/sdcc.dsw index f6f49ec2..731efe92 100644 --- a/sdcc.dsw +++ b/sdcc.dsw @@ -228,7 +228,7 @@ Package=<4> ############################################################################### -Project: "link_hc08"=.\as\hc08\link_hc08.dsp - Package Owner=<4> +Project: "link_hc08"=.\as\link\hc08\link_hc08.dsp - Package Owner=<4> Package=<5> {{{