copied only the required files to build link-gbz80 and included it on the makefile removing all the sdcc build

This commit is contained in:
Zal0
2020-04-07 07:18:44 +02:00
parent 1b7b595a06
commit 3e72fb605d
69 changed files with 19283 additions and 35 deletions

View File

@@ -26,14 +26,16 @@ TARGETSTRIP = $(TOOLSPREFIX)strip
TARGETCXXFLAGS =
# Directory containing the source to sdcc
SDCCDIR = $(TOPDIR)/sdcc
#SDCCDIR = $(ZGB_PATH)/../env/SDCC
#SDCCDIR = $(TOPDIR)/sdcc
SDCCDIR = $(ZGB_PATH)/../env/SDCC
# Directory containing the source to gbdk-lib
GBDKLIBDIR = $(TOPDIR)/gbdk-lib
# Directory containing the source to gbdk-support
GBDKSUPPORTDIR = $(TOPDIR)/gbdk-support
# Directory containing the source to maccer
MACCERDIR = $(TOPDIR)/maccer
# Directory containing the source to linker
LINKERDIR = $(TOPDIR)/link
# Base setup
# Extension to add to executables
@@ -53,7 +55,7 @@ NOISELOG = $(TOPDIR)/noise.log
all: native-build
clean: maccer-clean gbdk-support-clean gbdk-lib-clean
clean: maccer-clean linker-clean gbdk-support-clean gbdk-lib-clean
distclean: clean build-dir-clean
@@ -95,9 +97,9 @@ src: clean
tar czf gbdk-$(VER).tar.gz gbdk
# Base rules
gbdk-build: maccer-build gbdk-support-build gbdk-lib-build
gbdk-build: maccer-build linker-build gbdk-support-build gbdk-lib-build
gbdk-install: gbdk-support-install gbdk-lib-install
gbdk-install: build-bin-dir linker-install gbdk-support-install gbdk-lib-install
# Directories
build-bin-dir:
@@ -121,36 +123,7 @@ setup-from-cvs:
cvs -d :pserver:anonymous@cvs.gbdk.sourceforge.net:/cvsroot/gbdk -q co $(CVSFLAGS) gbdk-support
# Rules for sdcc
SDCCCONFIGUREFLAGS = \
--disable-mcs51-port \
--disable-avr-port \
--disable-ds390-port \
--disable-pic-port \
--disable-i186-port \
--disable-tlcs900h-port \
--disable-ucsim \
--disable-device-lib-build \
--disable-packihx
SDCCCONFIGUREFLAGS += \
--prefix=$(TARGETDIR) \
--program-suffix=$(EXEEXTENSION)
sdcc-build: $(SDCCDIR)/sdccconf.h
$(MAKE) -C $(SDCCDIR) SDCC_SUB_VERSION=$(PKG)-$(VER)
$(SDCCDIR)/sdccconf.h:
cd $(SDCCDIR); CC=$(TARGETCC) CXX=$(TARGETCXX) STRIP=$(TARGETSTRIP) RANLIB=$(TARGETRANLIB) CXXFLAGS=$(TARGETCXXFLAGS) ./configure $(SDCCCONFIGUREFLAGS) --host=$(HOSTOS)
sdcc-install: sdcc-build build-bin-dir
rm -fr tmp
$(MAKE) -C $(SDCCDIR) install prefix=$(TOPDIR)/tmp
cp tmp/bin/sdcc* tmp/bin/sdcpp* tmp/bin/link-* tmp/bin/as-* $(BUILDDIR)/bin
# PENDING: Hack below
sdcc-clean:
-$(MAKE) -C $(SDCCDIR) distclean
touch $(SDCCDIR)/doc/holder.pdf
# Rules for gbdk-support
gbdk-support-build:
@@ -184,10 +157,21 @@ gbdk-lib-examples-makefile:
# Rules for maccer
maccer-build:
$(MAKE) -C $(MACCERDIR)
$(MAKE) -C $(MACCERDIR) BUILDDIR=$(BUILDDIR)
maccer-clean:
$(MAKE) -C $(MACCERDIR) clean
#rules for linker
linker-build:
$(MAKE) -C $(LINKERDIR)
linker-install:
$(MAKE) -C $(LINKERDIR) install BUILDDIR=$(BUILDDIR)
linker-clean:
$(MAKE) -C $(LINKERDIR) clean
# Final binary
binary: binary-tidyup

16
link/Makefile Normal file
View File

@@ -0,0 +1,16 @@
PRJDIR = ./
LINK_DIR = $(shell pwd)
include Makefile.common
PORTS = gbz80
all:
$(MAKE) -C z80 _link-gbz80 E=$(E) BUILDDIR=../bin/
install: all
$(INSTALL) $(PRJDIR)/bin/link-gbz80 `echo $(BUILDDIR)/bin/link-gbz80|sed '$(transform)'`
$(STRIP) `echo $(BUILDDIR)/bin/link-gbz80.exe|sed '$(transform)'`
include clean.mk

65
link/Makefile.common Normal file
View File

@@ -0,0 +1,65 @@
# Generated automatically from Makefile.common.in by configure.
#
#
#
# HACK
PORT = mcs51
# Version
VERSION = 2.3.1
VERSIONHI = 2
VERSIONLO = 3
VERSIONP = 1
# Programs
SHELL = /bin/sh
CC = gcc
CPP = gcc -E
RANLIB = ranlib
INSTALL = install -c
YACC = bison -y
LEX = flex
AWK = gawk
STRIP = strip
prefix = /opt/gbdk
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
libdir = ${exec_prefix}/lib
datadir = ${prefix}/share
includedir = ${prefix}/include
mandir = ${prefix}/man
man1dir = $(mandir)/man1
man2dir = $(mandir)/man2
infodir = ${prefix}/info
srcdir = .
docdir = ${prefix}/share/doc/sdcc
# Modules to enable/disable
OPT_ENABLE_UCSIM = no
OPT_ENABLE_DEVICE_LIB_BUILD = no
OPT_ENABLE_PACKIHX = no
SLIB = $(PRJDIR)/support/Util
transform = s,$$,,;
# Flags
DEFS = $(subs -DHAVE_CONFIG_H,,-DHAVE_CONFIG_H)
CPPFLAGS = $(INCLUDEFLAGS) -I. -I$(PRJDIR) -I$(SLIB)
CFLAGS = -ggdb -O2 -pipe -Wall
M_OR_MM = -MM
EXTRALIBS =
# Shared settings between all the sub Makefiles
# Done here so that we don't have to start a Make from the top levelport
# directory.
# Library compilation options
SCC = $(PRJDIR)/src/sdcc
SAS = $(PRJDIR)/as/$(PORT)/as
CLEANSPEC = *.lst *.asm *.sym *~ *.cdb *.dep *.rul
OBJ = $(SOURCES:.c=.o)

8
link/README Normal file
View File

@@ -0,0 +1,8 @@
sdcc/link
---------
In gbdk the linker and assembler were split into seperate packages.
For now I'm keeping that split, and leaving the mcs51 version as is.
-- Michael

20
link/as/Makefile Normal file
View File

@@ -0,0 +1,20 @@
PRJDIR = ..
include $(PRJDIR)/Makefile.common
PORTS = z80 gbz80
DOCS = README abstra.doc appendk.txt asmlnk.doc asxhtm.html format.txt
all:
$(MAKE) -C z80 _as-z80 _as-gbz80 E=$(E) BUILDDIR=../../bin/
install: all install-doc
$(INSTALL) $(PRJDIR)/bin/as-z80 `echo $(bindir)/as-z80|sed '$(transform)'`
$(STRIP) `echo $(bindir)/as-z80|sed '$(transform)'`
$(INSTALL) $(PRJDIR)/bin/as-gbz80 `echo $(bindir)/as-gbz80|sed '$(transform)'`
$(STRIP) `echo $(bindir)/as-gbz80|sed '$(transform)'`
install-doc:
$(INSTALL) -d $(docdir)/aslink
cp -f `find doc -maxdepth 1 -not -type d` $(docdir)/aslink
include clean.mk

5
link/as/README Normal file
View File

@@ -0,0 +1,5 @@
sdcc/as
-------
Both the z80 and mcs51 assemblers are derrived from the same tree. One
day they may be re-combined.

131
link/as/as_z80.dsp Normal file
View File

@@ -0,0 +1,131 @@
# Microsoft Developer Studio Project File - Name="as_z80" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=as_z80 - 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 "as_z80.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 "as_z80.mak" CFG="as_z80 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "as_z80 - 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
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "as_z80___Win32_Debug"
# PROP BASE Intermediate_Dir "as_z80___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "z80"
# PROP Intermediate_Dir "z80"
# 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 /G3 /ML /W3 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /J /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 /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\as-z80.exe" /pdbtype:sept
# SUBTRACT LINK32 /incremental:no
# Begin Target
# Name "as_z80 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\z80\asdata.c
# End Source File
# Begin Source File
SOURCE=.\z80\asexpr.c
# End Source File
# Begin Source File
SOURCE=.\z80\aslex.c
# End Source File
# Begin Source File
SOURCE=.\z80\aslist.c
# End Source File
# Begin Source File
SOURCE=.\z80\asmain.c
# End Source File
# Begin Source File
SOURCE=.\z80\asout.c
# End Source File
# Begin Source File
SOURCE=.\z80\assubr.c
# End Source File
# Begin Source File
SOURCE=.\z80\assym.c
# End Source File
# Begin Source File
SOURCE=.\z80\z80adr.c
# End Source File
# Begin Source File
SOURCE=.\z80\z80ext.c
# End Source File
# Begin Source File
SOURCE=.\z80\z80mch.c
# End Source File
# Begin Source File
SOURCE=.\z80\z80pst.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\z80\alloc.h
# End Source File
# Begin Source File
SOURCE=.\z80\asm.h
# End Source File
# Begin Source File
SOURCE=.\z80\string.h
# End Source File
# Begin Source File
SOURCE=.\z80\z80.h
# End Source File
# 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

143
link/as/aslink.dsp Normal file
View File

@@ -0,0 +1,143 @@
# Microsoft Developer Studio Project File - Name="aslink" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=aslink - 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 "aslink.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 "aslink.mak" CFG="aslink - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "aslink - 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
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "aslink___Win32_Debug"
# PROP BASE Intermediate_Dir "aslink___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "mcs51"
# PROP Intermediate_Dir "mcs51"
# 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 /G3 /ML /W3 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /J /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 /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\aslink.exe" /pdbtype:sept
# SUBTRACT LINK32 /incremental:no /nodefaultlib
# Begin Target
# Name "aslink - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=mcs51\lkarea.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkdata.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkeval.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkhead.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkihx.c
# End Source File
# Begin Source File
SOURCE=mcs51\lklex.c
# End Source File
# Begin Source File
SOURCE=mcs51\lklibr.c
# End Source File
# Begin Source File
SOURCE=mcs51\lklist.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkmain.c
# End Source File
# Begin Source File
SOURCE=mcs51\lknoice.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkrloc.c
# End Source File
# Begin Source File
SOURCE=mcs51\lks19.c
# End Source File
# Begin Source File
SOURCE=mcs51\lkstore.c
# End Source File
# Begin Source File
SOURCE=mcs51\lksym.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\mcs51\alloc.h
# End Source File
# Begin Source File
SOURCE=.\mcs51\aslink.h
# End Source File
# Begin Source File
SOURCE=.\mcs51\asm.h
# End Source File
# Begin Source File
SOURCE=.\mcs51\i8051.h
# End Source File
# Begin Source File
SOURCE=.\mcs51\string.h
# End Source File
# 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

131
link/as/asx8051.dsp Normal file
View File

@@ -0,0 +1,131 @@
# Microsoft Developer Studio Project File - Name="asx8051" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=asx8051 - 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 "asx8051.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 "asx8051.mak" CFG="asx8051 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "asx8051 - 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
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# 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 "mcs51"
# PROP Intermediate_Dir "mcs51"
# 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 /G3 /ML /W3 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /J /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 /nologo /subsystem:console /debug /machine:I386 /out:"\sdcc\bin\asx8051.exe" /pdbtype:sept
# SUBTRACT LINK32 /incremental:no
# Begin Target
# Name "asx8051 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=mcs51\asdata.c
# End Source File
# Begin Source File
SOURCE=mcs51\asexpr.c
# End Source File
# Begin Source File
SOURCE=mcs51\aslex.c
# End Source File
# Begin Source File
SOURCE=mcs51\aslist.c
# End Source File
# Begin Source File
SOURCE=mcs51\asmain.c
# End Source File
# Begin Source File
SOURCE=mcs51\asnoice.c
# End Source File
# Begin Source File
SOURCE=mcs51\asout.c
# End Source File
# Begin Source File
SOURCE=mcs51\asstore.c
# End Source File
# Begin Source File
SOURCE=mcs51\assubr.c
# End Source File
# Begin Source File
SOURCE=mcs51\assym.c
# End Source File
# Begin Source File
SOURCE=mcs51\i51adr.c
# End Source File
# Begin Source File
SOURCE=mcs51\i51ext.c
# End Source File
# Begin Source File
SOURCE=mcs51\i51mch.c
# End Source File
# Begin Source File
SOURCE=mcs51\i51pst.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\mcs51\asm.h
# End Source File
# Begin Source File
SOURCE=.\mcs51\i8051.h
# End Source File
# 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

6
link/as/clean.mk Normal file
View File

@@ -0,0 +1,6 @@
clean:
$(MAKE) -C z80 -f clean.mk clean
distclean:
$(MAKE) -C z80 -f clean.mk distclean

53
link/as/z80/Makefile Normal file
View File

@@ -0,0 +1,53 @@
PRJDIR = ../..
include $(PRJDIR)/Makefile.common
OBJDIR = obj/$(EXT)
SDC = .
SLIBSRC = NewAlloc.c
SRC = asdata.c asexpr.c aslex.c aslist.c asmain.c asout.c \
assubr.c assym.c z80adr.c z80ext.c z80mch.c z80pst.c
OBJS = $(SRC:%.c=$(OBJDIR)/%.o)
SLIBOBJS = $(SLIBSRC:%.c=$(OBJDIR)/%.o)
BINS = $(BUILDDIR)as$(EXT)
CFLAGS += $(CPPFLAGS) $(OPTS) -I. -DINDEXLIB -DMLH_MAP -DUNIX -DSDK
CFLAGS += -funsigned-char
CFLAGS += -I$(SLIB)
LDFLAGS += -lm $(EXTRALIBS)
all: $(OBJDIR) dep $(BINS)
dep: Makefile.dep
Makefile.dep: $(SRC) *.h
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(SRC) > Makefile.dep
include Makefile.dep
$(OBJDIR):
mkdir -p $(OBJDIR)
$(BINS): $(OBJS) $(SLIBOBJS)
$(CC) -o $(BINS) $(OBJS) $(SLIBOBJS) $(LDFLAGS)
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: $(SLIB)/%.c
$(CC) -c $(CFLAGS) -o $@ $<
_as-z80:
$(MAKE) EXT=-z80$(E)
_as-gbz80:
$(MAKE) EXT=-gbz80$(E) OPTS=-DGAMEBOY
include clean.mk

97
link/as/z80/Makefile.in Normal file
View File

@@ -0,0 +1,97 @@
#
#
#
VERSION = @VERSION@
VERSIONHI = @VERSIONHI@
VERSIONLO = @VERSIONLO@
VERSIONP = @VERSIONP@
SHELL = /bin/sh
CC = @CC@
CPP = @CPP@
INSTALL = @INSTALL@
PRJDIR = ../..
srcdir = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
datadir = @datadir@
includedir = @include@
mandir = @mandir@
man1dir = $(mandir)/man1
man2dir = $(mandir)/man2
infodir = @infodir@
CPPFLAGS = @CPPFLAGS@ -I. -I$(PRJDIR)
CFLAGS = @CFLAGS@ -Wall -DINDEXLIB -DMLH_MAP -DUNIX -DSDK -funsigned-char -ggdb
M_OR_MM = @M_OR_MM@
LDFLAGS = @LDFLAGS@ -lm
ASOBJECTS = asdata.o asexpr.o aslex.o aslist.o asmain.o asout.o \
assubr.o assym.o z80adr.o z80ext.o z80mch.o z80pst.o
ASSOURCES = $(patsubst %.o,%.c,$(ASOBJECTS))
ASXZ80 = $(PRJDIR)/bin/as-z80
# Compiling entire program or any subproject
# ------------------------------------------
all: checkconf $(ASXZ80)
$(ASXZ80): $(ASOBJECTS)
$(CC) $(CFLAGS) -o $@ $(ASOBJECTS) $(LDFLAGS)
# Compiling and installing everything and runing test
# ---------------------------------------------------
install: all installdirs
$(INSTALL) $(ASXZ80) $(bindir)/as-z80
# Deleting all the installed files
# --------------------------------
uninstall:
rm -f $(bindir)/as-z80
# Performing self-test
# --------------------
check:
# Performing installation test
# ----------------------------
installcheck:
# Creating installation directories
# ---------------------------------
installdirs:
$(INSTALL) -d $(bindir)
# Creating dependencies
# ---------------------
dep: Makefile.dep
Makefile.dep: $(ASSOURCES) *.h $(PRJDIR)/*.h
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(ASSOURCES) >Makefile.dep
include Makefile.dep
include clean.mk
# My rules
# --------
.c.o:
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
# Remaking configuration
# ----------------------
checkconf:
@if [ -f $(PRJDIR)/devel ]; then\
$(MAKE) -f conf.mk srcdir="$(srcdir)" PRJDIR="$(PRJDIR)" freshconf;\
fi
# End of Makefile

10
link/as/z80/alloc.h Normal file
View File

@@ -0,0 +1,10 @@
/* alloc.h */
/* DECUS C */
#ifndef SDK
//extern char *alloc();
//extern char *malloc();
//extern char *calloc();
//extern char *realloc();
#endif

279
link/as/z80/asdata.c Normal file
View File

@@ -0,0 +1,279 @@
/* asdata.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include "asm.h"
/*)Module asdata.c
*
* The module asdata.c contains the global constants,
* structures, and variables used in the assembler.
*/
int aserr; /* ASxxxx error counter
*/
jmp_buf jump_env; /* compiler dependent structure
* used by setjmp() and longjmp()
*/
int inpfil; /* count of assembler
* input files specified
*/
int incfil; /* current file handle index
* for include files
*/
int cfile; /* current file handle index
* of input assembly files
*/
int flevel; /* IF-ELSE-ENDIF flag will be non
* zero for false conditional case
*/
int tlevel; /* current conditional level
*/
int ifcnd[MAXIF+1]; /* array of IF statement condition
* values (0 = FALSE) indexed by tlevel
*/
int iflvl[MAXIF+1]; /* array of IF-ELSE-ENDIF flevel
* values indexed by tlevel
*/
char afn[FILSPC]; /* afile temporary file name
*/
char srcfn[MAXFIL][FILSPC]; /* array of source file names
*/
int srcline[MAXFIL]; /* source line number
*/
char incfn[MAXINC][FILSPC]; /* array of include file names
*/
int incline[MAXINC]; /* include line number
*/
int radix; /* current number conversion radix:
* 2 (binary), 8 (octal), 10 (decimal),
* 16 (hexadecimal)
*/
int line; /* current assembler source
* line number
*/
int page; /* current page number
*/
int lop; /* current line number on page
*/
int pass; /* assembler pass number
*/
int lflag; /* -l, generate listing flag
*/
int gflag; /* -g, make undefined symbols global flag
*/
int aflag; /* -a, make all symbols global flag
*/
int oflag; /* -o, generate relocatable output flag
*/
int sflag; /* -s, generate symbol table flag
*/
int pflag; /* -p, enable listing pagination
*/
int xflag; /* -x, listing radix flag
*/
int fflag; /* -f(f), relocations flagged flag
*/
Addr_T laddr; /* address of current assembler line
* or value of .if argument
*/
Addr_T fuzz; /* tracks pass to pass changes in the
* address of symbols caused by
* variable length instruction formats
*/
int lmode; /* listing mode
*/
char *ep; /* pointer into error list
* array eb[NERR]
*/
char eb[NERR]; /* array of generated error codes
*/
char *ip; /* pointer into the assembler-source
* text line in ib[]
*/
char ib[NINPUT]; /* assembler-source text line
*/
char *cp; /* pointer to assembler output
* array cb[]
*/
char cb[NCODE]; /* array of assembler output values
*/
int *cpt; /* pointer to assembler relocation type
* output array cbt[]
*/
int cbt[NCODE]; /* array of assembler relocation types
* describing the data in cb[]
*/
char tb[NTITL]; /* Title string buffer
*/
char stb[NSBTL]; /* Subtitle string buffer
*/
char symtbl[] = { "Symbol Table" };
char aretbl[] = { "Area Table" };
char module[NCPS]; /* module name string
*/
/*
* The mne structure is a linked list of the assembler
* mnemonics and directives. The list of mnemonics and
* directives contained in the device dependent file
* xxxpst.c are hashed and linked into NHASH lists in
* module assym.c by syminit(). The structure contains
* the mnemonic/directive name, a subtype which directs
* the evaluation of this mnemonic/directive, a flag which
* is used to detect the end of the mnemonic/directive
* list in xxxpst.c, and a value which is normally
* associated with the assembler mnemonic base instruction
* value.
*
* struct mne
* {
* struct mne *m_mp; Hash link
* char m_id[NCPS]; Mnemonic
* char m_type; Mnemonic subtype
* char m_flag; Mnemonic flags
* Addr_T m_valu; Value
* };
*/
struct mne *mnehash[NHASH];
/*
* The sym structure is a linked list of symbols defined
* in the assembler source files. The first symbol is "."
* defined here. The entry 'struct tsym *s_tsym'
* links any temporary symbols following this symbol and
* preceeding the next normal symbol. The structure also
* contains the symbol's name, type (USER or NEW), flag
* (global, assigned, and multiply defined), a pointer
* to the area structure defining where the symbol is
* located, a reference number assigned by outgsd() in
* asout.c, and the symbols address relative to the base
* address of the area where the symbol is located.
*
* struct sym
* {
* struct sym *s_sp; Hash link
* struct tsym *s_tsym; Temporary symbol link
* char s_id[NCPS]; Symbol
* char s_type; Symbol subtype
* char s_flag; Symbol flags
* struct area *s_area; Area line, 0 if absolute
* int s_ref; Ref. number
* Addr_T s_addr; Address
* };
*/
struct sym sym[] = {
{ NULL, NULL, ".", S_USER, S_END, NULL, 0, }
};
struct sym *symp; /* pointer to a symbol structure
*/
struct sym *symhash[NHASH]; /* array of pointers to NHASH
* linked symbol lists
*/
/*
* The area structure contains the parameter values for a
* specific program or data section. The area structure
* is a linked list of areas. The initial default area
* is "_CODE" defined here, the next area structure
* will be linked to this structure through the structure
* element 'struct area *a_ep'. The structure contains the
* area name, area reference number ("_CODE" is 0) determined
* by the order of .area directives, area size determined
* from the total code and/or data in an area, area fuzz is
* an variable used to track pass to pass changes in the
* area size caused by variable length instruction formats,
* and area flags which specify the area's relocation type.
*
* struct area
* {
* struct area *a_ap; Area link
* char a_id[NCPS]; Area Name
* int a_ref; Reference number
* Addr_T a_size; Area size
* Addr_T a_fuzz; Area fuzz
* int a_flag; Area flags
* };
*/
struct area area[] = {
{ NULL, "_CODE", 0, 0, 0, A_CON|A_REL }
};
struct area *areap; /* pointer to an area structure
*/
FILE *lfp; /* list output file handle
*/
FILE *ofp; /* relocation output file handle
*/
FILE *tfp; /* symbol table output file handle
*/
FILE *sfp[MAXFIL]; /* array of assembler-source file handles
*/
FILE *ifp[MAXINC]; /* array of include-file file handles
*/
/*
* array of character types, one per
* ASCII character
*/
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

667
link/as/z80/asexpr.c Normal file
View File

@@ -0,0 +1,667 @@
/* asexpr.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include "asm.h"
/*)Module asexpr.c
*
* The module asexpr.c contains the routines to evaluate
* arithmetic/numerical expressions. The functions in
* asexpr.c perform a recursive evaluation of the arithmetic
* expression read from the assembler-source 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.
*
* asexpr.c contains the following functions:
* VOID abscheck()
* Addr_T absexpr()
* VOID clrexpr()
* int digit()
* VOID expr()
* int oprio()
* VOID term()
*
* asexpr.c contains no local/static variables
*/
/*)Function VOID expr(esp, n)
*
* expr * esp pointer to an expr structure
* 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
* stores its value and relocation information into
* the expr structure supplied by the user.
*
* local variables:
* int c current assembler-source
* text character
* int p current operator priority
* area * ap pointer to an area structure
* exp re internal expr structure
*
* global variables:
* char ctype[] array of character types, one per
* ASCII character
*
* functions called:
* VOID abscheck() asexpr.c
* VOID clrexpr() asexpr.c
* VOID expr() asexpr.c
* int getnb() aslex.c
* int oprio() asexpr.c
* VOID qerr() assubr.c
* VOID rerr() assubr.c
* VOID term() asexpr.c
* VOID unget() aslex.c
*
*
* side effects:
* An expression is evaluated modifying the user supplied
* expr structure, a sym structure maybe created for an
* undefined symbol, and the parse of the expression may
* terminate if a 'q' error occurs.
*/
VOID
expr(esp, n)
register struct expr *esp;
int n;
{
register int c, p;
struct area *ap;
struct expr re;
term(esp);
while (ctype[c = getnb()] & BINOP) {
/*
* Handle binary operators + - * / & | % ^ << >>
*/
if ((p = oprio(c)) <= n)
break;
if ((c == '>' || c == '<') && c != get())
qerr();
clrexpr(&re);
expr(&re, p);
esp->e_rlcf |= re.e_rlcf;
if (c == '+') {
/*
* esp + re, at least one must be absolute
*/
if (esp->e_base.e_ap == NULL) {
/*
* esp is absolute (constant),
* use area from re
*/
esp->e_base.e_ap = re.e_base.e_ap;
} else
if (re.e_base.e_ap) {
/*
* re should be absolute (constant)
*/
rerr();
}
if (esp->e_flag && re.e_flag)
rerr();
if (re.e_flag)
esp->e_flag = 1;
esp->e_addr += re.e_addr;
} else
if (c == '-') {
/*
* esp - re
*/
if ((ap = re.e_base.e_ap) != NULL) {
if (esp->e_base.e_ap == ap) {
esp->e_base.e_ap = NULL;
} else {
rerr();
}
}
if (re.e_flag)
rerr();
esp->e_addr -= re.e_addr;
} else {
/*
* Both operands (esp and re) must be constants
*/
abscheck(esp);
abscheck(&re);
switch (c) {
case '*':
esp->e_addr *= re.e_addr;
break;
case '/':
esp->e_addr /= re.e_addr;
break;
case '&':
esp->e_addr &= re.e_addr;
break;
case '|':
esp->e_addr |= re.e_addr;
break;
case '%':
esp->e_addr %= re.e_addr;
break;
case '^':
esp->e_addr ^= re.e_addr;
break;
case '<':
esp->e_addr <<= re.e_addr;
break;
case '>':
esp->e_addr >>= re.e_addr;
break;
default:
qerr();
break;
}
}
}
unget(c);
}
/*)Function Addr_T absexpr()
*
* The function absexpr() evaluates an expression, verifies it
* is absolute (i.e. not position dependent or relocatable), and
* returns its value.
*
* local variables:
* expr e expr structure
*
* global variables:
* none
*
* functions called:
* VOID abscheck() asexpr.c
* VOID clrexpr() asexpr.c
* VOID expr() asexpr.c
*
* side effects:
* If the expression is not absolute then
* a 'r' error is reported.
*/
Addr_T
absexpr()
{
struct expr e;
clrexpr(&e);
expr(&e, 0);
abscheck(&e);
return (e.e_addr);
}
/*)Function VOID term(esp)
*
* expr * esp pointer to an expr structure
*
* The function term() evaluates a single constant
* or symbol value prefaced by any unary operator
* ( +, -, ~, ', ", >, or < ). This routine is also
* responsible for setting the relocation type to symbol
* based (e.flag != 0) on global references.
*
* local variables:
* int c current character
* char id[] symbol name
* char * jp pointer to assembler-source text
* int n constant evaluation running sum
* int r current evaluation radix
* sym * sp pointer to a sym structure
* tsym * tp pointer to a tsym structure
* int v current digit evaluation
*
* global variables:
* char ctype[] array of character types, one per
* ASCII character
* sym * symp pointer to a symbol structure
*
* functions called:
* VOID abscheck() asexpr.c
* int digit() asexpr.c
* VOID err() assubr.c
* VOID expr() asexpr.c
* int is_abs() asexpr.c
* int get() aslex.c
* VOID getid() aslex.c
* int getmap() aslex.c
* int getnb() aslex.c
* sym * lookup() assym.c
* VOID qerr() assubr.c
* VOID unget() aslex.c
*
* side effects:
* An arithmetic term is evaluated, a symbol structure
* may be created, term evaluation may be terminated
* by a 'q' error.
*/
VOID
term(esp)
register struct expr *esp;
{
register int c, n;
register char *jp;
char id[NCPS];
struct sym *sp;
struct tsym *tp;
int r = 0, v;
c = getnb();
/*
* Discard the unary '+' at this point and
* also any reference to numerical arguments
* associated with the '#' prefix.
*/
while (c == '+' || c == '#') { c = getnb(); }
/*
* Evaluate all binary operators
* by recursively calling expr().
*/
if (c == LFTERM) {
expr(esp, 0);
if (getnb() != RTTERM)
qerr();
return;
}
if (c == '-') {
expr(esp, 100);
abscheck(esp);
esp->e_addr = 0 - esp->e_addr;
return;
}
if (c == '~') {
expr(esp, 100);
abscheck(esp);
esp->e_addr = ~esp->e_addr;
return;
}
if (c == '\'') {
esp->e_mode = S_USER;
esp->e_addr = getmap(-1)&0377;
return;
}
if (c == '\"') {
esp->e_mode = S_USER;
if (hilo) {
esp->e_addr = (getmap(-1)&0377)<<8;
esp->e_addr |= (getmap(-1)&0377);
} else {
esp->e_addr = (getmap(-1)&0377);
esp->e_addr |= (getmap(-1)&0377)<<8;
}
return;
}
if (c == '>' || c == '<') {
expr(esp, 100);
if (is_abs (esp)) {
/*
* evaluate msb/lsb directly
*/
if (c == '>')
esp->e_addr >>= 8;
esp->e_addr &= 0377;
return;
} else {
/*
* let linker perform msb/lsb, lsb is default
*/
esp->e_rlcf |= R_BYT2;
if (c == '>')
esp->e_rlcf |= R_MSB;
return;
}
}
/*
* Evaluate digit sequences as local symbols
* if followed by a '$' or as constants.
*/
if (ctype[c] & DIGIT) {
esp->e_mode = S_USER;
jp = ip;
while (ctype[(unsigned char)(*jp)] & RAD10) {
jp++;
}
if (*jp == '$') {
n = 0;
while ((v = digit(c, 10)) >= 0) {
n = 10*n + v;
c = get();
}
tp = symp->s_tsym;
while (tp) {
if (n == tp->t_num) {
esp->e_base.e_ap = tp->t_area;
esp->e_addr = tp->t_addr;
return;
}
tp = tp->t_lnk;
}
err('u');
return;
}
r = radix;
if (c == '0') {
c = get();
switch (c) {
case 'b':
case 'B':
r = 2;
c = get();
break;
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;
}
}
n = 0;
while ((v = digit(c, r)) >= 0) {
n = r*n + v;
c = get();
}
unget(c);
esp->e_addr = n;
return;
}
/*
* Evaluate '$' sequences as a temporary radix
* if followed by a '%', '&', '#', or '$'.
*/
if (c == '$') {
c = get();
if (c == '%' || c == '&' || c == '#' || c == '$') {
switch (c) {
case '%':
r = 2;
break;
case '&':
r = 8;
break;
case '#':
r = 10;
break;
case '$':
r = 16;
break;
default:
break;
}
c = get();
n = 0;
while ((v = digit(c, r)) >= 0) {
n = r*n + v;
c = get();
}
unget(c);
esp->e_mode = S_USER;
esp->e_addr = n;
return;
}
unget(c);
c = '$';
}
/*
* Evaluate symbols and labels
*/
if (ctype[c] & LETTER) {
esp->e_mode = S_USER;
getid(id, c);
sp = lookup(id);
if (sp->s_type == S_NEW) {
if (sp->s_flag&S_GBL) {
esp->e_flag = 1;
esp->e_base.e_sp = sp;
return;
}
err('u');
} else {
esp->e_mode = sp->s_type;
esp->e_addr = sp->s_addr;
esp->e_base.e_ap = sp->s_area;
}
return;
}
/*
* Else not a term.
*/
qerr();
}
/*)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 VOID abscheck(esp)
*
* expr * esp pointer to an expr structure
*
* The function abscheck() tests the evaluation of an
* expression to verify it is absolute. If the evaluation
* is relocatable then an 'r' error is noted and the expression
* made absolute.
*
* Note: The area type (i.e. ABS) is not checked because
* the linker can be told to explicitly relocate an
* absolute area.
*
* local variables:
* none
*
* global variables:
* none
*
* functions called:
* VOID rerr() assubr.c
*
* side effects:
* The expression may be changed to absolute and the
* 'r' error invoked.
*/
VOID
abscheck(esp)
register struct expr *esp;
{
if (esp->e_flag || esp->e_base.e_ap) {
esp->e_flag = 0;
esp->e_base.e_ap = NULL;
rerr();
}
}
/*)Function int is_abs(esp)
*
* expr * esp pointer to an expr structure
*
* The function is_abs() tests the evaluation of an
* expression to verify it is absolute. If the evaluation
* is absolute then 1 is returned, else 0 is returned.
*
* Note: The area type (i.e. ABS) is not checked because
* the linker can be told to explicitly relocate an
* absolute area.
*
* local variables:
* none
*
* global variables:
* none
*
* functions called:
* none
*
* side effects:
* none
*/
int
is_abs (esp)
register struct expr *esp;
{
if (esp->e_flag || esp->e_base.e_ap) {
return(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);
}
/*)Function VOID clrexpr(esp)
*
* expr * esp pointer to expression structure
*
* The function clrexpr() clears the expression structure.
*
* local variables:
* none
*
* global variables:
* none
*
* functions called:
* none
*
* side effects:
* expression structure cleared.
*/
VOID
clrexpr(esp)
register struct expr *esp;
{
esp->e_mode = 0;
esp->e_flag = 0;
esp->e_addr = 0;
esp->e_base.e_ap = NULL;
esp->e_rlcf = 0;
}

502
link/as/z80/aslex.c Normal file
View File

@@ -0,0 +1,502 @@
/* aslex.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber, M. Hope
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include "asm.h"
/*)Module aslex.c
*
* The module aslex.c includes the general lexical
* analysis routines for the assembler.
*
* aslex.c contains the following functions:
* char endline()
* char get()
* VOID getid(id,c)
* int getLine_()
* int getmap()
* char getnb()
* VOID getst()
* int more()
* VOID unget(c)
*
* aslex.c contains no local/static 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, first
* character must be a LETTER
*
* The function getid() scans the current assembler-source 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 and the first character found
* must be a LETTER else a 'q' error terminates the parse of this
* assembler-source text line.
*
* 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() aslex.c
* char getnb() aslex.c
* VOID unget() aslex.c
*
* side effects:
* use of getnb(), get(), and unget() updates the
* global pointer ip, the position in the current
* assembler-source text line.
*/
VOID
getid(id, c)
register int c;
char *id;
{
register char *p;
if (c < 0) {
c = getnb();
if ((ctype[c] & LETTER) == 0)
qerr();
}
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 getst(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, first
* character must be a LETTER
*
* The function getnbid() scans the current assembler-source text line
* from the current position copying the next character string into
* the external string buffer (id). The string ends when a SPACE or
* ILL 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 and the first character found
* must be a LETTER else a 'q' error terminates the parse of this
* assembler-source text line.
*
* 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() aslex.c
* char getnb() aslex.c
* VOID unget() aslex.c
*
* side effects:
* use of getnb(), get(), and unget() updates the
* global pointer ip, the position in the current
* assembler-source text line.
*/
VOID
getst(id, c)
register int c;
char *id;
{
register char *p;
if (c < 0) {
c = getnb();
if ((ctype[c] & LETTER) == 0)
qerr();
}
p = id;
do {
if (p < &id[NCPS])
*p++ = c;
} while (ctype[c=get()] & ~(SPACE|ILL));
unget(c);
while (p < &id[NCPS])
*p++ = 0;
}
/*)Function char getnb()
*
* The function getnb() scans the current assembler-source
* text line returning the first character not a SPACE or TAB.
*
* local variables:
* int c current character from
* assembler-source text line
*
* global variables:
* none
*
* called functions:
* char get() aslex.c
*
* side effects:
* use of get() updates the global pointer ip, the position
* in the current assembler-source text line
*/
char
getnb()
{
register int c;
while ((c=get()) == ' ' || c == '\t')
;
return (c);
}
/*)Function char get()
*
* The function get() returns the next character in the
* assembler-source text line, at the end of the line a
* NULL character is returned.
*
* local variables:
* int c current character from
* assembler-source text line
*
* global variables:
* char * ip pointer into the current
* assembler-source text line
*
* called functions:
* none
*
* side effects:
* updates ip to the next character position in the
* assembler-source 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
* assembler-source text line
*
* If (c) is not a NULL character then the global pointer ip
* is updated to point to the preceeding character in the
* assembler-source text line.
*
* NOTE: This function does not push the character (c)
* back into the assembler-source text line, only
* the pointer ip is changed.
*
* local variables:
* int c last character read from
* assembler-source text line
*
* global variables:
* char * ip position into the current
* assembler-source text line
*
* called functions:
* none
*
* side effects:
* ip decremented by 1 character position
*/
VOID
unget(c)
{
if (c)
if (ip != ib)
--ip;
}
/*)Function int getmap(d)
*
* int d value to compare with the
* assembler-source 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 the
* assembler-source text line
* int n looping counter
* int v current value of numeric conversion
*
* global variables:
* none
*
* called functions:
* char get() aslex.c
*
* side effects:
* use of get() updates the global pointer ip the position
* in the current assembler-source text line
*/
int
getmap(d)
{
register int c, n, v;
if ((c=get()) == '\0')
qerr();
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 getLine_()
*
* The function getLine_() reads a line of assembler-source text
* from an assembly source text file or an include file.
* Lines of text are processed from assembler-source files until
* all files have been read. If an include file is opened then
* lines of text are read from the include file (or nested
* include file) until the end of the include file is found.
* The input text line is copied into the global string ib[]
* and converted to a NULL terminated string. The function
* getLine_() returns a (1) after succesfully reading a line
* or a (0) if all files have been read.
*
* local variables:
* int i string length
*
* global variables:
* char ib[] string buffer containing
* assembler-source text line
* char ifp[] array of file handles for
* include files
* int incfil index for ifp[] specifies
* active include file
* int incline[] array of include file
* line numbers
* char sfp[] array of file handles for
* assembler source files
* int cfile index for sfp[] specifies
* active source file
* int srcline[] array of source file
* line numbers
* int inpfil maximum input file index
*
* called functions:
* int fclose() c-library
* char * fgets() c-library
* int strlen() c-library
*
* side effects:
* include file will be closed at detection of end of file.
* the next sequential source file may be selected.
* the global file indexes incfil or cfile may be changed.
* The respective source line or include line counter
* will be updated.
*/
int
getLine_()
{
register int i;
loop: if (incfil >= 0) {
if (fgets(ib, sizeof ib, ifp[incfil]) == NULL) {
#ifdef SDK
fclose(ifp[incfil]);
ifp[incfil--] = NULL;
#else /* SDK */
fclose(ifp[incfil--]);
#endif /* SDK */
lop = NLPP;
goto loop;
} else {
++incline[incfil];
}
} else {
if (fgets(ib, sizeof ib, sfp[cfile]) == NULL) {
if (++cfile <= inpfil) {
srcline[cfile] = 0;
goto loop;
}
return (0);
} else {
++srcline[cfile];
}
}
i = strlen(ib) - 1;
if (ib[i] == '\n')
ib[i] = 0;
if (i >= 1 && ib[i-1] == '\r')
ib[i-1] = 0;
return (1);
}
/*)Function int more()
*
* The function more() scans the assembler-source 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
* assembler-source text line
*
* global variables:
* none
*
* called functions:
* char getnb() aslex.c
* VOID unget() aslex.c
*
* side effects:
* use of getnb() and unget() updates the global pointer ip
* the position in the current assembler-source 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 assembler-source 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
* assembler-source text line
*
* global variables:
* none
*
* called functions:
* char getnb() aslex.c
*
* side effects:
* use of getnb() updates the global pointer ip the
* position in the current assembler-source text line
*/
char
endline()
{
register int c;
c = getnb();
return( (c == '\0' || c == ';') ? 0 : c );
}

810
link/as/z80/aslist.c Normal file
View File

@@ -0,0 +1,810 @@
/* aslist.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <sys/types.h>
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif
#include "asm.h"
/*)Module aslist.c
*
* The module aslist.c contains all the functions used
* to generate the assembler list and symbol output files.
*
* aslist.c contains the following functions:
* VOID list()
* VOID list1()
* VOID list2()
* VOID slew()
* VOID lstsym()
*
* The module aslist.c contains no local/static variables
*/
/*)Function VOID list()
*
* The function list() generates the listing output
* which includes the input source, line numbers,
* and generated code. Numerical output may be selected
* as hexadecimal, decimal, or octal.
*
* local variables:
* int * wp pointer to the assembled data bytes
* int * wpt pointer to the data byte mode
* int nb computed number of assembled bytes
*
* global variables:
* int cb[] array of assembler output values
* int cbt[] array of assembler relocation types
* describing the data in cb[]
* int * cp pointer to assembler output array cb[]
* int * cpt pointer to assembler relocation type
* output array cbt[]
* char eb[] array of generated error codes
* char * ep pointer into error list
* array eb[]
* char ib[] assembler-source text line
* FILE * lfp list output file handle
* int line current assembler source line number
* int lmode listing mode
* int xflag -x, listing radix flag
*
* functions called:
* int fprintf() c_library
* VOID list1() aslist.c
* int putc() c_library
* VOID slew() asslist.c
*
* side effects:
* Listing or symbol output updated.
*/
#ifndef MLH_LST
VOID
list()
{
register char *wp;
register int *wpt;
register int nb;
if (lfp == NULL || lmode == NLIST)
return;
/*
* Get Correct Line Number
*/
if (incfil >= 0) {
line = incline[incfil];
if (line == 0) {
if (incfil > 0) {
line = incline[incfil-1];
} else {
line = srcline[cfile];
}
}
} else {
line = srcline[cfile];
}
/*
* Move to next line.
*/
slew(lfp, pflag);
/*
* Output a maximum of NERR error codes with listing.
*/
while (ep < &eb[NERR])
*ep++ = ' ';
fprintf(lfp, "%.2s", eb);
/*
* Source listing only option.
*/
if (lmode == SLIST) {
fprintf(lfp, "%24s%5u %s\n", "", line, ib);
return;
}
#ifndef SDK
if (lmode == ALIST) {
outchk(HUGE,HUGE);
}
#endif
/*
* HEX output Option.
*/
if (xflag == 0) { /* HEX */
/*
* Equate only
*/
if (lmode == ELIST) {
fprintf(lfp, "%18s%04X", "", laddr);
fprintf(lfp, " %5u %s\n", line, ib);
return;
}
/*
* Address (with allocation)
*/
fprintf(lfp, " %04X", laddr);
if (lmode == ALIST || lmode == BLIST) {
fprintf(lfp, "%19s%5u %s\n", "", line, ib);
#ifndef SDK
outdot();
#endif
return;
}
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 6) > 0) {
wp += 6;
wpt += 6;
slew(lfp, 0);
fprintf(lfp, "%7s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
} else
/*
* OCTAL output Option.
*/
if (xflag == 1) { /* OCTAL */
/*
* Equate only
*/
if (lmode == ELIST) {
fprintf(lfp, "%16s%06o", "", laddr);
fprintf(lfp, " %5u %s\n", line, ib);
return;
}
/*
* Address (with allocation)
*/
fprintf(lfp, " %06o", laddr);
if (lmode == ALIST || lmode == BLIST) {
fprintf(lfp, "%17s%5u %s\n", "", line, ib);
#ifndef SDK
outdot();
#endif
return;
}
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 4) > 0) {
wp += 4;
wpt += 4;
slew(lfp, 0);
fprintf(lfp, "%9s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
} else
/*
* DECIMAL output Option.
*/
if (xflag == 2) { /* DECIMAL */
/*
* Equate only
*/
if (lmode == ELIST) {
fprintf(lfp, "%16s%05u", "", laddr);
fprintf(lfp, " %5u %s\n", line, ib);
return;
}
/*
* Address (with allocation)
*/
fprintf(lfp, " %05u", laddr);
if (lmode == ALIST || lmode == BLIST) {
fprintf(lfp, "%17s%5u %s\n", "", line, ib);
#ifndef SDK
outdot();
#endif
return;
}
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 4) > 0) {
wp += 4;
wpt += 4;
slew(lfp, 0);
fprintf(lfp, "%9s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
}
}
#else
VOID
list()
{
register char *wp;
register int *wpt;
register nb;
if (lfp == NULL || lmode == NLIST)
return;
/*
* Get Correct Line Number
*/
if (incfil >= 0) {
line = incline[incfil];
if (line == 0) {
if (incfil > 0) {
line = incline[incfil-1];
} else {
line = srcline[cfile];
}
}
} else {
line = srcline[cfile];
}
/*
* HEX output Option.
*/
/* Output filename relative_address line_number */
if (incfil >= 0) {
fprintf(lfp, "%s ", incfn[incfil]);
}
else {
fprintf(lfp, "%s ", srcfn[cfile]);
}
fprintf(lfp, "%u %04X\n", line, laddr);
#if 0
wp = cb;
wpt = cbt;
nb = (int) (cp - cb);
/*
* First line of output for this source line with data.
*/
list1(wp, wpt, nb, 1);
fprintf(lfp, " %5u %s\n", line, ib);
/*
* Subsequent lines of output if more data.
*/
while ((nb -= 6) > 0) {
wp += 6;
wpt += 6;
slew(lfp, 0);
fprintf(lfp, "%7s", "");
list1(wp, wpt, nb, 0);
putc('\n', lfp);
}
#endif
}
#endif /* MLH_LST */
/*)Function VOID list1(wp, wpt, nw, f)
*
* int f fill blank fields (1)
* int nb number of data bytes
* int * wp pointer to data bytes
* int * wpt pointer to data byte mode
*
* local variables:
* int i loop counter
*
* global variables:
* int xflag -x, listing radix flag
*
* functions called:
* VOID list2() asslist.c
* int fprintf() c_library
*
* side effects:
* Data formatted and output to listing.
*/
VOID
list1(wp, wpt, nb, f)
register char *wp;
register int *wpt, nb, f;
{
register int i;
/*
* HEX output Option.
*/
if (xflag == 0) { /* HEX */
/*
* Bound number of words to HEX maximum per line.
*/
if (nb > 6)
nb = 6;
/*
* Output bytes.
*/
for (i=0; i<nb; ++i) {
list2(*wpt++);
fprintf(lfp, "%02X", (*wp++)&0377);
}
/*
* Output blanks if required.
*/
if (f) {
while (i < 6) {
fprintf(lfp, " ");
++i;
}
}
} else
/*
* OCTAL output Option.
*/
if (xflag == 1) { /* OCTAL */
/*
* Bound number of words to OCTAL maximum per line.
*/
if (nb > 4)
nb = 4;
/*
* Output bytes.
*/
for (i=0; i<nb; ++i) {
list2(*wpt++);
fprintf(lfp, "%03o", (*wp++)&0377);
}
/*
* Output blanks if required.
*/
if (f) {
while (i < 4) {
fprintf(lfp, " ");
++i;
}
}
} else
/*
* DECIMAL output Option.
*/
if (xflag == 2) { /* DECIMAL */
/*
* Bound number of words to DECIMAL maximum per line.
*/
if (nb > 4)
nb = 4;
/*
* Output bytes.
*/
for (i=0; i<nb; ++i) {
list2(*wpt++);
fprintf(lfp, "%03u", (*wp++)&0377);
}
/*
* Output blanks if required.
*/
if (f) {
while (i < 4) {
fprintf(lfp, " ");
++i;
}
}
}
}
/*)Function VOID list2(wpt)
*
* int * wpt pointer to relocation mode
*
* The function list2() outputs the selected
* relocation flag as specified by fflag.
*
* local variables:
* int c relocation flag character
* int t relocation mode
*
* global variables:
* int fflag -f(f), relocations flagged flag
*
* functions called:
* int putc() c_library
*
* side effects:
* Relocation flag output to listing file.
*/
VOID
list2(t)
register int t;
{
register int c;
c = ' ';
/*
* Designate a relocatable word by `.
*/
if (fflag == 1) {
if (t & R_RELOC) {
c = '`';
}
} else
/*
* Designate a relocatable word by its mode:
* page0 or paged *
* unsigned u (v)
* operand offset p (q)
* relocatable symbol r (s)
*/
if (fflag >= 2) {
if (t & R_RELOC) {
if (t & (R_PAG0|R_PAG)) {
c = '*';
} else if (t & R_USGN) {
c = 'u';
} else if (t & R_PCR) {
c = 'p';
} else {
c = 'r';
}
if (t & R_HIGH) c += 1;
}
}
/*
* Output the selected mode.
*/
putc(c, lfp);
}
/*)Function VOID slew(fp, flag)
*
* FILE * fp file handle for listing
* int flag enable pagination
*
* The function slew() increments the page line count.
* If the page overflows and pagination is enabled:
* 1) put out a page skip,
* 2) a title,
* 3) a subtitle,
* 4) and reset the line count.
*
* local variables:
* none
*
* global variables:
* char cpu[] cpu type string
* int lop current line number on page
* int page current page number
* char stb[] Subtitle string buffer
* char tb[] Title string buffer
*
* functions called:
* int fprintf() c_library
*
* side effects:
* Increments page line counter, on overflow
* a new page header is output to the listing file.
*/
VOID
slew(fp,flag)
FILE *fp;
int flag;
{
if ((lop++ >= NLPP) && flag) {
fprintf(fp, "\fASxxxx Assembler %s (%s), page %u.\n",
VERSION, cpu, ++page);
fprintf(fp, "%s\n", tb);
fprintf(fp, "%s\n\n", stb);
lop = 5;
}
}
/*)Function VOID lstsym(fp)
*
* FILE * fp file handle for output
*
* The function lstsym() outputs alphabetically
* sorted symbol and area tables.
*
* local variables:
* int c temporary
* int i loop counter
* int j temporary
* int k temporary
* char * ptr pointer to an id string
* int nmsym number of symbols
* int narea number of areas
* sym * sp pointer to symbol structure
* sym ** p pointer to an array of
* pointers to symbol structures
* area * ap pointer to an area structure
*
* global variables:
* area * areap pointer to an area structure
* char aretbl[] string "Area Table"
* sym dot defined as sym[0]
* char stb[] Subtitle string buffer
* sym * symhash[] array of pointers to NHASH
* linked symbol lists
* char symtbl[] string "Symbol Table"
* FILE * tfp symbol table output file handle
* int xflag -x, listing radix flag
*
* functions called:
* int fprintf() c_library
* int putc() c_library
* VOID slew() aslist.c
* int strcmp() c_library
* char * strcpy() c_library
*
* side effects:
* Symbol and area tables output.
*/
VOID
lstsym(fp)
FILE *fp;
{
register int c, i, j, k;
register char *ptr;
int nmsym, narea;
struct sym *sp;
struct sym **p;
struct area *ap;
/*
* Symbol Table Header
*/
strcpy(stb, &symtbl[0]);
lop = NLPP;
if (fp == tfp)
page = 0;
slew(fp, 1);
/*
* Find number of symbols
*/
nmsym = 0;
for (i=0; i<NHASH; i++) {
sp = symhash[i];
while (sp) {
if (sp != &dot)
++nmsym;
sp = sp->s_sp;
}
}
if (nmsym == 0)
goto atable;
/*
* Allocate space for an array of pointers to symbols
* and load array.
*/
if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
== NULL) {
fprintf(fp, "Insufficient space to build Symbol Table.\n");
return;
}
nmsym = 0;
for (i=0; i<NHASH; i++) {
sp = symhash[i];
while (sp) {
if (sp != &dot)
p[nmsym++] = sp;
sp = sp->s_sp;
}
}
/*
* Bubble Sort on Symbol Table Array
*/
j = 1;
c = nmsym - 1;
while (j) {
j = 0;
for (i=0; i<c; ++i) {
if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
j = 1;
sp = p[i+1];
p[i+1] = p[i];
p[i] = sp;
}
}
}
/*
* Symbol Table Output
*/
for (i=0; i<nmsym;) {
sp = p[i];
if (sp->s_area) {
j = sp->s_area->a_ref;
if (xflag == 0) {
fprintf(fp, " %2X ", j);
} else
if (xflag == 1) {
fprintf(fp, "%3o ", j);
} else
if (xflag == 2) {
fprintf(fp, "%3u ", j);
}
} else {
fprintf(fp, " ");
}
ptr = &sp->s_id[0];
while (ptr < &sp->s_id[NCPS]) {
if ((c = *ptr++) != 0) {
putc(c, fp);
} else {
putc(' ', fp);
}
}
if (sp->s_flag & S_ASG) {
putc('=', fp);
} else {
putc(' ', fp);
}
if (sp->s_type == S_NEW) {
if (xflag == 0) {
fprintf(fp, " **** ");
} else
if (xflag == 1) {
fprintf(fp, "****** ");
} else
if (xflag == 2) {
fprintf(fp, " ***** ");
}
} else {
j = sp->s_addr;
if (xflag == 0) {
fprintf(fp, " %04X ", j);
} else
if (xflag == 1) {
fprintf(fp, "%06o ", j);
} else
if (xflag == 2) {
fprintf(fp, " %05u ", j);
}
}
j = 0;
if (sp->s_flag & S_GBL) {
putc('G', fp);
++j;
}
if (sp->s_area != NULL) {
putc('R', fp);
++j;
}
if (sp->s_type == S_NEW) {
putc('X', fp);
++j;
}
#if NCPS-8
putc('\n', fp);
slew(fp, 0);
++i;
#else
if (++i % 3 == 0) {
putc('\n', fp);
slew(fp, pflag);
} else
if (i < nmsym) {
while (j++ < 4)
putc(' ', fp);
fprintf(fp, "| ");
}
#endif
}
putc('\n', fp);
/*
* Area Table Header
*/
atable:
strcpy(stb, &aretbl[0]);
lop = NLPP;
slew(fp, 1);
/*
* Area Table Output
*/
narea = 0;
ap = areap;
while (ap) {
++narea;
ap = ap->a_ap;
}
for (i=0; i<narea; ++i) {
ap = areap;
for (j=i+1; j<narea; ++j)
ap = ap->a_ap;
j = ap->a_ref;
if (xflag == 0) {
fprintf(fp, " %2X ", j);
} else
if (xflag == 1) {
fprintf(fp, " %3o ", j);
} else
if (xflag == 2) {
fprintf(fp, " %3u ", j);
}
ptr = &ap->a_id[0];
while (ptr < &ap->a_id[NCPS]) {
if ((c = *ptr++) != 0) {
putc(c, fp);
} else {
putc(' ', fp);
}
}
j = ap->a_size;
k = ap->a_flag;
if (xflag==0) {
fprintf(fp, " size %4X flags %X\n", j, k);
} else
if (xflag==1) {
fprintf(fp, " size %6o flags %o\n", j, k);
} else
if (xflag==2) {
fprintf(fp, " size %5u flags %u\n", j, k);
}
}
}

598
link/as/z80/asm.h Normal file
View File

@@ -0,0 +1,598 @@
/* asm.h */
/*
* (C) Copyright 1989-1996
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#define VERSION "V01.75"
/*
* Case Sensitivity Flag
*/
#define CASE_SENSITIVE 0
/*)Module asm.h
*
* The module asm.h contains the definitions for constants,
* structures, global variables, and ASxxxx functions
* contained in the ASxxxx.c files. The two functions
* and three global variables from the machine dependent
* files are also defined.
*/
/*
* compiler/operating system specific definitions
*/
/* 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
/*
* Assembler definitions.
*/
#define LFTERM '(' /* Left expression delimeter */
#define RTTERM ')' /* Right expression delimeter */
#ifdef SDK
#define NCPS 32 /* characters per symbol */
#else /* SDK */
#define NCPS 8 /* Chars. per symbol */
#endif /* SDK */
/* #define NCPS 32 */ /* Chars. per symbol */
#define HUGE 1000 /* A huge number */
#define NERR 3 /* Errors per line */
#define NINPUT 128 /* Input buffer size */
#define NCODE 128 /* Listing code buffer size */
#define NTITL 64 /* Title buffer size */
#define NSBTL 64 /* SubTitle buffer size */
#define NHASH 64 /* Buckets in hash table */
#define HMASK 077 /* Hash mask */
#define NLPP 60 /* Lines per page */
#define MAXFIL 6 /* Maximum command line input files */
#define MAXINC 6 /* Maximum nesting of include files */
#define MAXIF 10 /* Maximum nesting of if/else/endif */
#define FILSPC 256 /* Chars. in filespec */
#define NLIST 0 /* No listing */
#define SLIST 1 /* Source only */
#define ALIST 2 /* Address only */
#define BLIST 3 /* Address only with allocation */
#define CLIST 4 /* Code */
#define ELIST 5 /* Equate only */
#define dot sym[0] /* Dot, current loc */
#define dca area[0] /* Dca, default code area */
typedef unsigned int Addr_T;
/*
* The area structure contains the parameter values for a
* specific program or data section. The area structure
* is a linked list of areas. The initial default area
* is "_CODE" defined in asdata.c, the next area structure
* will be linked to this structure through the structure
* element 'struct area *a_ap'. The structure contains the
* area name, area reference number ("_CODE" is 0) determined
* by the order of .area directives, area size determined
* from the total code and/or data in an area, area fuzz is
* a variable used to track pass to pass changes in the
* area size caused by variable length instruction formats,
* and area flags which specify the area's relocation type.
*/
struct area
{
struct area *a_ap; /* Area link */
char a_id[NCPS]; /* Area Name */
int a_ref; /* Ref. number */
Addr_T a_size; /* Area size */
Addr_T a_fuzz; /* Area fuzz */
int a_flag; /* Area flags */
};
/*
* The "A_" area constants define values used in
* generating the assembler area output data.
*
* Area flags
*
* 7 6 5 4 3 2 1 0
* +-----+-----+-----+-----+-----+-----+-----+-----+
* | | | | PAG | ABS | OVR | | |
* +-----+-----+-----+-----+-----+-----+-----+-----+
*/
#define A_CON 000 /* Concatenating */
#define A_OVR 004 /* Overlaying */
#define A_REL 000 /* Relocatable */
#define A_ABS 010 /* absolute */
#define A_NOPAG 000 /* Non-Paged */
#define A_PAG 020 /* Paged */
/*
* The "R_" relocation constants define values used in
* generating the assembler relocation output data for
* areas, symbols, and code.
*
* Relocation flags
*
* 7 6 5 4 3 2 1 0
* +-----+-----+-----+-----+-----+-----+-----+-----+
* | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
* +-----+-----+-----+-----+-----+-----+-----+-----+
*/
#define R_WORD 0000 /* 16 bit */
#define R_BYTE 0001 /* 8 bit */
#define R_AREA 0000 /* Base type */
#define R_SYM 0002
#define R_NORM 0000 /* PC adjust */
#define R_PCR 0004
#define R_BYT1 0000 /* Byte count for R_BYTE = 1 */
#define R_BYT2 0010 /* Byte count for R_BYTE = 2 */
#define R_SGND 0000 /* Signed Byte */
#define R_USGN 0020 /* Unsigned Byte */
#define R_NOPAG 0000 /* Page Mode */
#define R_PAG0 0040 /* Page '0' */
#define R_PAG 0100 /* Page 'nnn' */
#define R_LSB 0000 /* low byte */
#define R_MSB 0200 /* high byte */
/*
* Listing Control Flags
*/
#define R_HIGH 0040000 /* High Byte */
#define R_RELOC 0100000 /* Relocation */
#define R_DEF 00 /* Global def. */
#define R_REF 01 /* Global ref. */
#define R_REL 00 /* Relocatable */
#define R_ABS 02 /* Absolute */
#define R_GBL 00 /* Global */
#define R_LCL 04 /* Local */
/*
* The mne structure is a linked list of the assembler
* mnemonics and directives. The list of mnemonics and
* directives contained in the device dependent file
* xxxpst.c are hashed and linked into NHASH lists in
* module assym.c by syminit(). The structure contains
* the mnemonic/directive name, a subtype which directs
* the evaluation of this mnemonic/directive, a flag which
* is used to detect the end of the mnemonic/directive
* list in xxxpst.c, and a value which is normally
* associated with the assembler mnemonic base instruction
* value.
*/
struct mne
{
struct mne *m_mp; /* Hash link */
char m_id[NCPS]; /* Mnemonic */
char m_type; /* Mnemonic subtype */
char m_flag; /* Mnemonic flags */
Addr_T m_valu; /* Value */
};
/*
* The sym structure is a linked list of symbols defined
* in the assembler source files. The first symbol is "."
* defined in asdata.c. The entry 'struct tsym *s_tsym'
* links any temporary symbols following this symbol and
* preceeding the next normal symbol. The structure also
* contains the symbol's name, type (USER or NEW), flag
* (global, assigned, and multiply defined), a pointer
* to the area structure defining where the symbol is
* located, a reference number assigned by outgsd() in
* asout.c, and the symbols address relative to the base
* address of the area where the symbol is located.
*/
struct sym
{
struct sym *s_sp; /* Hash link */
struct tsym *s_tsym; /* Temporary symbol link */
char s_id[NCPS]; /* Symbol */
char s_type; /* Symbol subtype */
char s_flag; /* Symbol flags */
struct area *s_area; /* Area line, 0 if absolute */
int s_ref; /* Ref. number */
Addr_T s_addr; /* Address */
};
#define S_GBL 01 /* Global */
#define S_ASG 02 /* Assigned */
#define S_MDF 04 /* Mult. def */
#define S_END 010 /* End mark for pst. */
#define S_NEW 0 /* New name */
#define S_USER 1 /* User name */
/* unused slot */
/* unused slot */
/* unused slot */
#define S_BYTE 5 /* .byte */
#define S_WORD 6 /* .word */
#define S_ASCII 7 /* .ascii */
#define S_ASCIZ 8 /* .asciz */
#define S_BLK 9 /* .blkb or .blkw */
#define S_INCL 10 /* .include */
#define S_DAREA 11 /* .area */
#define S_ATYP 12 /* .area type */
#define S_AREA 13 /* .area name */
#define S_GLOBL 14 /* .globl */
#define S_PAGE 15 /* .page */
#define S_TITLE 16 /* .title */
#define S_SBTL 17 /* .sbttl */
#define S_IF 18 /* .if */
#define S_ELSE 19 /* .else */
#define S_ENDIF 20 /* .endif */
#define S_EVEN 21 /* .even */
#define S_ODD 22 /* .odd */
#define S_RADIX 23 /* .radix */
#define S_ORG 24 /* .org */
#define S_MODUL 25 /* .module */
#define S_ASCIS 26 /* .ascis */
#ifdef SDK
# define S_FLOAT 27 /* .df */
#endif
/*
* The tsym structure is a linked list of temporary
* symbols defined in the assembler source files following
* a normal symbol. The structure contains the temporary
* symbols number, a flag (multiply defined), a pointer to the
* area structure defining where the temporary structure
* is located, and the temporary symbol's address relative
* to the base address of the area where the symbol
* is located.
*/
struct tsym
{
struct tsym *t_lnk; /* Link to next */
int t_num; /* 0-lots$ */
char t_flg; /* flags */
struct area *t_area; /* Area */
Addr_T t_addr; /* Address */
};
/*
* External Definitions for all Global Variables
*/
extern int aserr; /* ASxxxx error counter
*/
extern jmp_buf jump_env; /* compiler dependent structure
* used by setjmp() and longjmp()
*/
extern int inpfil; /* count of assembler
* input files specified
*/
extern int incfil; /* current file handle index
* for include files
*/
extern int cfile; /* current file handle index
* of input assembly files
*/
extern int flevel; /* IF-ELSE-ENDIF flag will be non
* zero for false conditional case
*/
extern int tlevel; /* current conditional level
*/
extern int ifcnd[MAXIF+1]; /* array of IF statement condition
* values (0 = FALSE) indexed by tlevel
*/
extern int iflvl[MAXIF+1]; /* array of IF-ELSE-ENDIF flevel
* values indexed by tlevel
*/
extern char
afn[FILSPC]; /* afile() temporary filespec
*/
extern char
srcfn[MAXFIL][FILSPC]; /* array of source file names
*/
extern int
srcline[MAXFIL]; /* current source file line
*/
extern char
incfn[MAXINC][FILSPC]; /* array of include file names
*/
extern int
incline[MAXINC]; /* current include file line
*/
extern int radix; /* current number conversion radix:
* 2 (binary), 8 (octal), 10 (decimal),
* 16 (hexadecimal)
*/
extern int line; /* current assembler source
* line number
*/
extern int page; /* current page number
*/
extern int lop; /* current line number on page
*/
extern int pass; /* assembler pass number
*/
extern int lflag; /* -l, generate listing flag
*/
extern int gflag; /* -g, make undefined symbols global flag
*/
extern int aflag; /* -a, make all symbols global flag
*/
extern int oflag; /* -o, generate relocatable output flag
*/
extern int sflag; /* -s, generate symbol table flag
*/
extern int pflag; /* -p, enable listing pagination
*/
extern int xflag; /* -x, listing radix flag
*/
extern int fflag; /* -f(f), relocations flagged flag
*/
extern Addr_T laddr; /* address of current assembler line
* or value of .if argument
*/
extern Addr_T fuzz; /* tracks pass to pass changes in the
* address of symbols caused by
* variable length instruction formats
*/
extern int lmode; /* listing mode
*/
extern struct area area[]; /* array of 1 area
*/
extern struct area *areap; /* pointer to an area structure
*/
extern struct sym sym[]; /* array of 1 symbol
*/
extern struct sym *symp; /* pointer to a symbol structure
*/
extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
* linked symbol lists
*/
extern struct mne *mnehash[NHASH]; /* array of pointers to NHASH
* linked mnemonic/directive lists
*/
extern char *ep; /* pointer into error list
* array eb[NERR]
*/
extern char eb[NERR]; /* array of generated error codes
*/
extern char *ip; /* pointer into the assembler-source
* text line in ib[]
*/
extern char ib[NINPUT]; /* assembler-source text line
*/
extern char *cp; /* pointer to assembler output
* array cb[]
*/
extern char cb[NCODE]; /* array of assembler output values
*/
extern int *cpt; /* pointer to assembler relocation type
* output array cbt[]
*/
extern int cbt[NCODE]; /* array of assembler relocation types
* describing the data in cb[]
*/
extern char tb[NTITL]; /* Title string buffer
*/
extern char stb[NSBTL]; /* Subtitle string buffer
*/
extern char symtbl[]; /* string "Symbol Table"
*/
extern char aretbl[]; /* string "Area Table"
*/
extern char module[NCPS]; /* module name string
*/
extern FILE *lfp; /* list output file handle
*/
extern FILE *ofp; /* relocation output file handle
*/
extern FILE *tfp; /* symbol table output file handle
*/
extern FILE *sfp[MAXFIL]; /* array of assembler-source file handles
*/
extern FILE *ifp[MAXINC]; /* array of include-file file handles
*/
extern char ctype[128]; /* array of character types, one per
* ASCII character
*/
#if CASE_SENSITIVE
#else
extern char ccase[128]; /* an array of characters which
* perform the case translation function
*/
#endif
/*
* Definitions for Character Types
*/
#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
/*
* The exp structure is used to return the evaluation
* of an expression. The structure supports three valid
* cases:
* (1) The expression evaluates to a constant,
* mode = S_USER, flag = 0, addr contains the
* constant, and base = NULL.
* (2) The expression evaluates to a defined symbol
* plus or minus a constant, mode = S_USER,
* flag = 0, addr contains the constant, and
* base = pointer to area symbol.
* (3) The expression evaluates to a external
* global symbol plus or minus a constant,
* mode = S_NEW, flag = 1, addr contains the
* constant, and base = pointer to symbol.
*/
struct expr
{
char e_mode; /* Address mode */
char e_flag; /* Symbol flag */
Addr_T e_addr; /* Address */
union {
struct area *e_ap;
struct sym *e_sp;
} e_base; /* Rel. base */
char e_rlcf; /* Rel. flags */
};
/* C Library functions */
/* for reference only
extern VOID exit();
extern int fclose();
extern char * fgets();
extern FILE * fopen();
extern int fprintf();
extern VOID longjmp();
extern VOID * malloc();
extern int printf();
extern char putc();
extern int rewind();
extern int setjmp();
extern int strcmp();
extern char * strcpy();
extern int strlen();
extern char * strncpy();
*/
/* Machine independent functions */
/* asmain.c */
extern FILE * afile();
extern VOID asexit();
extern VOID asmbl();
extern int main();
extern VOID newdot();
extern VOID phase();
extern VOID usage();
/* aslex.c */
extern char endline();
extern char get();
extern VOID getid();
extern int getLine_();
extern int getmap();
extern char getnb();
extern VOID getst();
extern int more();
extern VOID unget();
/* assym.c */
extern struct area * alookup();
extern struct mne * mlookup();
extern int hash();
extern struct sym * lookup();
extern VOID * new();
extern int symeq();
extern VOID syminit();
extern VOID symglob();
extern VOID allglob();
/* assubr.c */
extern VOID aerr();
extern VOID diag();
extern VOID err();
extern char * geterr();
extern VOID qerr();
extern VOID rerr();
/* asexpr.c */
extern VOID abscheck();
extern Addr_T absexpr();
extern VOID clrexpr();
extern int digit();
extern int is_abs();
extern VOID expr();
extern int oprio();
extern VOID term();
/* aslist.c */
extern VOID list();
extern VOID list1();
extern VOID list2();
extern VOID lstsym();
extern VOID slew();
/* asout.c */
extern int hibyte();
extern int lobyte();
extern VOID out();
extern VOID outab();
extern VOID outarea();
extern VOID outaw();
extern VOID outall();
extern VOID outdot();
extern VOID outbuf();
extern VOID outchk();
extern VOID outgsd();
extern VOID outrb();
extern VOID outrw();
extern VOID outsym();
extern VOID out_lb();
extern VOID out_lw();
extern VOID out_rw();
extern VOID out_tw();
/* Machine dependent variables */
extern char * cpu;
extern char * dsft;
extern int hilo;
extern struct mne mne[];
/* Machine dependent functions */
extern VOID minit();

1197
link/as/z80/asmain.c Normal file

File diff suppressed because it is too large Load Diff

1084
link/as/z80/asout.c Normal file

File diff suppressed because it is too large Load Diff

254
link/as/z80/assubr.c Normal file
View File

@@ -0,0 +1,254 @@
/* assubr.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber, M. Hope
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include "asm.h"
/*)Module assubr.c
*
* The module assubr.c contains the error
* processing routines.
*
* assubr.c contains the following functions:
* VOID aerr()
* VOID diag()
* VOID err()
* VOID qerr()
* VOID rerr()
*
* assubr.c contains the local array of *error[]
*/
/*)Function VOID err(c)
*
* int c error type character
*
* The function err() logs the error code character
* suppressing duplicate errors. If the error code
* is 'q' then the parse of the current assembler-source
* text line is terminated.
*
* local variables:
* char * p pointer to the error array
*
* global variables:
* char eb[] array of generated error codes
*
* functions called:
* VOID longjmp() c_library
*
* side effects:
* The error code may be inserted into the
* error code array eb[] or the parse terminated.
*/
VOID
err(c)
register int c;
{
register char *p;
#ifndef SDK
aserr++;
#endif /* SDK */
p = eb;
while (p < ep)
if (*p++ == c)
return;
if (p < &eb[NERR]) {
*p++ = c;
ep = p;
}
if (c == 'q')
longjmp(jump_env, -1);
}
/*)Function VOID diag()
*
* The function diag() prints any error codes and
* the source line number to the stderr output device.
*
* local variables:
* char * p pointer to error code array eb[]
*
* global variables:
* int cfile current source file index
* char eb[] array of generated error codes
* char * ep pointer into error list
* int incfile current include file index
* char incfn[] array of include file names
* int incline[] array of include line numbers
* char srcfn[] array of source file names
* int srcline[] array of source line numbers
* FILE * stderr c_library
*
* functions called:
* int fprintf() c_library
* char * geterr() assubr.c
*
* side effects:
* none
*/
VOID
diag()
{
register char *p,*errstr;
if (eb != ep) {
p = eb;
#ifndef SDK
fprintf(stderr, "?ASxxxx-Error-<");
while (p < ep) {
fprintf(stderr, "%c", *p++);
}
fprintf(stderr, "> in line ");
if (incfil >= 0) {
fprintf(stderr, "%d", incline[incfil]);
fprintf(stderr, " of %s\n", incfn[incfil]);
} else {
fprintf(stderr, "%d", srcline[cfile]);
fprintf(stderr, " of %s\n", srcfn[cfile]);
}
p = eb;
#endif /* SDK */
while (p < ep) {
if ((errstr = geterr(*p++)) != NULL) {
#ifdef SDK
/* Modified to conform to gcc error standard, M. Hope, 7 Feb 98. */
if (incfil >= 0) {
fprintf(stderr, "%s:", incfn[incfil]);
fprintf(stderr, "%d: Error:", incline[incfil]);
}
else {
fprintf(stderr, "%s:", srcfn[cfile]);
fprintf(stderr, "%d: Error:", srcline[cfile]);
}
fprintf(stderr, " %s\n", errstr);
#else
fprintf(stderr, " %s\n", errstr);
#endif /* SDK */
}
}
#ifdef SDK
aserr++;
#endif /* SDK */
}
}
/*)Functions: VOID aerr()
* VOID qerr()
* VOID rerr()
*
* The functions aerr(), qerr(), and rerr() report their
* respective error type. These are included only for
* convenience.
*
* local variables:
* none
*
* global variables:
* none
*
* functions called:
* VOID err() assubr.c
*
* side effects:
* The appropriate error code is inserted into the
* error array and the parse may be terminated.
*/
/*
* Note an 'r' error.
*/
VOID
rerr()
{
err('r');
}
/*
* Note an 'a' error.
*/
VOID
aerr()
{
err('a');
}
/*
* Note a 'q' error.
*/
VOID
qerr()
{
err('q');
}
/*
* ASxxxx assembler errors
*/
char *errors[] = {
"<.> use \". = . + <arg>\" not \". = <arg>\"",
"<a> machine specific addressing or addressing mode error",
"<b> direct page boundary error",
"<d> direct page addressing error",
"<i> .include file error or an .if/.endif mismatch",
"<m> multiple definitions error",
"<o> .org in REL area or directive / mnemonic error",
"<p> phase error: label location changing between passes 2 and 3",
"<q> missing or improper operators, terminators, or delimiters",
"<r> relocation error",
"<u> undefined symbol encountered during assembly",
NULL
};
/*)Function: char *getarr(c)
*
* int c the error code character
*
* The function geterr() scans the list of errors returning the
* error string corresponding to the input error character.
*
* local variables:
* int i error index counter
*
* global variables:
* char *errors[] array of pointers to the
* error strings
*
* functions called:
* none
*
* side effects:
* A pointer to the appropriate
* error code string is returned.
*/
char *
geterr(c)
int c;
{
int i;
for (i=0; errors[i]!=NULL; i++) {
if (c == errors[i][1]) {
return(errors[i]);
}
}
return(NULL);
}

446
link/as/z80/assym.c Normal file
View File

@@ -0,0 +1,446 @@
/* assym.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <sys/types.h>
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif
#include "asm.h"
/*)Module assym.c
*
* The module assym.c contains the functions that operate
* on the mnemonic/directive and symbol structures.
*
* assym.c contains the following functions:
* VOID allglob()
* area * alookup()
* int hash()
* sym * lookup()
* mne * mlookup()
* VOID * new()
* int symeq()
* VOID syminit()
* VOID symglob()
*
* assym.c contains no local/static variables.
*/
/*)Function VOID syminit()
*
* The function syminit() is called early in the game
* to set up the hashtables. First all buckets in a
* table are cleared. Then a pass is made through
* the respective symbol lists, linking them into
* their hash buckets. Finally the base area pointer
* is set to 'dca'.
*
* local variables:
* int h computed hash value
* mne * mp pointer to a mne structure
* mne ** mpp pointer to an array of
* mne structure pointers
* sym * sp pointer to a sym structure
* sym ** spp pointer to an array of
* sym structure pointers
*
* global variables:
* area area[] single elememt area array
* area dca defined as area[0]
* mne * mnehash[] array of pointers to NHASH
* linked mnemonic/directive lists
* sym * symhash[] array of pointers to NHASH
* linked symbol lists
*
* functions called:
* none
*
* side effects:
* (1) The symbol hash tables are initialized,
* the only defined symbol is '.'.
* (2) The mnemonic/directive hash tables are
* initialized with the assembler directives
* and mnemonics found in the machine dependent
* file ___pst.c.
* (3) The area pointer is initialized to dca (area[0]).
*/
VOID
syminit()
{
register struct mne *mp;
struct mne **mpp;
register struct sym *sp;
struct sym **spp;
register int h;
mpp = &mnehash[0];
while (mpp < &mnehash[NHASH])
*mpp++ = NULL;
mp = &mne[0];
for (;;) {
h = hash(mp->m_id);
mp->m_mp = mnehash[h];
mnehash[h] = mp;
if (mp->m_flag&S_END)
break;
++mp;
}
spp = &symhash[0];
while (spp < &symhash[NHASH])
*spp++ = NULL;
sp = &sym[0];
for (;;) {
h = hash(sp->s_id);
sp->s_sp = symhash[h];
symhash[h] = sp;
if (sp->s_flag&S_END)
break;
++sp;
}
areap = &dca;
}
/*)Function area * alookup(id)
*
* char * id area name string
*
* The function alookup() searches the area list for a
* match with id. If the area is defined then a pointer
* to this area is returned else a NULL is returned.
*
* local variables:
* area * ap pointer to area structure
*
* global variables:
* area * areap pointer to an area structure
*
* functions called:
* int symeq() assym.c
*
* side effects:
* none
*/
struct area *
alookup(id)
char *id;
{
register struct area *ap;
ap = areap;
while (ap) {
if (symeq(id, ap->a_id)) {
return (ap);
}
ap = ap->a_ap;
}
return(NULL);
}
/*)Function mne * mlookup(id)
*
* char * id mnemonic/directive name string
*
* The function mlookup() searches the mnemonic/directive
* hash tables for a match returning a pointer to the
* mne structure else it returns a NULL.
*
* local variables:
* mne * mp pointer to mne structure
* int h calculated hash value
*
* global variables:
* mne * mnehash[] array of pointers to NHASH
* linked mnemonic/directive lists
*
* functions called:
* none
*
* side effects:
* none
*/
struct mne *
mlookup(id)
char *id;
{
register struct mne *mp;
register int h;
h = hash(id);
mp = mnehash[h];
while (mp) {
if (symeq(id, mp->m_id))
return (mp);
mp = mp->m_mp;
}
return (NULL);
}
/*)Function sym * lookup(id)
*
* char * id symbol name string
*
* 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.
* A pointer to this new sym structure is returned.
*
* 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() assym.c
* VOID * new() assym.c
* int symeq() assym.c
*
* side effects:
* If the function new() fails to allocate space
* for the new sym structure the assembly terminates.
*/
struct sym *
lookup(id)
char *id;
{
register struct sym *sp;
register int h;
h = hash(id);
sp = symhash[h];
while (sp) {
if (symeq(id, sp->s_id))
return (sp);
sp = sp->s_sp;
}
sp = (struct sym *) new (sizeof(struct sym));
sp->s_sp = symhash[h];
symhash[h] = sp;
sp->s_tsym = NULL;
strncpy(sp->s_id, id, NCPS);
sp->s_type = S_NEW;
sp->s_flag = 0;
sp->s_area = NULL;
sp->s_ref = 0;
sp->s_addr = 0;
return (sp);
}
/*)Function VOID symglob()
*
* The function symglob() will mark all symbols of
* type S_NEW as global. Called at the beginning of pass 1
* if the assembly option -g was specified.
*
* local variables:
* sym * sp pointer to a sym structure
* int i loop index
*
* global variables:
* sym * symhash[] array of pointers to NHASH
* linked symbol lists
*
* functions called:
* none
*
* side effects:
* Symbol types changed.
*/
VOID
symglob()
{
register struct sym *sp;
register int i;
for (i=0; i<NHASH; ++i) {
sp = symhash[i];
while (sp != NULL) {
if (sp->s_type == S_NEW)
sp->s_flag |= S_GBL;
sp = sp->s_sp;
}
}
}
/*)Function VOID allglob()
*
* The function allglob() will mark all symbols of
* type S_USER as global. Called at the beginning of pass 1
* if the assembly option -a was specified.
*
* local variables:
* sym * sp pointer to a sym structure
* int i loop index
*
* global variables:
* sym * symhash[] array of pointers to NHASH
* linked symbol lists
*
* functions called:
* none
*
* side effects:
* Symbol types changed.
*/
VOID
allglob()
{
register struct sym *sp;
register int i;
for (i=0; i<NHASH; ++i) {
sp = symhash[i];
while (sp != NULL) {
if (sp != &dot && sp->s_type == S_USER)
sp->s_flag |= S_GBL;
sp = sp->s_sp;
}
}
}
/*)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;
{
register int n;
n = NCPS;
do {
#if CASE_SENSITIVE
if (*p1++ != *p2++)
return (0);
#else
if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
return (0);
#endif
} while (--n);
return (1);
}
/*)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, n;
h = 0;
n = NCPS;
do {
#if CASE_SENSITIVE
h += *p++;
#else
h += ccase[(unsigned char)(*p++)];
#endif
} while (--n);
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
* assembly is terminated.
*
* local variables:
* VOID * p a general pointer
*
* global variables:
* none
*
* functions called:
* VOID asexit() asmain.c
* int fprintf() c_library
* VOID * malloc() c_library
*
* side effects:
* Memory is allocated, if allocation fails
* the assembly is terminated.
*/
VOID *
new(n)
unsigned int n;
{
register VOID *p;
if ((p = (VOID *) malloc(n)) == NULL) {
fprintf(stderr, "Out of space!\n");
asexit(1);
}
return (p);
}

23
link/as/z80/clean.mk Normal file
View File

@@ -0,0 +1,23 @@
# Deleting all files created by building the program
# --------------------------------------------------
clean:
rm -rf obj
rm -f *core *[%~] *.[oa]
rm -f .[a-z]*~
rm -f $(PRJDIR)/as-z80 as-z80
# Deleting all files created by configuring or building the program
# -----------------------------------------------------------------
distclean: clean
rm -f *.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

23
link/as/z80/conf.mk Normal file
View File

@@ -0,0 +1,23 @@
# Deleting all files created by building the program
# --------------------------------------------------
clean:
rm -f *core *[%~] *.[oa]
rm -f .[a-z]*~
rm -f $(PRJDIR)/as-z80 as-z80
# 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

10
link/as/z80/incld1.asm Normal file
View File

@@ -0,0 +1,10 @@
xxx ;1
.include "incld2.asm" ;2
;3
;4
;5
xxx ;6
;7
;8
;9
;10

10
link/as/z80/incld2.asm Normal file
View File

@@ -0,0 +1,10 @@
;1
xxx ;2
.include "incld3.asm" ;3
;4
;5
;6
xxx ;7
;8
;9
;10

10
link/as/z80/incld3.asm Normal file
View File

@@ -0,0 +1,10 @@
;1
;2
xxx ;3
.include "incld4.asm" ;4
;5
;6
;7
xxx ;8
;9
;10

10
link/as/z80/incld4.asm Normal file
View File

@@ -0,0 +1,10 @@
;1
;2
;3
xxx ;4
.include "incld5.asm" ;5
;6
;7
;8
xxx ;9
;10

10
link/as/z80/incld5.asm Normal file
View File

@@ -0,0 +1,10 @@
;1
;2
;3
;4
xxx ;5
.include "incldx.asm" ;6
;7
;8
;9
xxx ;10

42
link/as/z80/itsta.asm Normal file
View File

@@ -0,0 +1,42 @@
.include "incld1.asm" ;1
;2
;3
;4
;5
;6
;7
;8
;9
;10
xxx ;11
;
; This is a simple test of the error reporting
; for source and include files.
;
; assemble inctst:
; asxxxx itsta itstb
;
; ?ASxxxx-E-<o> in line 1 of incld1.asm
; ?ASxxxx-E-<o> in line 2 of incld2.asm
; ?ASxxxx-E-<o> in line 3 of incld3.asm
; ?ASxxxx-E-<o> in line 4 of incld4.asm
; ?ASxxxx-E-<o> in line 5 of incld5.asm
; ?ASxxxx-E-<i> in line 6 of incld5.asm
; ?ASxxxx-E-<o> in line 10 of incld5.asm
; ?ASxxxx-E-<o> in line 9 of incld4.asm
; ?ASxxxx-E-<o> in line 8 of incld3.asm
; ?ASxxxx-E-<o> in line 7 of incld2.asm
; ?ASxxxx-E-<o> in line 6 of incld1.asm
; ?ASxxxx-E-<o> in line 11 of itsta.asm
; ?ASxxxx-E-<o> in line 1 of incld1.asm
; ?ASxxxx-E-<o> in line 2 of incld2.asm
; ?ASxxxx-E-<o> in line 3 of incld3.asm
; ?ASxxxx-E-<o> in line 4 of incld4.asm
; ?ASxxxx-E-<o> in line 5 of incld5.asm
; ?ASxxxx-E-<i> in line 6 of incld5.asm
; ?ASxxxx-E-<o> in line 10 of incld5.asm
; ?ASxxxx-E-<o> in line 9 of incld4.asm
; ?ASxxxx-E-<o> in line 8 of incld3.asm
; ?ASxxxx-E-<o> in line 7 of incld2.asm
; ?ASxxxx-E-<o> in line 6 of incld1.asm
; ?ASxxxx-E-<o> in line 11 of itstb.asm

42
link/as/z80/itstb.asm Normal file
View File

@@ -0,0 +1,42 @@
.include "incld1.asm" ;1
;2
;3
;4
;5
;6
;7
;8
;9
;10
xxx ;11
;
; This is a simple test of the error reporting
; for source and include files.
;
; assemble inctst:
; asxxxx itsta itstb
;
; ?ASxxxx-E-<o> in line 1 of incld1.asm
; ?ASxxxx-E-<o> in line 2 of incld2.asm
; ?ASxxxx-E-<o> in line 3 of incld3.asm
; ?ASxxxx-E-<o> in line 4 of incld4.asm
; ?ASxxxx-E-<o> in line 5 of incld5.asm
; ?ASxxxx-E-<i> in line 6 of incld5.asm
; ?ASxxxx-E-<o> in line 10 of incld5.asm
; ?ASxxxx-E-<o> in line 9 of incld4.asm
; ?ASxxxx-E-<o> in line 8 of incld3.asm
; ?ASxxxx-E-<o> in line 7 of incld2.asm
; ?ASxxxx-E-<o> in line 6 of incld1.asm
; ?ASxxxx-E-<o> in line 11 of itsta.asm
; ?ASxxxx-E-<o> in line 1 of incld1.asm
; ?ASxxxx-E-<o> in line 2 of incld2.asm
; ?ASxxxx-E-<o> in line 3 of incld3.asm
; ?ASxxxx-E-<o> in line 4 of incld4.asm
; ?ASxxxx-E-<o> in line 5 of incld5.asm
; ?ASxxxx-E-<i> in line 6 of incld5.asm
; ?ASxxxx-E-<o> in line 10 of incld5.asm
; ?ASxxxx-E-<o> in line 9 of incld4.asm
; ?ASxxxx-E-<o> in line 8 of incld3.asm
; ?ASxxxx-E-<o> in line 7 of incld2.asm
; ?ASxxxx-E-<o> in line 6 of incld1.asm
; ?ASxxxx-E-<o> in line 11 of itstb.asm

15
link/as/z80/string.h Normal file
View File

@@ -0,0 +1,15 @@
/* STRING.H */
/* DECUC C */
extern char * strcat();
extern char * strchr();
extern int strcmp();
extern char * strcpy();
extern int streq();
extern int strlen();
extern char * strncat();
extern int strncmp();
extern char * strncpy();
extern int strneq();
extern char * strrchr();

68
link/as/z80/tconst.asm Normal file
View File

@@ -0,0 +1,68 @@
.title Assembler Link Test Constants
.module tconst
.area TEST (ABS,OVR)
bra1 == 0 ; branching constants
bra2 == 0x80
bra3 == 0x182
bra4 == 0x204
.blkb 0x7E ;bra1:
.blkb 0x02
.blkb 0x7F ;bra2:
.blkb 0x02
.blkb 0x02
.blkb 0x7F
.blkb 0x00 ;bra3:
.blkb 0x02
.blkb 0x80
.blkb 0x00 ;bra4:
.globl bra5,bra6,bra7,bra8
; branching labels
bra5: .blkb 0x7E ;bra5:
.blkb 0x02
bra6: .blkb 0x7F ;bra6:
.blkb 0x02
.blkb 0x02
.blkb 0x7F
bra7: .blkb 0x00 ;bra7:
.blkb 0x02
.blkb 0x80
bra8: .blkb 0x00 ;bra8:
; 12-Bit numbers are considered valid if:
; 1) the most significant 4 bits of the 16-bit number are zero
; 2) the most significant 4 bits of the 16-bit number are all ones
n0FFF == 0x0FFF ;largest positive
n1000 == 0x1000 ;+1
nF000 == 0xF000 ;largest negative
nEFFF == 0xEFFF ;-1
.area DIRECT (ABS,OVR)
.setdp
boundary == 0x101
minus1 == -1 ; paging / indexing constants
zero == 0
two55 == 0d255
two56 == 0d256
five11 == 0d511
five12 == 0d512
.globl lzero,ltwo55,ltwo56,lminus1
lzero: .blkb 0x00FF ; paging labels
ltwo55: .blkb 0x0001
ltwo56: .blkb 0xFEFF
lminus1:.blkb 0d0000

1013
link/as/z80/tz80.asm Normal file

File diff suppressed because it is too large Load Diff

47
link/as/z80/tz80l.asm Normal file
View File

@@ -0,0 +1,47 @@
.sbttl Assembler Link Tests
.module tz80l
; This file and TCONST.ASM should be assembled and linked.
;
; ASZ80 -XGOL TZ80L
; ASZ80 -XGOL TCONST
;
; ASLINK -C
; -XMS
; TZ80L
; TCONST
; -E
;
; The following tests verify the correct processing of
; external references for the branches.
;
; *L signifies an error will be reported at link time.
; branch test must be first
.area TEST (ABS,OVR)
.blkb 0x7E ;bra1:
jr C,bra1 ; 38 00 [38 80]
.blkb 0x7F ;bra2:
jr C,bra2 ;*L 38 00 [38 7F]
jr C,bra3 ; 38 00 [38 7F]
.blkb 0x7F
.blkb 0x00 ;bra3:
jr C,bra4 ;*L 38 00 [38 [80]
.blkb 0x80
.blkb 0x00 ;bra4:
.blkb 0x7E ;bra5:
jr C,bra5 ; 38 00 [38 80]
.blkb 0x7F ;bra6:
jr C,bra6 ;*L 38 00 [38 7F]
jr C,bra7 ; 38 00 [38 7F]
.blkb 0x7F
.blkb 0x00 ;bra7:
jr C,bra8 ;*L 38 00 [38 [80]
.blkb 0x80
.blkb 0x00 ;bra8:

191
link/as/z80/z80.h Normal file
View File

@@ -0,0 +1,191 @@
/* z80.h */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
/*)BUILD
$(PROGRAM) = ASZ80
$(INCLUDE) = {
ASM.H
Z80.H
}
$(FILES) = {
Z80EXT.C
Z80MCH.C
Z80ADR.C
Z80PST.C
ASMAIN.C
ASLEX.C
ASSYM.C
ASSUBR.C
ASEXPR.C
ASDATA.C
ASLIST.C
ASOUT.C
}
$(STACK) = 2000
*/
/*
* Indirect Addressing delimeters
*/
#define LFIND '('
#define RTIND ')'
/*
* Registers
*/
#define B 0
#define C 1
#define D 2
#define E 3
#define H 4
#define L 5
#define A 7
#define I 0107
#define R 0117
#define BC 0
#define DE 1
#define HL 2
#define SP 3
#define AF 4
#ifndef GAMEBOY
#define IX 5
#define IY 6
#else /* GAMEBOY */
#define HLD 5
#define HLI 6
#endif /* GAMEBOY */
/*
* Conditional definitions
*/
#define NZ 0
#define Z 1
#define NC 2
#define CS 3
#ifndef GAMEBOY
#define PO 4
#define PE 5
#define P 6
#define M 7
#endif /* GAMEBOY */
/*
* Symbol types
*/
#define S_IMMED 30
#define S_R8 31
#define S_R8X 32
#define S_R16 33
#define S_R16X 34
#define S_CND 35
#define S_FLAG 36
/*
* Indexing modes
*/
#define S_INDB 40
#define S_IDC 41
#define S_INDR 50
#define S_IDBC 50
#define S_IDDE 51
#define S_IDHL 52
#define S_IDSP 53
#ifndef GAMEBOY
#define S_IDIX 55
#define S_IDIY 56
#else /* GAMEBOY */
#define S_IDHLD 55
#define S_IDHLI 56
#endif /* GAMEBOY */
#define S_INDM 57
/*
* Instruction types
*/
#define S_LD 60
#define S_CALL 61
#define S_JP 62
#define S_JR 63
#define S_RET 64
#define S_BIT 65
#define S_INC 66
#define S_DEC 67
#define S_ADD 68
#define S_ADC 69
#define S_AND 70
#ifndef GAMEBOY
#define S_EX 71
#endif /* GAMEBOY */
#define S_PUSH 72
#ifndef GAMEBOY
#define S_IN 73
#define S_OUT 74
#endif /* GAMEBOY */
#define S_RL 75
#define S_RST 76
#define S_IM 77
#define S_INH1 78
#ifndef GAMEBOY
#define S_INH2 79
#define S_DJNZ 80
#endif /* GAMEBOY */
#define S_SUB 81
#define S_SBC 82
#ifdef GAMEBOY
#define S_STOP 83
#define S_LDH 84
#define S_LDA 85
#define S_LDHL 86
#endif /* GAMEBOY */
/*
* HD64180 Instructions
*/
#define X_HD64 90
#define X_INH2 91
#define X_IN 92
#define X_OUT 93
#define X_MLT 94
#define X_TST 95
#define X_TSTIO 96
struct adsym
{
char a_str[4]; /* addressing string */
int a_val; /* addressing mode value */
};
extern struct adsym R8[];
extern struct adsym R8X[];
extern struct adsym R16[];
extern struct adsym R16X[];
extern struct adsym CND[];
/* machine dependent functions */
/* z80adr.c */
extern int addr();
extern int admode();
extern int any();
extern int srch();
/* z80mch.c */
extern int comma();
extern int genop();
extern int gixiy();
extern VOID minit();
extern VOID machine(struct mne *mp) ;

256
link/as/z80/z80adr.c Normal file
View File

@@ -0,0 +1,256 @@
/* z80adr.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#include <stdio.h>
#include <setjmp.h>
#include "asm.h"
#include "z80.h"
/*
* Read an address specifier. Pack the
* address information into the supplied
* `expr' structure. Return the mode of
* the address.
*
* This addr(esp) routine performs the following addressing decoding:
*
* address mode flag addr base
* #n S_IMMED 0 n NULL
* label s_type ---- s_addr s_area
* [REG] S_IND+icode 0 0 NULL
* [label] S_INDM ---- s_addr s_area
* offset[REG] S_IND+icode ---- offset ----
*/
int
addr(esp)
register struct expr *esp;
{
register int c, mode = 0, indx;
if ((c = getnb()) == '#') {
expr(esp, 0);
esp->e_mode = S_IMMED;
} else
if (c == LFIND) {
if ((indx = admode(R8)) != 0) {
mode = S_INDB;
} else
if ((indx = admode(R16)) != 0) {
mode = S_INDR;
} else
if ((indx = admode(R8X)) != 0) {
mode = S_R8X;
aerr();
} else
if ((indx = admode(R16X)) != 0) {
mode = S_R16X;
aerr();
} else {
expr(esp, 0);
esp->e_mode = S_INDM;
}
if (indx) {
esp->e_mode = (mode + indx)&0xFF;
esp->e_base.e_ap = NULL;
}
if ((c = getnb()) != RTIND)
qerr();
} else {
unget(c);
if ((indx = admode(R8)) != 0) {
mode = S_R8;
} else
if ((indx = admode(R16)) != 0) {
mode = S_R16;
} else
if ((indx = admode(R8X)) != 0) {
mode = S_R8X;
} else
if ((indx = admode(R16X)) != 0) {
mode = S_R16X;
} else {
expr(esp, 0);
esp->e_mode = S_USER;
}
if (indx) {
esp->e_addr = indx&0xFF;
esp->e_mode = mode;
esp->e_base.e_ap = NULL;
}
if ((c = getnb()) == LFIND) {
#ifndef GAMEBOY
if ((indx=admode(R16))!=0
&& ((indx&0xFF)==IX || (indx&0xFF)==IY)) {
#else /* GAMEBOY */
if ((indx=admode(R16))!=0) {
#endif /* GAMEBOY */
esp->e_mode = S_INDR + (indx&0xFF);
} else {
aerr();
}
if ((c = getnb()) != RTIND)
qerr();
} else {
unget(c);
}
}
return (esp->e_mode);
}
/*
* Enter admode() to search a specific addressing mode table
* for a match. Return the addressing value on a match or
* zero for no match.
*/
int
admode(sp)
register struct adsym *sp;
{
register char *ptr;
register int i;
register char *ips;
ips = ip;
unget(getnb());
i = 0;
while ( *(ptr = (char *) &sp[i]) ) {
if (srch(ptr)) {
return(sp[i].a_val);
}
i++;
}
ip = ips;
return(0);
}
/*
* srch --- does string match ?
*/
int
srch(str)
register char *str;
{
register char *ptr;
ptr = ip;
#if CASE_SENSITIVE
while (*ptr && *str) {
if (*ptr != *str)
break;
ptr++;
str++;
}
if (*ptr == *str) {
ip = ptr;
return(1);
}
#else
while (*ptr && *str) {
if (ccase[(unsigned char)(*ptr)] != ccase[(unsigned char)(*str)])
break;
ptr++;
str++;
}
if (ccase[(unsigned char)(*ptr)] == ccase[(unsigned char)(*str)]) {
ip = ptr;
return(1);
}
#endif
if (!*str)
if (any(*ptr," \t\n,);")) {
ip = ptr;
return(1);
}
return(0);
}
/*
* any --- does str contain c?
*/
int
any(c,str)
char c, *str;
{
while (*str)
if(*str++ == c)
return(1);
return(0);
}
/*
* Registers
*/
struct adsym R8[] = {
{ "b", B|0400 },
{ "c", C|0400 },
{ "d", D|0400 },
{ "e", E|0400 },
{ "h", H|0400 },
{ "l", L|0400 },
{ "a", A|0400 },
{ "", 000 }
};
struct adsym R8X[] = {
{ "i", I|0400 },
{ "r", R|0400 },
{ "", 000 }
};
struct adsym R16[] = {
{ "bc", BC|0400 },
{ "de", DE|0400 },
{ "hl", HL|0400 },
{ "sp", SP|0400 },
#ifndef GAMEBOY
{ "ix", IX|0400 },
{ "iy", IY|0400 },
#else /* GAMEBOY */
{ "hl-", HLD|0400 },
{ "hl+", HLI|0400 },
{ "hld", HLD|0400 },
{ "hli", HLI|0400 },
#endif /* GAMEBOY */
{ "", 000 }
};
struct adsym R16X[] = {
{ "af", AF|0400 },
#ifndef GAMEBOY
{ "af'", AF|0400 },
#endif /* GAMEBOY */
{ "", 000 }
};
/*
* Conditional definitions
*/
struct adsym CND[] = {
{ "NZ", NZ|0400 },
{ "Z", Z |0400 },
{ "NC", NC|0400 },
{ "C", CS|0400 },
#ifndef GAMEBOY
{ "PO", PO|0400 },
{ "PE", PE|0400 },
{ "P", P |0400 },
{ "M", M |0400 },
#endif /* GAMEBOY */
{ "", 000 }
};

27
link/as/z80/z80ext.c Normal file
View File

@@ -0,0 +1,27 @@
/* z80ext.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#include <stdio.h>
#include <setjmp.h>
#include "asm.h"
#include "z80.h"
#ifndef GAMEBOY
char *cpu = "Zilog Z80 / Hitachi HD64180";
#else /* GAMEBOY */
char *cpu = "GameBoy Z80-like CPU";
#endif /* GAMEBOY */
int hilo = 0;
char *dsft = "ASM";

773
link/as/z80/z80mch.c Normal file
View File

@@ -0,0 +1,773 @@
/* z80mch.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#include <stdio.h>
#include <setjmp.h>
#include "asm.h"
#include "z80.h"
char imtab[3] = { 0x46, 0x56, 0x5E };
#ifndef GAMEBOY
int hd64;
#endif /* GAMEBOY */
/*
* Process a machine op.
*/
VOID
machine(mp)
struct mne *mp;
{
register int op, t1, t2;
struct expr e1, e2;
int rf, v1, v2;
clrexpr(&e1);
clrexpr(&e2);
op = mp->m_valu;
rf = mp->m_type;
#ifndef GAMEBOY
if (!hd64 && rf>X_HD64)
rf = 0;
#endif /* GAMEBOY */
switch (rf) {
case S_INH1:
outab(op);
break;
#ifndef GAMEBOY
case S_INH2:
outab(0xED);
outab(op);
break;
#endif /* GAMEBOY */
case S_RET:
if (more()) {
if ((v1 = admode(CND)) != 0) {
outab(op | v1<<3);
} else {
qerr();
}
} else {
outab(0xC9);
}
break;
case S_PUSH:
if (admode(R16X)) {
outab(op+0x30);
break;
} else
if ((v1 = admode(R16)) != 0 && (v1 &= 0xFF) != SP) {
if (v1 != gixiy(v1)) {
outab(op+0x20);
break;
}
outab(op | v1<<4);
break;
}
aerr();
break;
case S_RST:
v1 = absexpr();
if (v1 & ~0x38) {
aerr();
v1 = 0;
}
outab(op|v1);
break;
case S_IM:
expr(&e1, 0);
abscheck(&e1);
if (e1.e_addr > 2) {
aerr();
e1.e_addr = 0;
}
outab(op);
outab(imtab[e1.e_addr]);
break;
case S_BIT:
expr(&e1, 0);
t1 = 0;
v1 = e1.e_addr;
if (v1 > 7) {
++t1;
v1 &= 0x07;
}
op |= (v1<<3);
comma();
addr(&e2);
abscheck(&e1);
if (genop(0xCB, op, &e2, 0) || t1)
aerr();
break;
case S_RL:
t1 = 0;
t2 = addr(&e2);
if (more()) {
if ((t2 != S_R8) || (e2.e_addr != A))
++t1;
comma();
t2 = addr(&e2);
}
if (genop(0xCB, op, &e2, 0) || t1)
aerr();
break;
case S_AND:
case S_SUB:
t1 = 0;
t2 = addr(&e2);
if (more()) {
if ((t2 != S_R8) || (e2.e_addr != A))
++t1;
comma();
t2 = addr(&e2);
}
if (genop(0, op, &e2, 1) || t1)
aerr();
break;
case S_ADD:
case S_ADC:
case S_SBC:
t1 = addr(&e1);
t2 = 0;
if (more()) {
comma();
t2 = addr(&e2);
}
if (t2 == 0) {
if (genop(0, op, &e1, 1))
aerr();
break;
}
if ((t1 == S_R8) && (e1.e_addr == A)) {
if (genop(0, op, &e2, 1))
aerr();
break;
}
if ((t1 == S_R16) && (t2 == S_R16)) {
#ifndef GAMEBOY
if (rf == S_ADD)
op = 0x09;
if (rf == S_ADC)
op = 0x4A;
if (rf == S_SBC)
op = 0x42;
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((v1 == HL) && (v2 <= SP)) {
if (rf != S_ADD)
outab(0xED);
outab(op | (v2<<4));
break;
}
if (rf != S_ADD) {
aerr();
break;
}
if ((v1 == IX) && (v2 != HL) && (v2 != IY)) {
if (v2 == IX)
v2 = HL;
outab(0xDD);
outab(op | (v2<<4));
break;
}
if ((v1 == IY) && (v2 != HL) && (v2 != IX)) {
if (v2 == IY)
v2 = HL;
outab(0xFD);
outab(op | (v2<<4));
break;
}
}
#else /* GAMEBOY */
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((v1 == HL) && (v2 <= SP) && (rf == S_ADD)) {
outab(0x09 | (v2<<4));
break;
}
}
/*
* 0xE8 : ADD SP,#n
*/
if ((rf == S_ADD) && (t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
outab(0xE8);
outrb(&e2,0);
break;
}
#endif /* GAMEBOY */
aerr();
break;
case S_LD:
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if (t1 == S_R8) {
v1 = op | e1.e_addr<<3;
if (genop(0, v1, &e2, 0) == 0)
break;
if (t2 == S_IMMED) {
outab(e1.e_addr<<3 | 0x06);
outrb(&e2,0);
break;
}
}
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((t1 == S_R16) && (t2 == S_IMMED)) {
v1 = gixiy(v1);
outab(0x01|v1<<4);
outrw(&e2, 0);
break;
}
#ifndef GAMEBOY
if ((t1 == S_R16) && (t2 == S_INDM)) {
if (gixiy(v1) == HL) {
outab(0x2A);
} else {
outab(0xED);
outab(0x4B | v1<<4);
}
outrw(&e2, 0);
break;
}
if ((t1 == S_INDM) && (t2 == S_R16)) {
if (gixiy(v2) == HL) {
outab(0x22);
} else {
outab(0xED);
outab(0x43 | v2<<4);
}
outrw(&e1, 0);
break;
}
if ((t1 == S_R8) && (v1 == A) && (t2 == S_INDM)) {
outab(0x3A);
outrw(&e2, 0);
break;
}
if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
outab(0x32);
outrw(&e1, 0);
break;
}
#endif /* GAMEBOY */
if ((t2 == S_R8) && (gixiy(t1) == S_IDHL)) {
outab(0x70|v2);
if (t1 != S_IDHL)
outrb(&e1, 0);
break;
}
if ((t2 == S_IMMED) && (gixiy(t1) == S_IDHL)) {
outab(0x36);
if (t1 != S_IDHL)
outrb(&e1, 0);
outrb(&e2, 0);
break;
}
#ifndef GAMEBOY
if ((t1 == S_R8X) && (t2 == S_R8) && (v2 == A)) {
outab(0xED);
outab(v1);
break;
}
if ((t1 == S_R8) && (v1 == A) && (t2 == S_R8X)) {
outab(0xED);
outab(v2|0x10);
break;
}
#endif /* GAMEBOY */
if ((t1 == S_R16) && (v1 == SP)) {
if ((t2 == S_R16) && (gixiy(v2) == HL)) {
outab(0xF9);
break;
}
}
if ((t1 == S_R8) && (v1 == A)) {
if ((t2 == S_IDBC) || (t2 == S_IDDE)) {
outab(0x0A | (t2-S_INDR)<<4);
break;
}
}
if ((t2 == S_R8) && (v2 == A)) {
if ((t1 == S_IDBC) || (t1 == S_IDDE)) {
outab(0x02 | (t1-S_INDR)<<4);
break;
}
}
#ifdef GAMEBOY
/*
* 0x08 : LD (nn),SP
*/
if ((t1 == S_INDM) && (t2 == S_R16) && (v2 == SP)) {
outab(0x08);
outrw(&e1, 0);
break;
}
/*
* 0xEA : LD (nn),A
* 0xFA : LD A,(nn)
*/
if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
outab(0xEA);
outrw(&e1, 0);
break;
}
if ((t2 == S_INDM) && (t1 == S_R8) && (v1 == A)) {
outab(0xFA);
outrw(&e2, 0);
break;
}
/*
* 0x32 : LD (HL-),A
* 0x3A : LD A,(HL-)
*/
if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLD)) {
outab(0x3A);
break;
}
if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLD)) {
outab(0x32);
break;
}
/*
* 0x22 : LD (HL+),A
* 0x2A : LD A,(HL+)
*/
if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLI)) {
outab(0x2A);
break;
}
if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLI)) {
outab(0x22);
break;
}
#endif /* GAMEBOY */
aerr();
break;
#ifdef GAMEBOY
case S_STOP: /* 0x10 */
/*
* 0x10 : STOP
*/
outab(op);
outab(0x00);
break;
case S_LDH: /* 0xE0 */
/*
* 0xE0 : LDH (n),A = LD ($FF00+n),A
* 0xE2 : LDH (C),A = LD ($FF00+C),A
* 0xF0 : LDH A,(n) = LD A,($FF00+n)
* 0xF2 : LDH A,(C) = LD A,($FF00+C)
*/
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if ((t1 == S_INDM) && (t2 == S_R8) && (e2.e_addr == A)) {
outab(0xE0);
outrb(&e1, 0);
break;
}
if ((t1 == S_IDC) && (t2 == S_R8) && (e2.e_addr == A)) {
outab(0xE2);
break;
}
if ((t2 == S_INDM) && (t1 == S_R8) && (e1.e_addr == A)) {
outab(0xF0);
outrb(&e2, 0);
break;
}
if ((t2 == S_IDC) && (t1 == S_R8) && (e1.e_addr == A)) {
outab(0xF2);
break;
}
aerr();
break;
case S_LDA: /* 0xE8 */
/*
* 0xE8 : LDA SP,#n(SP)
* 0xF8 : LDA HL,#n(SP)
*/
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_INDR+SP)) {
outab(0xE8);
outrb(&e2,0);
break;
}
if ((t1 == S_R16) && (e1.e_addr == HL) && (t2 == S_INDR+SP)) {
outab(0xF8);
outrb(&e2,0);
break;
}
aerr();
break;
case S_LDHL: /* 0xF8 */
/*
* 0xF8 : LDHL SP,#n
*/
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
outab(0xF8);
outrb(&e2,0);
break;
}
aerr();
break;
#endif /* GAMEBOY */
#ifndef GAMEBOY
case S_EX:
t1 = addr(&e1);
comma();
t2 = addr(&e2);
if (t2 == S_R16) {
v1 = e1.e_addr;
v2 = e2.e_addr;
if ((t1 == S_IDSP) && (v1 == 0)) {
if (gixiy(v2) == HL) {
outab(op);
break;
}
}
if (t1 == S_R16) {
if ((v1 == DE) && (v2 == HL)) {
outab(0xEB);
break;
}
}
}
if ((t1 == S_R16X) && (t2 == S_R16X)) {
outab(0x08);
break;
}
aerr();
break;
case S_IN:
case S_OUT:
if (rf == S_IN) {
t1 = addr(&e1);
comma();
t2 = addr(&e2);
} else {
t2 = addr(&e2);
comma();
t1 = addr(&e1);
}
v1 = e1.e_addr;
v2 = e2.e_addr;
if (t1 == S_R8) {
if ((v1 == A) && (t2 == S_INDM)) {
outab(op);
outab(v2);
break;
}
if (t2 == S_IDC) {
outab(0xED);
outab(((rf == S_IN) ? 0x40 : 0x41) + (v1<<3));
break;
}
}
aerr();
break;
#endif /* GAMEBOY */
case S_DEC:
case S_INC:
t1 = addr(&e1);
v1 = e1.e_addr;
if (t1 == S_R8) {
outab(op|(v1<<3));
break;
}
if (t1 == S_IDHL) {
outab(op|0x30);
break;
}
if (t1 != gixiy(t1)) {
outab(op|0x30);
outrb(&e1,0);
break;
}
if (t1 == S_R16) {
v1 = gixiy(v1);
if (rf == S_INC) {
outab(0x03|(v1<<4));
break;
}
if (rf == S_DEC) {
outab(0x0B|(v1<<4));
break;
}
}
aerr();
break;
#ifndef GAMEBOY
case S_DJNZ:
case S_JR:
if ((v1 = admode(CND)) != 0 && rf != S_DJNZ) {
#else /* GAMEBOY */
case S_JR:
if ((v1 = admode(CND)) != 0) {
#endif /* GAMEBOY */
if ((v1 &= 0xFF) <= 0x18) {
op += (v1+1)<<3;
} else {
aerr();
}
comma();
}
expr(&e2, 0);
outab(op);
if (e2.e_base.e_ap == NULL || e2.e_base.e_ap == dot.s_area) {
v2 = e2.e_addr - dot.s_addr - 1;
if (pass == 2 && ((v2 < -128) || (v2 > 127)))
aerr();
outab(v2);
} else {
outrb(&e2, R_PCR);
}
if (e2.e_mode != S_USER)
rerr();
break;
case S_CALL:
if ((v1 = admode(CND)) != 0) {
op |= (v1&0xFF)<<3;
comma();
} else {
op = 0xCD;
}
expr(&e1, 0);
outab(op);
outrw(&e1, 0);
break;
case S_JP:
if ((v1 = admode(CND)) != 0) {
op |= (v1&0xFF)<<3;
comma();
expr(&e1, 0);
outab(op);
outrw(&e1, 0);
break;
}
t1 = addr(&e1);
if (t1 == S_USER) {
outab(0xC3);
outrw(&e1, 0);
break;
}
if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
outab(0xE9);
break;
}
aerr();
break;
#ifndef GAMEBOY
case X_HD64:
++hd64;
break;
case X_INH2:
outab(0xED);
outab(op);
break;
case X_IN:
case X_OUT:
if (rf == X_IN) {
t1 = addr(&e1);
comma();
t2 = addr(&e2);
} else {
t2 = addr(&e2);
comma();
t1 = addr(&e1);
}
if ((t1 == S_R8) && (t2 == S_INDM)) {
outab(0xED);
outab(op | e1.e_addr<<3);
outrb(&e2, 0);
break;
}
aerr();
break;
case X_MLT:
t1 = addr(&e1);
if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
outab(0xED);
outab(op | v1<<4);
break;
}
aerr();
break;
case X_TST:
t1 = addr(&e1);
if (t1 == S_R8) {
outab(0xED);
outab(op | e1.e_addr<<3);
break;
}
if (t1 == S_IDHL) {
outab(0xED);
outab(0x34);
break;
}
if (t1 == S_IMMED) {
outab(0xED);
outab(0x64);
outrb(&e1, 0);
break;
}
aerr();
break;
case X_TSTIO:
t1 = addr(&e1);
if (t1 == S_IMMED) {
outab(0xED);
outab(op);
outrb(&e1, 0);
break;
}
aerr();
break;
#endif /* GAMEBOY */
default:
err('o');
}
}
/*
* general addressing evaluation
* return(0) if general addressing mode output, else
* return(esp->e_mode)
*/
int
genop(pop, op, esp, f)
register int pop, op;
register struct expr *esp;
int f;
{
register int t1;
if ((t1 = esp->e_mode) == S_R8) {
if (pop)
outab(pop);
outab(op|esp->e_addr);
return(0);
}
if (t1 == S_IDHL) {
if (pop)
outab(pop);
outab(op|0x06);
return(0);
}
if (gixiy(t1) == S_IDHL) {
if (pop) {
outab(pop);
outrb(esp,0);
outab(op|0x06);
} else {
outab(op|0x06);
outrb(esp,0);
}
return(0);
}
if ((t1 == S_IMMED) && (f)) {
if (pop)
outab(pop);
outab(op|0x46);
outrb(esp,0);
return(0);
}
return(t1);
}
/*
* IX and IY prebyte check
*/
int
gixiy(v)
int v;
{
#ifndef GAMEBOY
if (v == IX) {
v = HL;
outab(0xDD);
} else if (v == IY) {
v = HL;
outab(0xFD);
} else if (v == S_IDIX) {
v = S_IDHL;
outab(0xDD);
} else if (v == S_IDIY) {
v = S_IDHL;
outab(0xFD);
}
#endif /* GAMEBOY */
return(v);
}
/*
* The next character must be a
* comma.
*/
int
comma()
{
if (getnb() != ',')
qerr();
return(1);
}
/*
* Machine dependent initialization
*/
VOID
minit()
{
#ifndef GAMEBOY
hd64 = 0;
#endif /* GAMEBOY */
}

179
link/as/z80/z80pst.c Normal file
View File

@@ -0,0 +1,179 @@
/* z80pst.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#include <stdio.h>
#include <setjmp.h>
#include "asm.h"
#include "z80.h"
struct mne mne[] = {
/* machine */
/* system */
{ NULL, "CON", S_ATYP, 0, A_CON },
{ NULL, "OVR", S_ATYP, 0, A_OVR },
{ NULL, "REL", S_ATYP, 0, A_REL },
{ NULL, "ABS", S_ATYP, 0, A_ABS|A_OVR },
{ NULL, "NOPAG", S_ATYP, 0, A_NOPAG },
{ NULL, "PAG", S_ATYP, 0, A_PAG },
{ NULL, ".byte", S_BYTE, 0, 0 },
{ NULL, ".db", S_BYTE, 0, 0 },
{ NULL, ".word", S_WORD, 0, 0 },
{ NULL, ".dw", S_WORD, 0, 0 },
{ NULL, ".df", S_FLOAT, 0, 0 },
{ NULL, ".ascii", S_ASCII, 0, 0 },
{ NULL, ".asciz", S_ASCIZ, 0, 0 },
{ NULL, ".blkb", S_BLK, 0, 1 },
{ NULL, ".ds", S_BLK, 0, 1 },
{ NULL, ".blkw", S_BLK, 0, 2 },
{ NULL, ".page", S_PAGE, 0, 0 },
{ NULL, ".title", S_TITLE, 0, 0 },
{ NULL, ".sbttl", S_SBTL, 0, 0 },
{ NULL, ".globl", S_GLOBL, 0, 0 },
{ NULL, ".area", S_DAREA, 0, 0 },
{ NULL, ".even", S_EVEN, 0, 0 },
{ NULL, ".odd", S_ODD, 0, 0 },
{ NULL, ".if", S_IF, 0, 0 },
{ NULL, ".else", S_ELSE, 0, 0 },
{ NULL, ".endif", S_ENDIF, 0, 0 },
{ NULL, ".include", S_INCL, 0, 0 },
{ NULL, ".radix", S_RADIX, 0, 0 },
{ NULL, ".org", S_ORG, 0, 0 },
{ NULL, ".module", S_MODUL, 0, 0 },
{ NULL, ".ascis", S_ASCIS, 0, 0 },
/* z80 / hd64180 */
{ NULL, "ld", S_LD, 0, 0x40 },
{ NULL, "call", S_CALL, 0, 0xC4 },
{ NULL, "jp", S_JP, 0, 0xC2 },
{ NULL, "jr", S_JR, 0, 0x18 },
#ifndef GAMEBOY
{ NULL, "djnz", S_DJNZ, 0, 0x10 },
#endif /* GAMEBOY */
{ NULL, "ret", S_RET, 0, 0xC0 },
{ NULL, "bit", S_BIT, 0, 0x40 },
{ NULL, "res", S_BIT, 0, 0x80 },
{ NULL, "set", S_BIT, 0, 0xC0 },
{ NULL, "inc", S_INC, 0, 0x04 },
{ NULL, "dec", S_DEC, 0, 0x05 },
{ NULL, "add", S_ADD, 0, 0x80 },
{ NULL, "adc", S_ADC, 0, 0x88 },
{ NULL, "sub", S_SUB, 0, 0x90 },
{ NULL, "sbc", S_SBC, 0, 0x98 },
{ NULL, "and", S_AND, 0, 0xA0 },
{ NULL, "cp", S_AND, 0, 0xB8 },
{ NULL, "or", S_AND, 0, 0xB0 },
{ NULL, "xor", S_AND, 0, 0xA8 },
#ifndef GAMEBOY
{ NULL, "ex", S_EX, 0, 0xE3 },
#endif /* GAMEBOY */
{ NULL, "push", S_PUSH, 0, 0xC5 },
{ NULL, "pop", S_PUSH, 0, 0xC1 },
#ifndef GAMEBOY
{ NULL, "in", S_IN, 0, 0xDB },
{ NULL, "out", S_OUT, 0, 0xD3 },
#endif /* GAMEBOY */
{ NULL, "rl", S_RL, 0, 0x10 },
{ NULL, "rlc", S_RL, 0, 0x00 },
{ NULL, "rr", S_RL, 0, 0x18 },
{ NULL, "rrc", S_RL, 0, 0x08 },
{ NULL, "sla", S_RL, 0, 0x20 },
{ NULL, "sra", S_RL, 0, 0x28 },
{ NULL, "srl", S_RL, 0, 0x38 },
{ NULL, "rst", S_RST, 0, 0xC7 },
#ifndef GAMEBOY
{ NULL, "im", S_IM, 0, 0xED },
#endif /* GAMEBOY */
{ NULL, "ccf", S_INH1, 0, 0x3F },
{ NULL, "cpl", S_INH1, 0, 0x2F },
{ NULL, "daa", S_INH1, 0, 0x27 },
{ NULL, "di", S_INH1, 0, 0xF3 },
{ NULL, "ei", S_INH1, 0, 0xFB },
#ifndef GAMEBOY
{ NULL, "exx", S_INH1, 0, 0xD9 },
#endif /* GAMEBOY */
{ NULL, "nop", S_INH1, 0, 0x00 },
{ NULL, "halt", S_INH1, 0, 0x76 },
{ NULL, "rla", S_INH1, 0, 0x17 },
{ NULL, "rlca", S_INH1, 0, 0x07 },
{ NULL, "rra", S_INH1, 0, 0x1F },
{ NULL, "rrca", S_INH1, 0, 0x0F },
{ NULL, "scf", S_INH1, 0, 0x37 },
#ifndef GAMEBOY
{ NULL, "cpd", S_INH2, 0, 0xA9 },
{ NULL, "cpdr", S_INH2, 0, 0xB9 },
{ NULL, "cpi", S_INH2, 0, 0xA1 },
{ NULL, "cpir", S_INH2, 0, 0xB1 },
{ NULL, "ind", S_INH2, 0, 0xAA },
{ NULL, "indr", S_INH2, 0, 0xBA },
{ NULL, "ini", S_INH2, 0, 0xA2 },
{ NULL, "inir", S_INH2, 0, 0xB2 },
{ NULL, "ldd", S_INH2, 0, 0xA8 },
{ NULL, "lddr", S_INH2, 0, 0xB8 },
{ NULL, "ldi", S_INH2, 0, 0xA0 },
{ NULL, "ldir", S_INH2, 0, 0xB0 },
{ NULL, "neg", S_INH2, 0, 0x44 },
{ NULL, "otdr", S_INH2, 0, 0xBB },
{ NULL, "otir", S_INH2, 0, 0xB3 },
{ NULL, "outd", S_INH2, 0, 0xAB },
{ NULL, "outi", S_INH2, 0, 0xA3 },
{ NULL, "reti", S_INH2, 0, 0x4D },
{ NULL, "retn", S_INH2, 0, 0x45 },
{ NULL, "rld", S_INH2, 0, 0x6F },
{ NULL, "rrd", S_INH2, 0, 0x67 },
/* 64180 */
{ NULL, ".hd64", X_HD64, 0, 0 },
{ NULL, "otdm", X_INH2, 0, 0x8B },
{ NULL, "otdmr", X_INH2, 0, 0x9B },
{ NULL, "otim", X_INH2, 0, 0x83 },
{ NULL, "otimr", X_INH2, 0, 0x93 },
{ NULL, "slp", X_INH2, 0, 0x76 },
{ NULL, "in0", X_IN, 0, 0x00 },
{ NULL, "out0", X_OUT, 0, 0x01 },
{ NULL, "mlt", X_MLT, 0, 0x4C },
{ NULL, "tst", X_TST, 0, 0x04 },
{ NULL, "tstio", X_TSTIO, S_END, 0x7 }
#else /* GAMEBOY */
{ NULL, "stop", S_STOP, 0, 0x10 },
{ NULL, "swap", S_RL, 0, 0x30 },
{ NULL, "reti", S_INH1, 0, 0xD9 },
{ NULL, "ldh", S_LDH, 0, 0xE0 },
{ NULL, "lda", S_LDA, 0, 0xE8 },
{ NULL, "ldhl", S_LDHL, S_END, 0xF }
#endif /* GAMEBOY */
};

4
link/clean.mk Normal file
View File

@@ -0,0 +1,4 @@
clean:
$(MAKE) -C z80 -f clean.mk clean
distclean: clean

46
link/sdccconf.h Normal file
View File

@@ -0,0 +1,46 @@
/* sdccconf.h. Generated automatically by configure. */
/*
*/
#ifndef SDCCCONF_HEADER
#define SDCCCONF_HEADER
#define SDCC_VERSION_HI 2
#define SDCC_VERSION_LO 3
#define SDCC_VERSION_P 1
#define SDCC_VERSION_STR "2.3.1"
#define PREFIX "/opt/gbdk"
#define DATADIR "/opt/gbdk/share/sdcc"
#define SRCDIR "/home/Zalo/Desktop/gb/gbdk-2020/sdcc"
#define STANDARD_INCLUDE_DIR "/opt/gbdk/share/sdcc/include"
#define SDCC_INCLUDE_DIR "/opt/gbdk/share/sdcc/include"
#define SDCC_LIB_DIR "/opt/gbdk/share/sdcc/lib"
#define STD_LIB "libsdcc"
#define STD_INT_LIB "libint"
#define STD_LONG_LIB "liblong"
#define STD_FP_LIB "libfloat"
#define STD_DS390_LIB "libds390"
/* #undef HAVE_SYS_SOCKET_H */
/* #undef HAVE_SYS_ISA_DEFS_H */
/* #undef HAVE_ENDIAN_H */
/* #undef HAVE_MACHINE_ENDIAN_H */
#define HAVE_STRERROR 1
#define OPT_DISABLE_MCS51 1
#define OPT_DISABLE_GBZ80 0
#define OPT_DISABLE_Z80 0
#define OPT_DISABLE_AVR 1
#define OPT_DISABLE_DS390 1
#define OPT_DISABLE_PIC 1
#define OPT_DISABLE_I186 1
#define OPT_DISABLE_TLCS900H 1
#define OPT_ENABLE_LIBGC 0
#endif
/* End of config.h */

View File

@@ -0,0 +1,90 @@
/*-------------------------------------------------------------------------
BuildCmd - SDCC Support function
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
/*! Build a command line with parameter substitution
*/
#include <string.h>
#include <assert.h>
void
buildCmdLine (char *into, const char **cmds,
const char *p1, const char *p2,
const char *p3, const char **list)
{
const char *p, *from;
*into = '\0';
while (*cmds)
{
from = *cmds;
cmds++;
/* See if it has a '$' anywhere - if not, just copy */
if ((p = strchr (from, '$')))
{
strncat (into, from, p - from);
/* seperate it */
strcat (into, " ");
from = p + 2;
p++;
switch (*p)
{
case '1':
if (p1)
strcat (into, p1);
break;
case '2':
if (p2)
strcat (into, p2);
break;
case '3':
if (p3)
strcat (into, p3);
break;
case 'l':
{
const char **tmp = list;
if (tmp)
{
while (*tmp)
{
strcat (into, *tmp);
strcat (into, " ");
tmp++;
}
}
break;
}
default:
assert (0);
}
}
strcat (into, from); // this includes the ".asm" from "$1.asm"
strcat (into, " ");
}
}

View File

@@ -0,0 +1,34 @@
/*-------------------------------------------------------------------------
BuildCmd - SDCC Support function
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#if !defined(__BUILDCMD_H)
#define __BUILDCMD_H
void
buildCmdLine (char *into, const char **cmds,
const char *p1, const char *p2,
const char *p3, const char **list) ;
#endif

View File

@@ -0,0 +1,99 @@
/*-------------------------------------------------------------------------
MySystem - SDCC Support function
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#include "common.h"
#include "newalloc.h"
#if defined(_MSC_VER)
#include <io.h>
#else
#include <sys/stat.h>
#endif
#if !defined(__BORLANDC__) && !defined(_MSC_VER)
#include <unistd.h>
#else
// No unistd.h in Borland C++
extern int access (const char *, int);
#define X_OK 1
#endif
/*!
Call an external program with arguements
*/
//char *ExePathList[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
char *ExePathList[] = {NULL, NULL}; /* First entry may be overwritten, so use two. */
int
my_system (const char *cmd)
{
int argsStart, e, i = 0;
char *cmdLine = NULL;
argsStart = strstr (cmd, " ") - cmd;
// try to find the command in predefined path's
while (ExePathList[i])
{
cmdLine = (char *) Safe_alloc (strlen (ExePathList[i]) + strlen (cmd) + 10);
strcpy (cmdLine, ExePathList[i]); // the path
strcat (cmdLine, DIR_SEPARATOR_STRING);
strncat (cmdLine, cmd, argsStart); // the command
#if NATIVE_WIN32
strcat (cmdLine, ".exe");
#endif
if (access (cmdLine, X_OK) == 0)
{
// the arguments
strcat (cmdLine, cmd + argsStart);
break;
}
Safe_free (cmdLine);
cmdLine = NULL;
i++;
}
if (verboseExec)
{
printf ("+ %s\n", cmdLine ? cmdLine : cmd);
}
if (cmdLine)
{
// command found in predefined path
e = system (cmdLine);
Safe_free (cmdLine);
}
else
{
// trust on $PATH
e = system (cmd);
}
return e;
}

View File

@@ -0,0 +1,32 @@
/*-------------------------------------------------------------------------
MySystem - SDCC Support function
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#if !defined(__MYSYSTEM_H)
#define __MYSYSTEM_H
int my_system (const char *cmd) ;
extern char *ExePathList[] ; // List of paths to try to locate exeucatbles
#endif

View File

@@ -0,0 +1,275 @@
/*
===============================================================================
NEWALLOC - SDCC Memory allocation functions
These functions are wrappers for the standard malloc, realloc and free
functions.
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.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
===============================================================================
*/
#include <stdio.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <assert.h>
#include "newalloc.h"
#include "sdccconf.h"
#if OPT_ENABLE_LIBGC
#include <gc/gc.h>
#define MALLOC GC_malloc
#define REALLOC GC_realloc
/* PENDING: This is a mild hack. If we try to GC_free something
allocated with malloc() then the program will segfault. Might as
well drop it and let the garbase collector take care of things.
*/
#define FREE(_a)
#else
#define MALLOC malloc
#define REALLOC realloc
#define FREE free
#endif
#define TRACEMALLOC 0
#if TRACEMALLOC
enum
{
TRACESIZE = 4096
};
static int _allocs[TRACESIZE];
static int _above;
static void
_dumpTrace(int code, void *parg)
{
int i;
for (i = 0; i < TRACESIZE; i++)
{
if (_allocs[i])
{
printf("%u %u\n", _allocs[i], i);
}
}
printf("%u above\n", _above);
}
static void
_log(int size)
{
static int registered;
if (registered == 0)
{
on_exit(_dumpTrace, NULL);
registered = 1;
}
if (size == 12)
{
_above++;
}
if (size >= TRACESIZE)
{
_above++;
}
else
{
_allocs[size]++;
}
}
#endif
/*
-------------------------------------------------------------------------------
Clear_realloc - Reallocate a memory block and clear any memory added with
out of memory error detection
-------------------------------------------------------------------------------
*/
void *Clear_realloc(void *OldPtr,size_t OldSize,size_t NewSize)
{
void *NewPtr ;
NewPtr = REALLOC(OldPtr,NewSize) ;
if (!NewPtr)
{
printf("ERROR - No more memory\n") ;
/* werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
exit (1);
}
if (NewPtr)
if (NewSize > OldSize)
memset((char *) NewPtr + OldSize,0x00,NewSize - OldSize) ;
return NewPtr ;
}
/*
-------------------------------------------------------------------------------
Safe_realloc - Reallocate a memory block with out of memory error detection
-------------------------------------------------------------------------------
*/
void *Safe_realloc(void *OldPtr,size_t NewSize)
{
void *NewPtr ;
NewPtr = REALLOC(OldPtr,NewSize) ;
if (!NewPtr)
{
printf("ERROR - No more memory\n") ;
/* werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
exit (1);
}
return NewPtr ;
}
/*
-------------------------------------------------------------------------------
Safe_calloc - Allocate a block of memory from the application heap, clearing
all data to zero and checking for out of memory errors.
-------------------------------------------------------------------------------
*/
void *Safe_calloc(size_t Elements,size_t Size)
{
void *NewPtr ;
NewPtr = MALLOC(Elements*Size) ;
#if TRACEMALLOC
_log(Elements*Size);
#endif
if (!NewPtr)
{
printf("ERROR - No more memory\n") ;
/* werror(E_OUT_OF_MEM,__FILE__,Size);*/
exit (1);
}
memset(NewPtr, 0, Elements*Size);
return NewPtr ;
}
/*
-------------------------------------------------------------------------------
Safe_malloc - Allocate a block of memory from the application heap
and checking for out of memory errors.
-------------------------------------------------------------------------------
*/
void *Safe_malloc(size_t Size)
{
void *NewPtr ;
NewPtr = MALLOC(Size) ;
#if TRACEMALLOC
_log(Size);
#endif
if (!NewPtr)
{
printf("ERROR - No more memory\n") ;
/* werror(E_OUT_OF_MEM,__FILE__,Size);*/
exit (1);
}
return NewPtr ;
}
void *Safe_alloc(size_t Size)
{
return Safe_calloc(1, Size);
}
void Safe_free(void *p)
{
FREE(p);
}
char *Safe_strdup(const char *sz)
{
char *pret;
assert(sz);
pret = Safe_alloc(strlen(sz) +1);
strcpy(pret, sz);
return pret;
}
void *traceAlloc(allocTrace *ptrace, void *p)
{
assert(ptrace);
assert(p);
/* Also handles where max == 0 */
if (ptrace->num == ptrace->max)
{
/* Add an offset to handle max == 0 */
ptrace->max = (ptrace->max+2)*2;
ptrace->palloced = Safe_realloc(ptrace->palloced, ptrace->max * sizeof(*ptrace->palloced));
}
ptrace->palloced[ptrace->num++] = p;
return p;
}
void freeTrace(allocTrace *ptrace)
{
int i;
assert(ptrace);
for (i = 0; i < ptrace->num; i++)
{
Safe_free(ptrace->palloced[i]);
}
ptrace->num = 0;
Safe_free(ptrace->palloced);
ptrace->palloced = NULL;
ptrace->max = 0;
}

463
link/support/Util/SDCCerr.c Normal file
View File

@@ -0,0 +1,463 @@
/*
* SDCCerr - Standard error handler
*
* 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 of the License, 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 Library 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include "SDCCerr.h"
#define USE_STDOUT_FOR_ERRORS 0
#if USE_STDOUT_FOR_ERRORS
#define DEFAULT_ERROR_OUT stdout
#else
#define DEFAULT_ERROR_OUT stderr
#endif
static struct {
ERROR_LOG_LEVEL logLevel;
FILE *out;
} _SDCCERRG;
extern char *filename ;
extern int lineno ;
extern int fatalError ;
/* Currently the errIndex field must match the position of the
* entry in the array. It is only included in order to make
* human error lookup easier.
*/
struct
{
int errIndex;
ERROR_LOG_LEVEL errType;
const char *errText;
} ErrTab [] =
{
{ E_DUPLICATE, ERROR_LEVEL_ERROR,
"Duplicate symbol '%s', symbol IGNORED" },
{ E_SYNTAX_ERROR, ERROR_LEVEL_ERROR,
"Syntax error, declaration ignored at '%s'" },
{ E_CONST_EXPECTED, ERROR_LEVEL_ERROR,
"Constant Expected Found Variable" },
{ E_OUT_OF_MEM, ERROR_LEVEL_ERROR,
"'malloc' failed file '%s' for size %ld" },
{ E_FILE_OPEN_ERR, ERROR_LEVEL_ERROR,
"'fopen' failed on file '%s'" },
{ E_INVALID_OCLASS, ERROR_LEVEL_ERROR,
"Internal Error Oclass invalid '%s'" },
{ E_CANNOT_ALLOC, ERROR_LEVEL_ERROR,
"Cannot allocate variable '%s'." },
{ E_OLD_STYLE, ERROR_LEVEL_ERROR,
"Old style C declaration. IGNORED '%s'" },
{ E_STACK_OUT, ERROR_LEVEL_ERROR,
"Out of stack Space. '%s' not allocated" },
{ E_INTERNAL_ERROR, ERROR_LEVEL_ERROR,
"FATAL Compiler Internal Error in file '%s' line number '%d' : %s \n"
"Contact Author with source code" },
{ E_LVALUE_REQUIRED, ERROR_LEVEL_ERROR,
"'lvalue' required for '%s' operation ." },
{ E_TMPFILE_FAILED, ERROR_LEVEL_ERROR,
"Creation of temp file failed" },
{ E_FUNCTION_EXPECTED, ERROR_LEVEL_ERROR,
"called object is not a function" },
{ E_USING_ERROR, ERROR_LEVEL_ERROR,
"'using', 'interrupt' or 'reentrant' must follow a function definiton .'%s'" },
{ E_SFR_INIT, ERROR_LEVEL_ERROR,
"Absolute address & initial value both cannot be specified for\n"
" a 'sfr','sbit' storage class, initial value ignored '%s'" },
{ W_INIT_IGNORED, ERROR_LEVEL_WARNING,
"Variable in the storage class cannot be initialized.'%s'" },
{ E_AUTO_ASSUMED, ERROR_LEVEL_ERROR,
"storage class not allowed for automatic variable '%s' in reentrant function unless static" },
{ E_AUTO_ABSA, ERROR_LEVEL_ERROR,
"absolute address not allowed for automatic var '%s' in reentrant function " },
{ W_INIT_WRONG, ERROR_LEVEL_WARNING,
"Initializer different levels of indirections" },
{ E_FUNC_REDEF, ERROR_LEVEL_ERROR,
"Function name '%s' redefined " },
{ E_ID_UNDEF, ERROR_LEVEL_ERROR,
"Undefined identifier '%s'" },
{ W_STACK_OVERFLOW, ERROR_LEVEL_WARNING,
"stack exceeds 256 bytes for function '%s'" },
{ E_NEED_ARRAY_PTR, ERROR_LEVEL_ERROR,
"Array or pointer required for '%s' operation " },
{ E_IDX_NOT_INT, ERROR_LEVEL_ERROR,
"Array index not an integer" },
{ E_ARRAY_BOUND, ERROR_LEVEL_ERROR,
"Array bound Exceeded, assuming zero" },
{ E_STRUCT_UNION, ERROR_LEVEL_ERROR,
"Structure/Union expected left of '.%s'" },
{ E_NOT_MEMBER, ERROR_LEVEL_ERROR,
"'%s' not a structure/union member" },
{ E_PTR_REQD, ERROR_LEVEL_ERROR,
"Pointer required" },
{ E_UNARY_OP, ERROR_LEVEL_ERROR,
"'unary %c': illegal operand" },
{ E_CONV_ERR, ERROR_LEVEL_ERROR,
"convertion error: integral promotion failed" },
{ E_INT_REQD, ERROR_LEVEL_ERROR,
"type must be INT for bit field definition" },
{ E_BITFLD_SIZE, ERROR_LEVEL_ERROR,
"bit field size greater than 16 . assuming 16" },
{ W_TRUNCATION, ERROR_LEVEL_WARNING,
"high order truncation might occur" },
{ E_CODE_WRITE, ERROR_LEVEL_ERROR,
"Attempt to assign value to a constant variable %s" },
{ E_LVALUE_CONST, ERROR_LEVEL_ERROR,
"Lvalue specifies constant object" },
{ E_ILLEGAL_ADDR, ERROR_LEVEL_ERROR,
"'&' illegal operand , %s" },
{ E_CAST_ILLEGAL, ERROR_LEVEL_ERROR,
"illegal cast (cast cannot be aggregate)" },
{ E_MULT_INTEGRAL, ERROR_LEVEL_ERROR,
"'*' bad operand" },
{ E_ARG_ERROR, ERROR_LEVEL_ERROR,
"Argument count error, argument ignored" },
{ E_ARG_COUNT, ERROR_LEVEL_ERROR,
"Function was expecting more arguments" },
{ E_FUNC_EXPECTED, ERROR_LEVEL_ERROR,
"Function name expected '%s'.ANSI style declaration REQUIRED" },
{ E_PLUS_INVALID, ERROR_LEVEL_ERROR,
"invalid operand '%s'" },
{ E_PTR_PLUS_PTR, ERROR_LEVEL_ERROR,
"pointer + pointer invalid" },
{ E_SHIFT_OP_INVALID, ERROR_LEVEL_ERROR,
"invalid operand for shift operator" },
{ E_COMPARE_OP, ERROR_LEVEL_ERROR,
"compare operand cannot be struct/union" },
{ E_BITWISE_OP, ERROR_LEVEL_ERROR,
"operand invalid for bitwise operation" },
{ E_ANDOR_OP, ERROR_LEVEL_ERROR,
"Invalid operand for '&&' or '||'" },
{ E_TYPE_MISMATCH, ERROR_LEVEL_ERROR,
"indirections to different types %s %s " },
{ E_AGGR_ASSIGN, ERROR_LEVEL_ERROR,
"cannot assign values to aggregates" },
{ E_ARRAY_DIRECT, ERROR_LEVEL_ERROR,
"bit Arrays can be accessed by literal index only" },
{ E_BIT_ARRAY, ERROR_LEVEL_ERROR,
"Array or Pointer to bit|sbit|sfr not allowed.'%s'" },
{ E_DUPLICATE_TYPEDEF, ERROR_LEVEL_ERROR,
"typedef/enum '%s' duplicate.Previous definiton Ignored" },
{ E_ARG_TYPE, ERROR_LEVEL_ERROR,
"Actual Argument type different from declaration %d" },
{ E_RET_VALUE, ERROR_LEVEL_ERROR,
"Function return value mismatch" },
{ E_FUNC_AGGR, ERROR_LEVEL_ERROR,
"Function cannot return aggregate. Func body ignored" },
{ E_FUNC_DEF, ERROR_LEVEL_ERROR,
"ANSI Style declaration needed" },
{ E_DUPLICATE_LABEL, ERROR_LEVEL_ERROR,
"Label name redefined '%s'" },
{ E_LABEL_UNDEF, ERROR_LEVEL_ERROR,
"Label undefined '%s'" },
{ E_FUNC_VOID, ERROR_LEVEL_ERROR,
"void function returning value" },
{ E_VOID_FUNC, ERROR_LEVEL_ERROR,
"function '%s' must return value" },
{ W_RETURN_MISMATCH, ERROR_LEVEL_WARNING,
"function return value mismatch" },
{ E_CASE_CONTEXT, ERROR_LEVEL_ERROR,
"'case/default' found without 'switch'.statement ignored" },
{ E_CASE_CONSTANT, ERROR_LEVEL_ERROR,
"'case' expression not constant. statement ignored" },
{ E_BREAK_CONTEXT, ERROR_LEVEL_ERROR,
"'break/continue' statement out of context" },
{ E_SWITCH_AGGR, ERROR_LEVEL_ERROR,
"nonintegral used in switch expression" },
{ E_FUNC_BODY, ERROR_LEVEL_ERROR,
"function '%s' already has body" },
{ E_UNKNOWN_SIZE, ERROR_LEVEL_ERROR,
"attempt to allocate variable of unknown size '%s'" },
{ E_AUTO_AGGR_INIT, ERROR_LEVEL_ERROR,
"aggregate 'auto' variable '%s' cannot be initialized" },
{ E_INIT_COUNT, ERROR_LEVEL_ERROR,
"too many initializers" },
{ E_INIT_STRUCT, ERROR_LEVEL_ERROR,
"struct/union/array '%s' :initialization needs curly braces" },
{ E_INIT_NON_ADDR, ERROR_LEVEL_ERROR,
"non-address initialization expression" },
{ E_INT_DEFINED, ERROR_LEVEL_ERROR,
"interrupt no '%d' already has a service routine '%s'" },
{ E_INT_ARGS, ERROR_LEVEL_ERROR,
"interrupt routine cannot have arguments, arguments ingored" },
{ E_INCLUDE_MISSING, ERROR_LEVEL_ERROR,
"critical compiler #include file missing. " },
{ E_NO_MAIN, ERROR_LEVEL_ERROR,
"function 'main' undefined" },
{ E_EXTERN_INIT, ERROR_LEVEL_ERROR,
"'extern' variable '%s' cannot be initialised " },
{ E_PRE_PROC_FAILED, ERROR_LEVEL_ERROR,
"Pre-Processor %s" },
{ E_DUP_FAILED, ERROR_LEVEL_ERROR,
"_dup call failed" },
{ E_INCOMPAT_TYPES, ERROR_LEVEL_ERROR,
"incompatible types" },
{ W_LOOP_ELIMINATE, ERROR_LEVEL_WARNING,
"'while' loop with 'zero' constant.loop eliminated" },
{ W_NO_SIDE_EFFECTS, ERROR_LEVEL_WARNING,
"%s expression has NO side effects.expr eliminated" },
{ W_CONST_TOO_LARGE, ERROR_LEVEL_PEDANTIC,
"constant value '%s', out of range." },
{ W_BAD_COMPARE, ERROR_LEVEL_WARNING,
"comparison will either, ALWAYs succeed or ALWAYs fail" },
{ E_TERMINATING, ERROR_LEVEL_ERROR,
"Compiler Terminating , contact author with source" },
{ W_LOCAL_NOINIT, ERROR_LEVEL_WARNING,
"'auto' variable '%s' may be used before initialization at %s(%d)" },
{ W_NO_REFERENCE, ERROR_LEVEL_WARNING,
"in function %s unreferenced %s : '%s'" },
{ E_OP_UNKNOWN_SIZE, ERROR_LEVEL_ERROR,
"unknown size for operand" },
{ W_LONG_UNSUPPORTED, ERROR_LEVEL_WARNING,
"'%s' 'long' not supported , declared as 'int' ." },
{ E_LITERAL_GENERIC, ERROR_LEVEL_ERROR,
//"illegal cast of LITERAL value to 'generic' pointer: assuming 'xdata' pointer" },
"illegal cast of LITERAL value to 'generic' pointer" },
{ E_SFR_ADDR_RANGE, ERROR_LEVEL_ERROR,
"%s '%s' address out of range" },
{ E_BITVAR_STORAGE, ERROR_LEVEL_ERROR,
"storage class CANNOT be specified for bit variable '%s'" },
{ E_EXTERN_MISMATCH, ERROR_LEVEL_ERROR,
"extern definition for '%s' mismatches with declaration." },
{ W_NONRENT_ARGS, ERROR_LEVEL_WARNING,
"Functions called via pointers must be 'reentrant' to take arguments" },
{ W_DOUBLE_UNSUPPORTED, ERROR_LEVEL_WARNING,
"type 'double' not supported assuming 'float'" },
{ W_IF_NEVER_TRUE, ERROR_LEVEL_WARNING,
"if-statement condition always false.if-statement not generated" },
{ W_FUNC_NO_RETURN, ERROR_LEVEL_WARNING,
"no 'return' statement found for function '%s'" },
{ W_PRE_PROC_WARNING, ERROR_LEVEL_WARNING,
"Pre-Processor %s" },
{ W_STRUCT_AS_ARG, ERROR_LEVEL_WARNING,
"structure '%s' passed as function argument changed to pointer" },
{ E_PREV_DEF_CONFLICT, ERROR_LEVEL_ERROR,
"conflict with previous definition of '%s' for attribute '%s'" },
{ E_CODE_NO_INIT, ERROR_LEVEL_ERROR,
"variable '%s' declared in code space must have initialiser" },
{ E_OPS_INTEGRAL, ERROR_LEVEL_ERROR,
"operands not integral for assignment operation" },
{ E_TOO_MANY_PARMS, ERROR_LEVEL_ERROR,
"too many parameters " },
{ E_TOO_FEW_PARMS, ERROR_LEVEL_ERROR,
"too few parameters" },
{ E_FUNC_NO_CODE, ERROR_LEVEL_ERROR,
"code not generated for '%s' due to previous errors" },
{ E_TYPE_MISMATCH_PARM, ERROR_LEVEL_ERROR,
"type mismatch for parameter number %d" },
{ E_INVALID_FLOAT_CONST, ERROR_LEVEL_ERROR,
"invalid float constant '%s'" },
{ E_INVALID_OP, ERROR_LEVEL_ERROR,
"invalid operand for '%s' operation" },
{ E_SWITCH_NON_INTEGER, ERROR_LEVEL_ERROR,
"switch value not an integer" },
{ E_CASE_NON_INTEGER, ERROR_LEVEL_ERROR,
"case label not an integer" },
{ W_FUNC_TOO_LARGE, ERROR_LEVEL_WARNING,
"function '%s' too large for global optimization" },
{ W_CONTROL_FLOW, ERROR_LEVEL_PEDANTIC,
"conditional flow changed by optimizer '%s(%d)':so said EVELYN the modified DOG" },
{ W_PTR_TYPE_INVALID, ERROR_LEVEL_WARNING,
"invalid type specifier for pointer type specifier ignored" },
{ W_IMPLICIT_FUNC, ERROR_LEVEL_WARNING,
"function '%s' implicit declaration" },
{ W_CONTINUE, ERROR_LEVEL_WARNING,
"%s" },
{ I_TOOMANY_SPILS, ERROR_LEVEL_INFO,
"extended by %d bytes for compiler temp(s) :in function '%s': %s " },
{ W_UNKNOWN_PRAGMA, ERROR_LEVEL_WARNING,
"unknown or unsupported #pragma directive '%s'" },
{ W_SHIFT_CHANGED, ERROR_LEVEL_PEDANTIC,
"%s shifting more than size of object changed to zero" },
{ W_UNKNOWN_OPTION, ERROR_LEVEL_WARNING,
"unknown compiler option '%s' ignored" },
{ W_UNSUPP_OPTION, ERROR_LEVEL_WARNING,
"option '%s' no longer supported '%s' " },
{ W_UNKNOWN_FEXT, ERROR_LEVEL_WARNING,
"don't know what to do with file '%s'. file extension unsupported" },
{ W_TOO_MANY_SRC, ERROR_LEVEL_WARNING,
"cannot compile more than one source file . file '%s' ignored" },
{ I_CYCLOMATIC, ERROR_LEVEL_INFO,
"function '%s', # edges %d , # nodes %d , cyclomatic complexity %d" },
{ E_DIVIDE_BY_ZERO, ERROR_LEVEL_ERROR,
"dividing by ZERO" },
{ E_FUNC_BIT, ERROR_LEVEL_ERROR,
"function cannot return 'bit'" },
{ E_CAST_ZERO, ERROR_LEVEL_ERROR,
"casting from to type 'void' is illegal" },
{ W_CONST_RANGE, ERROR_LEVEL_WARNING,
"constant is out of range %s" },
{ W_CODE_UNREACH, ERROR_LEVEL_PEDANTIC,
"unreachable code %s(%d)" },
{ E_NONPTR2_GENPTR, ERROR_LEVEL_ERROR,
"non-pointer type cast to generic pointer" },
{ W_POSSBUG, ERROR_LEVEL_WARNING,
"possible code generation error at line %d,\n"
" send source to sandeep.dutta@usa.net" },
{ E_INCOMPAT_PTYPES, ERROR_LEVEL_WARNING,
"pointer types incompatible " },
{ W_UNKNOWN_MODEL, ERROR_LEVEL_WARNING,
"unknown memory model at %s : %d" },
{ E_UNKNOWN_TARGET, ERROR_LEVEL_ERROR,
"cannot generate code for target '%s'" },
{ W_INDIR_BANKED, ERROR_LEVEL_WARNING,
"Indirect call to a banked function not implemented." },
{ W_UNSUPPORTED_MODEL, ERROR_LEVEL_WARNING,
"Model '%s' not supported for %s, ignored." },
{ W_BANKED_WITH_NONBANKED, ERROR_LEVEL_WARNING,
"Both banked and nonbanked attributes used. nonbanked wins." },
{ W_BANKED_WITH_STATIC, ERROR_LEVEL_WARNING,
"Both banked and static used. static wins." },
{ W_INT_TO_GEN_PTR_CAST, ERROR_LEVEL_WARNING,
"converting integer type to generic pointer: assuming XDATA" },
{ W_ESC_SEQ_OOR_FOR_CHAR, ERROR_LEVEL_WARNING,
"escape sequence out of range for char." },
{ E_INVALID_HEX, ERROR_LEVEL_ERROR,
"\\x used with no following hex digits." },
{ W_FUNCPTR_IN_USING_ISR, ERROR_LEVEL_WARNING,
"call via function pointer in ISR using non-zero register bank.\n"
" Cannot determine which register bank to save." },
{ E_NO_SUCH_BANK, ERROR_LEVEL_ERROR,
"called function uses unknown register bank %d." },
{ E_TWO_OR_MORE_DATA_TYPES, ERROR_LEVEL_ERROR,
"two or more data types in declaration for '%s'" },
{ E_LONG_OR_SHORT_INVALID, ERROR_LEVEL_ERROR,
"long or short specified for %s '%s'" },
{ E_SIGNED_OR_UNSIGNED_INVALID, ERROR_LEVEL_ERROR,
"signed or unsigned specified for %s '%s'" },
{ E_LONG_AND_SHORT_INVALID, ERROR_LEVEL_ERROR,
"both long and short specified for %s '%s'" },
{ E_SIGNED_AND_UNSIGNED_INVALID, ERROR_LEVEL_ERROR,
"both signed and unsigned specified for %s '%s'" },
{ E_TWO_OR_MORE_STORAGE_CLASSES, ERROR_LEVEL_ERROR,
"two or more storage classes in declaration for '%s'" },
{ W_EXESS_ARRAY_INITIALIZERS, ERROR_LEVEL_WARNING,
"excess elements in array initializer after `%s' at line %d" },
{ E_ARGUMENT_MISSING, ERROR_LEVEL_ERROR,
"Option %s requires an argument." },
{ W_STRAY_BACKSLASH, ERROR_LEVEL_WARNING,
"stray '\\' at column %d" },
{ W_NEWLINE_IN_STRING, ERROR_LEVEL_WARNING,
"newline in string constant" },
{ E_CANNOT_USE_GENERIC_POINTER, ERROR_LEVEL_ERROR,
"cannot use generic pointer %s to initialize %s" },
{ W_EXCESS_SHORT_OPTIONS, ERROR_LEVEL_WARNING,
"Only one short option can be specified at a time. Rest of %s ignored." },
{ E_VOID_VALUE_USED, ERROR_LEVEL_ERROR,
"void value not ignored as it ought to be" },
{ W_INTEGRAL2PTR_NOCAST, ERROR_LEVEL_WARNING,
"converting integral to pointer without a cast" },
{ W_PTR2INTEGRAL_NOCAST, ERROR_LEVEL_WARNING,
"converting pointer to integral without a cast" },
{ W_SYMBOL_NAME_TOO_LONG, ERROR_LEVEL_WARNING,
"symbol name too long, truncated to %d chars" },
{ W_CAST_STRUCT_PTR,ERROR_LEVEL_WARNING,
"cast of struct %s * to struct %s * " }
};
/*
-------------------------------------------------------------------------------
SetErrorOut - Set the error output file
-------------------------------------------------------------------------------
*/
FILE *SetErrorOut(FILE *NewErrorOut)
{
_SDCCERRG.out = NewErrorOut ;
return NewErrorOut ;
}
void
setErrorLogLevel (ERROR_LOG_LEVEL level)
{
_SDCCERRG.logLevel = level;
}
/*
-------------------------------------------------------------------------------
vwerror - Output a standard eror message with variable number of arguements
-------------------------------------------------------------------------------
*/
void vwerror (int errNum, va_list marker)
{
if (_SDCCERRG.out == NULL) {
_SDCCERRG.out = DEFAULT_ERROR_OUT;
}
if (ErrTab[errNum].errIndex != errNum)
{
fprintf(_SDCCERRG.out,
"*** Internal error: error table entry for %d inconsistent.", errNum);
}
if (ErrTab[errNum].errType >= _SDCCERRG.logLevel) {
if ( ErrTab[errNum].errType == ERROR_LEVEL_ERROR )
fatalError++ ;
if ( filename && lineno ) {
fprintf(_SDCCERRG.out, "%s(%d):",filename,lineno);
} else if (lineno) {
fprintf(_SDCCERRG.out, "at %d:", lineno);
}
switch(ErrTab[errNum].errType)
{
case ERROR_LEVEL_ERROR:
fprintf(_SDCCERRG.out, "error *** ");
break;
case ERROR_LEVEL_WARNING:
case ERROR_LEVEL_PEDANTIC:
fprintf(_SDCCERRG.out, "warning *** ");
break;
case ERROR_LEVEL_INFO:
fprintf(_SDCCERRG.out, "info *** ");
break;
default:
break;
}
vfprintf(_SDCCERRG.out, ErrTab[errNum].errText,marker);
fprintf(_SDCCERRG.out, "\n");
}
else {
// Below the logging level, drop.
}
}
/*
-------------------------------------------------------------------------------
werror - Output a standard eror message with variable number of arguements
-------------------------------------------------------------------------------
*/
void werror (int errNum, ... )
{
va_list marker;
va_start(marker,errNum);
vwerror(errNum, marker);
va_end( marker );
}

231
link/support/Util/SDCCerr.h Normal file
View File

@@ -0,0 +1,231 @@
/*
===============================================================================
SDCCERR - SDCC Standard error handler
===============================================================================
*/
#if !defined(__SDCCERR_H)
#define __SDCCERR_H
#include <stdio.h>
#include <stdarg.h>
/* ERROR Message Definition */
#define E_DUPLICATE 0 /* Duplicate variable */
#define E_SYNTAX_ERROR 1 /* Syntax Error */
#define E_CONST_EXPECTED 2 /* constant expected */
#define E_OUT_OF_MEM 3 /* malloc failed */
#define E_FILE_OPEN_ERR 4 /* File open failed */
#define E_INVALID_OCLASS 5 /* output class invalid */
#define E_CANNOT_ALLOC 6 /* cannot allocate space*/
#define E_OLD_STYLE 7 /* old style C ! allowed*/
#define E_STACK_OUT 8 /* v r out of stack */
#define E_INTERNAL_ERROR 9 /* unable to alloc tvar */
#define E_LVALUE_REQUIRED 10 /* lvalue required */
#define E_TMPFILE_FAILED 11 /* tmpfile creation failed */
#define E_FUNCTION_EXPECTED 12 /* function expected */
#define E_USING_ERROR 13 /* using in error */
#define E_SFR_INIT 14 /* init error for sbit */
#define W_INIT_IGNORED 15 /* initialiser ignored */
#define E_AUTO_ASSUMED 16 /* sclass auto assumed */
#define E_AUTO_ABSA 17 /* abs addr for auto var*/
#define W_INIT_WRONG 18 /* initializer type != */
#define E_FUNC_REDEF 19 /* func name redefined */
#define E_ID_UNDEF 20 /* identifer undefined */
#define W_STACK_OVERFLOW 21 /* stack overflow */
#define E_NEED_ARRAY_PTR 22 /* array or pointer reqd*/
#define E_IDX_NOT_INT 23 /* index not an integer */
#define E_ARRAY_BOUND 24 /* array limit exceeded */
#define E_STRUCT_UNION 25 /* struct,union expected*/
#define E_NOT_MEMBER 26 /* !struct/union member */
#define E_PTR_REQD 27 /* pointer required */
#define E_UNARY_OP 28 /* unary operator bad op*/
#define E_CONV_ERR 29 /* conversion error */
#define E_INT_REQD 30 /* bit field must be int*/
#define E_BITFLD_SIZE 31 /* bit field size > 16 */
#define W_TRUNCATION 32 /* high order trucation */
#define E_CODE_WRITE 33 /* trying 2 write to code */
#define E_LVALUE_CONST 34 /* lvalue is a const */
#define E_ILLEGAL_ADDR 35 /* address of bit */
#define E_CAST_ILLEGAL 36 /* cast illegal */
#define E_MULT_INTEGRAL 37 /* mult opernd must b integral */
#define E_ARG_ERROR 38 /* argument count error*/
#define E_ARG_COUNT 39 /* func expecting more */
#define E_FUNC_EXPECTED 40 /* func name expected */
#define E_PLUS_INVALID 41 /* plus invalid */
#define E_PTR_PLUS_PTR 42 /* pointer + pointer */
#define E_SHIFT_OP_INVALID 43 /* shft op op invalid */
#define E_COMPARE_OP 44 /* compare operand */
#define E_BITWISE_OP 45 /* bit op invalid op */
#define E_ANDOR_OP 46 /* && || op invalid */
#define E_TYPE_MISMATCH 47 /* type mismatch */
#define E_AGGR_ASSIGN 48 /* aggr assign */
#define E_ARRAY_DIRECT 49 /* array indexing in */
#define E_BIT_ARRAY 50 /* bit array not allowed */
#define E_DUPLICATE_TYPEDEF 51 /* typedef name duplicate */
#define E_ARG_TYPE 52 /* arg type mismatch */
#define E_RET_VALUE 53 /* return value mismatch */
#define E_FUNC_AGGR 54 /* function returing aggr */
#define E_FUNC_DEF 55 /* ANSI Style def neede */
#define E_DUPLICATE_LABEL 56 /* duplicate label name */
#define E_LABEL_UNDEF 57 /* undefined label used */
#define E_FUNC_VOID 58 /* void func ret value */
#define E_VOID_FUNC 59 /* func must return value */
#define W_RETURN_MISMATCH 60 /* return value mismatch */
#define E_CASE_CONTEXT 61 /* case stmnt without switch */
#define E_CASE_CONSTANT 62 /* case expression ! const*/
#define E_BREAK_CONTEXT 63 /* break statement invalid*/
#define E_SWITCH_AGGR 64 /* non integral for switch*/
#define E_FUNC_BODY 65 /* func has body already */
#define E_UNKNOWN_SIZE 66 /* variable has unknown size */
#define E_AUTO_AGGR_INIT 67 /* auto aggregates no init */
#define E_INIT_COUNT 68 /* too many initializers */
#define E_INIT_STRUCT 69 /* struct init wrong */
#define E_INIT_NON_ADDR 70 /* non address xpr for init */
#define E_INT_DEFINED 71 /* interrupt already over */
#define E_INT_ARGS 72 /* interrupt rtn cannot have args */
#define E_INCLUDE_MISSING 73 /* compiler include missing */
#define E_NO_MAIN 74 /* main function undefined */
#define E_EXTERN_INIT 75 /* extern variable initialised */
#define E_PRE_PROC_FAILED 76 /* preprocessor failed */
#define E_DUP_FAILED 77 /* file DUP failed */
#define E_INCOMPAT_TYPES 78 /* incompatible types casting */
#define W_LOOP_ELIMINATE 79 /* loop eliminated */
#define W_NO_SIDE_EFFECTS 80 /* expression has no side effects */
#define W_CONST_TOO_LARGE 81 /* constant out of range */
#define W_BAD_COMPARE 82 /* bad comparison */
#define E_TERMINATING 83 /* compiler terminating */
#define W_LOCAL_NOINIT 84 /* local reference before assignment */
#define W_NO_REFERENCE 85 /* no reference to local variable */
#define E_OP_UNKNOWN_SIZE 86 /* unknown size for operand */
#define W_LONG_UNSUPPORTED 87 /* 'long' not supported yet */
#define E_LITERAL_GENERIC 88 /* literal being cast to generic pointer */
#define E_SFR_ADDR_RANGE 89 /* sfr address out of range */
#define E_BITVAR_STORAGE 90 /* storage given for 'bit' variable */
#define E_EXTERN_MISMATCH 91 /* extern declaration mismatches */
#define W_NONRENT_ARGS 92 /* fptr non reentrant has args */
#define W_DOUBLE_UNSUPPORTED 93 /* 'double' not supported yet */
#define W_IF_NEVER_TRUE 94 /* if always false */
#define W_FUNC_NO_RETURN 95 /* no return statement found */
#define W_PRE_PROC_WARNING 96 /* preprocessor generated warning */
#define W_STRUCT_AS_ARG 97 /* structure passed as argument */
#define E_PREV_DEF_CONFLICT 98 /* previous definition conflicts with current */
#define E_CODE_NO_INIT 99 /* vars in code space must have initializer */
#define E_OPS_INTEGRAL 100 /* operans must be integral for certian assignments */
#define E_TOO_MANY_PARMS 101 /* too many parameters */
#define E_TOO_FEW_PARMS 102 /* to few parameters */
#define E_FUNC_NO_CODE 103 /* fatalError */
#define E_TYPE_MISMATCH_PARM 104 /* type mismatch for parameter */
#define E_INVALID_FLOAT_CONST 105 /* invalid floating point literal string */
#define E_INVALID_OP 106 /* invalid operand for some operation */
#define E_SWITCH_NON_INTEGER 107 /* switch value not integer */
#define E_CASE_NON_INTEGER 108 /* case value not integer */
#define W_FUNC_TOO_LARGE 109 /* function too large */
#define W_CONTROL_FLOW 110 /* control flow changed due to optimization */
#define W_PTR_TYPE_INVALID 111 /* invalid type specifier for pointer */
#define W_IMPLICIT_FUNC 112 /* function declared implicitly */
#define W_CONTINUE 113 /* more than one line */
#define I_TOOMANY_SPILS 114 /* too many spils occured */
#define W_UNKNOWN_PRAGMA 115 /* #pragma directive unsupported */
#define W_SHIFT_CHANGED 116 /* shift changed to zero */
#define W_UNKNOWN_OPTION 117 /* don't know the option */
#define W_UNSUPP_OPTION 118 /* processor reset has been redifned */
#define W_UNKNOWN_FEXT 119 /* unknown file extension */
#define W_TOO_MANY_SRC 120 /* can only compile one .c file at a time */
#define I_CYCLOMATIC 121 /* information message */
#define E_DIVIDE_BY_ZERO 122 /* / 0 */
#define E_FUNC_BIT 123 /* function cannot return bit */
#define E_CAST_ZERO 124 /* casting to from size zero */
#define W_CONST_RANGE 125 /* constant too large */
#define W_CODE_UNREACH 126 /* unreachable code */
#define E_NONPTR2_GENPTR 127 /* non pointer cast to generic pointer */
#define W_POSSBUG 128 /* possible code generation error */
#define E_INCOMPAT_PTYPES 129 /* incampatible pointer assignment */
#define W_UNKNOWN_MODEL 130 /* Unknown memory model */
#define E_UNKNOWN_TARGET 131 /* target not defined */
#define W_INDIR_BANKED 132 /* Indirect call to a banked fun */
#define W_UNSUPPORTED_MODEL 133 /* Unsupported model, ignored */
#define W_BANKED_WITH_NONBANKED 134 /* banked and nonbanked attributes mixed */
#define W_BANKED_WITH_STATIC 135 /* banked and static mixed */
#define W_INT_TO_GEN_PTR_CAST 136 /* Converting integer type to generic pointer. */
#define W_ESC_SEQ_OOR_FOR_CHAR 137 /* Escape sequence of of range for char */
#define E_INVALID_HEX 138 /* \x used with no following hex digits */
#define W_FUNCPTR_IN_USING_ISR 139 /* Call via function pointer in ISR with using attribute. */
#define E_NO_SUCH_BANK 140 /* 'using' attribute specifies non-existant register bank. */
#define E_TWO_OR_MORE_DATA_TYPES 141
#define E_LONG_OR_SHORT_INVALID 142 /* long or short invalid for .. */
#define E_SIGNED_OR_UNSIGNED_INVALID 143 /* signed or unsigned invalid for .. */
#define E_LONG_AND_SHORT_INVALID 144 /* long and short invalid for .. */
#define E_SIGNED_AND_UNSIGNED_INVALID 145 /* signed and unsigned invalid for .. */
#define E_TWO_OR_MORE_STORAGE_CLASSES 146
#define W_EXESS_ARRAY_INITIALIZERS 147 /* too much initializers for array */
#define E_ARGUMENT_MISSING 148 /* Option requires an argument. */
#define W_STRAY_BACKSLASH 149
#define W_NEWLINE_IN_STRING 150
#define E_CANNOT_USE_GENERIC_POINTER 151
#define W_EXCESS_SHORT_OPTIONS 152
#define E_VOID_VALUE_USED 153
#define W_INTEGRAL2PTR_NOCAST 154
#define W_PTR2INTEGRAL_NOCAST 155
#define W_SYMBOL_NAME_TOO_LONG 156
#define W_CAST_STRUCT_PTR 157 /* pointer to different structure types */
/** Describes the maximum error level that will be logged. Any level
* includes all of the levels listed after it.
*
*
*/
enum _ERROR_LOG_LEVEL {
/** Everything. Currently the same as PEDANTIC. */
ERROR_LEVEL_ALL,
/** All warnings, including those considered 'reasonable to use,
on occasion, in clean programs' (man 3 gcc). */
ERROR_LEVEL_PEDANTIC,
/** 'informational' warnings */
ERROR_LEVEL_INFO,
/** Most warnings. */
ERROR_LEVEL_WARNING,
/** Errors only. */
ERROR_LEVEL_ERROR
};
typedef enum _ERROR_LOG_LEVEL ERROR_LOG_LEVEL;
/** Sets the maximum error level to log.
See MAX_ERROR_LEVEL. The default is ERROR_LEVEL_ALL.
*/
void
setErrorLogLevel (ERROR_LOG_LEVEL level);
/*
-------------------------------------------------------------------------------
SetErrorOut - Set the error output file
-------------------------------------------------------------------------------
*/
FILE * SetErrorOut(FILE *NewErrorOut) ;
/*
-------------------------------------------------------------------------------
vwerror - Output a standard eror message with variable number of arguements
-------------------------------------------------------------------------------
*/
void vwerror (int errNum, va_list marker) ;
/*
-------------------------------------------------------------------------------
werror - Output a standard eror message with variable number of arguements
-------------------------------------------------------------------------------
*/
void werror (int errNum, ... ) ;
#endif

View File

@@ -0,0 +1,103 @@
/*
===============================================================================
NEWALLOC - SDCC Memory allocation functions
These functions are wrappers for the standard malloc, realloc and free
functions.
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.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
===============================================================================
*/
#if !defined(_NewAlloc_H)
#define _NewAlloc_H
#include <memory.h>
typedef struct _allocTrace
{
int num;
int max;
void **palloced;
} allocTrace;
/*
-------------------------------------------------------------------------------
Clear_realloc - Reallocate a memory block and clear any memory added with
out of memory error detection
-------------------------------------------------------------------------------
*/
void *Clear_realloc(void *OldPtr,size_t OldSize,size_t NewSize) ;
/*
-------------------------------------------------------------------------------
Safe_realloc - Reallocate a memory block with out of memory error detection
-------------------------------------------------------------------------------
*/
void *Safe_realloc(void *OldPtr,size_t NewSize) ;
/*
-------------------------------------------------------------------------------
Safe_calloc - Allocate a block of memory from the application heap, clearing
all data to zero and checking for out or memory errors.
-------------------------------------------------------------------------------
*/
void *Safe_calloc(size_t Elements,size_t Size) ;
/*
-------------------------------------------------------------------------------
Safe_malloc - Allocate a block of memory from the application heap
and checking for out or memory errors.
-------------------------------------------------------------------------------
*/
void *Safe_malloc(size_t Size) ;
/** Replacement for Safe_malloc that also zeros memory. To make it interchangable.
*/
void *Safe_alloc(size_t Size) ;
/** Function to make the replacements complete.
*/
void Safe_free(void *p);
/** Creates a copy of a string in a safe way.
*/
char *Safe_strdup(const char *sz);
/** Logs the allocated memory 'p' in the given trace for batch freeing
later using freeTrace.
*/
void *traceAlloc(allocTrace *ptrace, void *p);
/** Frees all the memory logged in the trace and resets the trace.
*/
void freeTrace(allocTrace *ptrace);
#endif

47
link/z80/Makefile Normal file
View File

@@ -0,0 +1,47 @@
PRJDIR = ..
include $(PRJDIR)/Makefile.common
OBJDIR = obj/$(EXT)
SLIBSRC = NewAlloc.c
SRC = lkarea.c lkdata.c lkeval.c lkhead.c lkihx.c lklex.c \
lklibr.c lklist.c lkmain.c lkrloc.c lks19.c lksym.c \
lkgb.c lkgg.c
OBJS = $(SRC:%.c=$(OBJDIR)/%.o)
SLIBOBJS = $(SLIBSRC:%.c=$(OBJDIR)/%.o)
BINS = $(BUILDDIR)link$(EXT)
CFLAGS += $(CPPFLAGS) $(OPTS) -DINDEXLIB -DMLH_MAP -DUNIX -DSDK
CFLAGS += -funsigned-char -DUNIX
CFLAGS += -I$(PRJDIR)/as/$(PORT) -I$(SLIB)
LDFLAGS += -lm $(EXTRALIBS)
all: $(BINS)
$(BINS): $(OBJDIR) $(BUILDDIR) $(OBJS) $(SLIBOBJS)
$(CC) -g -o $(BINS) $(OBJS) $(SLIBOBJS) $(LDFLAGS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(BUILDDIR):
mkdir -p $(BUILDDIR)
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: $(SLIB)/%.c
$(CC) -c $(CFLAGS) -o $@ $<
_link-z80:
$(MAKE) EXT=-z80$(E) PORT=z80
_link-gbz80:
$(MAKE) EXT=-gbz80$(E) OPTS=-DGAMEBOY PORT=z80
include clean.mk

104
link/z80/Makefile.in Normal file
View File

@@ -0,0 +1,104 @@
#
#
#
VERSION = @VERSION@
VERSIONHI = @VERSIONHI@
VERSIONLO = @VERSIONLO@
VERSIONP = @VERSIONP@
SHELL = /bin/sh
CC = @CC@
CPP = @CPP@
INSTALL = @INSTALL@
PRJDIR = ../..
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 = @infodir@
SLIB =$(PRJDIR)/support/Util
CPPFLAGS = @CPPFLAGS@ -I. -I$(PRJDIR) -I$(PRJDIR)/as/z80 -I$(SLIB)
CFLAGS = @CFLAGS@ -Wall -DINDEXLIB -DMLH_MAP -DUNIX -DSDK -DSDK_VERSION_STRING="\"3.0.0\"" -DTARGET_STRING="\"gbz80\"" -funsigned-char
M_OR_MM = @M_OR_MM@
LDFLAGS = @LDFLAGS@ -lm
SLIBOBJS = NewAlloc.o
LKOBJECTS = lkarea.o lkdata.o lkeval.o lkhead.o lkihx.o lklex.o \
lklibr.o lklist.o lkmain.o lkrloc.o lks19.o lksym.o \
lkgb.o lkgg.o
LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS))
LKZ80 = $(PRJDIR)/bin/link-z80
# Compiling entire program or any subproject
# ------------------------------------------
all: checkconf $(LKZ80)
$(LKZ80): $(SLIBOBJS) $(LKOBJECTS)
$(CC) $(CFLAGS) -o $@ $(SLIBOBJS) $(LKOBJECTS) $(LDFLAGS)
# Compiling and installing everything and runing test
# ---------------------------------------------------
install: all installdirs
$(INSTALL) $(LKZ80) $(bindir)/link-z80
# Deleting all the installed files
# --------------------------------
uninstall:
rm -f $(bindir)/link-z80
# Performing self-test
# --------------------
check:
# Performing installation test
# ----------------------------
installcheck:
# Creating installation directories
# ---------------------------------
installdirs:
$(INSTALL) -d $(bindir)
# Creating dependencies
# ---------------------
dep: Makefile.dep
Makefile.dep: $(LKSOURCES) *.h $(PRJDIR)/*.h
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(LKSOURCES) >Makefile.dep
include Makefile.dep
include clean.mk
# My rules
# --------
.c.o:
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
$(SLIBOBJS):%.o:$(SLIB)/%.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
# Remaking configuration
# ----------------------
checkconf:
@if [ -f $(PRJDIR)/devel ]; then\
$(MAKE) -f conf.mk srcdir="$(srcdir)" PRJDIR="$(PRJDIR)" freshconf;\
fi
# End of Makefile

720
link/z80/aslink.h Normal file
View File

@@ -0,0 +1,720 @@
/* aslink.h */
/*
* (C) Copyright 1989-1996
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber
*/
#include <limits.h>
#define VERSION "V01.75"
/*
* Case Sensitivity Flag
*/
#define CASE_SENSITIVE 0
/*)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
/*
* This file defines the format of the
* relocatable binary file.
*/
#ifdef SDK
#define NCPS 32 /* characters per symbol */
#else /* SDK */
#define NCPS 8 /* characters per symbol */
#endif /* SDK */
/* #define NCPS 32 */ /* characters per symbol */
#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 */
#define FILSPC PATH_MAX /* File spec length */
/*
* 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 value */
#define R_USGN 0x10 /* Unsigned value */
#define R_NOPAG 0x00 /* Page Mode */
#define R_PAG0 0x20 /* Page '0' */
#define R_PAG 0x40 /* Page 'nnn' */
/*
* Valid for R_BYT2:
*/
#define R_LSB 0x00 /* output low byte */
#define R_MSB 0x80 /* output high byte */
/*
* Global symbol types.
*/
#define S_REF 1 /* referenced */
#define S_DEF 2 /* defined */
/*
* Area types
*/
#define A_CON 000 /* concatenate */
#define A_OVR 004 /* overlay */
#define A_REL 000 /* relocatable */
#define A_ABS 010 /* absolute */
#define A_NOPAG 000 /* non-paged */
#define A_PAG 020 /* paged */
/*
* File types
*/
#define F_INV 0 /* invalid */
#define F_STD 1 /* stdin */
#define F_LNK 2 /* File.lnk */
#define F_REL 3 /* File.rel */
#ifdef SDK
#define F_CMD 4 /* Command line */
#endif /* SDK */
#ifdef GAMEBOY
/*
* Multiple banks support
*/
extern int nb_rom_banks;
extern int nb_ram_banks;
extern int current_rom_bank;
extern int mbc_type;
extern char cart_name[];
/*
* ROM patching support
*/
typedef struct _patch {
unsigned int addr;
unsigned char value;
struct _patch *next;
} patch;
extern patch* patches;
#endif /* GAMEBOY */
/*
* 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 */
char a_flag; /* Flag byte */
char a_id[NCPS]; /* Name */
};
/*
* 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[NCPS]; /* Name */
};
/*
* 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;
};
/*
* 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 char ctype[]; /* array of character types, one per
* ASCII character
*/
/*
* 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 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 *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 int oflag; /* Output file type flag
*/
extern int mflag; /* Map output flag
*/
#ifdef SDK
extern int symflag; /* no$gmb .sym output flag
*/
#endif
extern int xflag; /* Map file radix type flag
*/
extern int pflag; /* print linker command file flag
*/
extern int uflag; /* Listing relocation 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
*/
/* 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 link();
extern VOID lkexit();
extern int main();
extern VOID map();
#ifdef SDK
extern VOID sym();
#endif
extern int parse();
extern VOID setbas();
extern VOID setgbl();
extern VOID usage();
/* lklex.c */
extern char endline();
extern char get();
extern VOID getfid();
extern VOID getid();
extern int getLine_();
extern int getmap();
extern char getnb();
extern int more();
extern VOID skip();
extern VOID unget();
/* lkarea.c */
extern VOID lkparea();
extern VOID lnkarea();
extern VOID lnksect();
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 adw_w();
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();
/* lklibr.c */
extern VOID 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();
/* lkgb.h */
VOID gb(int in);
VOID gg(int in);

22
link/z80/clean.mk Normal file
View File

@@ -0,0 +1,22 @@
# Deleting all files created by building the program
# --------------------------------------------------
clean:
rm -f *core *[%~] *.[oa]
rm -f .[a-z]*~
rm -f $(PRJDIR)/link-z80 link-z80
rm -f *.dep
rm -rf obj
# Deleting all files created by configuring or building the program
# -----------------------------------------------------------------
distclean: clean
# 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

23
link/z80/conf.mk Normal file
View File

@@ -0,0 +1,23 @@
# Deleting all files created by building the program
# --------------------------------------------------
clean:
rm -f *core *[%~] *.[oa]
rm -f .[a-z]*~
rm -f $(PRJDIR)/link-z80 link-z80
# 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

430
link/z80/lkarea.c Normal file
View File

@@ -0,0 +1,430 @@
/* lkarea.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
#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++;
}
}
/*
* 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(id)
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);
}
/*)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_<areaname> and l_<areaname> 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.
*/
/*
* Resolve all area addresses.
*/
VOID
lnkarea()
{
register int rloc;
char temp[NCPS];
struct sym *sp;
rloc = 0;
ap = areap;
while (ap) {
if (ap->a_flag&A_ABS) {
/*
* Absolute sections
*/
lnksect(ap);
} else {
/*
* Relocatable sections
*/
if (ap->a_addr == 0)
ap->a_addr = rloc;
lnksect(ap);
rloc = ap->a_addr + ap->a_size;
}
/*
* Create symbols called:
* s_<areaname> the start address of the area
* l_<areaname> 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 = 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;
}
ap = ap->a_ap;
}
}
/*)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.
*/
VOID
lnksect(tap)
register 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 {
/*
* Concatenated sections
*/
while (taxp) {
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++;
}
}

465
link/z80/lkdata.c Normal file
View File

@@ -0,0 +1,465 @@
/* lkdata.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
//#include <alloc.h>
#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
*/
int oflag; /* Output file type flag
*/
int mflag; /* Map output flag
*/
#ifdef SDK
int symflag; /* no$gmb .sym output flag
*/
#endif
int xflag; /* Map file radix type flag
*/
int pflag; /* print linker command file flag
*/
int uflag; /* Listing relocation 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
*/
/*
* 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 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 *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
*/
/*
* 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[NCPS]; Name
* };
*/
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
*/
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

398
link/z80/lkeval.c Normal file
View File

@@ -0,0 +1,398 @@
/* lkeval.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
//#include <alloc.h>
#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(-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));
}
}
/* Shouldn't get here. */
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);
}

190
link/z80/lkgb.c Normal file
View File

@@ -0,0 +1,190 @@
/* lkgb.c */
/*
* P. Felber
*/
#ifdef GAMEBOY
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "aslink.h"
/* Value used to fill the unused portions of the image */
/* FFh puts less stress on a EPROM/Flash */
#define FILLVALUE 0xFF
#define CARTSIZE ((unsigned long)nb_rom_banks*16UL*1024UL)
#define NBSEG 8UL
#define SEGSIZE (CARTSIZE/NBSEG)
#define ROMSIZE 0x8000UL
#define BANKSTART 0x4000UL
#define BANKSIZE 0x4000UL
unsigned char *cart[NBSEG];
int nb_rom_banks;
int nb_ram_banks;
int current_rom_bank;
int mbc_type;
char cart_name[16] = "";
patch* patches = NULL;
VOID gb(int in)
{
static int first = 1;
unsigned long pos, chk;
int i;
patch *p;
if(first) {
for(i = 0; i < NBSEG; i++) {
if((cart[i] = malloc(SEGSIZE)) == NULL) {
fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
exit(-1);
}
memset(cart[i], FILLVALUE, SEGSIZE);
}
first = 0;
}
if(in) {
if(rtcnt > 2) {
if(hilo == 0)
pos = rtval[0] | (rtval[1]<<8);
else
pos = rtval[1] | (rtval[0]<<8);
/* Perform some validity checks */
if(pos >= ROMSIZE) {
fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
exit(-1);
}
if(current_rom_bank >= nb_rom_banks) {
fprintf(stderr, "ERROR: bank overflow (addr %x > %x)\n", current_rom_bank, nb_rom_banks);
exit(-1);
}
if(current_rom_bank > 0 && pos < BANKSTART) {
fprintf(stderr, "ERROR: address underflow (addr %lx < %lx)\n", pos, BANKSTART);
exit(-1);
}
if(nb_rom_banks == 2 && current_rom_bank > 0) {
fprintf(stderr, "ERROR: only 1 32kB segment with 2 bank\n");
exit(-1);
}
if(current_rom_bank > 1)
pos += (current_rom_bank-1)*BANKSIZE;
for(i = 2; i < rtcnt; i++) {
if(rtflg[i]) {
if(pos < CARTSIZE) {
if(cart[pos/SEGSIZE][pos%SEGSIZE] != FILLVALUE)
fprintf(stderr, "WARNING: possibly wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
} else {
fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
exit(-1);
}
pos++;
}
}
}
} else {
/* EOF */
if(cart_name[0] == 0 && linkp->f_idp != NULL) {
for(i = strlen(linkp->f_idp);
i > 0 && (isalnum(linkp->f_idp[i-1]) || linkp->f_idp[i-1] == '.');
i--)
;
for(pos = 0; pos < 16 && linkp->f_idp[i] != '.'; pos++, i++)
cart_name[pos] = toupper(linkp->f_idp[i]);
if(pos < 16)
cart_name[pos] = 0;
}
for(pos = 0x0134, i = 0;
pos < 0x0144 && cart_name[i];
pos++, i++)
cart[pos/SEGSIZE][pos%SEGSIZE] = cart_name[i];
for(; pos < 0x0144; pos++)
cart[pos/SEGSIZE][pos%SEGSIZE] = 0;
cart[0x147/SEGSIZE][0x147%SEGSIZE] = mbc_type;
switch(nb_rom_banks) {
case 2:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
break;
case 4:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 1;
break;
case 8:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 2;
break;
case 16:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 3;
break;
case 32:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 4;
break;
case 64:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 5;
break;
case 128:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 6;
break;
case 256:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 7;
break;
case 512:
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 8;
break;
default:
fprintf(stderr, "WARNING: unsupported number of ROM banks (%d)\n", nb_rom_banks);
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
break;
}
switch(nb_ram_banks) {
case 0:
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
break;
case 1:
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 2;
break;
case 4:
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 3;
break;
case 16:
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 4;
break;
default:
fprintf(stderr, "WARNING: unsupported number of RAM banks (%d)\n", nb_ram_banks);
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
break;
}
/* Patch before calculating the checksum */
if(patches)
for(p = patches; p; p = p->next)
cart[p->addr/SEGSIZE][p->addr%SEGSIZE] = p->value;
/* Update complement checksum */
chk = 0;
for(pos = 0x0134; pos < 0x014D; pos++)
chk += cart[pos/SEGSIZE][pos%SEGSIZE];
cart[0x014D/SEGSIZE][0x014D%SEGSIZE] = 0xE7 - (chk&0xFF);
/* Update checksum */
chk = 0;
cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = 0;
cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = 0;
for(i = 0; i < NBSEG; i++)
for(pos = 0; pos < SEGSIZE; pos++)
chk += cart[i][pos];
cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = (chk>>8)&0xFF;
cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = chk&0xFF;
for(i = 0; i < NBSEG; i++)
fwrite(cart[i], 1, SEGSIZE, ofp);
}
}
#endif /* GAMEBOY */

79
link/z80/lkgg.c Normal file
View File

@@ -0,0 +1,79 @@
/* lkgg.c */
/*
* P. Felber
*/
#ifdef GAMEGEAR
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "aslink.h"
#define CARTSIZE ((unsigned long)4*16UL*1024UL)
#define NBSEG 8UL
#define SEGSIZE (CARTSIZE/NBSEG)
unsigned char *cart[NBSEG];
#define ROMSIZE 0x10000UL
#define BANKSIZE 0x4000UL
int current_rom_bank;
VOID gg(int in)
{
static int first = 1;
unsigned long pos;
int i;
if(first) {
for(i = 0; i < NBSEG; i++) {
if((cart[i] = malloc(SEGSIZE)) == NULL) {
fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
exit(-1);
}
memset(cart[i], 0, SEGSIZE);
}
first = 0;
}
if(in) {
if(rtcnt > 2) {
if(hilo == 0)
pos = rtval[0] | (rtval[1]<<8);
else
pos = rtval[1] | (rtval[0]<<8);
/* Perform some validity checks */
if(pos >= ROMSIZE) {
fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
exit(-1);
}
if(current_rom_bank > 1)
pos += (current_rom_bank-1)*BANKSIZE;
for(i = 2; i < rtcnt; i++) {
if(rtflg[i]) {
if(pos < CARTSIZE) {
if(cart[pos/SEGSIZE][pos%SEGSIZE] != 0)
fprintf(stderr, "WARNING: wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
} else {
fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
exit(-1);
}
pos++;
}
}
}
} else {
/* EOF */
/* Patch before calculating the checksum */
for(i = 0; i < NBSEG; i++)
fwrite(cart[i], 1, SEGSIZE, ofp);
}
}
#endif /* GAMEGEAR */

154
link/z80/lkhead.c Normal file
View File

@@ -0,0 +1,154 @@
/* lkhead.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
//#include <alloc.h>
#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|A_OVR;
}
/*)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++;
}
}

134
link/z80/lkihx.c Normal file
View File

@@ -0,0 +1,134 @@
/* lkihx.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
//#include <alloc.h>
#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 function:
* VOID ihx(i)
*
* lkihx.c contains no local variables.
*/
/*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.
*/
/*)Function ihx(i)
*
* int i 0 - process data
* 1 - end of data
*
* The function ihx() outputs the relocated data
* in the standard Intel Hex 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
ihx(i)
{
register Addr_T chksum;
if (i) {
if (hilo == 0) {
chksum = rtval[0];
rtval[0] = rtval[1];
rtval[1] = chksum;
}
for (i = 0, chksum = -2; i < rtcnt; i++) {
if (rtflg[i])
chksum++;
}
fprintf(ofp, ":%02X", chksum);
for (i = 0; i < rtcnt ; i++) {
if (rtflg[i]) {
fprintf(ofp, "%02X", rtval[i]);
chksum += rtval[i];
}
if (i == 1) {
fprintf(ofp, "00");
}
}
fprintf(ofp, "%02X\n", (-chksum) & 0xff);
} else {
fprintf(ofp, ":00000001FF\n");
}
}

569
link/z80/lklex.c Normal file
View File

@@ -0,0 +1,569 @@
/* lklex.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
/*
* Extensions: P. Felber, M. Hope
*/
#include <stdio.h>
#include <string.h>
//#include <alloc.h>
#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()
* int 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 getfid(fid,c)
*
* char * str a pointer to a string of
* maximum length FILSPC
* 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 a
* non SPACE type character is found. The maximum number of
* characters copied is FILSPC. If the input string is larger than
* FILSPC characters then the string is truncated, if the input string
* is shorter than FILSPC characters then the string is NULL filled.
*
* 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[FILSPC-1])
*p++ = c;
c = get();
#ifdef SDK
} while (c);
#else /* SDK */
} while (c && (ctype[c] != SPACE));
#endif /* SDK */
while (p < &str[FILSPC])
*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 getLine_()
*
* The function 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
* 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
getLine_()
{
register int i, ftype;
register char *fid;
loop: if (pflag && cfp && cfp->f_type == F_STD)
fprintf(stdout, "ASlink >> ");
#ifdef SDK
if(cfp == NULL && filep != NULL && filep->f_type == F_CMD) {
char **argv = (char **)filep->f_idp;
if(argv[0] != NULL && strlen(argv[0]) < sizeof ib) {
strcpy(ib, argv[0]);
filep->f_idp = (char *)&argv[1];
} else {
filep = NULL;
return(0);
}
} else
#endif /* SDK */
if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
if (sfp) {
fclose(sfp);
#ifdef SDK
sfp = NULL;
#endif /* SDK */
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) {
#ifdef SDK
sfp = afile(fid, "lnk", 0);
#else /* SDK */
sfp = afile(fid, "LNK", 0);
#endif /* SDK */
} else
if (ftype == F_REL) {
#ifdef SDK
sfp = afile(fid, "", 0);
if (uflag && pass != 0) {
if ((tfp = afile(fid, "lst", 0)) != NULL) {
if ((rfp = afile(fid, "rst", 1)) == NULL) {
#else /* SDK */
sfp = afile(fid, "REL", 0);
if (uflag && pass != 0) {
if ((tfp = afile(fid, "LST", 0)) != NULL) {
if ((rfp = afile(fid, "RST", 1)) == NULL) {
#endif /* SDK */
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);
}
}
i = strlen(ib) - 1;
if (ib[i] == '\n')
ib[i] = 0;
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 );
}

810
link/z80/lklibr.c Normal file
View File

@@ -0,0 +1,810 @@
/* 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
*
*/
/*
* Extensions: P. Felber
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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()
*
*/
#ifdef INDEXLIB
typedef struct slibrarysymbol mlibrarysymbol;
typedef struct slibrarysymbol *pmlibrarysymbol;
struct slibrarysymbol {
char name[40];
pmlibrarysymbol next;
};
typedef struct slibraryfile mlibraryfile;
typedef struct slibraryfile *pmlibraryfile;
struct slibraryfile {
int loaded;
char *libspc;
char *str;
char relfil[FILSPC];
char filename[FILSPC];
pmlibrarysymbol symbols;
pmlibraryfile next;
};
int buildlibraryindex();
#endif /* INDEXLIB */
/*)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
*
* 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;
unget(getnb());
if (lbphead == NULL) {
addfile(NULL,ip);
return;
}
for (lbph=lbphead; lbph; lbph=lbph->next) {
addfile(lbph->path,ip);
}
}
/*)Function VOID 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.
*/
VOID
addfile(path,libfil)
char *path;
char *libfil;
{
FILE *fp;
char *str;
struct lbname *lbnh, *lbn;
if ((path != NULL) && (strchr(libfil,':') == NULL)){
str = (char *) new (strlen(path) + strlen(libfil) + 6);
strcpy(str,path);
#ifdef OTHERSYSTEM
#ifdef SDK
#ifdef UNIX
if (str[strlen(str)-1] != '/') {
strcat(str,"/");
#else /* UNIX */
if (str[strlen(str)-1] != '\\') {
strcat(str,"\\");
#endif /* UNIX */
#else /* SDK */
if (str[strlen(str)-1] != '\\') {
strcat(str,"\\");
#endif /* SDK */
}
#endif
} else {
str = (char *) new (strlen(libfil) + 5);
}
#ifdef OTHERSYSTEM
#ifdef SDK
#ifdef UNIX
if (libfil[0] == '/') { libfil++; }
#else /* UNIX */
if (libfil[0] == '\\') { libfil++; }
#endif /* UNIX */
#else /* SDK */
if (libfil[0] == '\\') { libfil++; }
#endif /* SDK */
#endif
strcat(str,libfil);
if(strchr(str,FSEPX) == NULL) {
sprintf(&str[strlen(str)], "%clib", FSEPX);
}
if ((fp = fopen(str, "r")) != 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;
}
if ((path != NULL) && (strchr(libfil,':') == NULL)){
lbnh->path = path;
}
lbnh->libfil = (char *) new (strlen(libfil) + 1);
strcpy(lbnh->libfil,libfil);
lbnh->libspc = str;
} else {
free(str);
}
}
/*)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; i<NHASH; ++i) {
sp = symhash[i];
while (sp) {
/* If we find an undefined symbol
* (one where S_DEF is not set), then
* try looking for it. If we find it
* in any of the libraries then
* increment symfnd. This will force
* another pass of symbol searching and
* make sure that back references work.
*/
if ((sp->s_type & S_DEF) == 0) {
if (fndsym(sp->s_id)) {
symfnd++;
}
}
sp = sp->s_sp;
}
}
}
}
/*)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.
*/
#ifdef INDEXLIB
/* First entry in the library object symbol cache */
mlibraryfile libr;
int fndsym( char *name )
{
struct lbfile *lbfh, *lbf;
pmlibraryfile ThisLibr;
pmlibrarysymbol ThisSym = NULL;
/* Build the index if this is the first call to fndsym */
if (libr.next==NULL)
buildlibraryindex();
/* Iterate through all library object files */
ThisLibr = libr.next;
while (ThisLibr) {
/* Iterate through all symbols in an object file */
ThisSym = ThisLibr->symbols->next;
while (ThisSym) {
if (!strcmp(ThisSym->name, name)) {
if (!ThisLibr->loaded) {
/* Object file is not loaded - add it to the list */
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 = ThisLibr->libspc;
lbfh->filspc = ThisLibr->str;
lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
strcpy(lbfh->relfil,ThisLibr->relfil);
loadfile(lbfh->filspc);
ThisLibr->loaded=1;
}
return (1); /* Found the symbol, return */
}
ThisSym=ThisSym->next; /* Next sym in library */
}
ThisLibr=ThisLibr->next; /* Next library in list */
}
return 0; /* Failure - symbol not found in any library */
};
/* buildlibraryindex - build an in-memory cache of the symbols contained in
* the libraries
*/
int buildlibraryindex()
{
FILE *libfp, *fp;
struct lbname *lbnh;
char relfil[NINPUT+2], *str, *path;
char buf[NINPUT+2], c;
char symname[NINPUT+2];
pmlibraryfile This;
pmlibrarysymbol ThisSym;
This=&libr;
/* Iterate through all library files */
/*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
libfp = fopen( lbnh->libspc, "r" );
if (libfp) {
path=lbnh->path;
/*
* Read in a line from the library file.
* This is the relative file specification
* for a .REL file in this library.
*/
/*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
relfil[NINPUT+1] = '\0';
relfil[strlen(relfil) - 1] = '\0';
if (path != NULL) {
str = (char *)new(strlen(path)+strlen(relfil)+6);
strcpy(str,path);
#ifdef OTHERSYSTEM
#ifdef SDK
#ifdef UNIX
if (str[strlen(str)-1] != '/') {
strcat(str,"/");
#else /* UNIX */
if (str[strlen(str)-1] != '\\') {
strcat(str,"\\");
#endif /* UNIX */
#else /* SDK */
if (str[strlen(str)-1] != '\\') {
strcat(str,"\\");
#endif /* SDK */
}
#endif
} else {
str = (char *)new(strlen(relfil) + 5);
}
#ifdef SDK
#ifdef UNIX
if (relfil[0] == '/') {
#else /* UNIX */
if (relfil[0] == '\\') {
#endif /* UNIX */
#else /* SDK */
if (relfil[0] == '\\') {
#endif /* SDK */
strcat(str,relfil+1);
} else {
strcat(str,relfil);
}
if(strchr(str,FSEPX) == NULL) {
#ifdef SDK
sprintf(&str[strlen(str)], "%co", FSEPX);
#else /* SDK */
sprintf(&str[strlen(str)], "%crel", FSEPX);
#endif /* SDK */
}
/*3*/ if ((fp = fopen(str, "r")) != NULL) {
/* Opened OK - create a new libraryfile object for it */
This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
if (This->next == NULL) {
printf("panic: cant allocate memory.\n");
exit(-1);
}
This=This->next;
This->next = NULL;
This->loaded=-1;
strcpy( This->filename, str );
ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
ThisSym->next = 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.
*/
/*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
buf[NINPUT+1] = '\0';
buf[strlen(buf) - 1] = '\0';
/*
* 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 it's an actual symbol, record it */
/*5*/ if (c == 'D') {
ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
ThisSym=ThisSym->next;
if (ThisSym == NULL) {
printf("panic: cant allocate memory.\n");
exit(-2);
}
This->loaded=0;
ThisSym->next=NULL;
This->str = str;
strcpy(This->relfil,relfil);
strcpy(ThisSym->name, symname);
This->libspc = lbnh->libspc;
}
} /* Closes while - read object file */
fclose(fp);
} /* Closes if object file opened OK */
} /* Ends while - processing all in libr */
fclose(libfp);
} /* Ends good open of libr file */
}
return 0;
}
#else /* INDEXLIB */
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;
/*
* Search through every library in the linked list "lbnhead".
*/
/*1*/ 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.
*/
/*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
relfil[NINPUT+1] = '\0';
relfil[strlen(relfil) - 1] = '\0';
if (path != NULL) {
str = (char *) new (strlen(path)+strlen(relfil)+6);
strcpy(str,path);
#ifdef OTHERSYSTEM
#ifdef SDK
#ifdef UNIX
if (str[strlen(str)-1] != '/') {
strcat(str,"/");
#else /* UNIX */
if (str[strlen(str)-1] != '\\') {
strcat(str,"\\");
#endif /* UNIX */
#else /* SDK */
if (str[strlen(str)-1] != '\\') {
strcat(str,"\\");
#endif /* SDK */
}
#endif
} else {
str = (char *) new (strlen(relfil) + 5);
}
#ifdef SDK
#ifdef UNIX
if (relfil[0] == '/') {
#else /* UNIX */
if (relfil[0] == '\\') {
#endif /* UNIX */
#else /* SDK */
if (relfil[0] == '\\') {
#endif /* SDK */
strcat(str,relfil+1);
} else {
strcat(str,relfil);
}
if(strchr(str,FSEPX) == NULL) {
#ifdef SDK
sprintf(&str[strlen(str)], "%co", FSEPX);
#else /* SDK */
sprintf(&str[strlen(str)], "%crel", FSEPX);
#endif /* SDK */
}
/*3*/ 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.
*/
/*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
buf[NINPUT+1] = '\0';
buf[strlen(buf) - 1] = '\0';
/*
* 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.
*/
/*5*/ 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);
strcpy(lbfh->relfil,relfil);
fclose(fp);
fclose(libfp);
loadfile(str);
return (1);
/*5*/ }
/*4*/ }
fclose(fp);
/*3*/ }
free(str);
/*2*/ }
fclose(libfp);
/*1*/ }
return(0);
}
#endif /* INDEXLIB */
/*)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) {
loadfile(lbfh->filspc);
}
}
/*)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() 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];
int i;
if ((fp = fopen(filspc,"r")) != NULL) {
while (fgets(str, NINPUT, fp) != NULL) {
str[NINPUT+1] = '\0';
i = strlen(str) - 1;
if (str[i] == '\n')
str[i] = '\0';
ip = str;
link();
}
fclose(fp);
}
}

1270
link/z80/lklist.c Normal file

File diff suppressed because it is too large Load Diff

1411
link/z80/lkmain.c Normal file

File diff suppressed because it is too large Load Diff

1171
link/z80/lkrloc.c Normal file

File diff suppressed because it is too large Load Diff

123
link/z80/lks19.c Normal file
View File

@@ -0,0 +1,123 @@
/* lks19.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
//#include <alloc.h>
#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 (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", (-chksum-1) & 0xff);
} else {
fprintf(ofp, "S9030000FC\n");
}
}

496
link/z80/lksym.c Normal file
View File

@@ -0,0 +1,496 @@
/* lksym.c */
/*
* (C) Copyright 1989-1995
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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()
{
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 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 int c, i, nglob;
struct sym *tsp;
struct sym **s;
char id[NCPS];
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) {
#ifdef SDK
fprintf(stderr, "Multiple definition of %s\n", id);
#else
fprintf(stderr, "Multiple definition of %.8s\n", id);
#endif
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);
/* Never reached */
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;
strncpy(sp->s_id, id, NCPS);
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; i<NHASH; ++i) {
sp = symhash[i];
while (sp) {
if (sp->s_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; i<hp->h_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;
{
register int n;
n = NCPS;
do {
#if CASE_SENSITIVE
if (*p1++ != *p2++)
return (0);
#else
if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
return (0);
#endif
} while (--n);
return (1);
}
/*)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, n;
h = 0;
n = NCPS;
do {
#if CASE_SENSITIVE
h += *p++;
#else
h += ccase[(unsigned char)(*p++)];
#endif
} while (--n);
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,*q;
register unsigned int i;
if ((p = (char *) malloc(n)) == NULL) {
fprintf(stderr, "Out of space!\n");
lkexit(1);
}
for (i=0,q=p; i<n; i++) {
*q++ = 0;
}
return (p);
}