mirror of
https://github.com/Museum-of-Art-and-Digital-Entertainment/macross.git
synced 2025-04-13 23:37:02 +00:00
Initial commit from macross.tar.gz
MD5 (macross.tar.gz) = 4ecb4a6e015b11fef043fe78d1eedb61
This commit is contained in:
commit
98a36557e4
34
DOC
Normal file
34
DOC
Normal file
@ -0,0 +1,34 @@
|
||||
/u0/chip/macross:
|
||||
This directory contains the source to Macross. Here's what's here:
|
||||
|
||||
DOC - this file
|
||||
|
||||
Makefile - current makefile
|
||||
Makefile_6502 - makefile for 6502 version
|
||||
Makefile_68000 - makefile for 68000
|
||||
|
||||
There are both 6502 and 68000 versions of Macross, though the 68000
|
||||
version has not been very well tested. Source for both is here. Source files
|
||||
which come in different flavors for the different versions are marked 6502 or
|
||||
68000 in their names as appropriate. There are two different Makefiles also.
|
||||
At any given time, either the 6502 version or the 68000 version is the
|
||||
'working' version. The 'working' version is what the default makefile
|
||||
'Makefile' will produce. Typing 'make foobar' will change the working version
|
||||
by swapping the makefiles.
|
||||
|
||||
*.c, *.h, *.y - source for the program
|
||||
|
||||
doc/ - the manual and other user documentation are here
|
||||
notes68/ - notes on 68000 syntax and operand structure
|
||||
opt/ - working directory for 'optimized' version. When I
|
||||
was developing the program, I needed to keep two separate copies of
|
||||
the source and object code. This is because the C compiler can
|
||||
compile with debugging or with optimization, but not both. The
|
||||
version that folks use needs to be compiled with optimization, but I
|
||||
need a version with debugging to fix any problems that crop up. Since
|
||||
the time to recompile the whole thing is so enormous, it was easiest
|
||||
to keep two copies. In the interest of saving file space, all that is
|
||||
in this directory now, however, are the Makefiles for compiling with
|
||||
optimization.
|
||||
|
||||
slinky/ - Slinky lives here
|
164
Makefile
Normal file
164
Makefile
Normal file
@ -0,0 +1,164 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
# to make for another target CPU, redefine PROC to the name of the target
|
||||
# processor, e.g., 68000
|
||||
PROC =6502
|
||||
|
||||
OBJECTS = y.tab.o actions.o buildStuff1.o buildStuff2.o\
|
||||
buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o\
|
||||
emitBranch.o emitStuff.o encode.o errorStuff.o expressionSemantics.o fixups.o\
|
||||
garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o\
|
||||
malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o\
|
||||
statementSemantics.o structSemantics.o tokenStrings.o
|
||||
|
||||
SOURCES = macross_$(PROC).y actions_$(PROC).c buildStuff1.c buildStuff2.c\
|
||||
buildStuff3.c builtInFunctions.c builtInFunsSD_$(PROC).c debugPrint.c\
|
||||
debugPrintSD_$(PROC).c emitBranch_$(PROC).c emitStuff.c encode.c errorStuff.c\
|
||||
expressionSemantics.c fixups.c garbage.c initialize.c lexer.c listing.c\
|
||||
lookups.c macrossTables_$(PROC).c main.c malloc.c object.c\
|
||||
operandStuffSD_$(PROC).c parserMisc.c semanticMisc.c statementSemantics.c\
|
||||
structSemantics.c tokenStrings_$(PROC).c lexerTables.h macrossGlobals.h\
|
||||
macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h driver.c slinkyExpressions.h
|
||||
|
||||
HEADERS = macrossTypes.h macrossGlobals.h
|
||||
|
||||
.c.o:
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) $*.c
|
||||
|
||||
.c.run:
|
||||
cc -o $* $*.c
|
||||
|
||||
macross: $(OBJECTS)
|
||||
cc -g -o macross $(OBJECTS)
|
||||
|
||||
driver: driver.c
|
||||
cc -o driver driver.c
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross; make macross >&errorfyle)" &
|
||||
|
||||
install: macross
|
||||
cp macross /u1/gg/bin/macross_tmp
|
||||
strip /u1/gg/bin/macross_tmp
|
||||
mv /u1/gg/bin/macross_$(PROC) /u1/gg/bin/macross_$(PROC).old
|
||||
mv /u1/gg/bin/macross_tmp /u1/gg/bin/macross_$(PROC)
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/mycroft/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/shem/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/weyr/u1/gg/bin
|
||||
|
||||
dinstall: driver
|
||||
cp driver /u1/gg/bin/driver_tmp
|
||||
strip /u1/gg/bin/driver_tmp
|
||||
mv /u1/gg/bin/driver_tmp /u1/gg/bin/driver/macross
|
||||
cp /u1/gg/bin/driver /net/mycroft/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/shem/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/weyr/u1/gg/bin/macross
|
||||
|
||||
change:
|
||||
rm *.o
|
||||
rm *.tab.*
|
||||
cp Makefile_68000 Makefile
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
cp $? /net/kessel/u0/chip/macross
|
||||
cp $? /net/kessel/u0/chip/macross/prof
|
||||
cp $? opt
|
||||
date >.mark
|
||||
date >/net/kessel/u0/chip/macross/.mark
|
||||
date >/net/kessel/u0/chip/macross/prof/.mark
|
||||
date >opt/.mark
|
||||
|
||||
macrossTypes.h: macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h
|
||||
|
||||
actions.o: actions_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) actions_$(PROC).c
|
||||
mv actions_$(PROC).o actions.o
|
||||
|
||||
buildStuff1.o: buildStuff1.c $(HEADERS)
|
||||
|
||||
buildStuff2.o: buildStuff2.c $(HEADERS)
|
||||
|
||||
buildStuff3.o: buildStuff3.c $(HEADERS)
|
||||
|
||||
builtInFunctions.o: builtInFunctions.c $(HEADERS)
|
||||
|
||||
builtInFunsSD.o: builtInFunsSD_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) builtInFunsSD_$(PROC).c
|
||||
mv builtInFunsSD_$(PROC).o builtInFunsSD.o
|
||||
|
||||
debugPrint.o: debugPrint.c y.tab.h $(HEADERS)
|
||||
|
||||
debugPrintSD.o: debugPrintSD_$(PROC).c y.tab.h $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) debugPrintSD_$(PROC).c
|
||||
mv debugPrintSD_$(PROC).o debugPrintSD.o
|
||||
|
||||
emitBranch.o: emitBranch_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) emitBranch_$(PROC).c
|
||||
mv emitBranch_$(PROC).o emitBranch.o
|
||||
|
||||
emitStuff.o: emitStuff.c $(HEADERS)
|
||||
cc -c -g -DBYTESWAPPED -DTARGET_CPU=CPU_$(PROC) emitStuff.c
|
||||
|
||||
encode.o: encode.c $(HEADERS)
|
||||
|
||||
errorStuff.o: errorStuff.c $(HEADERS)
|
||||
|
||||
expressionSemantics.o: expressionSemantics.c y.tab.h $(HEADERS)
|
||||
|
||||
fixups.o: fixups.c $(HEADERS)
|
||||
|
||||
garbage.o: garbage.c y.tab.h $(HEADERS)
|
||||
|
||||
initialize.o: initialize.c $(HEADERS)
|
||||
|
||||
lexer.o: lexer.c lexerTables.h y.tab.h $(HEADERS)
|
||||
|
||||
listing.o: listing.c $(HEADERS)
|
||||
|
||||
lookups.o: lookups.c $(HEADERS)
|
||||
|
||||
macrossTables.o: macrossTables_$(PROC).c y.tab.h macrossTypes.h
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) macrossTables_$(PROC).c
|
||||
mv macrossTables_$(PROC).o macrossTables.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
|
||||
main.o: main.c $(HEADERS)
|
||||
|
||||
object.o: object.c $(HEADERS)
|
||||
|
||||
operandStuffSD.o: operandStuffSD_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) operandStuffSD_$(PROC).c
|
||||
mv operandStuffSD_$(PROC).o operandStuffSD.o
|
||||
|
||||
parserMisc.o: parserMisc.c y.tab.h $(HEADERS)
|
||||
|
||||
semanticMisc.o: semanticMisc.c $(HEADERS)
|
||||
|
||||
statementSemantics.o: statementSemantics.c $(HEADERS)
|
||||
|
||||
structSemantics.o: structSemantics.c $(HEADERS)
|
||||
|
||||
tokenStrings.o: tokenStrings_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) tokenStrings_$(PROC).c
|
||||
mv tokenStrings_$(PROC).o tokenStrings.o
|
||||
|
||||
y.tab.o: y.tab.c $(HEADERS)
|
||||
cc -c -g -DYYDEBUG -DTARGET_CPU=CPU_$(PROC) y.tab.c
|
||||
|
||||
y.tab.c y.tab.h: macross_$(PROC).y
|
||||
yacc -d macross_$(PROC).y
|
||||
|
||||
y.output: macross_$(PROC).y
|
||||
yacc -vd macross_$(PROC).y
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o y.output y.tab.c y.tab.h macross
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
162
Makefile_6502
Normal file
162
Makefile_6502
Normal file
@ -0,0 +1,162 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
# to make for another target CPU, redefine PROC to the name of the target
|
||||
# processor, e.g., 68000
|
||||
PROC =6502
|
||||
|
||||
OBJECTS = y.tab.o actions.o buildStuff1.o buildStuff2.o\
|
||||
buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o\
|
||||
emitBranch.o emitStuff.o errorStuff.o expressionSemantics.o fixups.o\
|
||||
garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o\
|
||||
malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o\
|
||||
statementSemantics.o structSemantics.o tokenStrings.o
|
||||
|
||||
SOURCES = macross_$(PROC).y actions_$(PROC).c buildStuff1.c buildStuff2.c\
|
||||
buildStuff3.c builtInFunctions.c builtInFunsSD_$(PROC).c debugPrint.c\
|
||||
debugPrintSD_$(PROC).c emitBranch_$(PROC).c emitStuff.c errorStuff.c\
|
||||
expressionSemantics.c fixups.c garbage.c initialize.c lexer.c listing.c\
|
||||
lookups.c macrossTables_$(PROC).c main.c malloc.c object.c\
|
||||
operandStuffSD_$(PROC).c parserMisc.c semanticMisc.c statementSemantics.c\
|
||||
structSemantics.c tokenStrings_$(PROC).c lexerTables.h macrossGlobals.h\
|
||||
macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h driver.c
|
||||
|
||||
HEADERS = macrossTypes.h macrossGlobals.h
|
||||
|
||||
.c.o:
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) $*.c
|
||||
|
||||
.c.run:
|
||||
cc -o $* $*.c
|
||||
|
||||
macross: $(OBJECTS)
|
||||
cc -g -o macross $(OBJECTS)
|
||||
|
||||
driver: driver.c
|
||||
cc -o driver driver.c
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross; make macross >&errorfyle)" &
|
||||
|
||||
install: macross
|
||||
cp macross /u1/gg/bin/macross_tmp
|
||||
strip /u1/gg/bin/macross_tmp
|
||||
mv /u1/gg/bin/macross_$(PROC) /u1/gg/bin/macross_$(PROC).old
|
||||
mv /u1/gg/bin/macross_tmp /u1/gg/bin/macross_$(PROC)
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/mycroft/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/shem/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/weyr/u1/gg/bin
|
||||
|
||||
dinstall: driver
|
||||
cp driver /u1/gg/bin/driver_tmp
|
||||
strip /u1/gg/bin/driver_tmp
|
||||
mv /u1/gg/bin/driver_tmp /u1/gg/bin/driver/macross
|
||||
cp /u1/gg/bin/driver /net/mycroft/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/shem/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/weyr/u1/gg/bin/macross
|
||||
|
||||
change:
|
||||
rm *.o
|
||||
rm *.tab.*
|
||||
cp Makefile_68000 Makefile
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
cp $? /net/kessel/u0/chip/macross
|
||||
cp $? /net/kessel/u0/chip/macross/prof
|
||||
cp $? opt
|
||||
date >.mark
|
||||
date >/net/kessel/u0/chip/macross/.mark
|
||||
date >/net/kessel/u0/chip/macross/prof/.mark
|
||||
date >opt/.mark
|
||||
|
||||
macrossTypes.h: macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h
|
||||
|
||||
actions.o: actions_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) actions_$(PROC).c
|
||||
mv actions_$(PROC).o actions.o
|
||||
|
||||
buildStuff1.o: buildStuff1.c $(HEADERS)
|
||||
|
||||
buildStuff2.o: buildStuff2.c $(HEADERS)
|
||||
|
||||
buildStuff3.o: buildStuff3.c $(HEADERS)
|
||||
|
||||
builtInFunctions.o: builtInFunctions.c $(HEADERS)
|
||||
|
||||
builtInFunsSD.o: builtInFunsSD_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) builtInFunsSD_$(PROC).c
|
||||
mv builtInFunsSD_$(PROC).o builtInFunsSD.o
|
||||
|
||||
debugPrint.o: debugPrint.c y.tab.h $(HEADERS)
|
||||
|
||||
debugPrintSD.o: debugPrintSD_$(PROC).c y.tab.h $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) debugPrintSD_$(PROC).c
|
||||
mv debugPrintSD_$(PROC).o debugPrintSD.o
|
||||
|
||||
emitBranch.o: emitBranch_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) emitBranch_$(PROC).c
|
||||
mv emitBranch_$(PROC).o emitBranch.o
|
||||
|
||||
emitStuff.o: emitStuff.c $(HEADERS)
|
||||
cc -c -g -DBYTESWAPPED -DTARGET_CPU=CPU_$(PROC) emitStuff.c
|
||||
|
||||
errorStuff.o: errorStuff.c $(HEADERS)
|
||||
|
||||
expressionSemantics.o: expressionSemantics.c y.tab.h $(HEADERS)
|
||||
|
||||
fixups.o: fixups.c $(HEADERS)
|
||||
|
||||
garbage.o: garbage.c y.tab.h $(HEADERS)
|
||||
|
||||
initialize.o: initialize.c $(HEADERS)
|
||||
|
||||
lexer.o: lexer.c lexerTables.h y.tab.h $(HEADERS)
|
||||
|
||||
listing.o: listing.c $(HEADERS)
|
||||
|
||||
lookups.o: lookups.c $(HEADERS)
|
||||
|
||||
macrossTables.o: macrossTables_$(PROC).c y.tab.h macrossTypes.h
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) macrossTables_$(PROC).c
|
||||
mv macrossTables_$(PROC).o macrossTables.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
|
||||
main.o: main.c $(HEADERS)
|
||||
|
||||
object.o: object.c $(HEADERS)
|
||||
|
||||
operandStuffSD.o: operandStuffSD_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) operandStuffSD_$(PROC).c
|
||||
mv operandStuffSD_$(PROC).o operandStuffSD.o
|
||||
|
||||
parserMisc.o: parserMisc.c y.tab.h $(HEADERS)
|
||||
|
||||
semanticMisc.o: semanticMisc.c $(HEADERS)
|
||||
|
||||
statementSemantics.o: statementSemantics.c $(HEADERS)
|
||||
|
||||
structSemantics.o: structSemantics.c $(HEADERS)
|
||||
|
||||
tokenStrings.o: tokenStrings_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) tokenStrings_$(PROC).c
|
||||
mv tokenStrings_$(PROC).o tokenStrings.o
|
||||
|
||||
y.tab.o: y.tab.c $(HEADERS)
|
||||
cc -c -g -DYYDEBUG -DTARGET_CPU=CPU_$(PROC) y.tab.c
|
||||
|
||||
y.tab.c y.tab.h: macross_$(PROC).y
|
||||
yacc -d macross_$(PROC).y
|
||||
|
||||
y.output: macross_$(PROC).y
|
||||
yacc -vd macross_$(PROC).y
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o y.output y.tab.c y.tab.h macross
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
162
Makefile_68000
Normal file
162
Makefile_68000
Normal file
@ -0,0 +1,162 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
# to make for another target CPU, redefine PROC to the name of the target
|
||||
# processor, e.g., 68000
|
||||
PROC =68000
|
||||
|
||||
OBJECTS = y.tab.o actions.o buildStuff1.o buildStuff2.o\
|
||||
buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o\
|
||||
emitBranch.o emitStuff.o errorStuff.o expressionSemantics.o fixups.o\
|
||||
garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o\
|
||||
malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o\
|
||||
statementSemantics.o structSemantics.o tokenStrings.o
|
||||
|
||||
SOURCES = macross_$(PROC).y actions_$(PROC).c buildStuff1.c buildStuff2.c\
|
||||
buildStuff3.c builtInFunctions.c builtInFunsSD_$(PROC).c debugPrint.c\
|
||||
debugPrintSD_$(PROC).c emitBranch_$(PROC).c emitStuff.c errorStuff.c\
|
||||
expressionSemantics.c fixups.c garbage.c initialize.c lexer.c listing.c\
|
||||
lookups.c macrossTables_$(PROC).c main.c malloc.c object.c\
|
||||
operandStuffSD_$(PROC).c parserMisc.c semanticMisc.c statementSemantics.c\
|
||||
structSemantics.c tokenStrings_$(PROC).c lexerTables.h macrossGlobals.h\
|
||||
macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h driver.c
|
||||
|
||||
HEADERS = macrossTypes.h macrossGlobals.h
|
||||
|
||||
.c.o:
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) $*.c
|
||||
|
||||
.c.run:
|
||||
cc -o $* $*.c
|
||||
|
||||
macross: $(OBJECTS)
|
||||
cc -g -o macross $(OBJECTS)
|
||||
|
||||
driver: driver.c
|
||||
cc -o driver driver.c
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross; make macross >&errorfyle)" &
|
||||
|
||||
install: macross
|
||||
cp macross /u1/gg/bin/macross_tmp
|
||||
strip /u1/gg/bin/macross_tmp
|
||||
mv /u1/gg/bin/macross_$(PROC) /u1/gg/bin/macross_$(PROC).old
|
||||
mv /u1/gg/bin/macross_tmp /u1/gg/bin/macross_$(PROC)
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/mycroft/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/shem/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/weyr/u1/gg/bin
|
||||
|
||||
dinstall: driver
|
||||
cp driver /u1/gg/bin/driver_tmp
|
||||
strip /u1/gg/bin/driver_tmp
|
||||
mv /u1/gg/bin/driver_tmp /u1/gg/bin/driver/macross
|
||||
cp /u1/gg/bin/driver /net/mycroft/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/shem/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/weyr/u1/gg/bin/macross
|
||||
|
||||
change:
|
||||
rm *.o
|
||||
rm *.tab.*
|
||||
cp Makefile_6502 Makefile
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
cp $? /net/kessel/u0/chip/macross
|
||||
cp $? /net/kessel/u0/chip/macross/prof
|
||||
cp $? opt
|
||||
date >.mark
|
||||
date >/net/kessel/u0/chip/macross/.mark
|
||||
date >/net/kessel/u0/chip/macross/prof/.mark
|
||||
date >opt/.mark
|
||||
|
||||
macrossTypes.h: macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h
|
||||
|
||||
actions.o: actions_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) actions_$(PROC).c
|
||||
mv actions_$(PROC).o actions.o
|
||||
|
||||
buildStuff1.o: buildStuff1.c $(HEADERS)
|
||||
|
||||
buildStuff2.o: buildStuff2.c $(HEADERS)
|
||||
|
||||
buildStuff3.o: buildStuff3.c $(HEADERS)
|
||||
|
||||
builtInFunctions.o: builtInFunctions.c $(HEADERS)
|
||||
|
||||
builtInFunsSD.o: builtInFunsSD_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) builtInFunsSD_$(PROC).c
|
||||
mv builtInFunsSD_$(PROC).o builtInFunsSD.o
|
||||
|
||||
debugPrint.o: debugPrint.c y.tab.h $(HEADERS)
|
||||
|
||||
debugPrintSD.o: debugPrintSD_$(PROC).c y.tab.h $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) debugPrintSD_$(PROC).c
|
||||
mv debugPrintSD_$(PROC).o debugPrintSD.o
|
||||
|
||||
emitBranch.o: emitBranch_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) emitBranch_$(PROC).c
|
||||
mv emitBranch_$(PROC).o emitBranch.o
|
||||
|
||||
emitStuff.o: emitStuff.c $(HEADERS)
|
||||
cc -c -g -DBYTESWAPPED -DTARGET_CPU=CPU_$(PROC) emitStuff.c
|
||||
|
||||
errorStuff.o: errorStuff.c $(HEADERS)
|
||||
|
||||
expressionSemantics.o: expressionSemantics.c y.tab.h $(HEADERS)
|
||||
|
||||
fixups.o: fixups.c $(HEADERS)
|
||||
|
||||
garbage.o: garbage.c y.tab.h $(HEADERS)
|
||||
|
||||
initialize.o: initialize.c $(HEADERS)
|
||||
|
||||
lexer.o: lexer.c lexerTables.h y.tab.h $(HEADERS)
|
||||
|
||||
listing.o: listing.c $(HEADERS)
|
||||
|
||||
lookups.o: lookups.c $(HEADERS)
|
||||
|
||||
macrossTables.o: macrossTables_$(PROC).c y.tab.h macrossTypes.h
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) macrossTables_$(PROC).c
|
||||
mv macrossTables_$(PROC).o macrossTables.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
|
||||
main.o: main.c $(HEADERS)
|
||||
|
||||
object.o: object.c $(HEADERS)
|
||||
|
||||
operandStuffSD.o: operandStuffSD_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) operandStuffSD_$(PROC).c
|
||||
mv operandStuffSD_$(PROC).o operandStuffSD.o
|
||||
|
||||
parserMisc.o: parserMisc.c y.tab.h $(HEADERS)
|
||||
|
||||
semanticMisc.o: semanticMisc.c $(HEADERS)
|
||||
|
||||
statementSemantics.o: statementSemantics.c $(HEADERS)
|
||||
|
||||
structSemantics.o: structSemantics.c $(HEADERS)
|
||||
|
||||
tokenStrings.o: tokenStrings_$(PROC).c $(HEADERS)
|
||||
cc -c -g -DTARGET_CPU=CPU_$(PROC) tokenStrings_$(PROC).c
|
||||
mv tokenStrings_$(PROC).o tokenStrings.o
|
||||
|
||||
y.tab.o: y.tab.c $(HEADERS)
|
||||
cc -c -g -DYYDEBUG -DTARGET_CPU=CPU_$(PROC) y.tab.c
|
||||
|
||||
y.tab.c y.tab.h: macross_$(PROC).y
|
||||
yacc -d macross_$(PROC).y
|
||||
|
||||
y.output: macross_$(PROC).y
|
||||
yacc -vd macross_$(PROC).y
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o y.output y.tab.c y.tab.h macross
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
511
actions_6502.c
Normal file
511
actions_6502.c
Normal file
@ -0,0 +1,511 @@
|
||||
/*
|
||||
actions.c -- Actions associated with various machine instruction
|
||||
classes (6502 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
16-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
#define operand (evaluatedOperands[0])
|
||||
#define address (evaluatedOperands[0])->value
|
||||
#define class (evaluatedOperands[0])->addressMode
|
||||
#define binary opcode->opcode
|
||||
|
||||
/*
|
||||
These routines are vectored off of the opcode lookup table. Each
|
||||
instruction is of a particular category that defines which address modes
|
||||
it accepts its operands in and what size (one byte or two) the operands
|
||||
are. There is one "actionsXXXX" routine for each of these categories that
|
||||
grabs the operand, checks the address mode, and emits the binary opcode
|
||||
and operand.
|
||||
*/
|
||||
|
||||
void
|
||||
actionsDir1(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define ZERO_PAGE_ADDRESS_BIT 0x00
|
||||
#define NON_ZERO_PAGE_ADDRESS_BIT 0x08
|
||||
|
||||
if(class==EXPRESSION_OPND && isByteAddress(operand) &&
|
||||
isDefined(operand)){
|
||||
emitByte(binary | ZERO_PAGE_ADDRESS_BIT);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | NON_ZERO_PAGE_ADDRESS_BIT);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsDir2(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
if (wordCheck(address)) {
|
||||
emitByte(binary);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsDirIndir(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define DIRECT_ADDRESS_BIT 0x00
|
||||
#define INDIRECT_ADDRESS_BIT 0x20
|
||||
|
||||
if (wordCheck(address)) {
|
||||
if (class == INDIRECT_OPND)
|
||||
emitByte(binary | INDIRECT_ADDRESS_BIT);
|
||||
else
|
||||
emitByte(binary | DIRECT_ADDRESS_BIT);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsDirX1(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_X1 0x04
|
||||
#define A_REGISTER_BITS_X1 0x08
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_X1 0x0C
|
||||
#define X_INDEXED_ZERO_PAGE_BITS_X1 0x14
|
||||
#define X_INDEXED_NON_ZERO_PAGE_BITS_X1 0x1C
|
||||
|
||||
if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_X1);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_X1);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class==X_INDEXED_OPND || class==X_SELECTED_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | X_INDEXED_ZERO_PAGE_BITS_X1);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | X_INDEXED_NON_ZERO_PAGE_BITS_X1);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else {
|
||||
emitByte(binary | A_REGISTER_BITS_X1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsDirX2(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_X2 0x00
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_X2 0x08
|
||||
#define X_INDEXED_ZERO_PAGE_BITS_X2 0x10
|
||||
#define X_INDEXED_NON_ZERO_PAGE_BITS_X2 0x18
|
||||
|
||||
if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_X2);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_X2);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | X_INDEXED_ZERO_PAGE_BITS_X2);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | X_INDEXED_NON_ZERO_PAGE_BITS_X2);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsDirX3(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_X2);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_X2);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | X_INDEXED_ZERO_PAGE_BITS_X2);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsDirY(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_Y 0x00
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_Y 0x08
|
||||
#define Y_INDEXED_ZERO_PAGE_BITS_Y 0x10
|
||||
|
||||
if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_Y);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_Y);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | Y_INDEXED_ZERO_PAGE_BITS_Y);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsImmDir(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define IMMEDIATE_DATA_BITS_ID 0x00
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_ID 0x04
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_ID 0x0C
|
||||
|
||||
if (class == IMMEDIATE_OPND) {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | IMMEDIATE_DATA_BITS_ID);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
} else {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_ID);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_ID);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsImmDirX(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define IMMEDIATE_DATA_BITS_IX 0x00
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_IX 0x04
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_IX 0x0C
|
||||
#define X_INDEXED_ZERO_PAGE_BITS_IX 0x14
|
||||
#define X_INDEXED_NON_ZERO_PAGE_BITS_IX 0x1C
|
||||
|
||||
if (class == IMMEDIATE_OPND) {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | IMMEDIATE_DATA_BITS_IX);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
} else if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_IX);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_IX);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | X_INDEXED_ZERO_PAGE_BITS_IX);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | X_INDEXED_NON_ZERO_PAGE_BITS_IX);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsImmDirY(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define IMMEDIATE_DATA_BITS_IY 0x00
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_IY 0x04
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_IY 0x0C
|
||||
#define Y_INDEXED_ZERO_PAGE_BITS_IY 0x14
|
||||
#define Y_INDEXED_NON_ZERO_PAGE_BITS_IY 0x1C
|
||||
|
||||
if (class == IMMEDIATE_OPND) {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | IMMEDIATE_DATA_BITS_IY);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
} else if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_IY);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary|DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_IY);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | Y_INDEXED_ZERO_PAGE_BITS_IY);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | Y_INDEXED_NON_ZERO_PAGE_BITS_IY);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsImmIndex(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
#define PRE_INDEXED_BITS_A 0x00
|
||||
#define DIRECT_ADDRESS_ZERO_PAGE_BITS_A 0x04
|
||||
#define IMMEDIATE_DATA_BITS_A 0x08
|
||||
#define DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_A 0x0C
|
||||
#define POST_INDEXED_BITS_A 0x10
|
||||
#define X_INDEXED_ZERO_PAGE_BITS_A 0x14
|
||||
#define Y_INDEXED_NON_ZERO_PAGE_BITS_A 0x18
|
||||
#define X_INDEXED_NON_ZERO_PAGE_BITS_A 0x1C
|
||||
|
||||
if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_A);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary |DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_A);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class==X_INDEXED_OPND || class==X_SELECTED_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | X_INDEXED_ZERO_PAGE_BITS_A);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | X_INDEXED_NON_ZERO_PAGE_BITS_A);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class==Y_INDEXED_OPND || class==Y_SELECTED_OPND) {
|
||||
if (wordCheck(address)) {
|
||||
emitByte(binary | Y_INDEXED_NON_ZERO_PAGE_BITS_A);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class == IMMEDIATE_OPND) {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | IMMEDIATE_DATA_BITS_A);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
} else if (class == POST_INDEXED_Y_OPND) {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | POST_INDEXED_BITS_A);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
} else {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | PRE_INDEXED_BITS_A);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsIndex(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
if (class == EXPRESSION_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | DIRECT_ADDRESS_ZERO_PAGE_BITS_A);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary |DIRECT_ADDRESS_NON_ZERO_PAGE_BITS_A);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class==X_INDEXED_OPND || class==X_SELECTED_OPND) {
|
||||
if (isByteAddress(operand) && isDefined(operand)) {
|
||||
emitByte(binary | X_INDEXED_ZERO_PAGE_BITS_A);
|
||||
emitByte(address);
|
||||
} else if (wordCheck(address)) {
|
||||
emitByte(binary | X_INDEXED_NON_ZERO_PAGE_BITS_A);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class==Y_INDEXED_OPND || class==Y_SELECTED_OPND) {
|
||||
if (wordCheck(address)) {
|
||||
emitByte(binary | Y_INDEXED_NON_ZERO_PAGE_BITS_A);
|
||||
putFixupsHere(WORD_FIXUP, 0);
|
||||
emitWord(address);
|
||||
}
|
||||
} else if (class == POST_INDEXED_Y_OPND) {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | POST_INDEXED_BITS_A);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
} else {
|
||||
if (byteCheck(address)) {
|
||||
emitByte(binary | PRE_INDEXED_BITS_A);
|
||||
putFixupsHere(BYTE_FIXUP, 0);
|
||||
emitByte(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
actionsNone(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
emitByte(binary);
|
||||
}
|
||||
|
||||
void
|
||||
actionsRelative(opcode, numberOfOperands, evaluatedOperands)
|
||||
opcodeTableEntryType *opcode;
|
||||
int numberOfOperands;
|
||||
valueType *evaluatedOperands[];
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (operand->kindOfValue == UNDEFINED_VALUE || (currentCodeMode ==
|
||||
RELOCATABLE_BUFFER && targetOffset == 0))
|
||||
offset = 0;
|
||||
else
|
||||
offset = address - (currentLocationCounter.value - targetOffset) - 1;
|
||||
if (offset < 0)
|
||||
offset--;
|
||||
if (isByteOffset(offset)) {
|
||||
emitByte(binary);
|
||||
putFixupsHere(BYTE_RELATIVE_FIXUP, 0);
|
||||
emitByte(offset);
|
||||
} else {
|
||||
error(RELATIVE_OFFSET_TOO_LARGE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Miscellaneous helper predicates.
|
||||
*/
|
||||
|
||||
bool
|
||||
isByte(value)
|
||||
int value;
|
||||
{
|
||||
return (-129<value && value<256);
|
||||
}
|
||||
|
||||
bool
|
||||
isByteOffset(value)
|
||||
int value;
|
||||
{
|
||||
return (-129<value && value<128);
|
||||
}
|
||||
|
||||
bool
|
||||
isWordOffset(value)
|
||||
int value;
|
||||
{
|
||||
return (-32769<value && value<32768);
|
||||
}
|
||||
|
||||
bool
|
||||
isByteAddress(value)
|
||||
valueType *value;
|
||||
{
|
||||
return(value->kindOfValue==ABSOLUTE_VALUE && isByte(value->value));
|
||||
}
|
||||
|
||||
bool
|
||||
isWord(value)
|
||||
int value;
|
||||
{
|
||||
return (-32769<value && value<65536);
|
||||
}
|
||||
|
||||
bool
|
||||
byteCheck(value)
|
||||
int value;
|
||||
{
|
||||
if (isByte(value)) {
|
||||
return(TRUE);
|
||||
} else {
|
||||
error(BYTE_VALUE_TOO_LARGE_ERROR, value);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
wordCheck(value)
|
||||
int value;
|
||||
{
|
||||
if (isWord(value)) {
|
||||
return(TRUE);
|
||||
} else {
|
||||
printf("word: %d\n", value);
|
||||
error(WORD_VALUE_TOO_LARGE_ERROR, value);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
isDefined(value)
|
||||
valueType *value;
|
||||
{
|
||||
return(value!=NULL && value->kindOfValue!=UNDEFINED_VALUE);
|
||||
}
|
1089
actions_68000.c
Normal file
1089
actions_68000.c
Normal file
File diff suppressed because it is too large
Load Diff
547
buildStuff1.c
Normal file
547
buildStuff1.c
Normal file
@ -0,0 +1,547 @@
|
||||
/*
|
||||
buildStuff1.c -- Routines to build parse-tree structures for the
|
||||
Macross assembler. This module is target processor
|
||||
independent.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
1-November-1984
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
char *saveString();
|
||||
|
||||
/* Generic routine to create statement nodes */
|
||||
statementType *
|
||||
newStatement(kind, body)
|
||||
statementKindType kind;
|
||||
statementBodyType body;
|
||||
{
|
||||
statementType *result;
|
||||
|
||||
result = typeAlloc(statementType);
|
||||
result->kindOfStatement = kind;
|
||||
result->labels = NULL;
|
||||
result->statementBody = body;
|
||||
result->nextStatement = NULL;
|
||||
result->fileName = currentFileName;
|
||||
result->lineNumber = currentLineNumber;
|
||||
result->cumulativeLineNumber = cumulativeLineNumber;
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*
|
||||
These routines specifically build top-level parse-tree nodes corresponding
|
||||
to the different types of Macross statements. There is one such routine of
|
||||
the form "buildXxxxStatement" for each kind of Macross statement.
|
||||
*/
|
||||
|
||||
statementType *
|
||||
buildAlignStatement(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
return(newStatement(ALIGN_STATEMENT,
|
||||
(alignStatementBodyType *) expression));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildAssertStatement(condition, message)
|
||||
expressionType *condition;
|
||||
expressionType *message;
|
||||
{
|
||||
assertStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(assertStatementBodyType);
|
||||
|
||||
result->condition = condition;
|
||||
result->message = message;
|
||||
return(newStatement(ASSERT_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildBlockStatement(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
return(newStatement(BLOCK_STATEMENT,
|
||||
(blockStatementBodyType *) expressionList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildByteStatement(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
return(newStatement(BYTE_STATEMENT,
|
||||
(byteStatementBodyType *) expressionList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildConstrainStatement(expression, block)
|
||||
expressionType *expression;
|
||||
blockType *block;
|
||||
{
|
||||
constrainStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(constrainStatementBodyType);
|
||||
|
||||
result->constraint = expression;
|
||||
result->constrainedBlock = block;
|
||||
return(newStatement(CONSTRAIN_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildDbyteStatement(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
return(newStatement(DBYTE_STATEMENT,
|
||||
(dbyteStatementBodyType *) expressionList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildDefineStatement(name, value)
|
||||
stringType *name;
|
||||
expressionType *value;
|
||||
{
|
||||
defineStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(defineStatementBodyType);
|
||||
result->theSymbol = lookupOrEnterSymbol(name, UNKNOWN_SYMBOL);
|
||||
result->theValue = value;
|
||||
return(newStatement(DEFINE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildDoUntilStatement(body, condition)
|
||||
blockType *body;
|
||||
conditionType condition;
|
||||
{
|
||||
doUntilStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(doUntilStatementBodyType);
|
||||
result->doUntilCondition = condition;
|
||||
result->doUntilLoop = body;
|
||||
return(newStatement(DO_UNTIL_STATEMENT,result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildDoWhileStatement(body, condition)
|
||||
blockType *body;
|
||||
conditionType condition;
|
||||
{
|
||||
doWhileStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(doWhileStatementBodyType);
|
||||
result->doWhileCondition = condition;
|
||||
result->doWhileLoop = body;
|
||||
return(newStatement(DO_WHILE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildDoStatement(body, end)
|
||||
blockType *body;
|
||||
doEndType *end;
|
||||
{
|
||||
statementType *result;
|
||||
|
||||
if (end->doEndKind == UNTIL_END)
|
||||
result = buildDoUntilStatement(body, end->doEndCondition);
|
||||
else if (end->doEndKind == WHILE_END)
|
||||
result = buildDoWhileStatement(body, end->doEndCondition);
|
||||
else
|
||||
botch("bad do-end kind: %d\n", end->doEndCondition);
|
||||
qfree(end);
|
||||
return(result);
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildExternStatement(identifierList)
|
||||
identifierListType *identifierList;
|
||||
{
|
||||
return(newStatement(EXTERN_STATEMENT,
|
||||
(externStatementBodyType *) identifierList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildFreturnStatement(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
return(newStatement(FRETURN_STATEMENT,
|
||||
(freturnStatementBodyType *) expression));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildFunctionStatement(name, arguments, body)
|
||||
stringType *name;
|
||||
argumentDefinitionListType *arguments;
|
||||
blockType *body;
|
||||
{
|
||||
functionStatementBodyType *result;
|
||||
symbolTableEntryType *testSymbol;
|
||||
|
||||
testSymbol = lookupOrEnterSymbol(name, FUNCTION_SYMBOL);
|
||||
if (testSymbol->context->usage != FUNCTION_SYMBOL && testSymbol->
|
||||
context->usage != UNKNOWN_FUNCTION_SYMBOL) {
|
||||
error(SYMBOL_ALREADY_THERE_ERROR, symbName(testSymbol));
|
||||
return(NULL);
|
||||
}
|
||||
result = typeAlloc(functionStatementBodyType);
|
||||
result->functionName = saveString(name);
|
||||
result->theArguments = arguments;
|
||||
result->theBlock = body;
|
||||
return(newStatement(FUNCTION_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildGroupStatement(block)
|
||||
blockType *block;
|
||||
{
|
||||
return(newStatement(GROUP_STATEMENT,
|
||||
(groupStatementBodyType *) block));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildIfStatement(head, continuation, continuationKind)
|
||||
ifHeadType *head;
|
||||
ifContinuationType continuation;
|
||||
ifContinuationKindType continuationKind;
|
||||
{
|
||||
ifStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(ifStatementBodyType);
|
||||
|
||||
result->ifCondition = head->headCondition;
|
||||
result->consequence = head->headBody;
|
||||
if (continuationKind == NO_CONTINUATION)
|
||||
result->continuation.blockUnion = NULL;
|
||||
else if (continuationKind == ELSE_CONTINUATION) {
|
||||
result->continuation.continuationBodyUnion =
|
||||
typeAlloc(ifContinuationBodyType);
|
||||
result->continuation.continuationBodyUnion->ifCondition =
|
||||
ALWAYS_COND;
|
||||
result->continuation.continuationBodyUnion->consequence =
|
||||
continuation.blockUnion;
|
||||
result->continuation.continuationBodyUnion->
|
||||
continuation.continuationBodyUnion = NULL;
|
||||
} else if (continuationKind == ELSEIF_CONTINUATION)
|
||||
result->continuation = continuation;
|
||||
else
|
||||
botch("bad continuation kind: %d\n", continuationKind);
|
||||
qfree(head);
|
||||
return(newStatement(IF_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildIncludeStatement(filename)
|
||||
expressionType *filename;
|
||||
{
|
||||
return(newStatement(INCLUDE_STATEMENT,
|
||||
(includeStatementBodyType *) filename));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildInstructionStatement(opcode, operands)
|
||||
opcodeTableEntryType *opcode;
|
||||
operandListType *operands;
|
||||
{
|
||||
instructionStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(instructionStatementBodyType);
|
||||
result->kindOfInstruction = OPCODE_INSTRUCTION;
|
||||
result->theInstruction.opcodeUnion = opcode;
|
||||
result->theOperands = operands;
|
||||
return(newStatement(INSTRUCTION_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildLongStatement(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
return(newStatement(LONG_STATEMENT,
|
||||
(longStatementBodyType *) expressionList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMacroStatement(macro, arguments, body)
|
||||
macroTableEntryType *macro;
|
||||
argumentDefinitionListType *arguments;
|
||||
blockType *body;
|
||||
{
|
||||
macroStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(macroStatementBodyType);
|
||||
result->theMacro = macro;
|
||||
result->theArguments = arguments;
|
||||
result->theBlock = body;
|
||||
return(newStatement(MACRO_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMacroInstructionStatement(macro, operands)
|
||||
macroTableEntryType *macro;
|
||||
operandListType *operands;
|
||||
{
|
||||
instructionStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(instructionStatementBodyType);
|
||||
result->kindOfInstruction = MACRO_INSTRUCTION;
|
||||
result->theInstruction.macroUnion = macro;
|
||||
result->theOperands = operands;
|
||||
return(newStatement(INSTRUCTION_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMdefineStatement(name, value)
|
||||
stringType *name;
|
||||
expressionType *value;
|
||||
{
|
||||
mdefineStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mdefineStatementBodyType);
|
||||
result->theSymbol = lookupOrEnterSymbol(name, DEAD_SYMBOL);
|
||||
result->theValue = value;
|
||||
return(newStatement(MDEFINE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMdoUntilStatement(body, condition)
|
||||
blockType *body;
|
||||
ExpressionType *condition;
|
||||
{
|
||||
mdoUntilStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mdoUntilStatementBodyType);
|
||||
result->mdoUntilCondition = condition;
|
||||
result->mdoUntilLoop = body;
|
||||
return(newStatement(MDO_UNTIL_STATEMENT,result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMdoWhileStatement(body, condition)
|
||||
blockType *body;
|
||||
expressionType *condition;
|
||||
{
|
||||
mdoWhileStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mdoWhileStatementBodyType);
|
||||
result->mdoWhileCondition = condition;
|
||||
result->mdoWhileLoop = body;
|
||||
return(newStatement(MDO_WHILE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMdoStatement(body, end)
|
||||
blockType *body;
|
||||
doEndType *end;
|
||||
{
|
||||
statementType *result;
|
||||
|
||||
if (end->doEndKind == UNTIL_END)
|
||||
result = buildMdoUntilStatement(body, end->doEndCondition);
|
||||
else if (end->doEndKind == WHILE_END)
|
||||
result = buildMdoWhileStatement(body, end->doEndCondition);
|
||||
else
|
||||
botch("bad mdo-end kind: %d\n", end->doEndCondition);
|
||||
qfree(end);
|
||||
return(result);
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMforStatement(forExpressions, body)
|
||||
forExpressionsType *forExpressions;
|
||||
blockType *body;
|
||||
{
|
||||
mforStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mforStatementBodyType);
|
||||
result->initExpression = forExpressions->initExpression;
|
||||
result->testExpression = forExpressions->testExpression;
|
||||
result->incrExpression = forExpressions->incrExpression;
|
||||
result->forLoop = body;
|
||||
qfree(forExpressions);
|
||||
return(newStatement(MFOR_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMifStatement(head, continuation, continuationKind)
|
||||
mifHeadType *head;
|
||||
mifContinuationType continuation;
|
||||
ifContinuationKindType continuationKind;
|
||||
{
|
||||
mifStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mifStatementBodyType);
|
||||
|
||||
result->mifCondition = head->headCondition;
|
||||
result->mifConsequence = head->headBody;
|
||||
if (continuationKind == NO_CONTINUATION)
|
||||
result->mifContinuation.mifContinuationBodyUnion = NULL;
|
||||
else if (continuationKind == ELSE_CONTINUATION) {
|
||||
result->mifContinuation.mifContinuationBodyUnion =
|
||||
typeAlloc(mifContinuationBodyType);
|
||||
result->mifContinuation.mifContinuationBodyUnion->
|
||||
mifCondition = NULL;
|
||||
result->mifContinuation.mifContinuationBodyUnion->
|
||||
mifConsequence = continuation.mifBlockUnion;
|
||||
result->mifContinuation.mifContinuationBodyUnion->
|
||||
mifContinuation.mifContinuationBodyUnion = NULL;
|
||||
} else if (continuationKind == ELSEIF_CONTINUATION)
|
||||
result->mifContinuation = continuation;
|
||||
else
|
||||
botch("bad mif continuation kind: %d\n", continuationKind);
|
||||
qfree(head);
|
||||
return(newStatement(MIF_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMswitchStatement(switchExpression, cases)
|
||||
expressionType *switchExpression;
|
||||
caseListType *cases;
|
||||
{
|
||||
mswitchStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mswitchStatementBodyType);
|
||||
result->switchExpression = switchExpression;
|
||||
result->cases = cases;
|
||||
return(newStatement(MSWITCH_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMvariableStatement(name, value, dimension)
|
||||
stringType *name;
|
||||
expressionListType *value;
|
||||
expressionType *dimension;
|
||||
{
|
||||
mvariableStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mvariableStatementBodyType);
|
||||
result->theSymbol = lookupOrEnterSymbol(name, DEAD_SYMBOL);
|
||||
result->theValue = value;
|
||||
result->theDimension = dimension;
|
||||
return(newStatement(MVARIABLE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildMwhileStatement(condition, body)
|
||||
expressionType *condition;
|
||||
blockType *body;
|
||||
{
|
||||
mwhileStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(mwhileStatementBodyType);
|
||||
result->mwhileCondition = condition;
|
||||
result->mwhileLoop = body;
|
||||
return(newStatement(MWHILE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildNullStatement()
|
||||
{
|
||||
return(newStatement(NULL_STATEMENT, NULL));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildOrgStatement(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
return(newStatement(ORG_STATEMENT,
|
||||
(orgStatementBodyType *) expression));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildPerformStatement(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
return(newStatement(PERFORM_STATEMENT,
|
||||
(performStatementBodyType *) expression));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildRelStatement()
|
||||
{
|
||||
return(newStatement(REL_STATEMENT, NULL));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildStartStatement(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
return(newStatement(START_STATEMENT,
|
||||
(startStatementBodyType *) expression));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildStringStatement(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
return(newStatement(STRING_STATEMENT,
|
||||
(stringStatementBodyType *) expressionList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildStructStatement(name, body)
|
||||
symbolTableEntryType *name;
|
||||
blockType *body;
|
||||
{
|
||||
structStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(structStatementBodyType);
|
||||
result->structBody = body;
|
||||
result->structName = name;
|
||||
return(newStatement(STRUCT_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildTargetStatement(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
return(newStatement(TARGET_STATEMENT,
|
||||
(targetStatementBodyType *) expression));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildUndefineStatement(identifierList)
|
||||
identifierListType *identifierList;
|
||||
{
|
||||
return(newStatement(UNDEFINE_STATEMENT,
|
||||
(undefineStatementBodyType *) identifierList));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildVariableStatement(name, value, dimension)
|
||||
stringType *name;
|
||||
expressionListType *value;
|
||||
expressionType *dimension;
|
||||
{
|
||||
variableStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(variableStatementBodyType);
|
||||
result->theSymbol = lookupOrEnterSymbol(name, VARIABLE_SYMBOL);
|
||||
result->theValue = value;
|
||||
result->theDimension = dimension;
|
||||
return(newStatement(VARIABLE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildWhileStatement(condition, body)
|
||||
conditionType condition;
|
||||
blockType *body;
|
||||
{
|
||||
whileStatementBodyType *result;
|
||||
|
||||
result = typeAlloc(whileStatementBodyType);
|
||||
result->whileCondition = condition;
|
||||
result->whileLoop = body;
|
||||
return(newStatement(WHILE_STATEMENT, result));
|
||||
}
|
||||
|
||||
statementType *
|
||||
buildWordStatement(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
return(newStatement(WORD_STATEMENT,
|
||||
(wordStatementBodyType *) expressionList));
|
||||
}
|
||||
|
BIN
buildStuff1.o
Normal file
BIN
buildStuff1.o
Normal file
Binary file not shown.
358
buildStuff2.c
Normal file
358
buildStuff2.c
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
buildStuff2.c -- More routines to build parse-tree structures for the
|
||||
Macross assembler. This module is target processor
|
||||
independent.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
2-November-1984
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/*
|
||||
These are all the miscellaneous routines for building pieces of parse-tree
|
||||
structures.
|
||||
*/
|
||||
|
||||
|
||||
/* Fragments of statement structures */
|
||||
|
||||
caseType *
|
||||
buildCase(caseTags, caseBody)
|
||||
expressionListType *caseTags;
|
||||
blockType *caseBody;
|
||||
{
|
||||
caseType *result;
|
||||
|
||||
result = typeAlloc(caseType);
|
||||
result->caseTags = caseTags;
|
||||
result->caseBody = caseBody;
|
||||
return(result);
|
||||
}
|
||||
|
||||
doEndType *
|
||||
buildDoEnd(condition, kindOfDoEnd)
|
||||
conditionType condition;
|
||||
doEndKindType kindOfDoEnd;
|
||||
{
|
||||
doEndType *result;
|
||||
|
||||
result = typeAlloc(doEndType);
|
||||
result->doEndKind = kindOfDoEnd;
|
||||
result->doEndCondition = condition;
|
||||
return(result);
|
||||
}
|
||||
|
||||
forExpressionsType *
|
||||
buildForExpressions(initExpression, testExpression, incrExpression)
|
||||
expressionType *initExpression;
|
||||
expressionType *testExpression;
|
||||
expressionType *incrExpression;
|
||||
{
|
||||
forExpressionsType *result;
|
||||
|
||||
result = typeAlloc(forExpressionsType);
|
||||
result->initExpression = initExpression;
|
||||
result->testExpression = testExpression;
|
||||
result->incrExpression = incrExpression;
|
||||
return(result);
|
||||
}
|
||||
|
||||
ifHeadType *
|
||||
buildIfHead(condition, block)
|
||||
conditionType condition;
|
||||
blockType *block;
|
||||
{
|
||||
ifHeadType *result;
|
||||
|
||||
result = typeAlloc(ifHeadType);
|
||||
result->headCondition = condition;
|
||||
result->headBody = block;
|
||||
return(result);
|
||||
}
|
||||
|
||||
mdoEndType *
|
||||
buildMdoEnd(condition, kindOfMdoEnd)
|
||||
expressionType *condition;
|
||||
doEndKindType kindOfMdoEnd;
|
||||
{
|
||||
mdoEndType *result;
|
||||
|
||||
result = typeAlloc(mdoEndType);
|
||||
result->mdoEndKind = kindOfMdoEnd;
|
||||
result->mdoEndCondition = condition;
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
mifHeadType *
|
||||
buildMifHead(condition, block)
|
||||
expressionType *condition;
|
||||
blockType *block;
|
||||
{
|
||||
mifHeadType *result;
|
||||
|
||||
result = typeAlloc(mifHeadType);
|
||||
result->headCondition = condition;
|
||||
result->headBody = block;
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/* Fragments of expression structures */
|
||||
|
||||
arrayTermType *
|
||||
buildArrayTerm(array, index)
|
||||
expressionType *array;
|
||||
expressionType *index;
|
||||
{
|
||||
arrayTermType *result;
|
||||
|
||||
result = typeAlloc(arrayTermType);
|
||||
result->arrayName = array;
|
||||
result->arrayIndex = index;
|
||||
return(result);
|
||||
}
|
||||
|
||||
binopTermType *
|
||||
buildBinopTerm(binop, leftArgument, rightArgument)
|
||||
binopKindType binop;
|
||||
expressionType *leftArgument;
|
||||
expressionType *rightArgument;
|
||||
{
|
||||
binopTermType *result;
|
||||
|
||||
result = typeAlloc(binopTermType);
|
||||
result->binop = binop;
|
||||
result->leftArgument = leftArgument;
|
||||
result->rightArgument = rightArgument;
|
||||
return(result);
|
||||
}
|
||||
|
||||
functionCallTermType *
|
||||
buildFunctionCall(functionName, arguments)
|
||||
stringType *functionName;
|
||||
operandListType *arguments;
|
||||
{
|
||||
functionCallTermType *result;
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
|
||||
result = typeAlloc(functionCallTermType);
|
||||
result->functionName = lookupOrEnterSymbol(functionName,
|
||||
UNKNOWN_FUNCTION_SYMBOL);
|
||||
result->parameters = arguments;
|
||||
return(result);
|
||||
}
|
||||
|
||||
postOpTermType *
|
||||
buildPostOpTerm(postOp, postOpArgument)
|
||||
postOpKindType postOp;
|
||||
expressionType *postOpArgument;
|
||||
{
|
||||
postOpTermType *result;
|
||||
|
||||
result = typeAlloc(postOpTermType);
|
||||
result->postOp = postOp;
|
||||
result->postOpArgument = postOpArgument;
|
||||
return(result);
|
||||
}
|
||||
|
||||
preOpTermType *
|
||||
buildPreOpTerm(preOp, preOpArgument)
|
||||
preOpKindType preOp;
|
||||
expressionType *preOpArgument;
|
||||
{
|
||||
preOpTermType *result;
|
||||
|
||||
result = typeAlloc(preOpTermType);
|
||||
result->preOp = preOp;
|
||||
result->preOpArgument = preOpArgument;
|
||||
return(result);
|
||||
}
|
||||
|
||||
unopTermType *
|
||||
buildUnopTerm(unop, unopArgument)
|
||||
unopKindType unop;
|
||||
expressionType *unopArgument;
|
||||
{
|
||||
unopTermType *result;
|
||||
|
||||
result = typeAlloc(unopTermType);
|
||||
result->unop = unop;
|
||||
result->unopArgument = unopArgument;
|
||||
return(result);
|
||||
}
|
||||
|
||||
expressionTermType *
|
||||
buildExpressionTerm(kindOfExpressionTerm, arg1, arg2, arg3)
|
||||
expressionTermKindType kindOfExpressionTerm;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
expressionType *result;
|
||||
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
|
||||
result = typeAlloc(expressionType);
|
||||
result->kindOfTerm = kindOfExpressionTerm;
|
||||
switch (kindOfExpressionTerm) {
|
||||
|
||||
case IDENTIFIER_EXPR:
|
||||
result->expressionTerm.identifierUnion =
|
||||
(identifierTermType *) arg1;
|
||||
break;
|
||||
|
||||
case ARRAY_EXPR:
|
||||
result->expressionTerm.arrayUnion =
|
||||
buildArrayTerm((expressionType *) arg1,
|
||||
(expressionType *) arg2);
|
||||
break;
|
||||
|
||||
case FUNCTION_CALL_EXPR:
|
||||
result->expressionTerm.functionCallUnion =
|
||||
(functionCallTermType *) arg1;
|
||||
break;
|
||||
|
||||
case NUMBER_EXPR:
|
||||
result->expressionTerm.numberUnion = (numberTermType) arg1;
|
||||
break;
|
||||
|
||||
case STRING_EXPR:
|
||||
result->expressionTerm.stringUnion = (stringTermType *) arg1;
|
||||
break;
|
||||
|
||||
case SUBEXPRESSION_EXPR:
|
||||
result->expressionTerm.subexpressionUnion =
|
||||
(subexpressionTermType *) arg1;
|
||||
break;
|
||||
|
||||
case UNOP_EXPR:
|
||||
result->expressionTerm.unopUnion =
|
||||
buildUnopTerm((unopKindType) arg1,
|
||||
(expressionType *) arg2);
|
||||
break;
|
||||
|
||||
case ASSIGN_EXPR:
|
||||
case BINOP_EXPR:
|
||||
result->expressionTerm.binopUnion =
|
||||
buildBinopTerm((binopKindType) arg1,
|
||||
(expressionType *) arg2,
|
||||
(expressionType *) arg3);
|
||||
break;
|
||||
|
||||
case PREOP_EXPR:
|
||||
result->expressionTerm.preOpUnion =
|
||||
buildPreOpTerm((preOpKindType) arg1,
|
||||
(expressionType *) arg2);
|
||||
break;
|
||||
|
||||
case POSTOP_EXPR:
|
||||
result->expressionTerm.postOpUnion =
|
||||
buildPostOpTerm((postOpKindType) arg1,
|
||||
(expressionType *) arg2);
|
||||
break;
|
||||
|
||||
case HERE_EXPR:
|
||||
result->expressionTerm.hereUnion = (hereTermType *) NULL;
|
||||
break;
|
||||
|
||||
case CONDITION_CODE_EXPR:
|
||||
result->expressionTerm.conditionCodeUnion =
|
||||
(conditionCodeTermType) arg1;
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("invalid expression term kind: %d\n",
|
||||
kindOfExpressionTerm);
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/* Other stuff */
|
||||
|
||||
macroTableEntryType *
|
||||
buildMacroTableEntry(name)
|
||||
stringType *name;
|
||||
{
|
||||
macroTableEntryType *result;
|
||||
char *saveString();
|
||||
|
||||
result = typeAlloc(macroTableEntryType);
|
||||
result->macroName = saveString(name);
|
||||
result->nextMacro = NULL;
|
||||
result->arguments = NULL;
|
||||
result->body = NULL;
|
||||
return(result);
|
||||
}
|
||||
|
||||
symbolTableEntryType *
|
||||
buildSymbolTableEntry(name, usage)
|
||||
stringType *name;
|
||||
symbolUsageKindType usage;
|
||||
{
|
||||
symbolTableEntryType *result;
|
||||
char *saveString();
|
||||
|
||||
result = typeAlloc(symbolTableEntryType);
|
||||
result->symbolName = saveString(name);
|
||||
result->nextSymbol = NULL;
|
||||
result->context = typeAlloc(symbolInContextType);
|
||||
result->referenceCount = 0;
|
||||
dupValue(result->context->value, UndefinedValue);
|
||||
result->context->attributes = 0;
|
||||
result->context->referenceCount = 0;
|
||||
result->context->usage = usage;
|
||||
result->context->pushedContexts = NULL;
|
||||
result->context->environmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
|
||||
return(result);
|
||||
}
|
||||
|
||||
codeBreakType *
|
||||
buildCodeBreak(kind, address, data)
|
||||
codeBreakKindType kind;
|
||||
addressType address;
|
||||
int data;
|
||||
{
|
||||
codeBreakType *result;
|
||||
|
||||
result = typeAlloc(codeBreakType);
|
||||
result->kindOfBreak = kind;
|
||||
result->breakAddress = address;
|
||||
result->breakData = data;
|
||||
result->nextBreak = NULL;
|
||||
return(result);
|
||||
}
|
||||
|
||||
reservationListType *
|
||||
buildReservation(startAddress, blockSize, nextReservation)
|
||||
addressType startAddress;
|
||||
int blockSize;
|
||||
reservationListType *nextReservation;
|
||||
{
|
||||
reservationListType *result;
|
||||
|
||||
result = typeAlloc(reservationListType);
|
||||
result->startAddress = startAddress;
|
||||
result->blockSize = blockSize;
|
||||
result->nextReservation = nextReservation;
|
||||
return(result);
|
||||
}
|
||||
|
||||
simpleFixupListType *
|
||||
buildSimpleFixupList(locationToFixup, previousList)
|
||||
valueType locationToFixup;
|
||||
simpleFixupListType *previousList;
|
||||
{
|
||||
simpleFixupListType *result;
|
||||
|
||||
result = typeAlloc(simpleFixupListType);
|
||||
result->locationToFixup = locationToFixup;
|
||||
result->nextFixup = previousList;
|
||||
return(result);
|
||||
}
|
BIN
buildStuff2.o
Normal file
BIN
buildStuff2.o
Normal file
Binary file not shown.
232
buildStuff3.c
Normal file
232
buildStuff3.c
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
buildStuff3.c -- Still more routines to build parse-tree structures
|
||||
for the Macross assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
2-November-1984
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/*
|
||||
These routines all build list-type structures. Since yacc likes to build
|
||||
things left-recursively but we don't want lists to be backwards (which
|
||||
would then necessitate reversing them at some point -- yuck), we employ
|
||||
the ruse of substituting for the first element of a list a different
|
||||
struct which is identical to a normal one but contains an additional field
|
||||
for a pointer to the tail element of the list. We can then add things
|
||||
directly onto the tail as we like.
|
||||
*/
|
||||
|
||||
argumentListHeadType *
|
||||
buildArgumentList(new, rest, arrayTag)
|
||||
stringType *new;
|
||||
argumentListHeadType *rest;
|
||||
bool arrayTag;
|
||||
{
|
||||
argumentListHeadType *newListHead;
|
||||
argumentDefinitionListType *newArgument;
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
|
||||
if (rest == NULL) {
|
||||
newListHead = typeAlloc(argumentListHeadType);
|
||||
newListHead->theArgument = lookupOrEnterSymbol(new,
|
||||
DEAD_SYMBOL);
|
||||
newListHead->nextArgument = NULL;
|
||||
newListHead->tail = NULL;
|
||||
newListHead->arrayTag = arrayTag;
|
||||
return(newListHead);
|
||||
} else {
|
||||
newArgument = typeAlloc(argumentDefinitionListType);
|
||||
newArgument->theArgument = lookupOrEnterSymbol(new,
|
||||
DEAD_SYMBOL);
|
||||
newArgument->nextArgument = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextArgument = newArgument;
|
||||
else
|
||||
rest->nextArgument = newArgument;
|
||||
rest->tail = newArgument;
|
||||
rest->arrayTag = arrayTag;
|
||||
return(rest);
|
||||
}
|
||||
}
|
||||
|
||||
caseListHeadType *
|
||||
buildCaseList(new, rest)
|
||||
caseType *new;
|
||||
caseListHeadType *rest;
|
||||
{
|
||||
caseListHeadType *newListHead;
|
||||
caseListType *newCase;
|
||||
|
||||
if (rest == NULL) {
|
||||
newListHead = typeAlloc(caseListHeadType);
|
||||
newListHead->theCase = new;
|
||||
newListHead->nextCase = NULL;
|
||||
newListHead->tail = NULL;
|
||||
return(newListHead);
|
||||
} else {
|
||||
newCase = typeAlloc(caseListType);
|
||||
newCase->theCase = new;
|
||||
newCase->nextCase = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextCase = newCase;
|
||||
else
|
||||
rest->nextCase = newCase;
|
||||
rest->tail = newCase;
|
||||
return(rest);
|
||||
}
|
||||
}
|
||||
|
||||
expressionListHeadType *
|
||||
buildExpressionList(new, rest)
|
||||
expressionType *new;
|
||||
expressionListHeadType *rest;
|
||||
{
|
||||
expressionListHeadType *newListHead;
|
||||
expressionListType *newListEntry;
|
||||
|
||||
if (rest == NULL) {
|
||||
newListHead = typeAlloc(expressionListHeadType);
|
||||
newListHead->theExpression = new;
|
||||
newListHead->nextExpression = NULL;
|
||||
newListHead->tail = NULL;
|
||||
return(newListHead);
|
||||
} else {
|
||||
newListEntry = typeAlloc(expressionListType);
|
||||
newListEntry->theExpression = new;
|
||||
newListEntry->nextExpression = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextExpression = newListEntry;
|
||||
else
|
||||
rest->nextExpression = newListEntry;
|
||||
rest->tail = newListEntry;
|
||||
return(rest);
|
||||
}
|
||||
}
|
||||
|
||||
identifierListHeadType *
|
||||
buildIdentifierList(new, rest, usage)
|
||||
stringType *new;
|
||||
identifierListHeadType *rest;
|
||||
symbolUsageKindType usage;
|
||||
{
|
||||
identifierListType *newListEntry;
|
||||
identifierListHeadType *newListHead;
|
||||
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
|
||||
if (rest == NULL) {
|
||||
newListHead = typeAlloc(identifierListHeadType);
|
||||
newListHead->theSymbol = lookupOrEnterSymbol(new, usage);
|
||||
newListHead->nextIdentifier = NULL;
|
||||
newListHead->tail = NULL;
|
||||
return(newListHead);
|
||||
} else {
|
||||
newListEntry = typeAlloc(identifierListType);
|
||||
newListEntry->theSymbol = lookupOrEnterSymbol(new, usage);
|
||||
newListEntry->nextIdentifier = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextIdentifier = newListEntry;
|
||||
else
|
||||
rest->nextIdentifier = newListEntry;
|
||||
rest->tail = newListEntry;
|
||||
return(rest);
|
||||
}
|
||||
}
|
||||
|
||||
labelListHeadType *
|
||||
buildLabelList(new, rest)
|
||||
symbolTableEntryType *new;
|
||||
labelListHeadType *rest;
|
||||
{
|
||||
labelListHeadType *newLabelHead;
|
||||
labelListType *newLabel;
|
||||
|
||||
if (rest == NULL) {
|
||||
newLabelHead = typeAlloc(labelListHeadType);
|
||||
newLabelHead->theLabel = new;
|
||||
newLabelHead->nextLabel = NULL;
|
||||
newLabelHead->tail = NULL;
|
||||
return(newLabelHead);
|
||||
} else {
|
||||
newLabel = typeAlloc(labelListType);
|
||||
newLabel->theLabel = new;
|
||||
newLabel->nextLabel = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextLabel = newLabel;
|
||||
else
|
||||
rest->nextLabel = newLabel;
|
||||
rest->tail = newLabel;
|
||||
return(rest);
|
||||
}
|
||||
}
|
||||
|
||||
operandListHeadType *
|
||||
buildOperandList(new, rest)
|
||||
operandType *new;
|
||||
operandListHeadType *rest;
|
||||
{
|
||||
operandListHeadType *newListHead;
|
||||
|
||||
if (rest == NULL) {
|
||||
newListHead = typeAlloc(operandListHeadType);
|
||||
newListHead->kindOfOperand = new->kindOfOperand;
|
||||
newListHead->theOperand = new->theOperand;
|
||||
newListHead->nextOperand = NULL;
|
||||
newListHead->tail = NULL;
|
||||
qfree(new);
|
||||
return(newListHead);
|
||||
} else {
|
||||
new->nextOperand = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextOperand = new;
|
||||
else
|
||||
rest->nextOperand = new;
|
||||
rest->tail = new;
|
||||
return(rest);
|
||||
}
|
||||
}
|
||||
|
||||
selectionListHeadType *
|
||||
buildSelectionList(new, rest)
|
||||
selectionListType *new;
|
||||
selectionListHeadType *rest;
|
||||
{
|
||||
return((selectionListHeadType *) buildIdentifierList(new, rest));
|
||||
}
|
||||
|
||||
statementListHeadType *
|
||||
buildStatementList(new, rest)
|
||||
statementType *new;
|
||||
statementListHeadType *rest;
|
||||
{
|
||||
statementListHeadType *newListHead;
|
||||
|
||||
if (new == NULL)
|
||||
return(rest);
|
||||
if (rest == NULL) {
|
||||
newListHead = typeAlloc(statementListHeadType);
|
||||
newListHead->kindOfStatement = new->kindOfStatement;
|
||||
newListHead->labels = new->labels;
|
||||
newListHead->statementBody = new->statementBody;
|
||||
newListHead->lineNumber = new->lineNumber;
|
||||
newListHead->fileName = new->fileName;
|
||||
newListHead->cumulativeLineNumber = new->cumulativeLineNumber;
|
||||
newListHead->nextStatement = NULL;
|
||||
newListHead->tail = NULL;
|
||||
qfree(new);
|
||||
return(newListHead);
|
||||
} else {
|
||||
new->nextStatement = NULL;
|
||||
if (rest->tail != NULL)
|
||||
rest->tail->nextStatement = new;
|
||||
else
|
||||
rest->nextStatement = new;
|
||||
rest->tail = new;
|
||||
return(rest);
|
||||
}
|
||||
}
|
BIN
buildStuff3.o
Normal file
BIN
buildStuff3.o
Normal file
Binary file not shown.
1033
builtInFunctions.c
Normal file
1033
builtInFunctions.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
builtInFunctions.o
Normal file
BIN
builtInFunctions.o
Normal file
Binary file not shown.
BIN
builtInFunsSD.o
Normal file
BIN
builtInFunsSD.o
Normal file
Binary file not shown.
237
builtInFunsSD_6502.c
Normal file
237
builtInFunsSD_6502.c
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
builtInFunsSD_6502.c -- Code for target-processor dependent
|
||||
intrinsic user callable functions in the Macross assembler.
|
||||
(6502 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
23-April-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/* Helper functions, defined in builtInFunctions.c */
|
||||
valueType *makeBooleanValue();
|
||||
valueType *makeFailureValue();
|
||||
valueType *makeIntegerValue();
|
||||
valueType *makeOperandValue();
|
||||
valueType *makeStringValue();
|
||||
valueType *makeUndefinedValue();
|
||||
|
||||
|
||||
/* Check if operand is the accumulator */
|
||||
valueType *
|
||||
isARegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
A_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is DIRECT */
|
||||
valueType *
|
||||
isDirectModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
EXPRESSION_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is IMMEDIATE */
|
||||
valueType *
|
||||
isImmediateModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
IMMEDIATE_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is INDEXED (either X or Y) */
|
||||
valueType *
|
||||
isIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
X_INDEXED_OPND || evaluatedParameter->addressMode ==
|
||||
Y_INDEXED_OPND || evaluatedParameter->addressMode ==
|
||||
X_SELECTED_OPND || evaluatedParameter->addressMode ==
|
||||
Y_SELECTED_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is INDIRECT */
|
||||
valueType *
|
||||
isIndirectModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
INDIRECT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is POST-INDEXED */
|
||||
valueType *
|
||||
isPostIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
POST_INDEXED_Y_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is PRE-INDEXED */
|
||||
valueType *
|
||||
isPreIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
PRE_INDEXED_X_OPND || evaluatedParameter->
|
||||
addressMode == PRE_SELECTED_X_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is X-INDEXED */
|
||||
valueType *
|
||||
isXIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
X_INDEXED_OPND || evaluatedParameter->addressMode ==
|
||||
X_SELECTED_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand is the X index register */
|
||||
valueType *
|
||||
isXRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
X_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is Y-INDEXED */
|
||||
valueType *
|
||||
isYIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
Y_INDEXED_OPND || evaluatedParameter->addressMode ==
|
||||
Y_SELECTED_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand is the Y index register */
|
||||
valueType *
|
||||
isYRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(evaluatedParameter->addressMode ==
|
||||
Y_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
505
builtInFunsSD_68000.c
Normal file
505
builtInFunsSD_68000.c
Normal file
@ -0,0 +1,505 @@
|
||||
/*
|
||||
builtInFunsSD_68000.c -- Code for target-processor dependent
|
||||
intrinsic user callable functions in the Macross assembler.
|
||||
(68000 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
26-April-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/* Helper functions, defined in builtInFunctions.c */
|
||||
valueType *makeBooleanValue();
|
||||
valueType *makeFailureValue();
|
||||
valueType *makeIntegerValue();
|
||||
valueType *makeOperandValue();
|
||||
valueType *makeStringValue();
|
||||
valueType *makeUndefinedValue();
|
||||
|
||||
|
||||
/* Get address register component of operand */
|
||||
valueType *
|
||||
getAddressRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeIntegerValue(getAddressRegister(
|
||||
evaluatedParameter->addressMode)));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get data register component of operand */
|
||||
valueType *
|
||||
getDataRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeIntegerValue(getDataRegister(evaluatedParameter->
|
||||
addressMode)));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get index register component of operand */
|
||||
valueType *
|
||||
getIndexRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeIntegerValue(getIndexRegister(evaluatedParameter->
|
||||
addressMode)));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get register component of operand */
|
||||
valueType *
|
||||
getRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeIntegerValue(getRegister(evaluatedParameter->
|
||||
addressMode)));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get word/long component of operand */
|
||||
valueType *
|
||||
getWLBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeIntegerValue(getWL(evaluatedParameter->
|
||||
addressMode)));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is absolute */
|
||||
valueType *
|
||||
isAbsoluteModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == ABSOLUTE_SHORT_OPND ||
|
||||
operandKindField(evaluatedParameter->addressMode) ==
|
||||
ABSOLUTE_LONG_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is absolute long */
|
||||
valueType *
|
||||
isAbsoluteLongModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == ABSOLUTE_LONG_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is absolute short */
|
||||
valueType *
|
||||
isAbsoluteShortModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == ABSOLUTE_SHORT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is an address register */
|
||||
valueType *
|
||||
isARegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == A_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is the condition code register */
|
||||
valueType *
|
||||
isCCRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == CC_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is a control register */
|
||||
valueType *
|
||||
isControlRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == CONTROL_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is a data register */
|
||||
valueType *
|
||||
isDRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == D_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is DFC register */
|
||||
valueType *
|
||||
isDFCRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == CONTROL_REGISTER_OPND &&
|
||||
getRegister(evaluatedParameter->addressMode) ==
|
||||
DFC_REGISTER));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is displacement */
|
||||
valueType *
|
||||
isDisplacementModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == DISPLACEMENT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is IMMEDIATE */
|
||||
valueType *
|
||||
isImmediateModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == IMMEDIATE_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is indexed */
|
||||
valueType *
|
||||
isIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == INDEXED_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is indirect */
|
||||
valueType *
|
||||
isIndirectModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == A_REGISTER_INDIRECT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is pc displacement */
|
||||
valueType *
|
||||
isPCDisplacementModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == PC_DISPLACEMENT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is pc indexed */
|
||||
valueType *
|
||||
isPCIndexedModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == PC_INDEXED_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is postincrement */
|
||||
valueType *
|
||||
isPostincrementModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == POSTINCREMENT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand's address mode is predecrement */
|
||||
valueType *
|
||||
isPredecrementModeBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == PREDECREMENT_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is SFC register */
|
||||
valueType *
|
||||
isSFCRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == CONTROL_REGISTER_OPND &&
|
||||
getRegister(evaluatedParameter->addressMode) ==
|
||||
SFC_REGISTER));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is the status register */
|
||||
valueType *
|
||||
isStatusRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == STATUS_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is user stack pointer */
|
||||
valueType *
|
||||
isUSPBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == USP_REGISTER_OPND));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if operand is VB register */
|
||||
valueType *
|
||||
isVBRegisterBIF(parameterList, kindOfFixup)
|
||||
operandListType *parameterList;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
valueType *evaluatedParameter;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
|
||||
if (parameterList != NULL) {
|
||||
evaluatedParameter = evaluateOperand(parameterList, NO_FIXUP);
|
||||
return(makeBooleanValue(operandKindField(evaluatedParameter->
|
||||
addressMode) == CONTROL_REGISTER_OPND &&
|
||||
getRegister(evaluatedParameter->addressMode) ==
|
||||
VBR_REGISTER));
|
||||
} else {
|
||||
return(makeBooleanValue(FALSE));
|
||||
}
|
||||
}
|
19
conditionDefs_6502.h
Normal file
19
conditionDefs_6502.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
conditionDefs_6502.h -- Define types for 6502 branch condition codes.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
18-April-1985
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CARRY_COND, ZERO_COND, NEGATIVE_COND, OVERFLOW_COND, LT_COND,
|
||||
LEQ_COND, SLT_COND, SLEQ_COND,
|
||||
ALWAYS_COND,
|
||||
NOT_CARRY_COND, NOT_ZERO_COND, NOT_NEGATIVE_COND,
|
||||
NOT_OVERFLOW_COND, GEQ_COND, GT_COND, SGEQ_COND, SGT_COND,
|
||||
NEVER_COND,
|
||||
NOT_FOUND_COND,
|
||||
} conditionType;
|
||||
|
||||
#define COMPOUND_BRANCH_MAX 3
|
20
conditionDefs_68000.h
Normal file
20
conditionDefs_68000.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
conditionDefs_68000.h -- Define types for 68000 condition codes.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
25-April-1985
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CARRY_COND, EQUAL_COND, OVERFLOW_COND, MINUS_COND, LT_COND,
|
||||
LEQ_COND, LOW_OR_SAME_COND,
|
||||
ALWAYS_COND,
|
||||
NOT_CARRY_COND, NOT_EQUAL_COND, NOT_OVERFLOW_COND, PLUS_COND,
|
||||
GEQ_COND, GT_COND, HIGH_COND,
|
||||
NEVER_COND,
|
||||
NOT_FOUND_COND,
|
||||
} conditionType;
|
||||
|
||||
#define COMPOUND_BRANCH_MAX 1
|
||||
|
1200
debugPrint.c
Normal file
1200
debugPrint.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
debugPrint.o
Normal file
BIN
debugPrint.o
Normal file
Binary file not shown.
BIN
debugPrintSD.o
Normal file
BIN
debugPrintSD.o
Normal file
Binary file not shown.
249
debugPrintSD_6502.c
Normal file
249
debugPrintSD_6502.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
debugPrintSD_6502.c -- Routines to print out things for debugging
|
||||
purposes (system dependent routines, 6502 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
23-April-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
|
||||
int tablevel;
|
||||
|
||||
/* Fundamental nop print operation */
|
||||
#define nullPrint(thing) if (thing==NULL) { tab(); printf("()\n"); return; }
|
||||
|
||||
void
|
||||
printCondition(condition)
|
||||
conditionType condition;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'conditionType'. */
|
||||
static char *conditionTable[] = {
|
||||
"carry",
|
||||
"zero",
|
||||
"negative",
|
||||
"overflow",
|
||||
"lt",
|
||||
"leq",
|
||||
"slt",
|
||||
"sleq",
|
||||
"always",
|
||||
"!carry",
|
||||
"!zero",
|
||||
"!negative",
|
||||
"!overflow",
|
||||
"geq",
|
||||
"gt",
|
||||
"sgeq",
|
||||
"sgt",
|
||||
"never",
|
||||
};
|
||||
|
||||
printf("%s", conditionTable[(int)condition]);
|
||||
}
|
||||
|
||||
void
|
||||
printOperandKind(kind)
|
||||
operandKindType kind;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'operandKindType'. */
|
||||
static char *operandKindTable[] = {
|
||||
"expression opnd",
|
||||
"immediate opnd",
|
||||
"indirect opnd",
|
||||
"a register opnd",
|
||||
"x register opnd",
|
||||
"y register opnd",
|
||||
"post indexed y opnd",
|
||||
"pre indexed x opnd",
|
||||
"x indexed opnd",
|
||||
"y indexed opnd",
|
||||
"x selected opnd",
|
||||
"y selected opnd",
|
||||
"pre selected x opnd",
|
||||
"string opnd",
|
||||
"block opnd",
|
||||
};
|
||||
|
||||
printf("%s", operandKindTable[(int)kind]);
|
||||
}
|
||||
|
||||
void
|
||||
printToken(token)
|
||||
int token;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the set of '#define's in
|
||||
the file 'y.tab.h' as produced by yacc. */
|
||||
static char *tokenTable[] = {
|
||||
"A",
|
||||
"ALIGN",
|
||||
"ASSERT",
|
||||
"BLOCK",
|
||||
"BYTE",
|
||||
"CONSTRAIN",
|
||||
"DBYTE",
|
||||
"DEFINE",
|
||||
"DO",
|
||||
"ELSE",
|
||||
"ELSEIF",
|
||||
"ENDFILE",
|
||||
"EOL",
|
||||
"EXTERN",
|
||||
"FRETURN",
|
||||
"FUNCTION",
|
||||
"HERE",
|
||||
"IF",
|
||||
"INCLUDE",
|
||||
"LONG",
|
||||
"MACRO",
|
||||
"MCASE",
|
||||
"MDEFAULT",
|
||||
"MDEFINE",
|
||||
"MDO",
|
||||
"MELSE",
|
||||
"MELSEIF",
|
||||
"MFOR",
|
||||
"MIF",
|
||||
"MSWITCH",
|
||||
"MUNTIL",
|
||||
"MVARIABLE",
|
||||
"MWHILE",
|
||||
"ORG",
|
||||
"REL",
|
||||
"START",
|
||||
"STRING",
|
||||
"STRUCT",
|
||||
"TARGET",
|
||||
"UNDEFINE",
|
||||
"UNTIL",
|
||||
"VARIABLE",
|
||||
"WHILE",
|
||||
"WORD",
|
||||
"X",
|
||||
"Y",
|
||||
"ConditionCode",
|
||||
"Identifier",
|
||||
"MacroName",
|
||||
"Number",
|
||||
"Opcode",
|
||||
"TextString",
|
||||
"ASSIGN",
|
||||
"LOGICAL_OR",
|
||||
"LOGICAL_XOR",
|
||||
"LOGICAL_AND",
|
||||
"BITWISE_OR",
|
||||
"BITWISE_XOR",
|
||||
"BITWISE_AND",
|
||||
"EQUAL_TO",
|
||||
"NOT_EQUAL_TO",
|
||||
"LESS_THAN",
|
||||
"LESS_THAN_OR_EQUAL_TO",
|
||||
"GREATER_THAN",
|
||||
"GREATER_THAN_OR_EQUAL_TO",
|
||||
"LEFT_SHIFT",
|
||||
"RIGHT_SHIFT",
|
||||
"ADD",
|
||||
"SUB",
|
||||
"MUL",
|
||||
"DIV",
|
||||
"MOD",
|
||||
"UNARY_MINUS",
|
||||
"LOGICAL_NOT",
|
||||
"BITWISE_NOT",
|
||||
"HI_BYTE",
|
||||
"LO_BYTE",
|
||||
"SELECT",
|
||||
"INCREMENT",
|
||||
"DECREMENT",
|
||||
};
|
||||
|
||||
if (token >= A) {
|
||||
printf("%s", tokenTable[token - A]);
|
||||
} else {
|
||||
printf("'%c'", token);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
nullPrint(operand);
|
||||
tab(); printf("(operand: [");
|
||||
printOperandKind(operand->kindOfOperand);
|
||||
printf("]\n");
|
||||
tablevel++;
|
||||
switch (operand->kindOfOperand) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case IMMEDIATE_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case INDIRECT_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
break;
|
||||
|
||||
case X_REGISTER_OPND:
|
||||
break;
|
||||
|
||||
case Y_REGISTER_OPND:
|
||||
break;
|
||||
|
||||
case POST_INDEXED_Y_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case PRE_INDEXED_X_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case X_INDEXED_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case Y_INDEXED_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case X_SELECTED_OPND:
|
||||
printIdentifierList(operand->theOperand);
|
||||
break;
|
||||
|
||||
case Y_SELECTED_OPND:
|
||||
printIdentifierList(operand->theOperand);
|
||||
break;
|
||||
|
||||
case PRE_SELECTED_X_OPND:
|
||||
printIdentifierList(operand->theOperand);
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
tab(); printf("(string: \"%s\")\n", operand->theOperand);
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
printBlock(operand->theOperand);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("fooey: bad operand kind %d\n", operand->
|
||||
kindOfOperand);
|
||||
break;
|
||||
}
|
||||
tablevel--;
|
||||
tab(); printf(")\n");
|
||||
}
|
309
debugPrintSD_68000.c
Normal file
309
debugPrintSD_68000.c
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
debugPrintSD_68000.c -- Routines to print out things for debugging
|
||||
purposes (system dependent routines, 68000 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
26-April-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
|
||||
int tablevel;
|
||||
|
||||
/* Fundamental nop print operation */
|
||||
#define nullPrint(thing) if (thing==NULL) { tab(); printf("()\n"); return; }
|
||||
|
||||
void
|
||||
printCondition(condition)
|
||||
conditionType condition;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'conditionType'. */
|
||||
static char *conditionTable[] = {
|
||||
"carry",
|
||||
"equal",
|
||||
"overflow",
|
||||
"minus",
|
||||
"lt",
|
||||
"leq",
|
||||
"ls",
|
||||
"always",
|
||||
"!carry",
|
||||
"!equal",
|
||||
"!overflow",
|
||||
"plus",
|
||||
"geq",
|
||||
"gt",
|
||||
"high",
|
||||
"never",
|
||||
};
|
||||
|
||||
printf("%s", conditionTable[(int)condition]);
|
||||
}
|
||||
|
||||
void
|
||||
printRegister(reg)
|
||||
int reg;
|
||||
{
|
||||
if (reg < 8)
|
||||
printf(" a%d", reg);
|
||||
else
|
||||
printf(" d%d", reg - 8);
|
||||
}
|
||||
|
||||
void
|
||||
printControlRegister(reg)
|
||||
int reg;
|
||||
{
|
||||
switch (reg) {
|
||||
case SFC_REGISTER: printf("sfc"); break;
|
||||
case DFC_REGISTER: printf("dfc"); break;
|
||||
case VBR_REGISTER: printf("vbr"); break;
|
||||
default: botch("Bad control register %d\n", reg); break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printOperandKind(kind)
|
||||
operandKindType kind;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'operandKindType'. */
|
||||
static char *operandKindTable[] = {
|
||||
"expression opnd",
|
||||
"string opnd",
|
||||
"block opnd",
|
||||
"data register opnd",
|
||||
"address register opnd",
|
||||
"address register indirect opnd",
|
||||
"postincrement opnd",
|
||||
"predecrement opnd",
|
||||
"displacement opnd",
|
||||
"indexed opnd",
|
||||
"program counter displacement opnd",
|
||||
"program counter indexed opnd",
|
||||
"immediate opnd",
|
||||
"absolute short opnd",
|
||||
"absolute long opnd",
|
||||
"condition code register opnd",
|
||||
"status register opnd",
|
||||
"user stack pointer opnd",
|
||||
"control register opnd",
|
||||
};
|
||||
|
||||
printf("%s", operandKindTable[(int)operandKindField(kind)]);
|
||||
if (isRegisterOperand(kind))
|
||||
printRegister(getRegister(kind));
|
||||
if (isControlRegisterOperand(kind))
|
||||
printControlRegister(getRegister(kind));
|
||||
if (isIndexedOperand(kind))
|
||||
printRegister(getIndexRegister(kind));
|
||||
}
|
||||
|
||||
bool
|
||||
isRegisterOperand(kind)
|
||||
operandKindType kind;
|
||||
{
|
||||
kind = operandKindField(kind);
|
||||
return(kind==D_REGISTER_OPND || kind==A_REGISTER_OPND ||
|
||||
kind==A_REGISTER_INDIRECT_OPND || kind==POSTINCREMENT_OPND ||
|
||||
kind==PREDECREMENT_OPND || kind==DISPLACEMENT_OPND ||
|
||||
kind==INDEXED_OPND || kind==SELECTED_OPND ||
|
||||
kind==INDEX_SELECTED_OPND);
|
||||
}
|
||||
|
||||
bool
|
||||
isIndexedOperand(kind)
|
||||
operandKindType kind;
|
||||
{
|
||||
kind = operandKindField(kind);
|
||||
return(kind==INDEXED_OPND || kind==PC_INDEXED_OPND || kind==
|
||||
INDEX_SELECTED_OPND);
|
||||
}
|
||||
|
||||
bool
|
||||
isControlRegisterOperand(kind)
|
||||
operandKindType kind;
|
||||
{
|
||||
return(operandKindField(kind) == CONTROL_REGISTER_OPND);
|
||||
}
|
||||
|
||||
void
|
||||
printToken(token)
|
||||
int token;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the set of '#define's in
|
||||
the file 'y.tab.h' as produced by yacc. */
|
||||
static char *tokenTable[] = {
|
||||
"A0",
|
||||
"A1",
|
||||
"A2",
|
||||
"A3",
|
||||
"A4",
|
||||
"A5",
|
||||
"A6",
|
||||
"A7",
|
||||
"ALIGN",
|
||||
"ASSERT",
|
||||
"BLOCK",
|
||||
"BYTE",
|
||||
"CCR",
|
||||
"CONSTRAIN",
|
||||
"D0",
|
||||
"D1",
|
||||
"D2",
|
||||
"D3",
|
||||
"D4",
|
||||
"D5",
|
||||
"D6",
|
||||
"D7",
|
||||
"DBYTE",
|
||||
"DEFINE",
|
||||
"DFC",
|
||||
"DO",
|
||||
"ELSE",
|
||||
"ELSEIF",
|
||||
"ENDFILE",
|
||||
"EOL",
|
||||
"EXTERN",
|
||||
"FRETURN",
|
||||
"FUNCTION",
|
||||
"HERE",
|
||||
"IF",
|
||||
"INCLUDE",
|
||||
"L",
|
||||
"LONG",
|
||||
"MACRO",
|
||||
"MCASE",
|
||||
"MDEFAULT",
|
||||
"MDEFINE",
|
||||
"MDO",
|
||||
"MELSE",
|
||||
"MELSEIF",
|
||||
"MFOR",
|
||||
"MIF",
|
||||
"MSWITCH",
|
||||
"MUNTIL",
|
||||
"MVARIABLE",
|
||||
"MWHILE",
|
||||
"ORG",
|
||||
"PC",
|
||||
"REL",
|
||||
"SFC",
|
||||
"SR",
|
||||
"START",
|
||||
"STRING",
|
||||
"STRUCT",
|
||||
"TARGET",
|
||||
"UNDEFINE",
|
||||
"UNTIL",
|
||||
"USP",
|
||||
"VARIABLE",
|
||||
"VBR",
|
||||
"W",
|
||||
"WHILE",
|
||||
"WORD",
|
||||
"X",
|
||||
"Y",
|
||||
"ConditionCode",
|
||||
"Identifier",
|
||||
"MacroName",
|
||||
"Number",
|
||||
"Opcode",
|
||||
"TextString",
|
||||
"ASSIGN",
|
||||
"LOGICAL_OR",
|
||||
"LOGICAL_XOR",
|
||||
"LOGICAL_AND",
|
||||
"BITWISE_OR",
|
||||
"BITWISE_XOR",
|
||||
"BITWISE_AND",
|
||||
"EQUAL_TO",
|
||||
"NOT_EQUAL_TO",
|
||||
"LESS_THAN",
|
||||
"LESS_THAN_OR_EQUAL_TO",
|
||||
"GREATER_THAN",
|
||||
"GREATER_THAN_OR_EQUAL_TO",
|
||||
"LEFT_SHIFT",
|
||||
"RIGHT_SHIFT",
|
||||
"ADD",
|
||||
"SUB",
|
||||
"MUL",
|
||||
"DIV",
|
||||
"MOD",
|
||||
"UNARY_MINUS",
|
||||
"LOGICAL_NOT",
|
||||
"BITWISE_NOT",
|
||||
"HI_BYTE",
|
||||
"LO_BYTE",
|
||||
"SELECT",
|
||||
"INCREMENT",
|
||||
"DECREMENT",
|
||||
};
|
||||
|
||||
if (token >= A0) {
|
||||
printf("%s", tokenTable[token - A0]);
|
||||
} else {
|
||||
printf("'%c'", token);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
nullPrint(operand);
|
||||
tab(); printf("(operand: [");
|
||||
printOperandKind(operand->kindOfOperand);
|
||||
printf("]\n");
|
||||
tablevel++;
|
||||
switch (operand->kindOfOperand) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
case DISPLACEMENT_OPND:
|
||||
case INDEXED_OPND:
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
case PC_INDEXED_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
printExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case D_REGISTER_OPND:
|
||||
case A_REGISTER_OPND:
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
case POSTINCREMENT_OPND:
|
||||
case PREDECREMENT_OPND:
|
||||
case CC_REGISTER_OPND:
|
||||
case STATUS_REGISTER_OPND:
|
||||
case USP_REGISTER_OPND:
|
||||
case CONTROL_REGISTER_OPND:
|
||||
break;
|
||||
|
||||
case SELECTED_OPND:
|
||||
case INDEX_SELECTED_OPND:
|
||||
printIdentifierList(operand->theOperand);
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
tab(); printf("(string: \"%s\")\n", operand->theOperand);
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
printBlock(operand->theOperand);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("fooey: bad operand kind %d\n", operand->
|
||||
kindOfOperand);
|
||||
break;
|
||||
}
|
||||
tablevel--;
|
||||
tab(); printf(")\n");
|
||||
}
|
463
doc/genmacros.itr
Normal file
463
doc/genmacros.itr
Normal file
@ -0,0 +1,463 @@
|
||||
.TL
|
||||
\s+9genmacros.m\s-9
|
||||
.AU
|
||||
a macro library for use with the 6502 version of Macross
|
||||
.AI
|
||||
Lucasfilm Ltd. Games Division
|
||||
\\*(DY
|
||||
.ds LH genmacros.m
|
||||
.ds CH \\*(DY
|
||||
.ds RH Reference Manual
|
||||
.ds LF Lucasfilm Ltd. Proprietary Information
|
||||
.ds CF - % -
|
||||
.ds RF CONFIDENTIAL
|
||||
.PP
|
||||
These macros have been concocted by various people for the convenience and
|
||||
amusement of those programming the 6502 using \fIMacross\fR. The will be
|
||||
found in the file \fB/u1/gg/lib/6502/genmacros.m\fR. To use them, insert the
|
||||
following statement somewhere near the beginning of your \fIMacross\fR
|
||||
program:
|
||||
.nf
|
||||
|
||||
\fBinclude "/u1/gg/lib/6502/genmacros.m"\fR
|
||||
|
||||
.fi
|
||||
Easy, no? What follows is a summary of the macros, grouped roughly by
|
||||
category.
|
||||
.sp 1
|
||||
.SH
|
||||
\s+2Macros to save and restore registers\s-2
|
||||
.nf
|
||||
|
||||
\fBphr\fR
|
||||
.fi
|
||||
.IP
|
||||
Push all registers (i.e., the accumulator and the X and Y index registers)
|
||||
onto the stack.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBplr\fR
|
||||
.fi
|
||||
.IP
|
||||
Pull the registers (the accumulator and the X and Y index registers) off the
|
||||
stack.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBphx\fR
|
||||
.fi
|
||||
.IP
|
||||
Push the X register onto the stack.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBplx\fR
|
||||
.fi
|
||||
.IP
|
||||
Pull the X register off of the stack.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBphy\fR
|
||||
.fi
|
||||
.IP
|
||||
Push the Y register onto the stack.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBply\fR
|
||||
.fi
|
||||
.IP
|
||||
Pull the Y register off of the stack.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBpushaddr \fIaddress\fR
|
||||
.fi
|
||||
.IP
|
||||
Push \fIaddress\fR onto the stack to \fBrts\fR to.
|
||||
.sp 1
|
||||
.SH
|
||||
\s+2Macros to move data around with\s-2
|
||||
.PP
|
||||
These macros provide an address mode independent method of moving bytes from
|
||||
one place to another. The source and destination arguments of these macros
|
||||
may, generally speaking, be in any address mode you desire (except, of course,
|
||||
that the destination can't be immediate mode!).
|
||||
.nf
|
||||
|
||||
\fBmovm \fIn\fB, \fIdest\fB, \fIsrc\fR
|
||||
.fi
|
||||
.IP
|
||||
Move multiple \(em move \fIn\fR bytes from \fIsrc\fR to \fIdest\fR. The bytes
|
||||
are moved using the accumulator as an intermediary.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovmx \fIn\fB, \fIdest\fB, \fIsrc\fR
|
||||
.fi
|
||||
.IP
|
||||
Move multiple \(em move \fIn\fR bytes from \fIsrc\fR to \fIdest\fR. The bytes
|
||||
are moved using the X register as an intermediary.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovmy \fIn\fB, \fIdest\fB, \fIsrc\fR
|
||||
.fi
|
||||
.IP
|
||||
Move multiple \(em move \fIn\fR bytes from \fIsrc\fR to \fIdest\fR. The bytes
|
||||
are moved using the Y register as an intermediary.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmv2m \fIn\fB, \fIdest1\fB, \fIdest2\fB, \fIsrc\fR
|
||||
.fi
|
||||
.IP
|
||||
Move multiple to two destinations \(em move \fIn\fR bytes from \fIsrc\fR to
|
||||
both \fIdest1\fR and \fIdest2\fR. The bytes are moved using the acuumulator
|
||||
as an intermediary.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmoveb \fIsrc\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Move byte \(em move one byte from \fIsrc\fR to \fIdest\fR via the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovew \fIsrc\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Move word \(em move one word from \fIsrc\fR to \fIdest\fR via the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovexb \fIsrc\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Move byte \(em move one byte from \fIsrc\fR to \fIdest\fR via the X register.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovexw \fIsrc\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Move word \(em move one word from \fIsrc\fR to \fIdest\fR via the X register.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmoveyb \fIsrc\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Move byte \(em move one byte from \fIsrc\fR to \fIdest\fR via the Y register.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmoveyw \fIsrc\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Move word \(em move one word from \fIsrc\fR to \fIdest\fR via the Y register.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovb \fIdest\fB, \fIsrc\fR
|
||||
.fi
|
||||
.IP
|
||||
Move byte \(em move one byte from \fIsrc\fR to \fIdest\fR via the accumulator.
|
||||
This is distinguished from \fBmoveb\fR in that it has the order of the
|
||||
operands reversed. This confusing feature is provided for compatibility with
|
||||
\fBa65\fR.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBmovw \fIdest\fB, \fIsrc\fR
|
||||
.fi
|
||||
.IP
|
||||
Move word \(em move one word from \fIsrc\fR to \fIdest\fR via the accumulator.
|
||||
This is distinguished from \fBmovew\fR in that it has the order of the
|
||||
operands reversed. This confusing feature is provided for compatibility with
|
||||
\fBa65\fR.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBclrm \fIn\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Clear multiple \(em clears (zeros) \fIn\fR bytes starting at \fIdest\fR.
|
||||
Leaves a zero in the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBclrb \fIdest\fR
|
||||
\fBclearb \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Clear byte \(em clears (zeros) one byte at \fIdest\fR. Leaves a zero in the
|
||||
accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBclrw \fIdest\fR
|
||||
\fBclearw \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Clear word \(em clears (zeros) one word at \fIdest\fR. Leaves a zero in the
|
||||
accumulator.
|
||||
.sp 1
|
||||
.SH
|
||||
\s+2Arithmetic macros\s-2
|
||||
.nf
|
||||
|
||||
\fBaddm \fIn\fB, \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Add multiple \(em adds the \fIn\fR byte numbers found at \fIsrc1\fR and
|
||||
\fIsrc2\fR and puts the result at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBaddb \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Add byte \(em adds the one byte numbers \fIsrc1\fR and \fIsrc2\fR and puts the
|
||||
one byte result in \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBaddw \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Add word \(em adds the two byte numbers \fIsrc1\fR and \fIsrc2\fR and puts the
|
||||
two byte result in \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBsubm \fIn\fB, \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Subtract multiple \(em subtracts the \fIn\fR byte number found at \fIsrc2\fR
|
||||
from the same sized number found at \fIsrc1\fR and puts the \fIn\fR byte
|
||||
result in \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBsubb \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Subtract byte \(em subtracts the one byte number \fIsrc2\fR from \fIsrc1\fR
|
||||
and puts the one byte result in \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBsubw \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Subtract word \(em subtracts the two byte numbers \fIsrc2\fR from \fIsrc1\fR
|
||||
and puts the two byte result in \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBcmpm \fIn\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Compare multiple \(em compares the two \fIn\fR byte numbers found at
|
||||
\fIsrc1\fR and \fIsrc2\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBcmpb \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Compare byte \(em compares the one byte numbers \fIsrc1\fR and \fIsrc2\fR.
|
||||
Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBcmpw \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
||||
.IP
|
||||
Compare word \(em compares the two byte numbers \fIsrc1\fR and \fIsrc2\fR.
|
||||
Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBnegm \fIn\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Negate multiple \(em negates the \fIn\fR byte number at \fIdest\fR. Clobbers
|
||||
the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBnegb \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Negate byte \(em negates the one byte number at \fIdest\fR. Clobbers the
|
||||
accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBnegw \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Negate word \(em negates the two byte number at \fIdest\fR. Clobbers the
|
||||
accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBasrm \fIn\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Arithmetic shift right multiple \(em performs a rightward one-bit arithmetic
|
||||
shift of the \fIn\fR byte number at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBasrb \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Arithmetic shift right byte \(em performs a rightward one-bit arithmetic
|
||||
shift of the byte at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBasrw \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Arithmetic shift right word \(em performs a rightward one-bit arithmetic
|
||||
shift of the word at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBaslm \fIn\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Arithmetic shift left multiple \(em performs a leftward one-bit arithmetic
|
||||
shift of the \fIn\fR byte number at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBaslb \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Arithmetic shift left byte \(em performs a leftward one-bit arithmetic
|
||||
shift of the byte at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBaslw \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Arithmetic shift left word \(em performs a leftward one-bit arithmetic
|
||||
shift of the word at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBlsrm \fIn\fB, \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Logical shift right multiple \(em performs a rightward one-bit logical shift
|
||||
of the \fIn\fR byte number at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBlsrb \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Logical shift right byte \(em performs a rightward one-bit logical shift of
|
||||
the byte at \fIdest\fR. Clobbers the accumulator.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBlsrw \fIdest\fR
|
||||
.fi
|
||||
.IP
|
||||
Logical shift right word \(em performs a rightward one-bit logical shift of
|
||||
the word at \fIdest\fR. Clobbers the accumulator.
|
||||
.SH
|
||||
.sp 1
|
||||
\s+2Flow-of-control macros\s-2
|
||||
.nf
|
||||
|
||||
\fBrepeat \fIn\fB { \fIcode\fB }\fR
|
||||
.fi
|
||||
.IP
|
||||
Replicates the block of \fIMacross\fR statements \fIcode\fR \fIn\fR times.
|
||||
.LP
|
||||
.nf
|
||||
|
||||
\fBloop \fIcounter\fB, \fIstart\fB, \fIend\fB { \fIcode\fB }\fR
|
||||
.fi
|
||||
.IP
|
||||
Generic ``do-loop'' \(em generates 6502 code for a loop that initializes
|
||||
\fIcounter\fR to \fIstart\fR, and then repeatedly executes \fIcode\fR,
|
||||
incrementing \fIcounter\fR until it reaches the value \fIend\fR.
|
||||
\fICounter\fR may be ``\fBx\fR'' to denote the X index register, ``\fBy\fR''
|
||||
to denote the Y index register, or a memory location. \fIStart\fR and
|
||||
\fIend\fR may be referenced in any 6502 address mode.
|
||||
.SH
|
||||
.sp 1
|
||||
\s+2Miscellaneous macros\s-2
|
||||
.nf
|
||||
|
||||
\fBmbyte \fIn\fR
|
||||
.fi
|
||||
.IP
|
||||
Generates \fIn\fR zero data bytes.
|
||||
.bp
|
||||
.CD
|
||||
\s+5\fBAppendix \*- Summary of the macros\fR\s-5
|
||||
.DE
|
||||
.LP
|
||||
.nf
|
||||
\fBaddb \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBaddm \fIn\fB, \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBaddw \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBaslb \fIdest\fR
|
||||
\fBaslm \fIn\fB, \fIdest\fR
|
||||
\fBaslw \fIdest\fR
|
||||
\fBasrb \fIdest\fR
|
||||
\fBasrm \fIn\fB, \fIdest\fR
|
||||
\fBasrw \fIdest\fR
|
||||
\fBclearb \fIdest\fR
|
||||
\fBclearw \fIdest\fR
|
||||
\fBclrb \fIdest\fR
|
||||
\fBclrm \fIn\fB, \fIdest\fR
|
||||
\fBclrw \fIdest\fR
|
||||
\fBcmpb \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBcmpm \fIn\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBcmpw \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBloop \fIcounter\fB, \fIstart\fB, \fIend\fB, \fIcode\fR
|
||||
\fBlsrb \fIdest\fR
|
||||
\fBlsrm \fIn\fB, \fIdest\fR
|
||||
\fBlsrw \fIdest\fR
|
||||
\fBmbyte \fIn\fR
|
||||
\fBmovb \fIdest\fB, \fIsrc\fR
|
||||
\fBmoveb \fIsrc\fB, \fIdest\fR
|
||||
\fBmovew \fIdest\fB, \fIsrc\fR
|
||||
\fBmovexb \fIsrc\fB, \fIdest\fR
|
||||
\fBmovexw \fIsrc\fB, \fIdest\fR
|
||||
\fBmoveyb \fIsrc\fB, \fIdest\fR
|
||||
\fBmoveyw \fIsrc\fB, \fIdest\fR
|
||||
\fBmovm \fIn\fB, \fIdest\fB, \fIsrc\fR
|
||||
\fBmovmx \fIn\fB, \fIdest\fB, \fIsrc\fR
|
||||
\fBmovmy \fIn\fB, \fIdest\fB, \fIsrc\fR
|
||||
\fBmovw \fIsrc\fB, \fIdest\fR
|
||||
\fBmv2m \fIn\fB, \fIdest1\fB, \fIdest2\fB, \fIsrc\fR
|
||||
\fBnegb \fIdest\fR
|
||||
\fBnegm \fIn\fB, \fIdest\fR
|
||||
\fBnegw \fIdest\fR
|
||||
\fBphr\fR
|
||||
\fBphx\fR
|
||||
\fBphy\fR
|
||||
\fBplr\fR
|
||||
\fBplx\fR
|
||||
\fBply\fR
|
||||
\fBpushaddr \fIaddress\fR
|
||||
\fBrepeat \fIn\fB, \fIcode\fR
|
||||
\fBsubb \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBsubm \fIn\fB, \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
\fBsubw \fIdest\fB, \fIsrc1\fB, \fIsrc2\fR
|
||||
.fi
|
85
doc/handyHelpfulHints.t
Normal file
85
doc/handyHelpfulHints.t
Normal file
@ -0,0 +1,85 @@
|
||||
Handy Helpful Hints for using make/macross/slinky
|
||||
|
||||
1. You need two header files: a header and a sub-header. The sub-header
|
||||
declares 'define' symbols, zero page labels (as local labels), macros,
|
||||
functions, and so on. The header includes the sub-header and then
|
||||
additionally contains 'extern' declarations for all program-space labels and
|
||||
non-zero page variable-space labels plus 'define' declarations which refer to
|
||||
externals.
|
||||
|
||||
Non-zero page variable-space should be laid out in one file that includes just
|
||||
the sub-header. The rest of the program should be spread among files each of
|
||||
which includes the header.
|
||||
|
||||
2. In any given Macross assembly (usually one source file plus all of the
|
||||
other files that it 'include's), you can classify each symbol in two different
|
||||
orthogonal ways: whether it is global or local on the one hand and whether it
|
||||
is defined in this assembly or defined in some other assembly.
|
||||
|
||||
Being defined means that the symbol has a value which is known and can
|
||||
therefore be used to generate code. If a symbol has a value when it is
|
||||
encountered during assembly, then that value can be used immediately.
|
||||
If not, then we must wait until linking when (presumably) the value will be
|
||||
known.
|
||||
|
||||
Being global means that the symbol's value is known outside of the assembly in
|
||||
which the symbol is defined (i.e., that the value is "published" in the object
|
||||
file for use by the linker). Conversely, being local means that the value is
|
||||
known only in the one assembly.
|
||||
|
||||
Let's look at the four possible cases when a symbol is encountered during
|
||||
assembly:
|
||||
|
||||
LOCAL, DEFINED: this is the usual case. The value is used at assembly time.
|
||||
Multiple independent assemblies can define local symbols with the same names
|
||||
without conflicting with each other when they are linked.
|
||||
|
||||
LOCAL, UNDEFINED: this shouldn't happen. You will get a complaint from the
|
||||
assembler.
|
||||
|
||||
GLOBAL, DEFINED: during assembly, the symbol is treated just like a defined
|
||||
local symbol. However, the value is "published" in the object file for use by
|
||||
the linker. The symbol value can be made global either or both of two
|
||||
different ways: with an 'extern' declaration
|
||||
extern foo ; makes the symbol 'foo' global
|
||||
or, if the symbol is a label, by using two colons instead of one
|
||||
foo:: word 123 ; 'foo' is global
|
||||
bar: word 456 ; 'bar' is local
|
||||
If a global symbol is defined in more than one object file, the linker will
|
||||
complain.
|
||||
|
||||
GLOBAL, UNDEFINED: this means that the assembler assumes that the value of the
|
||||
symbol will be defined at link time. You still have to tell the assembler
|
||||
that the symbol is global with an 'extern' statement.
|
||||
|
||||
Note that all macro, function and variable (Macross variables, not 6502
|
||||
storage locations used as variables) names MUST be local, as must be struct
|
||||
names and struct fields. The assembler will complain if you try to declare
|
||||
one of these 'extern'.
|
||||
|
||||
A 'define' symbol must be local if it refers to any global symbols in its
|
||||
definition.
|
||||
|
||||
3. The fewer global symbols there are, the faster the link will run.
|
||||
|
||||
4. When juggling a program that consists of multiple source and object files,
|
||||
only a very foolish person would not use 'make'.
|
||||
|
||||
5. Emacs has a very nice feature whereby you can run 'make' under emacs and
|
||||
then get taken automagically to the errors:
|
||||
|
||||
The emacs function 'compile' (or 'new-compile' on some systems), which is
|
||||
usually bound to ^X^C (also to the shift-F5 key on my Concept terminal; I
|
||||
don't know about others), will run make and put the output from make (error
|
||||
messages and so on) in a buffer with a new window.
|
||||
|
||||
After compiling with make, the emacs function 'next-error', which is usually
|
||||
bound to ^X^N (also to the the F5 key on my Concept) will search in the error
|
||||
message buffer for the first C-compiler-style error message (which is what
|
||||
Macross outputs), read the file name and line number from the error message
|
||||
and then (in another window) position the cursor at that line of that file.
|
||||
Entering this command again takes you to the next error message, and then the
|
||||
next, and so on. The wonderful thing about this is that if you edit your
|
||||
source file, emacs keeps track of how you have shifted things around so that
|
||||
it will always take you to the location of the next error, even if your
|
||||
editing has invalidated the line numbers in the error messages!
|
224
doc/linkerReleaseNotes
Normal file
224
doc/linkerReleaseNotes
Normal file
@ -0,0 +1,224 @@
|
||||
An informal introduction to
|
||||
code relocation
|
||||
and
|
||||
multi-file linking
|
||||
using
|
||||
Macross and Slinky
|
||||
|
||||
To use:
|
||||
|
||||
First, let me explain that if you don't want to use the linker and assemble
|
||||
your programs in pieces, you need do nothing. Macross will continue to
|
||||
operate for you just as it always has (except that it will be somewhat faster
|
||||
since it no longer will be keeping track of some stuff internally that only
|
||||
matters to the linker). If you're not interested stop reading this right now.
|
||||
|
||||
There is a new command line option for Macross, '-c'. This signals to the
|
||||
assembler that, rather than generating a plain old ordinary object file, you
|
||||
want it to produce a special linkable object file that contains all kinds of
|
||||
information that the linker will need later. (I know it's obscure, but I'm
|
||||
running out of letters and the C compiler uses this flag to signal the same
|
||||
thing (maybe it should be '-m' or would that be even more obscure?)). E.g.:
|
||||
|
||||
macross -c -o foo foo.m
|
||||
|
||||
To link object files together, you use Slinky. The command is
|
||||
|
||||
slinky file1 file2 file3 ...
|
||||
|
||||
where file1, file2, etc. were generated by Macross using the '-c' option
|
||||
described in the previous paragraph. By default the output will go in the
|
||||
file 's.out' but the aesthetically enlightened will use the '-o' option to
|
||||
slinky that will name the output file whatever you want. E.g.:
|
||||
|
||||
slinky -o foobar file1 file2 file3 ...
|
||||
|
||||
will name the output 'foobar' (just like the '-o' option to Macross). The
|
||||
output file from Slinky will be a standard a65-style object file suitable for
|
||||
downloading to your Atari or whatever. *Don't* try to directly download an
|
||||
unlinked object that was produced by Macross using '-c'. Doing so will make
|
||||
the downloader choke, puke and die (actually, I haven't tried this, but in any
|
||||
case it will be wrong and the result will most likely be ugly).
|
||||
|
||||
Simple, no? Actually no, because...
|
||||
|
||||
You need to write your Macross programs in a way that can allow the various
|
||||
files to be assembled separately. This requires an understanding of two
|
||||
important concepts: 1. relocation and 2. external symbols.
|
||||
|
||||
A Macross relocatable object file consists of a bunch of little pieces of
|
||||
object code (called 'segments') plus some other bookkeeping info. Each of
|
||||
these little pieces of object code is either 'absolute' or 'relocatable'.
|
||||
Being absolute means that a segment is given a fixed, pre-specified location
|
||||
in memory. Being relocatable means that the segment can go wherever the
|
||||
linker finds room to put it.
|
||||
|
||||
All right, you ask, how do my pieces of code get to be absolute or
|
||||
relocatable? Well, at any given time, Macross is assembling in either
|
||||
absolute-mode or relocatable-mode (it starts out in relocatable-mode (always
|
||||
did, bet you didn't even notice!)). It gets into absolute-mode using the
|
||||
'org' statement with an absolute-value as the address to org to, i.e.,
|
||||
|
||||
org 0x1000
|
||||
|
||||
This starts an absolute segment at location 0x1000. The segment continues
|
||||
until the next 'org' or 'rel' statement. Macross gets into relocatable-mode
|
||||
via the 'rel' statement:
|
||||
|
||||
rel
|
||||
|
||||
or by an 'org' statement with a relocatable value as the address to org to
|
||||
(actually, using an org in this way is, as of the current implementation,
|
||||
somewhat questionable). The relocatable segment continues until the next
|
||||
'org' kicks Macross out of relocatable-mode or you use a 'constrain' or
|
||||
'align' statement. Each of the latter two (in relocatable-mode but not in
|
||||
absolute-mode) starts a new relocatable segment which is aligned or
|
||||
constrained appropriately at link-time. Also, a new relocatable segment
|
||||
starts at the end of the block that is the argument of a 'constrain'
|
||||
statement (again, in relocatable mode only).
|
||||
|
||||
It is important for you to know where (in your source code) relocatable
|
||||
segments begin and end, because each segment is relocated by the linker
|
||||
independently of all the others. Thus, even though two segments might be
|
||||
adjacent in your Macross source, in the eventual linked object they might not
|
||||
be. Thus relative branches across segment boundaries may go out of range and
|
||||
you cannot expect the flow of program execution to be continuous from one
|
||||
segment to another, i.e., that the last instruction in a segment will be
|
||||
followed immediately by the first instruction of the segment that follows it
|
||||
in the source. For example, in the following:
|
||||
|
||||
...stuff...
|
||||
and 123
|
||||
constrain (0x100) {
|
||||
sta foobar
|
||||
...more stuff...
|
||||
|
||||
you can't assume that the 'sta' will follow the 'and'. So
|
||||
|
||||
RULE #1 -- Don't allow program flow of control to fall through from one
|
||||
segment to the next.
|
||||
|
||||
RULE #2 -- Don't do relative branches across segment boundaries ('jmp's and
|
||||
'jsr's are OK).
|
||||
|
||||
COROLLARY -- You can't put an 'align' or 'constrain' statement inside an 'if',
|
||||
'while', 'do while' or 'do until' statement, and putting one inside a macro is
|
||||
very likely to result in a weird program bug unless you really understand what
|
||||
you are doing.
|
||||
|
||||
As with segments, a symbol in your Macross program is either absolute or
|
||||
relocatable. The value of an absolute symbol (called an 'absolute value') is
|
||||
a location in an absolute segment (or simply a fixed number like 42 or 137).
|
||||
A relocatable symbol has a value (called a 'relocatable value') which is a
|
||||
location in a relocatable segment. The important point to note is that the
|
||||
value of a relocatable symbol is not known until the program is linked and the
|
||||
relocatable segment to which it refers is given an actual location in memory.
|
||||
|
||||
This in turn means that Macross can't do any assembly-time arithmetic with the
|
||||
symbol since it doesn't know what value to compute with. Since storing away
|
||||
whole expressions in the object file would be both costly and messy we don't
|
||||
even try. The only arithmetic operation that the linker knows how to do is
|
||||
simple addition. Thus, the only operation you can perform with a relocatable
|
||||
symbol or value is simple addition, and then only in contexts where the result
|
||||
of the computation will get stored in the resultant object somewhere, such as
|
||||
the argument to an instruction or a 'byte' or 'word' statement. Thus the
|
||||
following are OK, for example (let's say 'foo' and 'bar' are relocatable
|
||||
symbols):
|
||||
|
||||
and foo+3
|
||||
ora bar-10 ; OK since this is just adding -10
|
||||
word foo+bar
|
||||
|
||||
but these are not
|
||||
|
||||
and foo*3 ; not addition
|
||||
ora 10-bar ; can't subtract 'bar'
|
||||
lda (bar+10)/7 ; even though 'bar' gets added, the result of
|
||||
; the addition is needed for the division
|
||||
|
||||
So,
|
||||
|
||||
RULE #3 -- No arithmetic more complicated than simple addition is allowed with
|
||||
relocatable symbols or values.
|
||||
|
||||
Now to explain external symbols...
|
||||
|
||||
First of all, you need to understand about symbols being *defined*. When we
|
||||
say that a symbol is 'defined' we mean that it has a value that the assembler
|
||||
or linker can use. A symbol gets defined by the Macross 'define' statement or
|
||||
by being used as a label. In order to actually use a symbol, e.g. as part of
|
||||
the operand of an instruction, the symbol must be defined *somewhere*.
|
||||
|
||||
Now let's say you have a subroutine that is defined in one file (actually, the
|
||||
label which is associated with the entry point to the subroutine is defined in
|
||||
that file, but let's not quibble), but which is called (using a 'jsr') from a
|
||||
second file. Two pieces of information need to be given to Macross when it
|
||||
assembles these files. In the first file, where the subroutine label is
|
||||
defined, you need to tell Macross, "Hey, this label is going to be used
|
||||
outside of this file, so put something in the object file that will tell the
|
||||
linker that it's here." In the second file, where the label is used (but not
|
||||
defined), you need to tell Macross, "Yes, I know this symbol isn't defined
|
||||
here. Don't worry about it. It's defined elsewhere and the linker will worry
|
||||
about it." Both of these pieces of information are conveyed by declaring the
|
||||
symbol to be external using the Macross 'extern' statement. E.g., in the
|
||||
first file:
|
||||
|
||||
extern foo
|
||||
...stuff...
|
||||
foo: ...more stuff...
|
||||
rts
|
||||
|
||||
and in the second file:
|
||||
|
||||
extern foo
|
||||
...stuff...
|
||||
jsr foo
|
||||
...more stuff...
|
||||
|
||||
In addition to this, a shorthand form of declaring a label to be external when
|
||||
it is defined is supported: you simply use two colons instead of one. In our
|
||||
example above, then, the first file could be:
|
||||
|
||||
...stuff...
|
||||
foo:: ...more stuff...
|
||||
rts
|
||||
|
||||
and the result would be exactly the same. So,
|
||||
|
||||
RULE #4 -- If you want a symbol's value to be carried across multiple files,
|
||||
that symbol MUST be declared external in the file where it is defined and in
|
||||
all files in which it is used.
|
||||
|
||||
Note that, as with relocatable symbols, symbols which are defined externally
|
||||
do not have a value which is known to Macross at assembly-time (though symbols
|
||||
which are external but which are defined in a given file do have such a value
|
||||
presuming that they are not also relocatable). This means that the same
|
||||
restrictions about arithmetic on relocatable symbols apply to externally
|
||||
defined symbols:
|
||||
|
||||
RULE #3a -- No arithmetic more complicated than simple addition is allowed
|
||||
with externally defined symbols.
|
||||
|
||||
Not to belabor the obvious, but it is of course an error to define an external
|
||||
symbol in more than one file. The linker will catch this and complain if you
|
||||
try.
|
||||
|
||||
In summary then:
|
||||
|
||||
RULE #1 -- Don't allow program flow of control to fall through from one
|
||||
segment to the next.
|
||||
|
||||
RULE #2 -- Don't do relative branches across segment boundaries ('jmp's and
|
||||
'jsr's are OK).
|
||||
|
||||
COROLLARY -- You can't put an 'align' or 'constrain' statement inside an 'if',
|
||||
'while', 'do while' or 'do until' statement, and putting one inside a macro is
|
||||
very likely to result in a weird program bug unless you really understand what
|
||||
you are doing.
|
||||
|
||||
RULE #3 -- No arithmetic more complicated than simple addition is allowed with
|
||||
relocatable symbols or values or symbols which are defined externally.
|
||||
|
||||
RULE #4 -- If you want a symbol's value to be carried across multiple files,
|
||||
that symbol MUST be declared external in the file in which it is defined and
|
||||
in all files in which it is used.
|
315
doc/macros.itr
Normal file
315
doc/macros.itr
Normal file
@ -0,0 +1,315 @@
|
||||
;
|
||||
; potentially popular macros for the macross assembler
|
||||
;
|
||||
; 11-Jan-85 cbm converted for Macross from original a65
|
||||
;
|
||||
|
||||
mif (!isDefined(_macros_)) {
|
||||
define _macros_ = 1
|
||||
;
|
||||
; push and pop X and Y registers
|
||||
;
|
||||
macro phx {
|
||||
txa
|
||||
pha
|
||||
}
|
||||
macro plx {
|
||||
pla
|
||||
tax
|
||||
}
|
||||
macro phy {
|
||||
tya
|
||||
pha
|
||||
}
|
||||
macro ply {
|
||||
pla
|
||||
tay
|
||||
}
|
||||
|
||||
macro call arg {
|
||||
jsr arg
|
||||
}
|
||||
|
||||
macro return {
|
||||
rts
|
||||
}
|
||||
|
||||
macro callret arg {
|
||||
jmp arg ; same as jsr arg; rts
|
||||
}
|
||||
|
||||
macro save arg {
|
||||
lda arg
|
||||
pha
|
||||
}
|
||||
|
||||
macro restore arg {
|
||||
pla
|
||||
sta arg
|
||||
}
|
||||
|
||||
; ================================================================
|
||||
; some auxiliary functions for the macros that follow
|
||||
;
|
||||
|
||||
; MAKE-FIRST-BYTE - access low byte for any addressing mode
|
||||
function makeFirstByte(operand) {
|
||||
mif (isImmediateMode(operand)) {
|
||||
freturn(/operand)
|
||||
} melse {
|
||||
freturn(operand)
|
||||
}
|
||||
}
|
||||
|
||||
; MAKE-SECOND-BYTE - access high byte for any addr mode except (post y zzz)
|
||||
function makeSecondByte(operand) {
|
||||
mif (isImmediateMode(operand)) {
|
||||
freturn(?operand)
|
||||
} melse {
|
||||
freturn(operand + 1)
|
||||
}
|
||||
}
|
||||
|
||||
; MAKE-NTH-BYTE - similarly access arbitrary byte
|
||||
function makeNthByte(operand, n) {
|
||||
mif (isImmediateMode(operand)) {
|
||||
freturn((operand >> (8 * (n - 1))) & 0xFF)
|
||||
} melse {
|
||||
freturn(operand + n - 1)
|
||||
}
|
||||
}
|
||||
|
||||
; ================================================================
|
||||
; MOVM, MOVEB, MOVB, MOVEW, MOVW, CLEARB, and CLEARW
|
||||
; Note that the args on MOVEx are src,dst as opposed to
|
||||
; MOVx, which uses dst,src.
|
||||
;
|
||||
|
||||
; MOVM - move multiple
|
||||
macro movm n, dst, src {
|
||||
mvariable i
|
||||
mfor (i=1, i<=n, i++) {
|
||||
lda makeNthByte(src, i)
|
||||
sta makeNthByte(dst, i)
|
||||
}
|
||||
}
|
||||
|
||||
; MOVEB - move byte from src to dst
|
||||
macro moveb src, dst {
|
||||
lda src
|
||||
sta dst
|
||||
}
|
||||
|
||||
; MOVB - for those who like their destination before their source
|
||||
macro movb dst, src {
|
||||
lda src
|
||||
sta dst
|
||||
}
|
||||
|
||||
; MOVEW - move word from src to dst
|
||||
; works for all addressing moves EXCEPT (post y zzz)
|
||||
macro movew src, dst {
|
||||
lda makeFirstByte(src)
|
||||
sta makeFirstByte(dst)
|
||||
lda makeSecondByte(src)
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; MOVW - and another with destination before source
|
||||
; works for all addressing moves EXCEPT (post y zzz)
|
||||
macro movw dst, src {
|
||||
lda makeFirstByte(src)
|
||||
sta makeFirstByte(dst)
|
||||
lda makeSecondByte(src)
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; CLEARB - zero byte dst
|
||||
macro clearb dst {
|
||||
lda #0
|
||||
sta dst
|
||||
}
|
||||
|
||||
; CLEARW - zero word dst
|
||||
; works for all addressing modes EXCEPT (post y dst)
|
||||
macro clearw dst {
|
||||
lda #0
|
||||
sta makeFirstByte(dst)
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; ================================================================
|
||||
; the general macros
|
||||
;
|
||||
|
||||
; MOVWB - move byte SRC to word DST
|
||||
; works for all addressing modes EXCEPT (post y zzz)
|
||||
macro movwb dst, src {
|
||||
lda src
|
||||
sta makeFirstByte(dst)
|
||||
lda #0
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; ADDM - add multiple
|
||||
macro addm n, dst, src, src1 {
|
||||
mvariable i
|
||||
clc
|
||||
mfor (i=1, i<=n, i++) {
|
||||
lda makeNthByte(src, i)
|
||||
adc makeNthByte(src1, i)
|
||||
sta makeNthByte(dst, i)
|
||||
}
|
||||
}
|
||||
|
||||
; ADDB - byte dst = byte src0 + byte src1
|
||||
macro addb dst, src0, src1 {
|
||||
clc
|
||||
lda src0
|
||||
adc src1
|
||||
sta dst
|
||||
}
|
||||
|
||||
; ADDW - word dst = word src0 + word src1
|
||||
; works for all addressing modes EXCEPT (post y zzz)
|
||||
macro addw dst, src0, src1 {
|
||||
clc
|
||||
lda makeFirstByte(src0)
|
||||
adc makeFirstByte(src1)
|
||||
sta makeFirstByte(dst)
|
||||
lda makeSecondByte(src0)
|
||||
adc makeSecondByte(src1)
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; ADDWWB - word dst = word src0 + byte src1
|
||||
; works for all addressing modes EXCEPT (post y zzz)
|
||||
macro addwwb dst, src0, src1 {
|
||||
clc
|
||||
lda makeFirstByte(src0)
|
||||
adc src1
|
||||
sta makeFirstByte(dst)
|
||||
lda makeSecondByte(src0)
|
||||
adc #0
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; SUBB - byte dst = byte src0 - byte src1
|
||||
macro subb dst, src0, src1 {
|
||||
sec
|
||||
lda src0
|
||||
sbc src1
|
||||
sta dst
|
||||
}
|
||||
|
||||
; SUBW - word dst = word src0 - word src1
|
||||
; works for all addressing modes EXCEPT (post y zzz)
|
||||
macro subw dst, src0, src1 {
|
||||
sec
|
||||
lda makeFirstByte(src0)
|
||||
sbc makeFirstByte(src1)
|
||||
sta makeFirstByte(dst)
|
||||
lda makeSecondByte(src0)
|
||||
sbc makeSecondByte(src1)
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; SUBWWB - word dst = word src0 - byte src1
|
||||
; works for all addressing modes EXCEPT (post y zzz)
|
||||
macro subwwb dst, src0, src1 {
|
||||
sec
|
||||
lda makeFirstByte(src0)
|
||||
sbc src1
|
||||
sta makeFirstByte(dst)
|
||||
lda makeSecondByte(src0)
|
||||
sbc #0
|
||||
sta makeSecondByte(dst)
|
||||
}
|
||||
|
||||
; ================================================================
|
||||
; cmpm, cmpb, cmpw
|
||||
; compare two quantities (arbitrary length, byte, and word)
|
||||
; set the condition flags following s0-s1
|
||||
;
|
||||
macro cmpm n, s0, s1 {
|
||||
mvariable i
|
||||
mfor (i=1, i<=n, i++) {
|
||||
lda makeNthByte(s0, i)
|
||||
sbc makeNthByte(s1, i)
|
||||
}
|
||||
}
|
||||
|
||||
macro cmpb s0, s1 {
|
||||
sec
|
||||
lda s0
|
||||
sbc s1
|
||||
}
|
||||
|
||||
macro cmpw s0, s1 {
|
||||
sec
|
||||
lda makeFirstByte(s0)
|
||||
sbc makeFirstByte(s1)
|
||||
lda makeSecondByte(s0)
|
||||
sbc makeSecondByte(s1)
|
||||
}
|
||||
|
||||
;
|
||||
; ASLM - multiply all by 2
|
||||
macro aslm n, s0 {
|
||||
mvariable i
|
||||
asl s0
|
||||
mfor (i = 2, i <= n, i++) {
|
||||
rol makeNthByte(s0, i)
|
||||
}
|
||||
}
|
||||
|
||||
; ================================================================
|
||||
; asrm, asrb, asrw
|
||||
; Arithmetic Shift Right (with sign extend).
|
||||
;
|
||||
macro asrm n, s0 {
|
||||
mvariable i = n
|
||||
lda makeNthByte(s0, i)
|
||||
cmp #0x80
|
||||
mwhile (i > 0) {
|
||||
ror makeNthByte(s0, i--)
|
||||
}
|
||||
}
|
||||
|
||||
macro asrb s0 {
|
||||
lda s0
|
||||
cmp #0x80
|
||||
ror s0
|
||||
}
|
||||
|
||||
macro asrw s0 {
|
||||
lda makeSecondByte(s0)
|
||||
cmp #0x80
|
||||
ror makeSecondByte(s0)
|
||||
ror makeFirstByte(s0)
|
||||
}
|
||||
|
||||
; ================================================================
|
||||
; repeat n {code. . .}
|
||||
; repeat n instances of code. e.g.,
|
||||
; repeat 6 {
|
||||
; lda x[foo]
|
||||
; sta x[bar]
|
||||
; inx
|
||||
; }
|
||||
; will generate inline code to move 6 bytes
|
||||
;
|
||||
macro repeat count, blockToRepeat {
|
||||
mvariable i = count
|
||||
mwhile (i-- > 0) {
|
||||
blockToRepeat
|
||||
}
|
||||
}
|
||||
|
||||
macro includef fname {
|
||||
printf("Including %s\n", fname)
|
||||
include fname
|
||||
}
|
||||
|
||||
|
||||
} ; *** end -- mif (!isDefined(_macros_)) ***
|
108
doc/macross.1
Normal file
108
doc/macross.1
Normal file
@ -0,0 +1,108 @@
|
||||
.TH MACROSS 1 "27 November 1985"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
macross \- Macross assembler
|
||||
.SH SYNOPSIS
|
||||
.B macross
|
||||
[ option ] ... file ...
|
||||
.SH DESCRIPTION
|
||||
.I Macross
|
||||
is a fancy macro cross assembler for the 6502.
|
||||
.I Macross
|
||||
assembles the given files in the order specified on the command line. Macross
|
||||
source file names must end with ``\fB.m\fR''.
|
||||
.PP
|
||||
The following options are interpreted by
|
||||
.IR macross .
|
||||
.TP
|
||||
.BI \-l " listfile"
|
||||
Produce an assembler listing in the file
|
||||
.IR listfile
|
||||
showing the object code generated. If
|
||||
.IR listfile
|
||||
is ``\fB-\fR'' the listing will be printed on the standard output.
|
||||
.TP
|
||||
.B \-m
|
||||
When listing is enabled, causes the assembler to include in the listing
|
||||
synthesized lines showing the code generated by macros.
|
||||
.TP
|
||||
.B \-g
|
||||
Suppress assembly-time garbage collection of unused dynamic storage space
|
||||
(may speed up small assemblies).
|
||||
.TP
|
||||
.B \-d
|
||||
Print esoteric debug information showing parse trees generated by the parser.
|
||||
(Generally not of interest to the casual user).
|
||||
.TP
|
||||
.B \-D
|
||||
Print even more esoteric debug information showing parser states. (Almost
|
||||
certainly not of interest to the casual user).
|
||||
.TP
|
||||
.B \-e
|
||||
Print esoteric debug information showing emitted binary as it is generated.
|
||||
(Even duller than parser states).
|
||||
.TP
|
||||
.BI \-s " dumpfile"
|
||||
Place a symbol table dump in the file
|
||||
.IR dumpfile
|
||||
at the end of assembly. If
|
||||
.IR dumpfile
|
||||
is ``\fB-\fR'', the symbol table dump will go to the standard output.
|
||||
.TP
|
||||
.BI \-S " dumpfile"
|
||||
As \fB-s\fR, except also dump internal symbols normally not of interest.
|
||||
.TP
|
||||
.BI \-h " dumpfile"
|
||||
As \fB-s\fR, except that the symbols are dumped in the form of Macross
|
||||
\fBdefine\fR statements.
|
||||
.TP
|
||||
.BI \-H " dumpfile"
|
||||
As \fB-h\fR, except that it only dumps defined external symbols.
|
||||
.TP
|
||||
.B \-a
|
||||
If a symbol dump has been specified, have it include unreferenced \fBdefine\fR
|
||||
symbols (these are not normally displayed in a symbol table dump listing).
|
||||
.TP
|
||||
.BI \-o " output"
|
||||
Name the final output file
|
||||
.IR output .
|
||||
If this option is not used the output will be placed in the file `m.out'.
|
||||
.TP
|
||||
.BI \-P " processor"
|
||||
Assemble for the target processor
|
||||
.IR processor .
|
||||
The allowed values are \fB6502\fR and \fB68000\fR. If this option is not
|
||||
used \fB6502\fR will be assumed.
|
||||
.TP
|
||||
.B \-c
|
||||
Make the object file produced be a linkable object suitable for use with the
|
||||
\fIslinky\fR linker.
|
||||
.TP
|
||||
.B \-p
|
||||
Produce position independent code for the \fBelse\fP clause of
|
||||
\fBif-then-else\fP statements. This is accomplished by emitting a
|
||||
\fBbcc/bcs\fP branch pair instead of a \fBjmp\fP instruction.
|
||||
.TP
|
||||
.B \-t
|
||||
Be terse about error messages. Output no more than one error message for a
|
||||
given line.
|
||||
.TP
|
||||
.B \-u
|
||||
Don't discard the temporary intermediate files generated during the listing
|
||||
process when the assemble exits (used for debugging the listing facility).
|
||||
.TP
|
||||
.B \-v
|
||||
Print the \fImacross\fP version number on the standard output before beginning
|
||||
assembly.
|
||||
.TP
|
||||
.B \-B
|
||||
When generating branches for nested \fBif-then-else\fR constructs, generate
|
||||
code like that generated by \fBa65\fR. This code will be slightly less
|
||||
efficient but will be completely backwards compatible.
|
||||
.SH "SEE ALSO"
|
||||
slinky(1), the Macross manual
|
||||
.SH DIAGNOSTICS
|
||||
The diagnostics produced by Macross are \fIintended\fR to be self-explanatory.
|
||||
.SH BUGS
|
||||
Errors in the input may sometimes produce bizarre and unexpected results.
|
||||
There are probably lots of bugs that are as yet undetected.
|
66
doc/slinky.1
Normal file
66
doc/slinky.1
Normal file
@ -0,0 +1,66 @@
|
||||
.TH SLINKY 1 "28 February 1986"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
slinky \- slinky linker
|
||||
.SH SYNOPSIS
|
||||
.B slinky
|
||||
[ option ] ... file ...
|
||||
.SH DESCRIPTION
|
||||
.I Slinky
|
||||
is a multi-file relocating object linker designed to be used in conjunction
|
||||
with the
|
||||
.I Macross
|
||||
assembler.
|
||||
.I Slinky
|
||||
links the given
|
||||
.I Macross
|
||||
object files in the order specified on the command line together into one
|
||||
executable object file.
|
||||
.PP
|
||||
The following options are interpreted by
|
||||
.IR slinky .
|
||||
.TP
|
||||
.B \-d
|
||||
Print esoteric debug information (you don't want to use this).
|
||||
.TP
|
||||
.B \-e
|
||||
Print different esoteric debug information (you don't want to use this
|
||||
either).
|
||||
.TP
|
||||
.B \-v
|
||||
Print the \fIslinky\fP version number on the standard output before linking.
|
||||
.TP
|
||||
.BI \-l " hexaddress"
|
||||
By default, \fIslinky\fP starts putting relocatable modules at location 0x100.
|
||||
The \fB-l\fR option lets you tell it to put things anywhere. This option can
|
||||
be used more than once in a single link command and can be interspersed with
|
||||
the names of the object files being linked. Thus
|
||||
.br
|
||||
\fBslinky foo.obj -l 0x3800 bar.obj baz.obj -l 0x5000 snood.obj\fP
|
||||
.br
|
||||
loads `foo.obj' starting at location 0x100, `bar.obj' and `baz.obj'
|
||||
consecutively starting at location 0x3800 and `snood.obj' starting at location
|
||||
0x5000.
|
||||
.TP
|
||||
.BI \-o " output"
|
||||
Name the final output file
|
||||
.IR output .
|
||||
If this option is not used the output will be placed in the file `s.out'.
|
||||
.TP
|
||||
.BI \-m " mapfile"
|
||||
Generate a load map listing, showing the values of all symbols after linking
|
||||
and put it in the file
|
||||
.IR mapfile .
|
||||
If
|
||||
.IR mapfile
|
||||
is ``\fB-\fR'', the load map will go to the standard output.
|
||||
.TP
|
||||
.B \-n
|
||||
If generating a load map, suppress the printing of the names of the files that
|
||||
reference each symbol.
|
||||
.SH "SEE ALSO"
|
||||
macross(1), the Macross manual
|
||||
.SH DIAGNOSTICS
|
||||
The diagnostics produced by Slinky are \fIintended\fR to be self-explanatory.
|
||||
.SH BUGS
|
||||
Who knows what bugs lurk there? Nobody's used it yet!
|
2124
doc/writeup_6502.itr
Normal file
2124
doc/writeup_6502.itr
Normal file
File diff suppressed because it is too large
Load Diff
2262
doc/writeup_68000.itr
Normal file
2262
doc/writeup_68000.itr
Normal file
File diff suppressed because it is too large
Load Diff
47
driver.c
Normal file
47
driver.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
driver.c -- Top level driver program for all versions of Macross
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
3-May-1985
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define MACROSS_6502 "/u1/gg/bin/macross_6502"
|
||||
#define MACROSS_68000 "/u1/gg/bin/macross_68000"
|
||||
|
||||
char *m6502 = "6502";
|
||||
char *m68000 = "68000";
|
||||
|
||||
char **mlist;
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
char *processor = m6502;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
mlist = (char **)calloc(argc + 1, sizeof (char **));
|
||||
for (i=1, j=1; i<argc; i++) {
|
||||
if (argv[i][0] == '-' && argv[i][1]== 'P') {
|
||||
processor = argv[++i];
|
||||
} else {
|
||||
mlist[j++] = argv[i];
|
||||
}
|
||||
}
|
||||
mlist[0] = processor;
|
||||
mlist[j] = NULL;
|
||||
if (strcmp(processor, m6502) == 0) {
|
||||
execv(MACROSS_6502, mlist);
|
||||
fprintf(stderr, "Macross: driver can't fork to %s for some reason\n", MACROSS_6502);
|
||||
} else if (strcmp(processor, m68000) == 0) {
|
||||
execv(MACROSS_68000, mlist);
|
||||
fprintf(stderr, "Macross: driver can't fork to %s for some reason\n", MACROSS_68000);
|
||||
} else {
|
||||
fprintf(stderr, "Macross: '%s' is an unknown processor\n", processor);
|
||||
}
|
||||
exit(1);
|
||||
}
|
BIN
emitBranch.o
Normal file
BIN
emitBranch.o
Normal file
Binary file not shown.
157
emitBranch_6502.c
Normal file
157
emitBranch_6502.c
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
emitBranch_6502.c -- Routines to deal with code generation for
|
||||
branches and jumps in the Macross assembler (6502
|
||||
version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
23-April-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/* emitRelativeBranch emits a relative branch instruction for the 6502,
|
||||
branching from the current location given a condition to branch upon and a
|
||||
target address. */
|
||||
|
||||
void
|
||||
emitRelativeBranch(condition, target, fixupLocation)
|
||||
conditionType condition;
|
||||
valueType *target;
|
||||
valueType fixupLocation[COMPOUND_BRANCH_MAX];
|
||||
{
|
||||
int i;
|
||||
|
||||
#define COMPOUND 0x00
|
||||
#define BPL_OPCODE 0x10
|
||||
#define BMI_OPCODE 0x30
|
||||
#define BVC_OPCODE 0x50
|
||||
#define BVS_OPCODE 0x70
|
||||
#define BCC_OPCODE 0x90
|
||||
#define BCS_OPCODE 0xB0
|
||||
#define BNE_OPCODE 0xD0
|
||||
#define NOP_OPCODE 0xEA
|
||||
#define BEQ_OPCODE 0xF0
|
||||
|
||||
static byte conditionalBranchOpcodes[] = {
|
||||
/* CARRY_COND */ BCS_OPCODE,
|
||||
/* ZERO_COND */ BEQ_OPCODE,
|
||||
/* NEGATIVE_COND */ BMI_OPCODE,
|
||||
/* OVERFLOW_COND */ BVS_OPCODE,
|
||||
/* LT_COND */ BCC_OPCODE,
|
||||
/* LEQ_COND */ COMPOUND,
|
||||
/* SLT_COND */ COMPOUND,
|
||||
/* SLEQ_COND */ COMPOUND,
|
||||
/* ALWAYS_COND */ NOP_OPCODE,
|
||||
/* NOT_CARRY_COND */ BCC_OPCODE,
|
||||
/* NOT_ZERO_COND */ BNE_OPCODE,
|
||||
/* NOT_NEGATIVE_COND */ BPL_OPCODE,
|
||||
/* NOT_OVERFLOW_COND */ BVC_OPCODE,
|
||||
/* GEQ_COND */ BCS_OPCODE,
|
||||
/* GT_COND */ COMPOUND,
|
||||
/* SGEQ_COND */ COMPOUND,
|
||||
/* SGT_COND */ COMPOUND,
|
||||
/* NEVER_COND */ NOP_OPCODE
|
||||
};
|
||||
|
||||
#define conditionalFixup(n) if (fixupLocation != NULL) \
|
||||
fixupLocation[n] = currentLocationCounter; \
|
||||
emitRelativeByteOffset(target);
|
||||
|
||||
if (fixupLocation != NULL)
|
||||
for (i=0; i<COMPOUND_BRANCH_MAX; i++)
|
||||
fixupLocation[i].value = -1;
|
||||
if (conditionalBranchOpcodes[(int)condition] != COMPOUND) {
|
||||
emitByte(conditionalBranchOpcodes[(int)condition]);
|
||||
conditionalFixup(0);
|
||||
} else switch (condition) {
|
||||
|
||||
case GT_COND:
|
||||
emitByte(BEQ_OPCODE); emitByte(2);
|
||||
emitByte(BCS_OPCODE); conditionalFixup(0);
|
||||
break;
|
||||
|
||||
case LEQ_COND:
|
||||
emitByte(BCC_OPCODE); conditionalFixup(0);
|
||||
emitByte(BEQ_OPCODE); conditionalFixup(1);
|
||||
break;
|
||||
|
||||
case SGEQ_COND:
|
||||
emitByte(BVS_OPCODE); emitByte(4);
|
||||
emitByte(BPL_OPCODE); conditionalFixup(0);
|
||||
emitByte(BMI_OPCODE); emitByte(2);
|
||||
emitByte(BMI_OPCODE); conditionalFixup(1);
|
||||
break;
|
||||
|
||||
case SGT_COND:
|
||||
emitByte(BEQ_OPCODE); emitByte(8);
|
||||
emitByte(BVS_OPCODE); emitByte(4);
|
||||
emitByte(BPL_OPCODE); conditionalFixup(0);
|
||||
emitByte(BMI_OPCODE); emitByte(2);
|
||||
emitByte(BMI_OPCODE); conditionalFixup(1);
|
||||
break;
|
||||
|
||||
case SLEQ_COND:
|
||||
emitByte(BEQ_OPCODE); conditionalFixup(0);
|
||||
emitByte(BVS_OPCODE); emitByte(4);
|
||||
emitByte(BMI_OPCODE); conditionalFixup(1);
|
||||
emitByte(BPL_OPCODE); emitByte(2);
|
||||
emitByte(BPL_OPCODE); conditionalFixup(2);
|
||||
break;
|
||||
|
||||
case SLT_COND:
|
||||
emitByte(BVS_OPCODE); emitByte(4);
|
||||
emitByte(BMI_OPCODE); conditionalFixup(0);
|
||||
emitByte(BPL_OPCODE); emitByte(2);
|
||||
emitByte(BPL_OPCODE); conditionalFixup(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("non-compound condition leaked thru!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitJump emits a 6502 jump instruction given the target address */
|
||||
|
||||
simpleFixupListType *
|
||||
emitJump(target, previousFixups)
|
||||
valueType *target;
|
||||
simpleFixupListType *previousFixups;
|
||||
{
|
||||
simpleFixupListType *result;
|
||||
valueType picFixup[COMPOUND_BRANCH_MAX];
|
||||
|
||||
simpleFixupListType *buildSimpleFixupList();
|
||||
|
||||
#define JUMP_OPCODE 0x4C
|
||||
|
||||
result = previousFixups;
|
||||
if (positionIndependentCodeMode) {
|
||||
if (target == NULL) {
|
||||
emitRelativeBranch(CARRY_COND, NULL, picFixup);
|
||||
result = buildSimpleFixupList(picFixup[0], result);
|
||||
emitRelativeBranch(NOT_CARRY_COND, NULL, picFixup);
|
||||
result = buildSimpleFixupList(picFixup[0], result);
|
||||
} else {
|
||||
emitRelativeBranch(CARRY_COND, target, NULL);
|
||||
emitRelativeBranch(NOT_CARRY_COND, target, NULL);
|
||||
}
|
||||
} else {
|
||||
emitByte(JUMP_OPCODE);
|
||||
if (target == NULL) {
|
||||
result = buildSimpleFixupList(currentLocationCounter,
|
||||
result);
|
||||
emitWord(0);
|
||||
} else {
|
||||
if (target->kindOfValue != ABSOLUTE_VALUE)
|
||||
noteAnonymousReference();
|
||||
emitWordValue(target);
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
116
emitBranch_68000.c
Normal file
116
emitBranch_68000.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
emitBranch_68000.c -- Routines to deal with code generation for
|
||||
branches and jumps in the Macross assembler (68000
|
||||
version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
29-April-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/* emitRelativeBranch emits a relative branch instruction for the 68000,
|
||||
branching from the current location given a condition to branch upon and a
|
||||
target address. */
|
||||
|
||||
void
|
||||
emitRelativeBranch(condition, target, fixupLocation)
|
||||
conditionType condition;
|
||||
valueType *target;
|
||||
valueType *fixupLocation;
|
||||
{
|
||||
int i;
|
||||
|
||||
#define BCS_OPCODE 0x65
|
||||
#define BCC_OPCODE 0x64
|
||||
#define BEQ_OPCODE 0x67
|
||||
#define BGE_OPCODE 0x6C
|
||||
#define BGT_OPCODE 0x6E
|
||||
#define BHI_OPCODE 0x62
|
||||
#define BLE_OPCODE 0x6F
|
||||
#define BLS_OPCODE 0x63
|
||||
#define BLT_OPCODE 0x6D
|
||||
#define BMI_OPCODE 0x6B
|
||||
#define BNE_OPCODE 0x66
|
||||
#define BPL_OPCODE 0x6A
|
||||
#define BVC_OPCODE 0x68
|
||||
#define BVS_OPCODE 0x69
|
||||
#define BRA_OPCODE 0x60
|
||||
|
||||
static byte conditionalBranchOpcodes[] = {
|
||||
/* CARRY_COND */ BCS_OPCODE,
|
||||
/* EQUAL_COND */ BEQ_OPCODE,
|
||||
/* OVERFLOW_COND */ BVS_OPCODE,
|
||||
/* MINUS_COND */ BMI_OPCODE,
|
||||
/* LT_COND */ BLT_OPCODE,
|
||||
/* LEQ_COND */ BLE_OPCODE,
|
||||
/* LOW_OR_SAME */ BLS_OPCODE,
|
||||
/* ALWAYS_COND */ BRA_OPCODE,
|
||||
/* NOT_CARRY_COND */ BCC_OPCODE,
|
||||
/* NOT_EQUAL_COND */ BNE_OPCODE,
|
||||
/* NOT_OVERFLOW_COND */ BVC_OPCODE,
|
||||
/* PLUS_COND */ BPL_OPCODE,
|
||||
/* GEQ_COND */ BGE_OPCODE,
|
||||
/* GT_COND */ BGT_OPCODE,
|
||||
/* HIGH_COND */ BHI_OPCODE,
|
||||
/* NEVER_COND */ 0,
|
||||
};
|
||||
|
||||
if (fixupLocation != NULL)
|
||||
fixupLocation->value = -1;
|
||||
if (condition == NEVER_COND)
|
||||
return;
|
||||
emitByte(conditionalBranchOpcodes[(int)condition]);
|
||||
if (isByteOffset(target - (currentLocationCounter.value + 1))) {
|
||||
if (fixupLocation != NULL)
|
||||
*fixupLocation = currentLocationCounter;
|
||||
emitRelativeByteOffset(target);
|
||||
} else {
|
||||
emitByte(0);
|
||||
if (fixupLocation != NULL)
|
||||
*fixupLocation = currentLocationCounter;
|
||||
emitRelativeWordOffset(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitJump emits a 68000 jump instruction given the target address */
|
||||
|
||||
simpleFixupListType *
|
||||
emitJump(target, previousFixups)
|
||||
valueType *target;
|
||||
simpleFixupListType *previousFixups;
|
||||
{
|
||||
simpleFixupListType *result;
|
||||
|
||||
simpleFixupListType *buildSimpleFixupList();
|
||||
|
||||
#define JUMP_OPCODE_WORD 0x4EF8
|
||||
#define JUMP_OPCODE_LONG 0x4EF9
|
||||
#define JUMP_OPCODE_PC_REL 0x4EFA
|
||||
|
||||
result = previousFixups;
|
||||
if (target == NULL) {
|
||||
emitWord(JUMP_OPCODE_LONG);
|
||||
result = buildSimpleFixupList(currentLocationCounter, result);
|
||||
emitWord(0);
|
||||
} else if (target->kindOfValue != ABSOLUTE_VALUE) {
|
||||
emitWord(JUMP_OPCODE_LONG);
|
||||
noteAnonymousReference();
|
||||
emitLongValue(target);
|
||||
} else if (isWordOffset(target->value-currentLocationCounter.value)) {
|
||||
emitWord(JUMP_OPCODE_PC_REL);
|
||||
emitWord(target->value - currentLocationCounter.value);
|
||||
} else if (isWord(target)) {
|
||||
emitWord(JUMP_OPCODE_WORD);
|
||||
emitWord(target);
|
||||
} else {
|
||||
emitWord(JUMP_OPCODE_LONG);
|
||||
emitLong(target);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
560
emitStuff.c
Normal file
560
emitStuff.c
Normal file
@ -0,0 +1,560 @@
|
||||
/*
|
||||
emitStuff.c -- Routines to actually generate binary stuff for the
|
||||
Macross assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
14-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/*
|
||||
Emitted code is stored in places that are allocated dynamically as they
|
||||
are needed. This saves us from having to keep umpteenK of code buffer
|
||||
around ALL the time and also lets us keep track of where code has actually
|
||||
been put for purposes of generating the final object module.
|
||||
|
||||
The structure of the code storage is: there are two code region structs
|
||||
(type 'codeRegionType'), one each for absolute and relocatable code. These
|
||||
are stored in the global array 'codeRegions' which is indexed by
|
||||
'currentCodeMode' which in turn indicates whether we are emitting aboslute
|
||||
or relocatable code. Each of these region structs contains a vector of
|
||||
[currently 64] pointers to code segment structs (type 'codeSegmentType').
|
||||
Each code segment represents a [currently 1Kbyte] piece of the target
|
||||
processor address space; it contains the high and low addresses within
|
||||
that space that have been occupied up until now and a pointer to a
|
||||
[1Kbyte] buffer that actually contains the code.
|
||||
|
||||
Initially, the code regions are filled with vectors of null pointers and
|
||||
there are no code segments allocated. As code is emitted, the space for
|
||||
the code segments and their associated buffers is allocated using 'malloc'.
|
||||
Only the actual buffers needed are allocated, resulting in substantial
|
||||
storage savings.
|
||||
|
||||
A complication that can arise from Macross 'struct's. Structs are
|
||||
assembled in a small scratch buffer and then transferred to the main code
|
||||
buffers as needed.
|
||||
*/
|
||||
|
||||
|
||||
/* incarnateCodeBuffer causes code buffer space to actually be allocated */
|
||||
|
||||
void
|
||||
incarnateCodeBuffer(bufferNum, bufferKind)
|
||||
int bufferNum;
|
||||
codeBufferKindType bufferKind;
|
||||
{
|
||||
codeSegmentType *newCodeSegment;
|
||||
codeBufferType *newCodeBuffer;
|
||||
int i;
|
||||
|
||||
newCodeSegment = typeAlloc(codeSegmentType);
|
||||
newCodeBuffer = typeAlloc(codeBufferType);
|
||||
for (i=0; i<CODE_BUFFER_SIZE; i++)
|
||||
(*newCodeBuffer)[i] = 0;
|
||||
newCodeSegment->codeStartAddress = 0xFFFF + 1;
|
||||
newCodeSegment->codeEndAddress = -1;
|
||||
newCodeSegment->codeBuffer = newCodeBuffer;
|
||||
codeRegions[(int)bufferKind]->codeSegments[bufferNum] =
|
||||
newCodeSegment;
|
||||
}
|
||||
|
||||
|
||||
/* putByte actually puts a byte in code storage somewhere, given the address
|
||||
and the byte itself. It tracks down the appropriate code buffer, taking
|
||||
care to make sure said buffer actually exists before using it. */
|
||||
|
||||
void
|
||||
putByte(address, byteValue)
|
||||
addressType address;
|
||||
byte byteValue;
|
||||
{
|
||||
int bufferNum;
|
||||
int bufferPos;
|
||||
codeBufferType *theBuffer;
|
||||
codeSegmentType *theSegment;
|
||||
|
||||
bufferNum = bufferNumber(address);
|
||||
bufferPos = bufferPosition(address);
|
||||
if (bufferNum >= CODE_BUFFERS_IN_ADDRESS_SPACE) {
|
||||
fatalError(ADDRESS_OUTSIDE_ADDRESS_SPACE_ERROR, address);
|
||||
return;
|
||||
}
|
||||
theSegment = codeRegions[(int)currentCodeMode]->codeSegments[
|
||||
bufferNum];
|
||||
if (theSegment == NULL) {
|
||||
incarnateCodeBuffer(bufferNum, currentCodeMode);
|
||||
theSegment = codeRegions[(int)currentCodeMode]->codeSegments[
|
||||
bufferNum];
|
||||
}
|
||||
theBuffer = theSegment->codeBuffer;
|
||||
if (currentCodeMode == RELOCATABLE_BUFFER && address >
|
||||
relocatableHighWaterMark)
|
||||
relocatableHighWaterMark = address;
|
||||
if (address > theSegment->codeEndAddress)
|
||||
theSegment->codeEndAddress = address;
|
||||
if (address < theSegment->codeStartAddress)
|
||||
theSegment->codeStartAddress = address;
|
||||
if (address > codeRegions[(int)currentCodeMode]->regionEndAddress)
|
||||
codeRegions[(int)currentCodeMode]->regionEndAddress = address;
|
||||
if (address < codeRegions[(int)currentCodeMode]->regionStartAddress)
|
||||
codeRegions[(int)currentCodeMode]->regionStartAddress =
|
||||
address;
|
||||
(*theBuffer)[bufferPos] = byteValue;
|
||||
}
|
||||
|
||||
|
||||
/* mapByte is like 'putByte', but places its values in the struct assembly
|
||||
buffer */
|
||||
|
||||
void
|
||||
mapByte(address, byteValue)
|
||||
int address;
|
||||
byte byteValue;
|
||||
{
|
||||
if (address < MAXIMUM_ALLOWED_STRUCT_SIZE)
|
||||
structScratchBuffer[address] = byteValue;
|
||||
}
|
||||
|
||||
|
||||
/* emitByte outputs one byte at the current location in either the current
|
||||
code buffer or the current struct assembly buffer */
|
||||
|
||||
void
|
||||
emitByte(byteValue)
|
||||
byte byteValue;
|
||||
{
|
||||
if (debug || emitPrint)
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitByte(%x: %x)\n", currentLocationCounter.
|
||||
value, byteValue);
|
||||
else
|
||||
printf("emitByte in struct (%x: %x)\n",
|
||||
currentFieldOffset, byteValue);
|
||||
if (structNestingDepth == 0) {
|
||||
putByte(currentLocationCounter.value++, byteValue);
|
||||
} else {
|
||||
mapByte(currentFieldOffset++, byteValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitWord similarly emits a word */
|
||||
|
||||
void
|
||||
emitWord(wordValue)
|
||||
wordType wordValue;
|
||||
{
|
||||
byteToWordType convert;
|
||||
int loByte, hiByte;
|
||||
|
||||
/* We hack around with this, even though it's less portable, so that we can
|
||||
avoid doing a division and a modulo on every word we emit (since code
|
||||
emission is in the inner loop). */
|
||||
|
||||
#ifdef BYTESWAPPED
|
||||
loByte = 1;
|
||||
hiByte = 0;
|
||||
#else
|
||||
loByte = 0;
|
||||
hiByte = 1;
|
||||
#endif
|
||||
convert.wordPart = wordValue;
|
||||
if (debug || emitPrint)
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitWord(%x: %x)\n", currentLocationCounter.
|
||||
value, wordValue);
|
||||
else
|
||||
printf("emitWord in struct (%x: %x)\n",
|
||||
currentFieldOffset, wordValue);
|
||||
if (structNestingDepth == 0) {
|
||||
#if TARGET_CPU == CPU_6502
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[loByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[hiByte]);
|
||||
#else if TARGET_CPU == CPU_68000
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[hiByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[loByte]);
|
||||
#endif
|
||||
} else {
|
||||
#if TARGET_CPU == CPU_6502
|
||||
mapByte(currentFieldOffset++, convert.bytePart[loByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[hiByte]);
|
||||
#else if TARGET_CPU == CPU_68000
|
||||
mapByte(currentFieldOffset++, convert.bytePart[hiByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[loByte]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* emitLong similarly emits a long */
|
||||
|
||||
void
|
||||
emitLong(longValue)
|
||||
longType longValue;
|
||||
{
|
||||
byteToLongType convert;
|
||||
int loByte, secondByte, thirdByte, hiByte;
|
||||
|
||||
/* We hack around with this, even though it's less portable, so that we can
|
||||
avoid doing a division and a modulo on every long we emit (since code
|
||||
emission is in the inner loop). */
|
||||
|
||||
#ifdef BYTESWAPPED
|
||||
/* Sun workstation... */
|
||||
loByte = 3;
|
||||
secondByte = 2;
|
||||
thirdByte = 1;
|
||||
hiByte = 0;
|
||||
#else
|
||||
/* Vax... */
|
||||
loByte = 0;
|
||||
secondByte = 1;
|
||||
thirdByte = 2;
|
||||
hiByte = 3;
|
||||
#endif
|
||||
convert.longPart = longValue;
|
||||
if (debug || emitPrint)
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitLong(%x: %x)\n", currentLocationCounter.
|
||||
value, longValue);
|
||||
else
|
||||
printf("emitLong in struct (%x: %x)\n",
|
||||
currentFieldOffset, longValue);
|
||||
if (structNestingDepth == 0) {
|
||||
#if TARGET_CPU == CPU_6502
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[loByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[secondByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[thirdByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[hiByte]);
|
||||
#else if TARGET_CPU == CPU_68000
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[hiByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[thirdByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[secondByte]);
|
||||
putByte(currentLocationCounter.value++,
|
||||
convert.bytePart[loByte]);
|
||||
#endif
|
||||
} else {
|
||||
#if TARGET_CPU == CPU_6502
|
||||
mapByte(currentFieldOffset++, convert.bytePart[loByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[secondByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[thirdByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[hiByte]);
|
||||
#else if TARGET_CPU == CPU_68000
|
||||
mapByte(currentFieldOffset++, convert.bytePart[hiByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[thirdByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[secondByte]);
|
||||
mapByte(currentFieldOffset++, convert.bytePart[loByte]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitByteValue takes the byte to be emitted out of a 'valueType' */
|
||||
|
||||
void
|
||||
emitByteValue(byteValue)
|
||||
valueType *byteValue;
|
||||
{
|
||||
if (byteValue->kindOfValue == ABSOLUTE_VALUE || byteValue->kindOfValue ==
|
||||
RELOCATABLE_VALUE || byteValue->kindOfValue == UNDEFINED_VALUE) {
|
||||
if (byteCheck(byteValue->value) && byteValue->kindOfValue!=FAIL) {
|
||||
if (debug || emitPrint) {
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitByteValue(%x: ",currentLocationCounter.value);
|
||||
else
|
||||
printf("emitByteValue in struct (%x:",currentFieldOffset);
|
||||
printValue(byteValue);
|
||||
printf(")\n");
|
||||
}
|
||||
emitByte(byteValue->value);
|
||||
}
|
||||
} else {
|
||||
if (byteValue->kindOfValue != FAIL)
|
||||
error(NON_ADDRESS_BYTE_VALUE_ERROR, valueKindString(byteValue->
|
||||
kindOfValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitString similarly spits out a string of bytes */
|
||||
|
||||
void
|
||||
emitString(string)
|
||||
stringType *string;
|
||||
{
|
||||
if (debug || emitPrint)
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitString(%x: \"%s\")\n",
|
||||
currentLocationCounter.value, string);
|
||||
else
|
||||
printf("emitString in struct(%x: \"%s\")\n",
|
||||
currentFieldOffset, string);
|
||||
/* Horrible terrible no good very bad cretinous ugly hack, but no graceful
|
||||
way to avoid it: a 0xFF byte in the string means output a 0x00 byte in
|
||||
the object. This is so we can embed nuls in strings without embedding
|
||||
nuls in strings, so to speak. We assume that the character 0xFF is not
|
||||
likely to be needed since ASCII (and ATASCII) is a seven bit character
|
||||
code. */
|
||||
while (*string != NULL)
|
||||
if ((*string & 0xFF) == 0xFF) {
|
||||
emitByte('\0');
|
||||
string++;
|
||||
} else {
|
||||
emitByte(*string++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitWordValue emits a word out of a 'valueType' */
|
||||
|
||||
void
|
||||
emitWordValue(wordValue)
|
||||
valueType *wordValue;
|
||||
{
|
||||
if (wordValue->kindOfValue == ABSOLUTE_VALUE || wordValue->kindOfValue ==
|
||||
RELOCATABLE_VALUE || wordValue->kindOfValue == UNDEFINED_VALUE) {
|
||||
if (wordCheck(wordValue->value) && wordValue->kindOfValue!=FAIL) {
|
||||
if (debug || emitPrint) {
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitWordValue(%x: ",currentLocationCounter.value);
|
||||
else
|
||||
printf("emitWordValue in struct (%x:",currentFieldOffset);
|
||||
printValue(wordValue);
|
||||
printf(")\n");
|
||||
}
|
||||
emitWord(wordValue->value);
|
||||
}
|
||||
} else {
|
||||
if (wordValue->kindOfValue != FAIL)
|
||||
error(NON_ADDRESS_WORD_VALUE_ERROR, valueKindString(wordValue->
|
||||
kindOfValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* emitLongValue emits a long out of a 'valueType' */
|
||||
|
||||
void
|
||||
emitLongValue(longValue)
|
||||
valueType *longValue;
|
||||
{
|
||||
if (longValue->kindOfValue == ABSOLUTE_VALUE || longValue->kindOfValue ==
|
||||
RELOCATABLE_VALUE || longValue->kindOfValue == UNDEFINED_VALUE) {
|
||||
if (longValue->kindOfValue != FAIL) {
|
||||
if (debug || emitPrint) {
|
||||
if (structNestingDepth == 0)
|
||||
printf("emitLongValue(%x: ",currentLocationCounter.value);
|
||||
else
|
||||
printf("emitLongValue in struct (%x:",currentFieldOffset);
|
||||
printValue(longValue);
|
||||
printf(")\n");
|
||||
}
|
||||
emitLong(longValue->value);
|
||||
}
|
||||
} else {
|
||||
if (longValue->kindOfValue != FAIL)
|
||||
error(NON_ADDRESS_LONG_VALUE_ERROR, valueKindString(longValue->
|
||||
kindOfValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* pokeByteValue is like 'emitByte' but it's random access */
|
||||
|
||||
void
|
||||
pokeByteValue(location, value)
|
||||
addressType location;
|
||||
valueType *value;
|
||||
{
|
||||
currentLocationCounter.value = location;
|
||||
emitByteValue(value);
|
||||
}
|
||||
|
||||
|
||||
/* ditto pokeWordValue */
|
||||
|
||||
void
|
||||
pokeWordValue(location, value)
|
||||
addressType location;
|
||||
valueType *value;
|
||||
{
|
||||
currentLocationCounter.value = location;
|
||||
emitWordValue(value);
|
||||
}
|
||||
|
||||
|
||||
/* ditto pokeLongValue */
|
||||
|
||||
void
|
||||
pokeLongValue(location, value)
|
||||
addressType location;
|
||||
valueType *value;
|
||||
{
|
||||
currentLocationCounter.value = location;
|
||||
emitLongValue(value);
|
||||
}
|
||||
|
||||
|
||||
/* ditto pokeRelativeByteValue. This is a special case used in fixing up
|
||||
relative branches */
|
||||
|
||||
void
|
||||
pokeRelativeByteValue(location, value)
|
||||
addressType location;
|
||||
valueType *value;
|
||||
{
|
||||
int offset;
|
||||
|
||||
currentLocationCounter.value = location;
|
||||
offset = value->value - (location - targetOffset) - 1;
|
||||
if (offset < 0)
|
||||
offset--;
|
||||
/* if (currentCodeMode == RELOCATABLE_BUFFER)
|
||||
offset = 0;*/
|
||||
if (isByteOffset(offset)) {
|
||||
emitByte(offset);
|
||||
} else {
|
||||
error(RELATIVE_OFFSET_TOO_LARGE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* ditto pokeRelativeWordValue. This is a special case used in fixing up
|
||||
relative branches */
|
||||
|
||||
void
|
||||
pokeRelativeWordValue(location, value)
|
||||
addressType location;
|
||||
valueType *value;
|
||||
{
|
||||
int offset;
|
||||
|
||||
currentLocationCounter.value = location;
|
||||
offset = value->value - (location - targetOffset);
|
||||
if (isWordOffset(offset)) {
|
||||
emitWord(offset);
|
||||
} else {
|
||||
error(RELATIVE_OFFSET_TOO_LARGE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* getByte fetches a byte back out of the labyrinth of code buffers */
|
||||
|
||||
byte
|
||||
getByte(address)
|
||||
addressType address;
|
||||
{
|
||||
int bufferNum;
|
||||
int bufferPos;
|
||||
codeBufferType *theBuffer;
|
||||
codeSegmentType *theSegment;
|
||||
|
||||
bufferNum = bufferNumber(address);
|
||||
bufferPos = bufferPosition(address);
|
||||
theSegment = codeRegions[(int)currentCodeMode]->codeSegments[
|
||||
bufferNum];
|
||||
if (theSegment == NULL)
|
||||
return(0);
|
||||
else
|
||||
return((*(theSegment->codeBuffer))[bufferPos]);
|
||||
}
|
||||
|
||||
void
|
||||
emitRelativeByteOffset(target)
|
||||
valueType *target;
|
||||
{
|
||||
int saveTargetOffset;
|
||||
|
||||
if (target == NULL) {
|
||||
emitByte(0);
|
||||
} else {
|
||||
(target->value)++;
|
||||
saveTargetOffset = targetOffset;
|
||||
targetOffset = 0;
|
||||
pokeRelativeByteValue(currentLocationCounter.value, target);
|
||||
targetOffset = saveTargetOffset;
|
||||
(target->value)--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
emitRelativeWordOffset(target)
|
||||
valueType *target;
|
||||
{
|
||||
int saveTargetOffset;
|
||||
|
||||
if (target == NULL) {
|
||||
emitWord(0);
|
||||
} else {
|
||||
saveTargetOffset = targetOffset;
|
||||
targetOffset = 0;
|
||||
pokeRelativeWordValue(currentLocationCounter.value, target);
|
||||
targetOffset = saveTargetOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/* fixupBranch repairs a previously undefined branch once the branch address
|
||||
has become known. */
|
||||
|
||||
void
|
||||
fixupBranch(location, target)
|
||||
valueType location[COMPOUND_BRANCH_MAX];
|
||||
valueType target;
|
||||
{
|
||||
valueType saveCurrentLocation;
|
||||
int saveTargetOffset;
|
||||
int i;
|
||||
|
||||
saveCurrentLocation = currentLocationCounter;
|
||||
saveTargetOffset = targetOffset;
|
||||
targetOffset = 0;
|
||||
for (i=0; i<COMPOUND_BRANCH_MAX; i++) {
|
||||
if (location[i].value >= 0)
|
||||
pokeRelativeByteValue(location[i].value, &target);
|
||||
}
|
||||
targetOffset = saveTargetOffset;
|
||||
currentLocationCounter = saveCurrentLocation;
|
||||
}
|
||||
|
||||
|
||||
/* fixupJump similarly repairs a jump */
|
||||
|
||||
void
|
||||
fixupJump(locations, target)
|
||||
simpleFixupListType *locations;
|
||||
valueType target;
|
||||
{
|
||||
valueType saveCurrentLocation;
|
||||
simpleFixupListType *oldLocation;
|
||||
|
||||
saveCurrentLocation = currentLocationCounter;
|
||||
while (locations != NULL) {
|
||||
currentLocationCounter = locations->locationToFixup;
|
||||
noteAnonymousReference();
|
||||
target.value -= targetOffset;
|
||||
if (positionIndependentCodeMode)
|
||||
pokeRelativeByteValue(locations->locationToFixup.
|
||||
value, &target);
|
||||
else
|
||||
pokeWordValue(locations->locationToFixup.value,
|
||||
&target);
|
||||
target.value += targetOffset;
|
||||
oldLocation = locations;
|
||||
locations = locations->nextFixup;
|
||||
free(oldLocation);
|
||||
}
|
||||
currentLocationCounter = saveCurrentLocation;
|
||||
}
|
BIN
emitStuff.o
Normal file
BIN
emitStuff.o
Normal file
Binary file not shown.
674
encode.c
Normal file
674
encode.c
Normal file
@ -0,0 +1,674 @@
|
||||
/* WARNING: this file has not yet been separated into 6502 and non-6052 parts */
|
||||
/*
|
||||
encode.c -- Routines to encode expressions for Macross object files.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
8-November-1985
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
#include "y.tab.h"
|
||||
#include "slinkyExpressions.h"
|
||||
|
||||
#define nullEncode(thing) if (thing==NULL) return(TRUE);
|
||||
#define byteOp(op) ((op)-256)
|
||||
|
||||
bool encodingFunction;
|
||||
|
||||
bool
|
||||
encodeByte(aByte)
|
||||
byte aByte;
|
||||
{
|
||||
if (expressionBufferSize < EXPRESSION_BUFFER_LIMIT) {
|
||||
expressionBuffer[expressionBufferSize++] = aByte;
|
||||
return(TRUE);
|
||||
} else {
|
||||
error(EXPRESSION_TOO_BIG_TO_FIT_IN_OBJECT_ERROR);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
encodeBigword(bigword)
|
||||
int bigword;
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<sizeof(int); ++i) {
|
||||
if (!encodeByte(bigword & 0xFF))
|
||||
return(FALSE);
|
||||
bigword >>= 8;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeAssignmentTerm(assignmentTerm, kindOfFixup)
|
||||
binopTermType *assignmentTerm;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
nullEncode(assignmentTerm);
|
||||
if ((assignmentKindType)assignmentTerm->binop != ASSIGN_ASSIGN) {
|
||||
error(FUNNY_ASSIGNMENT_KIND_IN_OBJECT_EXPRESSION_ERROR);
|
||||
return(FALSE);
|
||||
}
|
||||
return(
|
||||
encodeByte(BINOP_TAG) &&
|
||||
encodeByte(byteOp(ASSIGN)) &&
|
||||
encodeIdentifier(assignmentTerm->leftArgument) &&
|
||||
encodeExpression(assignmentTerm->rightArgument)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeBinopTerm(binopTerm, isTopLevel, kindOfFixup)
|
||||
binopTermType *binopTerm;
|
||||
bool isTopLevel;
|
||||
fixupKindType kindOfFixup;
|
||||
{
|
||||
bool encodeExpression();
|
||||
|
||||
nullEncode(binopTerm);
|
||||
return (
|
||||
encodeByte(BINOP_TAG) &&
|
||||
encodeByte(byteOp(binopTerm->binop)) &&
|
||||
encodeExpression(binopTerm->leftArgument) &&
|
||||
encodeExpression(binopTerm->rightArgument)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeCondition(condition)
|
||||
conditionType condition;
|
||||
{
|
||||
return(
|
||||
encodeByte(CONDITION_CODE_TAG) &&
|
||||
encodeByte(condition)
|
||||
);
|
||||
}
|
||||
|
||||
int
|
||||
functionNumber(function)
|
||||
functionDefinitionType *function;
|
||||
{
|
||||
if (function->ordinal == -1) {
|
||||
function->ordinal = externalFunctionCount++;
|
||||
if (externalFunctionList == NULL) {
|
||||
externalFunctionList = endOfExternalFunctionList =
|
||||
function;
|
||||
} else {
|
||||
endOfExternalFunctionList->nextExternalFunction =
|
||||
function;
|
||||
endOfExternalFunctionList = function;
|
||||
}
|
||||
}
|
||||
return(function->ordinal);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeFunctionCall(functionCall)
|
||||
functionCallTermType *functionCall;
|
||||
{
|
||||
functionDefinitionType *theFunction;
|
||||
int functionOrdinal;
|
||||
symbolInContextType *workingContext;
|
||||
operandListType *parameterList;
|
||||
|
||||
symbolInContextType *getWorkingContext();
|
||||
|
||||
nullEncode(functionCall);
|
||||
workingContext = getWorkingContext(functionCall->functionName);
|
||||
if (isFunction(workingContext)) {
|
||||
if (!encodeByte(FUNCTION_CALL_TAG))
|
||||
return(FALSE);
|
||||
theFunction = (functionDefinitionType *)workingContext->
|
||||
value->value;
|
||||
if (!encodeBigword(functionNumber(theFunction)))
|
||||
return(FALSE);
|
||||
} else if (isBuiltInFunction(workingContext)) {
|
||||
functionOrdinal = workingContext->value->value;
|
||||
if (builtInFunctionTable[functionOrdinal].isSpecialFunction)
|
||||
return(encodeValue((*builtInFunctionTable[
|
||||
functionOrdinal].functionEntry)(functionCall->
|
||||
parameters, NO_FIXUP)));
|
||||
if (!encodeByte(BUILTIN_FUNCTION_CALL_TAG))
|
||||
return(FALSE);
|
||||
if (builtInFunctionTable[functionOrdinal].ordinal < 0) {
|
||||
error(BUILT_IN_FUNCTION_NOT_AVAILABLE_IN_OBJECT_ERROR,
|
||||
builtInFunctionTable[functionOrdinal].
|
||||
functionName);
|
||||
return(FALSE);
|
||||
} else if (!encodeBigword(builtInFunctionTable[
|
||||
functionOrdinal].ordinal)) {
|
||||
return(FALSE);
|
||||
}
|
||||
} else {
|
||||
error(NOT_A_FUNCTION_ERROR, symbName(functionCall->
|
||||
functionName));
|
||||
return(FALSE);
|
||||
}
|
||||
parameterList = functionCall->parameters;
|
||||
if (!encodeByte(countParameters(parameterList)))
|
||||
return(FALSE);
|
||||
while (parameterList != NULL)
|
||||
if (!encodeOperand(parameterList))
|
||||
return(FALSE);
|
||||
else
|
||||
parameterList = parameterList->nextOperand;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeHere()
|
||||
{
|
||||
return(encodeByte(HERE_TAG));
|
||||
}
|
||||
|
||||
bool
|
||||
encodeIdentifier(identifier)
|
||||
symbolTableEntryType *identifier;
|
||||
{
|
||||
symbolInContextType *workingContext;
|
||||
environmentType *saveEnvironment;
|
||||
bool result;
|
||||
|
||||
nullEncode(identifier);
|
||||
|
||||
if (symbName(identifier)[0] == '$') {
|
||||
error(TEMP_SYMBOL_IN_OBJECT_ERROR, symbName(identifier));
|
||||
return(FALSE);
|
||||
}
|
||||
if (encodingFunction) {
|
||||
return(encodeByte(IDENTIFIER_TAG) &&
|
||||
encodeBigword(identifier->ordinal));
|
||||
}
|
||||
if ((workingContext = getWorkingContext(identifier)) == NULL) {
|
||||
error(UNDEFINED_SYMBOL_ERROR, symbName(identifier));
|
||||
return(FALSE);
|
||||
}
|
||||
if (workingContext->usage == FUNCTION_SYMBOL || workingContext->usage
|
||||
== BUILT_IN_FUNCTION_SYMBOL) {
|
||||
error(FUNCTION_IS_NOT_A_VALUE_ERROR, symbName(identifier));
|
||||
return(FALSE);
|
||||
}
|
||||
if (workingContext->value == NULL) {
|
||||
error(UNDEFINED_SYMBOL_ERROR, symbName(identifier));
|
||||
return(FALSE);
|
||||
}
|
||||
if (workingContext->value->kindOfValue == UNDEFINED_VALUE) {
|
||||
if (workingContext->attributes & GLOBAL_ATT) {
|
||||
return(encodeByte(IDENTIFIER_TAG) &&
|
||||
encodeBigword(identifier->ordinal));
|
||||
} else {
|
||||
error(UNDEFINED_SYMBOL_ERROR, symbName(identifier));
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
if (workingContext->value->kindOfValue == RELOCATABLE_VALUE) {
|
||||
return(encodeByte(IDENTIFIER_TAG) &&
|
||||
encodeBigword(identifier->ordinal));
|
||||
}
|
||||
if (workingContext->value->kindOfValue == FAIL) {
|
||||
error(UNASSIGNED_SYMBOL_ERROR, symbName(identifier));
|
||||
return(FALSE);
|
||||
}
|
||||
if (workingContext->value->kindOfValue == OPERAND_VALUE) {
|
||||
saveEnvironment = currentEnvironment;
|
||||
if (workingContext->usage == ARGUMENT_SYMBOL) {
|
||||
currentEnvironment = currentEnvironment->
|
||||
previousEnvironment;
|
||||
}
|
||||
result = encodeOperand(workingContext->value->value);
|
||||
currentEnvironment = saveEnvironment;
|
||||
return(result);
|
||||
}
|
||||
if (workingContext->value->kindOfValue == BLOCK_VALUE) {
|
||||
error(BLOCK_OPERAND_IN_OBJECT_EXPRESSION_ERROR);
|
||||
return(FALSE);
|
||||
}
|
||||
return(encodeValue(workingContext->value));
|
||||
}
|
||||
|
||||
bool
|
||||
encodeNumber(number)
|
||||
numberTermType number;
|
||||
{
|
||||
return(
|
||||
encodeByte(NUMBER_TAG) &&
|
||||
encodeBigword(number)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeRelocatableNumber(number)
|
||||
numberTermType number;
|
||||
{
|
||||
return(
|
||||
encodeByte(RELOCATABLE_TAG) &&
|
||||
encodeBigword(number)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
switch (operand->kindOfOperand) {
|
||||
case EXPRESSION_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case INDIRECT_OPND:
|
||||
case POST_INDEXED_Y_OPND:
|
||||
case PRE_INDEXED_X_OPND:
|
||||
case X_INDEXED_OPND:
|
||||
case Y_INDEXED_OPND:
|
||||
return(encodeExpression(operand->theOperand));
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
case X_REGISTER_OPND:
|
||||
case Y_REGISTER_OPND:
|
||||
error(REGISTER_OPERAND_IN_OBJECT_EXPRESSION_ERROR);
|
||||
return(FALSE);
|
||||
|
||||
case X_SELECTED_OPND:
|
||||
case Y_SELECTED_OPND:
|
||||
case PRE_SELECTED_X_OPND:
|
||||
error(SELECTION_OPERAND_IN_OBJECT_EXPRESSION_ERROR);
|
||||
return(FALSE);
|
||||
|
||||
case STRING_OPND:
|
||||
return(encodeString(operand->theOperand));
|
||||
|
||||
case BLOCK_OPND:
|
||||
error(BLOCK_OPERAND_IN_OBJECT_EXPRESSION_ERROR);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
encodePostopTerm(postopTerm)
|
||||
postOpTermType *postopTerm;
|
||||
{
|
||||
nullEncode(postopTerm);
|
||||
return(
|
||||
encodeByte(POSTOP_TAG) &&
|
||||
encodeByte(byteOp(postopTerm->postOp)) &&
|
||||
encodeExpression(postopTerm->postOpArgument)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodePreopTerm(preopTerm)
|
||||
preOpTermType *preopTerm;
|
||||
{
|
||||
nullEncode(preopTerm);
|
||||
return(
|
||||
encodeByte(PREOP_TAG) &&
|
||||
encodeByte(byteOp(preopTerm->preOp)) &&
|
||||
encodeExpression(preopTerm->preOpArgument)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeString(string)
|
||||
stringType *string;
|
||||
{
|
||||
if (!encodeByte(STRING_TAG))
|
||||
return(FALSE);
|
||||
while (*string != '\0') {
|
||||
if (!encodeByte(*string++))
|
||||
return(FALSE);
|
||||
}
|
||||
return(encodeByte('\0'));
|
||||
}
|
||||
|
||||
bool
|
||||
encodeUnopTerm(unopTerm)
|
||||
unopTermType *unopTerm;
|
||||
{
|
||||
nullEncode(unopTerm);
|
||||
return(
|
||||
encodeByte(UNOP_TAG) &&
|
||||
encodeByte(byteOp(unopTerm->unop)) &&
|
||||
encodeExpression(unopTerm->unopArgument)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeValue(value)
|
||||
valueType *value;
|
||||
{
|
||||
switch (value->kindOfValue) {
|
||||
case ABSOLUTE_VALUE:
|
||||
return(encodeNumber(value->value));
|
||||
|
||||
case RELOCATABLE_VALUE:
|
||||
return(encodeRelocatableNumber(value->value));
|
||||
|
||||
case OPERAND_VALUE:
|
||||
return(encodeOperand(value->value));
|
||||
|
||||
case STRING_VALUE:
|
||||
return(encodeString(value->value));
|
||||
|
||||
case CONDITION_VALUE:
|
||||
return(encodeCondition(value->value));
|
||||
|
||||
case DATA_VALUE:
|
||||
case BSS_VALUE:
|
||||
case STRUCT_VALUE:
|
||||
case FIELD_VALUE:
|
||||
case MACRO_VALUE:
|
||||
case UNDEFINED_VALUE:
|
||||
case FUNCTION_VALUE:
|
||||
case BLOCK_VALUE:
|
||||
case BUILT_IN_FUNCTION_VALUE:
|
||||
case ARRAY_VALUE:
|
||||
case FAIL:
|
||||
error(WRONG_KIND_OF_VALUE_IN_OBJECT_EXPRESSION_ERROR,
|
||||
valueKindString(value->kindOfValue));
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
encodeExpression(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
nullEncode(expression);
|
||||
switch (expression->kindOfTerm) {
|
||||
|
||||
case ARRAY_EXPR:
|
||||
error(ARRAY_TERM_IN_OBJECT_EXPRESSION_ERROR);
|
||||
return(FALSE);
|
||||
break;
|
||||
|
||||
case ASSIGN_EXPR:
|
||||
return(encodeAssignmentTerm(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case BINOP_EXPR:
|
||||
return(encodeBinopTerm(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case CONDITION_CODE_EXPR:
|
||||
return(encodeCondition(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case FUNCTION_CALL_EXPR:
|
||||
return(encodeFunctionCall(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case HERE_EXPR:
|
||||
return(encodeHere());
|
||||
break;
|
||||
|
||||
case IDENTIFIER_EXPR:
|
||||
return(encodeIdentifier(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case NUMBER_EXPR:
|
||||
return(encodeNumber(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case POSTOP_EXPR:
|
||||
return(encodePostopTerm(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case PREOP_EXPR:
|
||||
return(encodePreopTerm(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case SUBEXPRESSION_EXPR:
|
||||
encodeExpression(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case STRING_EXPR:
|
||||
return(encodeString(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case UNOP_EXPR:
|
||||
return(encodeUnopTerm(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
case VALUE_EXPR:
|
||||
return(encodeValue(expression->expressionTerm));
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("encodeExpression: funny expression kind %d\n",
|
||||
expression->kindOfTerm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
encodeAssertStatement(assertStatement)
|
||||
assertStatementBodyType *assertStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(ASSERT_TAG) &&
|
||||
encodeExpression(assertStatement->condition) &&
|
||||
encodeExpression(assertStatement->message)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeFreturnStatement(freturnStatement)
|
||||
freturnStatementBodyType *freturnStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(FRETURN_TAG) &&
|
||||
encodeExpression(freturnStatement)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMdefineStatement(mdefineStatement)
|
||||
defineStatementBodyType *mdefineStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(MDEFINE_TAG) &&
|
||||
encodeIdentifier(mdefineStatement->theSymbol) &&
|
||||
encodeExpression(mdefineStatement->theValue)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMdoUntilStatement(mdoUntilStatement)
|
||||
mdoUntilStatementBodyType *mdoUntilStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(MDOUNTIL_TAG) &&
|
||||
encodeExpression(mdoUntilStatement->mdoUntilCondition) &&
|
||||
encodeBlock(mdoUntilStatement->mdoUntilLoop)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMdoWhileStatement(mdoWhileStatement)
|
||||
mdoWhileStatementBodyType *mdoWhileStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(MDOWHILE_TAG) &&
|
||||
encodeExpression(mdoWhileStatement->mdoWhileCondition) &&
|
||||
encodeBlock(mdoWhileStatement->mdoWhileLoop)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMforStatement(mforStatement)
|
||||
mforStatementBodyType *mforStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(MFOR_TAG) &&
|
||||
encodeExpression(mforStatement->initExpression) &&
|
||||
encodeExpression(mforStatement->testExpression) &&
|
||||
encodeExpression(mforStatement->incrExpression) &&
|
||||
encodeBlock(mforStatement->forLoop)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMifStatement(mifStatement)
|
||||
mifStatementBodyType *mifStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(MIF_TAG) &&
|
||||
encodeExpression(mifStatement->mifCondition) &&
|
||||
encodeBlock(mifStatement->mifConsequence) &&
|
||||
encodeBlock(mifStatement->mifContinuation)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMswitchStatement(mswitchStatement)
|
||||
mswitchStatementBodyType *mswitchStatement;
|
||||
{
|
||||
caseListType *caseList;
|
||||
caseType *theCase;
|
||||
expressionListType *tagExpressionList;
|
||||
|
||||
if (!(encodeByte(MSWITCH_TAG) && encodeExpression(mswitchStatement->
|
||||
switchExpression)))
|
||||
return(FALSE);
|
||||
for (caseList=mswitchStatement->cases; caseList!=NULL; caseList=caseList->
|
||||
nextCase) {
|
||||
theCase = caseList->theCase;
|
||||
for (tagExpressionList=theCase->caseTags; tagExpressionList!=NULL;
|
||||
tagExpressionList=tagExpressionList->nextExpression) {
|
||||
if (!encodeExpression(tagExpressionList->theExpression))
|
||||
return(FALSE);
|
||||
}
|
||||
if (!encodeBlock(theCase->caseBody))
|
||||
return(FALSE);
|
||||
}
|
||||
return(encodeByte(END_TAG));
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMvariableStatement(mvariableStatement)
|
||||
mvariableStatementBodyType *mvariableStatement;
|
||||
{
|
||||
int length;
|
||||
|
||||
if ((length=expressionListLength(mvariableStatement->theValue) > 1) ||
|
||||
mvariableStatement->theDimension!=NULL) {
|
||||
error(ARRAY_MVARIABLE_IN_OBJECT_FUNCTION_ERROR);
|
||||
return(FALSE);
|
||||
}
|
||||
if (!(encodeByte(MVARIABLE_TAG) && encodeIdentifier(mvariableStatement->
|
||||
theSymbol)))
|
||||
return(FALSE);
|
||||
if (length == 1)
|
||||
return(encodeExpression(mvariableStatement->theValue->
|
||||
theExpression));
|
||||
else
|
||||
return(encodeExpression(NULL));
|
||||
}
|
||||
|
||||
bool
|
||||
encodeMwhileStatement(mwhileStatement)
|
||||
mwhileStatementBodyType *mwhileStatement;
|
||||
{
|
||||
return(
|
||||
encodeByte(MWHILE_TAG) &&
|
||||
encodeExpression(mwhileStatement->mwhileCondition) &&
|
||||
encodeBlock(mwhileStatement->mwhileLoop)
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
encodeStatement(statement)
|
||||
statementType *statement;
|
||||
{
|
||||
switch(statement->kindOfStatement) {
|
||||
|
||||
case ALIGN_STATEMENT:
|
||||
case BLOCK_STATEMENT:
|
||||
case BYTE_STATEMENT:
|
||||
case CONSTRAIN_STATEMENT:
|
||||
case DBYTE_STATEMENT:
|
||||
case DEFINE_STATEMENT:
|
||||
case DO_UNTIL_STATEMENT:
|
||||
case DO_WHILE_STATEMENT:
|
||||
case EXTERN_STATEMENT:
|
||||
case FUNCTION_STATEMENT:
|
||||
case IF_STATEMENT:
|
||||
case INCLUDE_STATEMENT:
|
||||
case INSTRUCTION_STATEMENT:
|
||||
case LONG_STATEMENT:
|
||||
case MACRO_STATEMENT:
|
||||
case ORG_STATEMENT:
|
||||
case REL_STATEMENT:
|
||||
case START_STATEMENT:
|
||||
case STRING_STATEMENT:
|
||||
case STRUCT_STATEMENT:
|
||||
case TARGET_STATEMENT:
|
||||
case UNDEFINE_STATEMENT:
|
||||
case VARIABLE_STATEMENT:
|
||||
case WHILE_STATEMENT:
|
||||
case WORD_STATEMENT:
|
||||
error(ILLEGAL_STATEMENT_IN_OBJECT_FILE_FUNCTION_ERROR,
|
||||
statementKindString(statement->kindOfStatement));
|
||||
return(FALSE);
|
||||
|
||||
case ASSERT_STATEMENT:
|
||||
return(encodeAssertStatement(statement->statementBody));
|
||||
|
||||
case FRETURN_STATEMENT:
|
||||
return(encodeFreturnStatement(statement->statementBody));
|
||||
|
||||
case GROUP_STATEMENT:
|
||||
return(encodeBlock(statement->statementBody));
|
||||
|
||||
case MDEFINE_STATEMENT:
|
||||
return(encodeMdefineStatement(statement->statementBody));
|
||||
|
||||
case MDO_UNTIL_STATEMENT:
|
||||
return(encodeMdoUntilStatement(statement->statementBody));
|
||||
|
||||
case MDO_WHILE_STATEMENT:
|
||||
return(encodeMdoWhileStatement(statement->statementBody));
|
||||
|
||||
case MFOR_STATEMENT:
|
||||
return(encodeMforStatement(statement->statementBody));
|
||||
|
||||
case MIF_STATEMENT:
|
||||
return(encodeMifStatement(statement->statementBody));
|
||||
|
||||
case MSWITCH_STATEMENT:
|
||||
return(encodeMswitchStatement(statement->statementBody));
|
||||
|
||||
case MVARIABLE_STATEMENT:
|
||||
return(encodeMvariableStatement(statement->statementBody));
|
||||
|
||||
case MWHILE_STATEMENT:
|
||||
return(encodeMwhileStatement(statement->statementBody));
|
||||
|
||||
case NULL_STATEMENT:
|
||||
return(TRUE);
|
||||
|
||||
case PERFORM_STATEMENT:
|
||||
return(encodeExpression(statement->statementBody));
|
||||
|
||||
default:
|
||||
botch("encodeStatementBody doesn't know kind %d\n",
|
||||
statement->kindOfStatement);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
encodeBlock(block)
|
||||
blockType *block;
|
||||
{
|
||||
if (!encodeByte(BLOCK_TAG))
|
||||
return(FALSE);
|
||||
while (block != NULL) {
|
||||
if (!encodeStatement(block))
|
||||
return(FALSE);
|
||||
block = block->nextStatement;
|
||||
}
|
||||
return(encodeByte(END_TAG));
|
||||
}
|
360
errorStuff.c
Normal file
360
errorStuff.c
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
errorStuff.c -- Error handling for the Macross assembler
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
5-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
bool nullStatementFlag;
|
||||
|
||||
/* puntOnError handles syntax errors and the like encountered during parsing
|
||||
or lexical analysis: it issues the relevent error message and scans the
|
||||
input up to the end of the line, in a (probably futile) effort to recover
|
||||
from the booboo. */
|
||||
|
||||
void
|
||||
puntOnError(theError, arg1, arg2, arg3)
|
||||
errorType theError;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
char c;
|
||||
void error();
|
||||
|
||||
while ((c = getc(input))!='\n' && c!=EOF)
|
||||
;
|
||||
ungetc(c, input);
|
||||
error(theError, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
|
||||
/* printErrorMessage is the general error message handler */
|
||||
|
||||
void
|
||||
printErrorMessage(theError, arg1, arg2, arg3)
|
||||
errorType theError;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'errorType'. */
|
||||
void fatalError();
|
||||
static bool dying = FALSE;
|
||||
|
||||
static char *errorMessageStrings[] = {
|
||||
"assignment in 'define' statement is not '='",
|
||||
"digit '%c' is not valid in base %d",
|
||||
"closing \"'\" missing in character constant",
|
||||
"closing '\"' missing in string constant",
|
||||
"octal value '0%o' too large to fit in a character",
|
||||
"character '%c' not allowed here",
|
||||
"comment not closed at end of file",
|
||||
"line comment not closed at end of file",
|
||||
"fatal: unable to open temporary scratch file '%s'",
|
||||
"%s cannot be a valid address for an 'org'",
|
||||
"negative block size in 'block' statement",
|
||||
"'%s' is %s and hence unassignable",
|
||||
"left and right hand sides of assignment are incompatible for '%s' operator",
|
||||
"operands of '%s' are incompatible with each other",
|
||||
"postincrement operand is %s and hence un-postincrementable",
|
||||
"postdecrement operand is %s and hence un-postdecrementable",
|
||||
"preincrement operand is %s and hence un-preincrementable",
|
||||
"predecrement operand is %s and hence un-predecrementable",
|
||||
"operand of '%s' is incompatible with operator",
|
||||
"value is not an address",
|
||||
"value is not an integer",
|
||||
"can't 'align' to zero or negative value",
|
||||
"left hand operand of '%s' has no value",
|
||||
"too many operands for '%s' instruction (should have %d)",
|
||||
"illegal address mode for '%s' instruction",
|
||||
"value %d is too large to fit in a byte",
|
||||
"value %d is too large to fit in a word",
|
||||
"illegal address mode for '%s' instruction",
|
||||
"divide by zero",
|
||||
"symbol '%s' undefined",
|
||||
"relative branch offset too large",
|
||||
"label '%s' previously defined",
|
||||
"fatal: can't open object file '%s'",
|
||||
"%s can't be made external",
|
||||
"warning: more than one output file name given on command line",
|
||||
"warning: '-%c' is not a recognized command line flag",
|
||||
"fatal: no output file name given on command line after '-o'",
|
||||
"fatal: unable to open input file '%s'",
|
||||
"fatal: unable to open include file '%s'",
|
||||
"%s cannot be a valid boolean value",
|
||||
"symbol '%s' was previously defined",
|
||||
"assignment to undeclared variable '%s'",
|
||||
"redefinition of variable '%s'",
|
||||
"'%s' is not a struct",
|
||||
"struct is too large for all components to be addressed",
|
||||
"struct field '%s' previously defined",
|
||||
"struct definition inside a struct definition",
|
||||
"'%s' is not a struct field",
|
||||
"macro '%s' previously defined",
|
||||
"macro definition inside a macro or function",
|
||||
"too many arguments given to macro '%s' (expects no more than %d)",
|
||||
"function definition inside a macro or function",
|
||||
"function '%s' previously defined",
|
||||
"too many arguments given to function '%s' (expects no more than %d)",
|
||||
"'%s' is not a function",
|
||||
"function '%s' did not return a value",
|
||||
"operand already has an address mode",
|
||||
"multiple address modes in expression",
|
||||
"include file name given is not a string",
|
||||
"start address previously given",
|
||||
"attempt to use function name '%s' as a value",
|
||||
"statement with side-effects not allowed inside a function",
|
||||
"symbolName can't find symbol",
|
||||
"error inside macro '%s'",
|
||||
"error inside function '%s'",
|
||||
"fatal: no listing file name given on command line after '-l'",
|
||||
"fatal: no symbol dump file name given on command line after '-%c'",
|
||||
"warning: more than one listing file name given on command line",
|
||||
"warning: more than one symbol dump file name given on command line",
|
||||
"fatal: can't open listing file '%s'",
|
||||
"fatal: can't open symbol dump file '%s'",
|
||||
"fatal: source file '%s' does not have a Macross source file name",
|
||||
"fatal: output file '%s' has a Macross source file name",
|
||||
"fatal: list file '%s' has a Macross source file name",
|
||||
"fatal: symbol dump file '%s' has a Macross source file name",
|
||||
"constraint value is not an integer",
|
||||
"constrained block crosses 0x%x boundary",
|
||||
"symbol '%s' has no value",
|
||||
"bad start address",
|
||||
"align inside constraint block -- alignment ignored",
|
||||
"constrain inside constraint block -- constraint ignored",
|
||||
"can't emit %s as a word",
|
||||
"can't emit %s as a byte",
|
||||
"too few operands for '%s' instruction (should have %d)",
|
||||
"bad color argument to 'atasciiColor'",
|
||||
"'printf' format argument is not a string",
|
||||
"'%s' argument #%d is not a string",
|
||||
"no arguments given to '%s'",
|
||||
"'%s' argument is not a string",
|
||||
"too few arguments to '%s'",
|
||||
"'%s' argument #%d is not an absolute value",
|
||||
"bad substring indices",
|
||||
"invalid 'assert' condition",
|
||||
"invalid 'assert' message",
|
||||
"'assert' failed: %s",
|
||||
"'assert' failed",
|
||||
"can't use %s as a switch value",
|
||||
"can't use %s as a case value",
|
||||
"can't forward reference a block",
|
||||
"warning: turning macro expansion listing off because listing in general is off",
|
||||
|
||||
"inappropriate address modes",
|
||||
"can't do byte address op",
|
||||
"quick data out of range",
|
||||
"ccr op is byte op",
|
||||
"sr op is word op",
|
||||
"shift op is word op",
|
||||
"cmp address is not byte op",
|
||||
"usp move is long op",
|
||||
"ccr move is word op",
|
||||
"sr move is word op",
|
||||
"cr move is long op",
|
||||
"address move not byte op",
|
||||
"trap data too large",
|
||||
"relative offset value too large",
|
||||
"can't do op from A register",
|
||||
"forward reference not allowed here",
|
||||
"fatal: address 0x%x is outside the available address space",
|
||||
"argument '%s' to 'apply' is not a macro name",
|
||||
"can't 'target' in relocatable mode",
|
||||
"%s cannot be a valid address for a 'target'",
|
||||
"macro '%s' is undefined",
|
||||
"bad position argument to 'nthChar'",
|
||||
"value argument to 'symbolDefine' is not an expression operand",
|
||||
"attempt to use %s as an array",
|
||||
"attempt to index an array with %s",
|
||||
"array index of %d exceeds maximum of %d",
|
||||
"too many initialization values for variable",
|
||||
"negative array index",
|
||||
"can't emit %s as a long",
|
||||
"can't use ++ or -- on an element of a string",
|
||||
"can't assign a non-character value into a string element",
|
||||
"negative array size given to 'makeArray'",
|
||||
"too many initialization values given to 'makeArray'",
|
||||
"array element has no value",
|
||||
"can't use prefix '%s' in an expression containing a forward reference",
|
||||
"can't use postfix '%s' in an expression containing a forward reference",
|
||||
"can't use assignment in an expression containing a forward reference",
|
||||
"fatal: too many errors (choke, gasp, wheeze, die...)",
|
||||
"expression too large for object file encoding",
|
||||
"operator assignment not allowed in object file expression",
|
||||
"temporary symbol '%s' in object file expression",
|
||||
"block operand in object file expression",
|
||||
"register operand in object file expression",
|
||||
"selection operand in object file expression (not yet)",
|
||||
"%s not allowed in object file expression",
|
||||
"array term not allowed in object file expression",
|
||||
"%s not allowed in object file function",
|
||||
"array mvariable declaration in object file function",
|
||||
"built-in function '%s' is not available in the linker",
|
||||
"fatal: no name definition given on command line after '-D'",
|
||||
"bad name definition: '%s'",
|
||||
"warning: perform statement has no side effects",
|
||||
};
|
||||
|
||||
static int errorCount = 0;
|
||||
|
||||
if (!terseErrorMessages || currentFileName != lastErrorFile ||
|
||||
currentLineNumber != lastErrorLine) {
|
||||
lastErrorFile = currentFileName;
|
||||
lastErrorLine = currentLineNumber;
|
||||
printf("\"%s\", line %d: ", currentFileName, currentLineNumber
|
||||
-1);
|
||||
printf(errorMessageStrings[(int)theError], arg1, arg2, arg3);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
if (++errorCount > ERROR_LIMIT && !dying) {
|
||||
dying = TRUE;
|
||||
fatalError(TOO_MANY_ERRORS_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
error(theError, arg1, arg2, arg3)
|
||||
errorType theError;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
printErrorMessage(theError, arg1, arg2, arg3);
|
||||
errorFlag = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
warning(theError, arg1, arg2, arg3)
|
||||
errorType theError;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
printErrorMessage(theError, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void
|
||||
fatalError(theError, arg1, arg2, arg3)
|
||||
errorType theError;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
printErrorMessage(theError, arg1, arg2, arg3);
|
||||
chokePukeAndDie();
|
||||
}
|
||||
|
||||
void
|
||||
fatalSystemError(theError, arg1, arg2, arg3)
|
||||
errorType theError;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
printErrorMessage(theError, arg1, arg2, arg3);
|
||||
perror("Unix says");
|
||||
chokePukeAndDie();
|
||||
}
|
||||
|
||||
/* yyerror is what yacc expects to call when it hits an error. Yacc passes
|
||||
the error message as a string (this is almost always 'syntax error'). */
|
||||
|
||||
void
|
||||
yyerror(s)
|
||||
char *s;
|
||||
{
|
||||
printf("\"%s\", line %d: %s\n", currentFileName, currentLineNumber,s);
|
||||
fflush(stdout);
|
||||
errorFlag = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* usageString is used in reporting errors having to do with symbol usage.
|
||||
It provides a translation between the internal representation and
|
||||
something printable (with the printable something designed to be embedded
|
||||
in a sentence). */
|
||||
|
||||
char *
|
||||
usageString(usageKind)
|
||||
symbolUsageKindType usageKind;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'symbolUsageKindType'. */
|
||||
|
||||
static char *usageStrings[NUM_OF_SYM_USAGES] = {
|
||||
"a struct name",
|
||||
"a struct field name",
|
||||
"a macro name",
|
||||
"an argument variable name",
|
||||
"a label",
|
||||
"an external symbol",
|
||||
"a variable",
|
||||
"a macro variable",
|
||||
"a symbol of unknown type",
|
||||
"a dead symbol",
|
||||
"a function name",
|
||||
"a built-in-function name",
|
||||
"a nested symbol of unknown type",
|
||||
"a define symbol",
|
||||
"a macro define symbol",
|
||||
"an unknown function",
|
||||
"an unknown macro",
|
||||
};
|
||||
return(usageStrings[(int)usageKind]);
|
||||
}
|
||||
|
||||
|
||||
/* valueKindString similarly deals with the different kinds of values. */
|
||||
|
||||
char *
|
||||
valueKindString(valueKind)
|
||||
valueKindType valueKind;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'valueKindType'. */
|
||||
|
||||
static char *valueKindStrings[] = {
|
||||
"an absolute value",
|
||||
"a data value",
|
||||
"a relocatable value",
|
||||
"a bss value",
|
||||
"a struct name",
|
||||
"a field name",
|
||||
"a macro name",
|
||||
"an operand value",
|
||||
"a string value",
|
||||
"a condition code",
|
||||
"an undefined value",
|
||||
"a function name",
|
||||
"a block of statements",
|
||||
"a built in function",
|
||||
"an array",
|
||||
"a failed expression"
|
||||
};
|
||||
return (valueKindStrings[(int)valueKind]);
|
||||
}
|
||||
|
||||
/* assignmentString similarly handles assignments */
|
||||
|
||||
char *
|
||||
assignmentString(assignment)
|
||||
assignmentKindType assignment;
|
||||
{
|
||||
/* This table MUST be maintained congruently with the definition of the
|
||||
enumerated type 'assignmentKindType'. */
|
||||
|
||||
static char *assignmentStringTable[] = {
|
||||
"=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=",
|
||||
"<<=", ">>=", "macross botch! no assigment"
|
||||
};
|
||||
return(assignmentStringTable[(int)assignment]);
|
||||
}
|
BIN
errorStuff.o
Normal file
BIN
errorStuff.o
Normal file
Binary file not shown.
39
errorfyle
Normal file
39
errorfyle
Normal file
@ -0,0 +1,39 @@
|
||||
make: Warning: Infinite loop: Target `macrossTypes.h' depends on itself
|
||||
cc -c -g -DYYDEBUG -DTARGET_CPU=CPU_6502 y.tab.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 actions_6502.c
|
||||
mv actions_6502.o actions.o
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 buildStuff1.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 buildStuff2.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 buildStuff3.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 builtInFunctions.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 builtInFunsSD_6502.c
|
||||
mv builtInFunsSD_6502.o builtInFunsSD.o
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 debugPrint.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 debugPrintSD_6502.c
|
||||
mv debugPrintSD_6502.o debugPrintSD.o
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 emitBranch_6502.c
|
||||
mv emitBranch_6502.o emitBranch.o
|
||||
cc -c -g -DBYTESWAPPED -DTARGET_CPU=CPU_6502 emitStuff.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 encode.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 errorStuff.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 expressionSemantics.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 fixups.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 garbage.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 initialize.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 lexer.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 listing.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 lookups.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 macrossTables_6502.c
|
||||
mv macrossTables_6502.o macrossTables.o
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 main.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 malloc.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 object.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 operandStuffSD_6502.c
|
||||
mv operandStuffSD_6502.o operandStuffSD.o
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 parserMisc.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 semanticMisc.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 statementSemantics.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 structSemantics.c
|
||||
cc -c -g -DTARGET_CPU=CPU_6502 tokenStrings_6502.c
|
||||
mv tokenStrings_6502.o tokenStrings.o
|
||||
cc -g -o macross y.tab.o actions.o buildStuff1.o buildStuff2.o buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o emitBranch.o emitStuff.o encode.o errorStuff.o expressionSemantics.o fixups.o garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o statementSemantics.o structSemantics.o tokenStrings.o
|
1219
expressionSemantics.c
Normal file
1219
expressionSemantics.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
expressionSemantics.o
Normal file
BIN
expressionSemantics.o
Normal file
Binary file not shown.
346
fixups.c
Normal file
346
fixups.c
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
fixups.c -- Routines to handle expressions being saved away for fixups
|
||||
in the Macross assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
20-December-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
operandType *dbOperand; /* safe temps for dbx hacking */
|
||||
expressionType *dbExpression;
|
||||
symbolTableEntryType *dbSymbol;
|
||||
|
||||
stringType *dbString = "graphics2.m";
|
||||
|
||||
#define nullDup(thing) if (thing==NULL) { return (NULL); }
|
||||
|
||||
#define expansionOff() {saveExpansion=expandMacros; expandMacros=FALSE;}
|
||||
#define expansionOn() expandMacros=saveExpansion;
|
||||
|
||||
/*
|
||||
Whenever a value is needed as the operand of an instruction or data
|
||||
statement, but one or more of the terms of the expression which define the
|
||||
value are themselves undefined symbols, we have to get fancy. What we do
|
||||
is use a zero value and save away a copy of the expression for later
|
||||
evaluation at a time (the end of assembly) when (hopefully) the undefined
|
||||
symbols will have been defined. It is necessary to save a copy of the
|
||||
expression, rather that the expression itself, since some of the terms of
|
||||
the expression may be variables whose value may change between now and
|
||||
when the saved expression gets reevaluated. When we are making the copy
|
||||
we replace any variables with their present values.
|
||||
|
||||
The routines below collectively duplicate expressions for later evaluation.
|
||||
*/
|
||||
|
||||
expressionType *
|
||||
generateFixupExpression(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
expressionType *result;
|
||||
expressionType *duplicateExpressionForFixup();
|
||||
|
||||
generatingFixup = TRUE;
|
||||
result = duplicateExpressionForFixup(expression, TRUE, FALSE);
|
||||
generatingFixup = FALSE;
|
||||
return(result);
|
||||
}
|
||||
|
||||
expressionType *
|
||||
duplicateExpressionForFixup(expression, isTopLevel, isSpecialFunctionOperand)
|
||||
expressionType *expression;
|
||||
bool isTopLevel;
|
||||
bool isSpecialFunctionOperand;
|
||||
{
|
||||
expressionType *result;
|
||||
expressionType *originalResult;
|
||||
valueType *value;
|
||||
symbolTableEntryType *identifier;
|
||||
symbolInContextType *context;
|
||||
operandType *newOperand;
|
||||
environmentType *saveEnvironment;
|
||||
bool saveExpansion;
|
||||
|
||||
operandType *duplicateOperandForFixup();
|
||||
symbolInContextType *getWorkingContext();
|
||||
functionCallTermType *duplicateFunctionCall();
|
||||
expressionType *duplicateArrayReference();
|
||||
valueType *evaluateIdentifier();
|
||||
valueType *evaluateHere();
|
||||
valueType *newValue();
|
||||
symbolTableEntryType *generateLocalLabel();
|
||||
stringType *saveString();
|
||||
|
||||
nullDup(expression);
|
||||
result = originalResult = typeAlloc(expressionType);
|
||||
*result = *expression;
|
||||
switch (expression->kindOfTerm) {
|
||||
|
||||
case STRING_EXPR:
|
||||
expand(moreExpression("%s", expression->expressionTerm.stringUnion));
|
||||
result->expressionTerm.stringUnion = saveString(originalResult->
|
||||
expressionTerm.stringUnion);
|
||||
break;
|
||||
|
||||
case IDENTIFIER_EXPR:
|
||||
identifier = expression->expressionTerm.identifierUnion;
|
||||
if (symbName(identifier)[0] == '$')
|
||||
identifier = result->expressionTerm.identifierUnion =
|
||||
generateLocalLabel(identifier);
|
||||
context = getWorkingContext(identifier);
|
||||
if (context->usage == ARGUMENT_SYMBOL && context->value->
|
||||
kindOfValue == OPERAND_VALUE) {
|
||||
if (isSpecialFunctionOperand) {
|
||||
while (context->usage == ARGUMENT_SYMBOL && context->value->
|
||||
kindOfValue == OPERAND_VALUE) {
|
||||
newOperand = (operandType *)context->value->value;
|
||||
if (newOperand->kindOfOperand == EXPRESSION_OPND &&
|
||||
(expression = newOperand->theOperand.
|
||||
expressionUnion) != NULL && expression->
|
||||
kindOfTerm == IDENTIFIER_EXPR) {
|
||||
identifier = expression->expressionTerm.
|
||||
identifierUnion;
|
||||
context = getWorkingContext(identifier);
|
||||
} else {
|
||||
expand(moreExpression("*fail*"));
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
expand(moreExpression("%s", symbName(identifier)));
|
||||
result->expressionTerm.identifierUnion = identifier;
|
||||
} else {
|
||||
saveEnvironment = currentEnvironment;
|
||||
currentEnvironment = currentEnvironment->previousEnvironment;
|
||||
if ((newOperand = duplicateOperandForFixup(
|
||||
context->value->value,
|
||||
FALSE)) == NULL) {
|
||||
result = NULL;
|
||||
} else {
|
||||
result->kindOfTerm = VALUE_EXPR;
|
||||
result->expressionTerm.valueUnion =
|
||||
newValue(OPERAND_VALUE,
|
||||
newOperand, newOperand->
|
||||
kindOfOperand);
|
||||
}
|
||||
currentEnvironment = saveEnvironment;
|
||||
}
|
||||
} else {
|
||||
expansionOff();
|
||||
if(!isUndefined(value = evaluateIdentifier(identifier,
|
||||
isTopLevel, NO_FIXUP_OK)) && value->kindOfValue !=
|
||||
RELOCATABLE_VALUE) {
|
||||
expansionOn();
|
||||
result->kindOfTerm = VALUE_EXPR;
|
||||
result->expressionTerm.valueUnion = value;
|
||||
expand((context->usage==MVARIABLE_SYMBOL ||
|
||||
context->usage==VARIABLE_SYMBOL ||
|
||||
context->usage==MDEFINE_SYMBOL) ?
|
||||
moreExpression("0x%x", value->value) :
|
||||
moreExpression("%s", symbName(identifier)));
|
||||
} else {
|
||||
expansionOn();
|
||||
expand(moreExpression("%s", symbName(identifier)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNCTION_CALL_EXPR:
|
||||
if ((result->expressionTerm.functionCallUnion =
|
||||
duplicateFunctionCall(expression->
|
||||
expressionTerm.functionCallUnion)) == NULL)
|
||||
result = NULL;
|
||||
break;
|
||||
|
||||
case NUMBER_EXPR:
|
||||
expand(moreExpression("0x%x", result->expressionTerm.numberUnion));
|
||||
/* keep unchanged */
|
||||
break;
|
||||
|
||||
case SUBEXPRESSION_EXPR:
|
||||
expand(moreExpression("("));
|
||||
if ((result->expressionTerm.subexpressionUnion =
|
||||
duplicateExpressionForFixup(expression->
|
||||
expressionTerm.subexpressionUnion,
|
||||
isTopLevel, FALSE)) == NULL)
|
||||
result = NULL;
|
||||
expand(moreExpression(")"));
|
||||
break;
|
||||
|
||||
case UNOP_EXPR:
|
||||
expand(moreExpression("%s", tokenString(expression->expressionTerm.
|
||||
unopUnion->unop)));
|
||||
result->expressionTerm.unopUnion = typeAlloc(unopTermType);
|
||||
result->expressionTerm.unopUnion->unop = expression->expressionTerm.
|
||||
unopUnion->unop;
|
||||
if ((result->expressionTerm.unopUnion->unopArgument =
|
||||
duplicateExpressionForFixup(expression->
|
||||
expressionTerm.unopUnion->unopArgument,
|
||||
FALSE, FALSE)) == NULL)
|
||||
result = NULL;
|
||||
break;
|
||||
|
||||
case BINOP_EXPR:
|
||||
result->expressionTerm.binopUnion = typeAlloc(binopTermType);
|
||||
result->expressionTerm.binopUnion->binop = expression->expressionTerm.
|
||||
binopUnion->binop;
|
||||
if ((result->expressionTerm.binopUnion->leftArgument =
|
||||
duplicateExpressionForFixup(expression->
|
||||
expressionTerm.binopUnion->leftArgument,
|
||||
FALSE, FALSE)) == NULL) {
|
||||
expand(moreExpression("*fail*"));
|
||||
result = NULL;
|
||||
} else {
|
||||
expand(moreExpression("%s", tokenString(expression->
|
||||
expressionTerm.binopUnion->binop)));
|
||||
if ((result->expressionTerm.binopUnion->rightArgument =
|
||||
duplicateExpressionForFixup(expression->
|
||||
expressionTerm.binopUnion->rightArgument,
|
||||
FALSE, FALSE)) == NULL) {
|
||||
result = NULL;
|
||||
expand(moreExpression("*fail*"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PREOP_EXPR:
|
||||
expand(moreExpression("*fail*"));
|
||||
error(CANT_USE_PREOP_WITH_FORWARD_REFERENCE_ERROR, tokenString(
|
||||
expression->expressionTerm.preOpUnion->preOp));
|
||||
result = NULL;
|
||||
break;
|
||||
|
||||
case POSTOP_EXPR:
|
||||
expand(moreExpression("*fail*"));
|
||||
error(CANT_USE_POSTOP_WITH_FORWARD_REFERENCE_ERROR, tokenString(
|
||||
expression->expressionTerm.postOpUnion->postOp));
|
||||
result = NULL;
|
||||
break;
|
||||
|
||||
case HERE_EXPR:
|
||||
result->kindOfTerm = VALUE_EXPR;
|
||||
result->expressionTerm.valueUnion = evaluateHere();
|
||||
expand(moreExpression("0x%x", result->expressionTerm.valueUnion->
|
||||
value));
|
||||
break;
|
||||
|
||||
case ASSIGN_EXPR:
|
||||
expand(moreExpression("*fail*"));
|
||||
error(CANT_USE_ASSIGNMENT_WITH_FORWARD_REFERENCE_ERROR);
|
||||
result = NULL;
|
||||
break;
|
||||
|
||||
case CONDITION_CODE_EXPR:
|
||||
/* keep unchanged */
|
||||
expand(moreExpression("%s", conditionString(expression->
|
||||
expressionTerm.conditionCodeUnion)));
|
||||
break;
|
||||
|
||||
case VALUE_EXPR:
|
||||
/* keep unchanged */
|
||||
expand(moreExpression("0x%x", expression->expressionTerm.valueUnion->
|
||||
value));
|
||||
break;
|
||||
|
||||
case ARRAY_EXPR:
|
||||
result = duplicateArrayReference(expression->expressionTerm.
|
||||
arrayUnion);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("duplicateExpression: funny expression kind %d\n",
|
||||
expression->kindOfTerm);
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
functionCallTermType *
|
||||
duplicateFunctionCall(functionCall)
|
||||
functionCallTermType *functionCall;
|
||||
{
|
||||
functionCallTermType *result;
|
||||
operandListType **argument;
|
||||
operandListType *parameterList;
|
||||
|
||||
operandListType *duplicateOperandForFixup();
|
||||
|
||||
result = typeAlloc(functionCallTermType);
|
||||
result->functionName = functionCall->functionName;
|
||||
expand(moreExpression("%s(", symbName(functionCall->functionName)));
|
||||
result->parameters = NULL;
|
||||
parameterList = functionCall->parameters;
|
||||
argument = &(result->parameters);
|
||||
while (parameterList != NULL) {
|
||||
*argument = duplicateOperandForFixup(parameterList,
|
||||
(functionCall->functionName->context->attributes &
|
||||
SPECIAL_FUNCTION_ATT) != 0);
|
||||
(*argument)->nextOperand = NULL;
|
||||
argument = &((*argument)->nextOperand);
|
||||
parameterList = parameterList->nextOperand;
|
||||
expand(parameterList != NULL ? moreExpression(", ") : 0);
|
||||
}
|
||||
expand(moreExpression(")"));
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
expressionType *
|
||||
duplicateArrayReference(arrayTerm)
|
||||
arrayTermType *arrayTerm;
|
||||
{
|
||||
anyOldThing *resultThing;
|
||||
valueKindType kindOfResult;
|
||||
expressionType *result;
|
||||
stringType *charPtr;
|
||||
valueType **valuePtr;
|
||||
environmentType *saveEnvironment;
|
||||
bool saveExpansion;
|
||||
operandType *newOperand;
|
||||
|
||||
valueType *newValue();
|
||||
operandType *duplicateOperandForFixup();
|
||||
anyOldThing *arrayLookup();
|
||||
|
||||
expansionOff();
|
||||
resultThing = arrayLookup(arrayTerm, &kindOfResult);
|
||||
expansionOn();
|
||||
if (*(valueType **)resultThing == NULL) {
|
||||
error(VALUELESS_ARRAY_ELEMENT_ERROR);
|
||||
result = NULL;
|
||||
} else if (kindOfResult == FAIL) {
|
||||
result = NULL;
|
||||
} else if (kindOfResult == STRING_VALUE) {
|
||||
charPtr = (stringType *)resultThing;
|
||||
result = typeAlloc(expressionType);
|
||||
result->kindOfTerm = VALUE_EXPR;
|
||||
result->expressionTerm.valueUnion = newValue(ABSOLUTE_VALUE,
|
||||
*charPtr, EXPRESSION_OPND);
|
||||
} else {
|
||||
valuePtr = (valueType **) resultThing;
|
||||
if ((*valuePtr)->kindOfValue == OPERAND_VALUE) {
|
||||
saveEnvironment = currentEnvironment;
|
||||
currentEnvironment = currentEnvironment->
|
||||
previousEnvironment;
|
||||
if ((newOperand = duplicateOperandForFixup((*
|
||||
valuePtr)->value, FALSE)) == NULL) {
|
||||
result = NULL;
|
||||
} else {
|
||||
result = typeAlloc(expressionType);
|
||||
result->kindOfTerm = VALUE_EXPR;
|
||||
result->expressionTerm.valueUnion = newValue(
|
||||
OPERAND_VALUE, newOperand,
|
||||
newOperand->kindOfOperand);
|
||||
}
|
||||
currentEnvironment = saveEnvironment;
|
||||
} else {
|
||||
result = typeAlloc(expressionType);
|
||||
result->kindOfTerm = VALUE_EXPR;
|
||||
dupValue(result->expressionTerm.valueUnion,*valuePtr);
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
829
garbage.c
Normal file
829
garbage.c
Normal file
@ -0,0 +1,829 @@
|
||||
/*
|
||||
garbage.c -- Routines to eat up a parse tree and throw it away
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
4-February-1985
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
#define nullFree(thing) if (thing == NULL) return;
|
||||
|
||||
void
|
||||
freeArrayTerm(arrayTerm)
|
||||
arrayTermType *arrayTerm;
|
||||
{
|
||||
void freeExpression();
|
||||
|
||||
nullFree(arrayTerm);
|
||||
freeExpression(arrayTerm->arrayName);
|
||||
freeExpression(arrayTerm->arrayIndex);
|
||||
free(arrayTerm);
|
||||
}
|
||||
|
||||
void
|
||||
freeAssignmentTerm(assignmentTerm)
|
||||
binopTermType *assignmentTerm;
|
||||
{
|
||||
void freeExpression();
|
||||
|
||||
nullFree(assignmentTerm);
|
||||
freeExpression(assignmentTerm->rightArgument);
|
||||
free(assignmentTerm);
|
||||
}
|
||||
|
||||
void
|
||||
freeBinopTerm(binopTerm)
|
||||
binopTermType *binopTerm;
|
||||
{
|
||||
void freeExpression();
|
||||
|
||||
nullFree(binopTerm);
|
||||
freeExpression(binopTerm->leftArgument);
|
||||
if (binopTerm->binop != SELECT)
|
||||
freeExpression(binopTerm->rightArgument);
|
||||
free(binopTerm);
|
||||
}
|
||||
|
||||
void
|
||||
freeFunctionCall(functionCall)
|
||||
functionCallTermType *functionCall;
|
||||
{
|
||||
void freeOperandList();
|
||||
|
||||
nullFree(functionCall);
|
||||
freeOperandList(functionCall->parameters);
|
||||
free(functionCall);
|
||||
}
|
||||
|
||||
void
|
||||
freePostopTerm(postopTerm)
|
||||
postOpTermType *postopTerm;
|
||||
{
|
||||
nullFree(postopTerm);
|
||||
free(postopTerm);
|
||||
}
|
||||
|
||||
void
|
||||
freePreopTerm(preopTerm)
|
||||
preOpTermType *preopTerm;
|
||||
{
|
||||
nullFree(preopTerm);
|
||||
free(preopTerm);
|
||||
}
|
||||
|
||||
void
|
||||
freeString(string)
|
||||
stringType *string;
|
||||
{
|
||||
nullFree(string);
|
||||
free(string);
|
||||
}
|
||||
|
||||
void
|
||||
freeUnopTerm(unopTerm)
|
||||
unopTermType *unopTerm;
|
||||
{
|
||||
void freeExpression();
|
||||
|
||||
nullFree(unopTerm);
|
||||
freeExpression(unopTerm->unopArgument);
|
||||
free(unopTerm);
|
||||
}
|
||||
|
||||
void
|
||||
freeExpression(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
nullFree(expression);
|
||||
switch (expression->kindOfTerm) {
|
||||
|
||||
case CONDITION_CODE_EXPR:
|
||||
case HERE_EXPR:
|
||||
case IDENTIFIER_EXPR:
|
||||
case NUMBER_EXPR:
|
||||
case VALUE_EXPR:
|
||||
case STRING_EXPR:
|
||||
break;
|
||||
|
||||
case ARRAY_EXPR:
|
||||
freeArrayTerm(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case ASSIGN_EXPR:
|
||||
freeAssignmentTerm(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case BINOP_EXPR:
|
||||
freeBinopTerm(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case FUNCTION_CALL_EXPR:
|
||||
freeFunctionCall(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case POSTOP_EXPR:
|
||||
freePostopTerm(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case PREOP_EXPR:
|
||||
freePreopTerm(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case SUBEXPRESSION_EXPR:
|
||||
freeExpression(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
case UNOP_EXPR:
|
||||
freeUnopTerm(expression->expressionTerm);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("freeExpression: funny expression kind %d\n",
|
||||
expression->kindOfTerm);
|
||||
break;
|
||||
}
|
||||
free(expression);
|
||||
}
|
||||
|
||||
void
|
||||
freeExpressionList(expressionList)
|
||||
expressionListType *expressionList;
|
||||
{
|
||||
expressionListType *newExpressionList;
|
||||
|
||||
while (expressionList != NULL) {
|
||||
freeExpression(expressionList->theExpression);
|
||||
newExpressionList = expressionList->nextExpression;
|
||||
free(expressionList);
|
||||
expressionList = newExpressionList;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeIdentifierList(identifierList)
|
||||
identifierListType *identifierList;
|
||||
{
|
||||
identifierListType *newIdentifierList;
|
||||
|
||||
while (identifierList != NULL) {
|
||||
newIdentifierList = identifierList->nextIdentifier;
|
||||
free(identifierList);
|
||||
identifierList = newIdentifierList;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeSelectionList(selectionList)
|
||||
selectionListType *selectionList;
|
||||
{
|
||||
freeIdentifierList(selectionList);
|
||||
}
|
||||
|
||||
void
|
||||
freeBlock(block)
|
||||
blockType *block;
|
||||
{
|
||||
void freeStatement();
|
||||
|
||||
nullFree(block);
|
||||
freeStatement(block);
|
||||
}
|
||||
|
||||
void
|
||||
freeCase(aCase)
|
||||
caseType *aCase;
|
||||
{
|
||||
freeExpressionList(aCase->caseTags);
|
||||
freeBlock(aCase->caseBody);
|
||||
free(aCase);
|
||||
}
|
||||
|
||||
void
|
||||
freeCaseList(caseList)
|
||||
caseListType *caseList;
|
||||
{
|
||||
caseListType *newCaseList;
|
||||
|
||||
while (caseList != NULL) {
|
||||
freeCase(caseList->theCase);
|
||||
newCaseList = caseList->nextCase;
|
||||
free(caseList);
|
||||
caseList = newCaseList;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeOperandList(operandList)
|
||||
operandListType *operandList;
|
||||
{
|
||||
freeOperand(operandList);
|
||||
}
|
||||
|
||||
void
|
||||
freeMacro(operands)
|
||||
operandListType *operands;
|
||||
{
|
||||
freeOperandList(operands);
|
||||
}
|
||||
|
||||
void
|
||||
freeMachineInstruction(operands)
|
||||
operandListType *operands;
|
||||
{
|
||||
freeOperandList(operands);
|
||||
}
|
||||
|
||||
void
|
||||
freeAlignStatement(alignStatement)
|
||||
alignStatementBodyType *alignStatement;
|
||||
{
|
||||
nullFree(alignStatement);
|
||||
freeExpression(alignStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeAssertStatement(assertStatement)
|
||||
assertStatementBodyType *assertStatement;
|
||||
{
|
||||
nullFree(assertStatement);
|
||||
freeExpression(assertStatement->condition);
|
||||
freeExpression(assertStatement->message);
|
||||
free(assertStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeBlockStatement(blockStatement)
|
||||
blockStatementBodyType *blockStatement;
|
||||
{
|
||||
nullFree(blockStatement);
|
||||
freeExpressionList(blockStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeByteStatement(byteStatement)
|
||||
byteStatementBodyType *byteStatement;
|
||||
{
|
||||
byteStatementBodyType *newByteStatement;
|
||||
|
||||
nullFree(byteStatement);
|
||||
while (byteStatement != NULL) {
|
||||
freeExpression(byteStatement->theExpression);
|
||||
newByteStatement = byteStatement->nextExpression;
|
||||
free(byteStatement);
|
||||
byteStatement = newByteStatement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeConstrainStatement(constrainStatement)
|
||||
constrainStatementBodyType *constrainStatement;
|
||||
{
|
||||
nullFree(constrainStatement);
|
||||
freeExpression(constrainStatement->constraint);
|
||||
freeBlock(constrainStatement->constrainedBlock);
|
||||
free(constrainStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeDbyteStatement(dbyteStatement)
|
||||
dbyteStatementBodyType *dbyteStatement;
|
||||
{
|
||||
dbyteStatementBodyType *newDbyteStatement;
|
||||
|
||||
nullFree(dbyteStatement);
|
||||
while (dbyteStatement != NULL) {
|
||||
freeExpression(dbyteStatement->theExpression);
|
||||
newDbyteStatement = dbyteStatement->nextExpression;
|
||||
free(dbyteStatement);
|
||||
dbyteStatement = newDbyteStatement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeDefineStatement(defineStatement)
|
||||
defineStatementBodyType *defineStatement;
|
||||
{
|
||||
nullFree(defineStatement);
|
||||
freeExpression(defineStatement->theValue);
|
||||
free(defineStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeDoUntilStatement(doUntilStatement)
|
||||
doUntilStatementBodyType *doUntilStatement;
|
||||
{
|
||||
nullFree(doUntilStatement);
|
||||
freeBlock(doUntilStatement->doUntilLoop);
|
||||
free(doUntilStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeDoWhileStatement(doWhileStatement)
|
||||
doWhileStatementBodyType *doWhileStatement;
|
||||
{
|
||||
nullFree(doWhileStatement);
|
||||
freeBlock(doWhileStatement->doWhileLoop);
|
||||
free(doWhileStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeExternStatement(externStatement)
|
||||
externStatementBodyType *externStatement;
|
||||
{
|
||||
freeIdentifierList(externStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeFreturnStatement(freturnStatement)
|
||||
freturnStatementBodyType *freturnStatement;
|
||||
{
|
||||
nullFree(freturnStatement);
|
||||
freeExpression(freturnStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeFunctionStatement(functionStatement)
|
||||
functionStatementBodyType *functionStatement;
|
||||
{
|
||||
nullFree(functionStatement);
|
||||
free(functionStatement->functionName);
|
||||
free(functionStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeIfStatement(ifStatement)
|
||||
ifStatementBodyType *ifStatement;
|
||||
{
|
||||
nullFree(ifStatement);
|
||||
if (ifStatement->consequence != NULL)
|
||||
freeBlock(ifStatement->consequence);
|
||||
if (ifStatement->continuation.continuationBodyUnion != NULL) {
|
||||
freeIfStatement(ifStatement->continuation);
|
||||
}
|
||||
free(ifStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeIncludeStatement(includeStatement)
|
||||
includeStatementBodyType *includeStatement;
|
||||
{
|
||||
nullFree(includeStatement);
|
||||
freeExpression(includeStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeInstructionStatement(instructionStatement)
|
||||
instructionStatementBodyType *instructionStatement;
|
||||
{
|
||||
nullFree(instructionStatement);
|
||||
switch(instructionStatement->kindOfInstruction) {
|
||||
|
||||
case OPCODE_INSTRUCTION:
|
||||
freeMachineInstruction(instructionStatement->theOperands);
|
||||
break;
|
||||
|
||||
case MACRO_INSTRUCTION:
|
||||
freeMacro(instructionStatement->theOperands);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("bad instruction type=%d\n", instructionStatement->
|
||||
kindOfInstruction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeLongStatement(longStatement)
|
||||
longStatementBodyType *longStatement;
|
||||
{
|
||||
longStatementBodyType *newLongStatement;
|
||||
|
||||
nullFree(longStatement);
|
||||
while (longStatement != NULL) {
|
||||
freeExpression(longStatement->theExpression);
|
||||
newLongStatement = longStatement->nextExpression;
|
||||
free(longStatement);
|
||||
longStatement = newLongStatement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeMacroStatement(macroStatement)
|
||||
macroStatementBodyType *macroStatement;
|
||||
{
|
||||
nullFree(macroStatement);
|
||||
free(macroStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMdefineStatement(mdefineStatement)
|
||||
defineStatementBodyType *mdefineStatement;
|
||||
{
|
||||
valueType *freeDefineExpression();
|
||||
|
||||
nullFree(mdefineStatement);
|
||||
freeExpression(mdefineStatement->theValue);
|
||||
free(mdefineStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMdoUntilStatement(mdoUntilStatement)
|
||||
mdoUntilStatementBodyType *mdoUntilStatement;
|
||||
{
|
||||
nullFree(mdoUntilStatement);
|
||||
freeBlock(mdoUntilStatement->mdoUntilLoop);
|
||||
freeExpression(mdoUntilStatement->mdoUntilCondition);
|
||||
}
|
||||
|
||||
void
|
||||
freeMdoWhileStatement(mdoWhileStatement)
|
||||
mdoWhileStatementBodyType *mdoWhileStatement;
|
||||
{
|
||||
nullFree(mdoWhileStatement);
|
||||
freeBlock(mdoWhileStatement->mdoWhileLoop);
|
||||
freeExpression(mdoWhileStatement->mdoWhileCondition);
|
||||
free(mdoWhileStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMifStatement(mifStatement)
|
||||
mifStatementBodyType *mifStatement;
|
||||
{
|
||||
nullFree(mifStatement);
|
||||
freeExpression(mifStatement->mifCondition);
|
||||
freeBlock(mifStatement->mifConsequence);
|
||||
freeMifStatement(mifStatement->mifContinuation.
|
||||
mifContinuationBodyUnion);
|
||||
free(mifStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMswitchStatement(mswitchStatement)
|
||||
mswitchStatementBodyType *mswitchStatement;
|
||||
{
|
||||
freeExpression(mswitchStatement->switchExpression);
|
||||
freeCaseList(mswitchStatement->cases);
|
||||
free(mswitchStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMforStatement(mforStatement)
|
||||
mforStatementBodyType *mforStatement;
|
||||
{
|
||||
nullFree(mforStatement);
|
||||
freeExpression(mforStatement->initExpression);
|
||||
freeExpression(mforStatement->testExpression);
|
||||
freeExpression(mforStatement->incrExpression);
|
||||
freeBlock(mforStatement->forLoop);
|
||||
free(mforStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMvariableStatement(mvariableStatement)
|
||||
mvariableStatementBodyType *mvariableStatement;
|
||||
{
|
||||
nullFree(mvariableStatement);
|
||||
if ((int)mvariableStatement->theDimension != -1)
|
||||
freeExpression(mvariableStatement->theDimension);
|
||||
freeExpressionList(mvariableStatement->theValue);
|
||||
free(mvariableStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeMwhileStatement(mwhileStatement)
|
||||
mwhileStatementBodyType *mwhileStatement;
|
||||
{
|
||||
nullFree(mwhileStatement);
|
||||
freeExpression(mwhileStatement->mwhileCondition);
|
||||
freeBlock(mwhileStatement->mwhileLoop);
|
||||
free(mwhileStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeOrgStatement(orgStatement)
|
||||
orgStatementBodyType *orgStatement;
|
||||
{
|
||||
nullFree(orgStatement);
|
||||
freeExpression(orgStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freePerformStatement(performStatement)
|
||||
performStatementBodyType *performStatement;
|
||||
{
|
||||
nullFree(performStatement);
|
||||
freeExpression(performStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeRelStatement(relStatement)
|
||||
relStatementBodyType *relStatement;
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
freeStartStatement(startStatement)
|
||||
startStatementBodyType *startStatement;
|
||||
{
|
||||
nullFree(startStatement);
|
||||
freeExpression(startStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeStringStatement(stringStatement)
|
||||
stringStatementBodyType *stringStatement;
|
||||
{
|
||||
stringStatementBodyType *newStringStatement;
|
||||
|
||||
nullFree(stringStatement);
|
||||
while (stringStatement != NULL) {
|
||||
freeExpression(stringStatement->theExpression);
|
||||
newStringStatement = stringStatement->nextExpression;
|
||||
free(stringStatement);
|
||||
stringStatement = newStringStatement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeStructStatement(structStatement)
|
||||
structStatementBodyType *structStatement;
|
||||
{
|
||||
nullFree(structStatement);
|
||||
freeBlock(structStatement->structBody);
|
||||
free(structStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeTargetStatement(targetStatement)
|
||||
targetStatementBodyType *targetStatement;
|
||||
{
|
||||
nullFree(targetStatement);
|
||||
freeExpression(targetStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeUndefineStatement(undefineStatement)
|
||||
undefineStatementBodyType *undefineStatement;
|
||||
{
|
||||
freeIdentifierList(undefineStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeVariableStatement(variableStatement)
|
||||
variableStatementBodyType *variableStatement;
|
||||
{
|
||||
nullFree(variableStatement);
|
||||
if ((int)variableStatement->theDimension != -1)
|
||||
freeExpression(variableStatement->theDimension);
|
||||
freeExpressionList(variableStatement->theValue);
|
||||
free(variableStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeWhileStatement(whileStatement)
|
||||
whileStatementBodyType *whileStatement;
|
||||
{
|
||||
nullFree(whileStatement);
|
||||
freeBlock(whileStatement->whileLoop);
|
||||
free(whileStatement);
|
||||
}
|
||||
|
||||
void
|
||||
freeWordStatement(wordStatement)
|
||||
wordStatementBodyType *wordStatement;
|
||||
{
|
||||
wordStatementBodyType *newWordStatement;
|
||||
|
||||
nullFree(wordStatement);
|
||||
while (wordStatement != NULL) {
|
||||
freeExpression(wordStatement->theExpression);
|
||||
newWordStatement = wordStatement->nextExpression;
|
||||
free(wordStatement);
|
||||
wordStatement = newWordStatement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeStatementBody(kind, body)
|
||||
statementKindType kind;
|
||||
statementBodyType body;
|
||||
{
|
||||
switch (kind) {
|
||||
|
||||
case ALIGN_STATEMENT:
|
||||
freeAlignStatement(body);
|
||||
break;
|
||||
|
||||
case ASSERT_STATEMENT:
|
||||
freeAssertStatement(body);
|
||||
break;
|
||||
|
||||
case BLOCK_STATEMENT:
|
||||
freeBlockStatement(body);
|
||||
break;
|
||||
|
||||
case BYTE_STATEMENT:
|
||||
freeByteStatement(body);
|
||||
break;
|
||||
|
||||
case CONSTRAIN_STATEMENT:
|
||||
freeConstrainStatement(body);
|
||||
break;
|
||||
|
||||
case DBYTE_STATEMENT:
|
||||
freeDbyteStatement(body);
|
||||
break;
|
||||
|
||||
case DEFINE_STATEMENT:
|
||||
freeDefineStatement(body);
|
||||
break;
|
||||
|
||||
case DO_UNTIL_STATEMENT:
|
||||
freeDoUntilStatement(body);
|
||||
break;
|
||||
|
||||
case DO_WHILE_STATEMENT:
|
||||
freeDoWhileStatement(body);
|
||||
break;
|
||||
|
||||
case EXTERN_STATEMENT:
|
||||
freeExternStatement(body);
|
||||
break;
|
||||
|
||||
case FRETURN_STATEMENT:
|
||||
freeFreturnStatement(body);
|
||||
break;
|
||||
|
||||
case FUNCTION_STATEMENT:
|
||||
freeFunctionStatement(body);
|
||||
break;
|
||||
|
||||
case GROUP_STATEMENT:
|
||||
freeBlock(body);
|
||||
break;
|
||||
|
||||
case IF_STATEMENT:
|
||||
freeIfStatement(body);
|
||||
break;
|
||||
|
||||
case INCLUDE_STATEMENT:
|
||||
freeIncludeStatement(body);
|
||||
break;
|
||||
|
||||
case INSTRUCTION_STATEMENT:
|
||||
freeInstructionStatement(body);
|
||||
break;
|
||||
|
||||
case LONG_STATEMENT:
|
||||
freeLongStatement(body);
|
||||
break;
|
||||
|
||||
case MACRO_STATEMENT:
|
||||
freeMacroStatement(body);
|
||||
break;
|
||||
|
||||
case MDEFINE_STATEMENT:
|
||||
freeMdefineStatement(body);
|
||||
break;
|
||||
|
||||
case MDO_UNTIL_STATEMENT:
|
||||
freeMdoUntilStatement(body);
|
||||
break;
|
||||
|
||||
case MDO_WHILE_STATEMENT:
|
||||
freeMdoWhileStatement(body);
|
||||
break;
|
||||
|
||||
case MIF_STATEMENT:
|
||||
freeMifStatement(body);
|
||||
break;
|
||||
|
||||
case MSWITCH_STATEMENT:
|
||||
freeMswitchStatement(body);
|
||||
break;
|
||||
|
||||
case MFOR_STATEMENT:
|
||||
freeMforStatement(body);
|
||||
break;
|
||||
|
||||
case MVARIABLE_STATEMENT:
|
||||
freeMvariableStatement(body);
|
||||
break;
|
||||
|
||||
case MWHILE_STATEMENT:
|
||||
freeMwhileStatement(body);
|
||||
break;
|
||||
|
||||
case NULL_STATEMENT:
|
||||
/* do nothing */
|
||||
break;
|
||||
|
||||
case ORG_STATEMENT:
|
||||
freeOrgStatement(body);
|
||||
break;
|
||||
|
||||
case PERFORM_STATEMENT:
|
||||
freePerformStatement(body);
|
||||
break;
|
||||
|
||||
case REL_STATEMENT:
|
||||
freeRelStatement(body);
|
||||
break;
|
||||
|
||||
case START_STATEMENT:
|
||||
freeStartStatement(body);
|
||||
break;
|
||||
|
||||
case STRING_STATEMENT:
|
||||
freeStringStatement(body);
|
||||
break;
|
||||
|
||||
case STRUCT_STATEMENT:
|
||||
freeStructStatement(body);
|
||||
break;
|
||||
|
||||
case TARGET_STATEMENT:
|
||||
freeTargetStatement(body);
|
||||
break;
|
||||
|
||||
case UNDEFINE_STATEMENT:
|
||||
freeUndefineStatement(body);
|
||||
break;
|
||||
|
||||
case VARIABLE_STATEMENT:
|
||||
freeVariableStatement(body);
|
||||
break;
|
||||
|
||||
case WHILE_STATEMENT:
|
||||
freeWhileStatement(body);
|
||||
break;
|
||||
|
||||
case WORD_STATEMENT:
|
||||
freeWordStatement(body);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("freeStatementBody doesn't know kind %d\n", kind);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeLabelList(labelList)
|
||||
labelListType *labelList;
|
||||
{
|
||||
labelListType *nextLabel;
|
||||
|
||||
while (labelList != NULL) {
|
||||
nextLabel = labelList->nextLabel;
|
||||
free(labelList);
|
||||
labelList = nextLabel;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeStatement(statement)
|
||||
statementType *statement;
|
||||
{
|
||||
statementType *newStatement;
|
||||
|
||||
while (statement != NULL) {
|
||||
freeLabelList(statement->labels);
|
||||
freeStatementBody(statement->kindOfStatement, statement->
|
||||
statementBody);
|
||||
newStatement = statement->nextStatement;
|
||||
free(statement);
|
||||
statement = newStatement;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeArray(array)
|
||||
arrayType *array;
|
||||
{
|
||||
int i;
|
||||
void freeValue();
|
||||
|
||||
if (array->arraySize > 0) {
|
||||
for (i=0; i<array->arraySize; i++)
|
||||
freeValue((array->arrayContents)[i]);
|
||||
free(array->arrayContents);
|
||||
}
|
||||
free(array);
|
||||
}
|
||||
|
||||
void
|
||||
freeValue(value)
|
||||
valueType *value;
|
||||
{
|
||||
if (value->kindOfValue == STRING_VALUE)
|
||||
freeString(value->value);
|
||||
else if (value->kindOfValue == ARRAY_VALUE)
|
||||
freeArray(value->value);
|
||||
free(value);
|
||||
}
|
557
initialize.c
Normal file
557
initialize.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
initialize.c -- Routines to get things going for the Macross assembler
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
6-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
#define isAlphaNumeric(c) (alphaNumericCharacterTable[c])
|
||||
|
||||
extern int yydebug;
|
||||
|
||||
static fileNameListType *bottomOfInputFileStack;
|
||||
static char *outputFileName;
|
||||
|
||||
void
|
||||
chokePukeAndDie()
|
||||
{
|
||||
unlink(outputFileName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
initializeStuff(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char **args;
|
||||
char *arg;
|
||||
int outputFilesFound;
|
||||
int listFilesFound;
|
||||
int symbolDumpFilesFound;
|
||||
char *listFileName;
|
||||
char *symbolDumpFileName;
|
||||
bool dontUnlinkTempFiles;
|
||||
|
||||
void createHashTables();
|
||||
void installBuiltInFunctions();
|
||||
void installPredefinedSymbols();
|
||||
void installCommandLineDefineSymbols();
|
||||
void openFirstInputFile();
|
||||
void queueInputFile();
|
||||
void noteCommandLineDefine();
|
||||
|
||||
for (i=0; i<128; i++) {
|
||||
lowerCaseCharacterTable[i] = i;
|
||||
alphabeticCharacterTable[i] = FALSE;
|
||||
numericCharacterTable[i] = FALSE;
|
||||
alphaNumericCharacterTable[i] = FALSE;
|
||||
}
|
||||
for (i='A'; i<='Z'; i++) {
|
||||
lowerCaseCharacterTable[i] = i - 'A' + 'a';
|
||||
alphabeticCharacterTable[i] = TRUE;
|
||||
alphabeticCharacterTable[i - 'A' + 'a'] = TRUE;
|
||||
alphaNumericCharacterTable[i] = TRUE;
|
||||
alphaNumericCharacterTable[i - 'A' + 'a'] = TRUE;
|
||||
}
|
||||
alphabeticCharacterTable['_'] = TRUE;
|
||||
alphaNumericCharacterTable['_'] = TRUE;
|
||||
for (i='0'; i<='9'; i++) {
|
||||
numericCharacterTable[i] = TRUE;
|
||||
alphaNumericCharacterTable[i] = TRUE;
|
||||
}
|
||||
|
||||
outputFilesFound = 0;
|
||||
listFilesFound = 0;
|
||||
symbolDumpFilesFound = 0;
|
||||
outputFileName = DEFAULT_OBJECT_FILE_NAME;
|
||||
dontUnlinkTempFiles = FALSE;
|
||||
produceLinkableObject = FALSE;
|
||||
|
||||
currentFileName = "<command line>"; /* for error messages... */
|
||||
currentLineNumber = 1; /* ...during startup */
|
||||
cumulativeLineNumber = 1;
|
||||
|
||||
nextEnvironmentNumber = GLOBAL_ENVIRONMENT_NUMBER;
|
||||
currentEnvironment = NULL;
|
||||
pushEnvironment(globalEnvironment);
|
||||
beneathFunction = FALSE;
|
||||
includeNestingDepth = 0;
|
||||
macroOrFunctionNestingDepth = 0;
|
||||
macroCallDepth = 0;
|
||||
tabCount = 1;
|
||||
statementEvaluationDepth = 0;
|
||||
structNestingDepth = 0;
|
||||
|
||||
performingFixups = FALSE;
|
||||
generatingFixup = FALSE;
|
||||
finishOperand = FALSE;
|
||||
unknownSymbolTag = UNKNOWN_SYMBOL;
|
||||
|
||||
haveUserStartAddress = FALSE;
|
||||
fixupStartAddress = FALSE;
|
||||
|
||||
currentLabelTagNumber = 0;
|
||||
currentLocalVariableList = NULL;
|
||||
inputFileStack = bottomOfInputFileStack = NULL;
|
||||
listingControlCounter = 0;
|
||||
nextLabelTagNumber = 1;
|
||||
commandLineDefines = NULL;
|
||||
|
||||
showAllSymbolsFlag = FALSE;
|
||||
backwardsCompatibleIfFlag = FALSE;
|
||||
debug = FALSE;
|
||||
yydebug = FALSE;
|
||||
emitPrint = FALSE;
|
||||
freeFlag = TRUE;
|
||||
freturnExit = FALSE;
|
||||
listingOn = FALSE;
|
||||
expandMacros = FALSE;
|
||||
standaloneExpansionFlag = FALSE;
|
||||
terseErrorMessages = FALSE;
|
||||
lastErrorLine = -1;
|
||||
lastErrorFile = NULL;
|
||||
symbolTableDumpOn = 0;
|
||||
positionIndependentCodeMode = FALSE;
|
||||
hackFlag = 0;
|
||||
|
||||
args = argv + 1;
|
||||
for (i=1; i<argc; i++) {
|
||||
arg = *args++;
|
||||
if (*arg != '-') {
|
||||
if (!isDotMName(arg)) {
|
||||
fatalError(FILE_NAME_IS_NOT_MACROSS_SOURCE_ERROR,
|
||||
arg);
|
||||
}
|
||||
queueInputFile(arg);
|
||||
continue;
|
||||
}
|
||||
for (j=1; arg[j]!='\0'; j++) switch (arg[j]) {
|
||||
|
||||
case 'a':
|
||||
showAllSymbolsFlag = TRUE;
|
||||
continue;
|
||||
|
||||
case 'B':
|
||||
backwardsCompatibleIfFlag = TRUE;
|
||||
continue;
|
||||
|
||||
case 'c':
|
||||
produceLinkableObject = TRUE;
|
||||
continue;
|
||||
|
||||
case 'd':
|
||||
debug = TRUE;
|
||||
continue;
|
||||
|
||||
case 'D':
|
||||
if (++i >= argc) {
|
||||
fatalError(NO_DASH_D_FILE_NAME_ERROR);
|
||||
} else {
|
||||
noteCommandLineDefine(*args++);
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'e':
|
||||
emitPrint = TRUE;
|
||||
continue;
|
||||
|
||||
case 'g':
|
||||
freeFlag = FALSE;
|
||||
continue;
|
||||
|
||||
case 'l':
|
||||
if (++i >= argc) {
|
||||
fatalError(NO_LIST_FILE_NAME_ERROR);
|
||||
} else {
|
||||
if (isDotMName(*args)) {
|
||||
fatalError(LIST_FILE_NAME_IS_MACROSS_SOURCE_ERROR,
|
||||
*args);
|
||||
}
|
||||
listFileName = *args++;
|
||||
listFilesFound++;
|
||||
}
|
||||
listingOn = TRUE;
|
||||
continue;
|
||||
|
||||
case 'm':
|
||||
expandMacros = TRUE;
|
||||
continue;
|
||||
|
||||
case 'o':
|
||||
if (++i >= argc) {
|
||||
fatalError(NO_DASH_O_FILE_NAME_ERROR);
|
||||
} else {
|
||||
if (isDotMName(*args)) {
|
||||
fatalError(OUTPUT_FILE_NAME_IS_MACROSS_SOURCE_ERROR,
|
||||
*args);
|
||||
}
|
||||
outputFileName = *args++;
|
||||
outputFilesFound++;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
positionIndependentCodeMode = TRUE;
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'h':
|
||||
case 'H':
|
||||
if (++i >= argc) {
|
||||
fatalError(NO_SYMBOL_DUMP_FILE_NAME_ERROR, arg[j]);
|
||||
} else {
|
||||
if (isDotMName(*args)) {
|
||||
fatalError(SYMBOL_DUMP_FILE_NAME_IS_MACROSS_SOURCE_ERROR,
|
||||
*args);
|
||||
}
|
||||
symbolDumpFileName = *args++;
|
||||
symbolDumpFilesFound++;
|
||||
}
|
||||
if (arg[j] == 'h') {
|
||||
hackFlag = 1;
|
||||
symbolTableDumpOn = 1;
|
||||
} else if (arg[j] == 'H') {
|
||||
hackFlag = 2;
|
||||
symbolTableDumpOn = 1;
|
||||
} else {
|
||||
symbolTableDumpOn = arg[j]=='s' ? 1 : 2;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 't':
|
||||
terseErrorMessages = TRUE;
|
||||
continue;
|
||||
|
||||
case 'u':
|
||||
dontUnlinkTempFiles = TRUE;
|
||||
continue;
|
||||
|
||||
case 'v':
|
||||
printVersion();
|
||||
continue;
|
||||
|
||||
case 'Y':
|
||||
yydebug = TRUE;
|
||||
continue;
|
||||
|
||||
default:
|
||||
warning(BAD_COMMAND_LINE_FLAG_ERROR, arg[j]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
openFirstInputFile();
|
||||
|
||||
if (outputFilesFound > 1) {
|
||||
warning(MORE_THAN_ONE_OUTPUT_FILE_ERROR);
|
||||
} else if ((objectFileOutput = fopen(outputFileName, "w"))==NULL) {
|
||||
fatalSystemError(CANT_OPEN_OBJECT_FILE_ERROR, outputFileName);
|
||||
}
|
||||
|
||||
if (listFilesFound > 1) {
|
||||
warning(MORE_THAN_ONE_LIST_FILE_ERROR);
|
||||
} else if (listFilesFound == 1) {
|
||||
if (strcmp(listFileName, "-") == 0) {
|
||||
listFileOutput = stdout;
|
||||
} else if ((listFileOutput = fopen(listFileName, "w"))==NULL){
|
||||
fatalSystemError(CANT_OPEN_LIST_FILE_ERROR, listFileName);
|
||||
}
|
||||
}
|
||||
|
||||
if (symbolDumpFilesFound > 1) {
|
||||
warning(MORE_THAN_ONE_SYMBOL_DUMP_FILE_ERROR);
|
||||
} else if (symbolDumpFilesFound == 1) {
|
||||
if (strcmp(symbolDumpFileName, "-") == 0) {
|
||||
symbolDumpFileOutput = stdout;
|
||||
} else if ((symbolDumpFileOutput = fopen(symbolDumpFileName,
|
||||
"w"))==NULL) {
|
||||
fatalSystemError(CANT_OPEN_SYMBOL_DUMP_FILE_ERROR, symbolDumpFileName);
|
||||
}
|
||||
}
|
||||
|
||||
expressionReferenceList[0] = expressionReferenceList[1] = NULL;
|
||||
numberOfReferencesInList[0] = numberOfReferencesInList[1] = 0;
|
||||
externalFunctionList = endOfExternalFunctionList = NULL;
|
||||
externalFunctionCount = 0;
|
||||
|
||||
currentLocationCounter.kindOfValue = RELOCATABLE_VALUE;
|
||||
currentLocationCounter.value = 0;
|
||||
targetOffset = 0;
|
||||
currentCodeMode = RELOCATABLE_BUFFER;
|
||||
relocatableHighWaterMark = -1;
|
||||
codeBreakList = NULL;
|
||||
lastCodeBreak = NULL;
|
||||
reservationList = NULL;
|
||||
|
||||
for (i=0; i<HASH_TABLE_SIZE; i++) {
|
||||
macroTable[i] = NULL;
|
||||
opcodeTable[i] = NULL;
|
||||
symbolTable[i] = NULL;
|
||||
keywordTable[i] = NULL;
|
||||
conditionTable[i] = NULL;
|
||||
}
|
||||
|
||||
absoluteCodeRegion.regionStartAddress = relocatableCodeRegion.
|
||||
regionStartAddress = 0xFFFF + 1;
|
||||
absoluteCodeRegion.regionEndAddress = relocatableCodeRegion.
|
||||
regionEndAddress = -1;
|
||||
for (i=0; i<CODE_BUFFERS_IN_ADDRESS_SPACE; i++) {
|
||||
absoluteCodeRegion.codeSegments[i] = NULL;
|
||||
relocatableCodeRegion.codeSegments[i] = NULL;
|
||||
}
|
||||
emptyBuffer = typeAlloc(codeBufferType);
|
||||
for (i=0; i<CODE_BUFFER_SIZE; i++)
|
||||
(*emptyBuffer)[i] = 0;
|
||||
|
||||
createHashTables();
|
||||
initializeLexDispatchTable();
|
||||
installBuiltInFunctions();
|
||||
installPredefinedSymbols();
|
||||
installCommandLineDefineSymbols();
|
||||
|
||||
if (listingOn) {
|
||||
if ((saveFileForPass2 = fopen(mktemp(pass2SourceFileName),
|
||||
"w+")) == NULL) {
|
||||
fatalSystemError(UNABLE_TO_OPEN_PASS_2_FILE_ERROR,
|
||||
pass2SourceFileName);
|
||||
}
|
||||
if (!dontUnlinkTempFiles)
|
||||
unlink(pass2SourceFileName); /* will take effect on
|
||||
program exit */
|
||||
|
||||
if ((indexFileForPass2 = fopen(mktemp(pass2IndexFileName),
|
||||
"w+")) == NULL) {
|
||||
fatalSystemError(UNABLE_TO_OPEN_PASS_2_FILE_ERROR,
|
||||
pass2IndexFileName);
|
||||
}
|
||||
if (!dontUnlinkTempFiles)
|
||||
unlink(pass2IndexFileName); /* will take effect on
|
||||
program exit */
|
||||
|
||||
if (expandMacros) {
|
||||
if ((macroFileForPass2 = fopen(mktemp(
|
||||
pass2MacroExpansionFileName),"w+")) == NULL) {
|
||||
fatalSystemError(
|
||||
UNABLE_TO_OPEN_PASS_2_FILE_ERROR,
|
||||
pass2MacroExpansionFileName);
|
||||
}
|
||||
if (!dontUnlinkTempFiles)
|
||||
unlink(pass2MacroExpansionFileName); /* will
|
||||
take effect on program exit */
|
||||
} else {
|
||||
macroFileForPass2 = fopen("/dev/null", "w+");
|
||||
}
|
||||
} else {
|
||||
if (expandMacros) {
|
||||
warning(MACRO_EXPANSION_WITHOUT_LISTING_ERROR);
|
||||
expandMacros = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
installBuiltInFunctions()
|
||||
{
|
||||
int i;
|
||||
symbolTableEntryType *newFunction;
|
||||
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
valueType *newValue();
|
||||
|
||||
for (i=0; builtInFunctionTable[i].functionName!=NULL; i++) {
|
||||
newFunction = lookupOrEnterSymbol(builtInFunctionTable[i].
|
||||
functionName, BUILT_IN_FUNCTION_SYMBOL);
|
||||
newFunction->context->value =newValue(BUILT_IN_FUNCTION_VALUE,
|
||||
i, EXPRESSION_OPND);
|
||||
if (builtInFunctionTable[i].isSpecialFunction)
|
||||
newFunction->context->attributes |=
|
||||
SPECIAL_FUNCTION_ATT;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
installPredefinedSymbols()
|
||||
{
|
||||
int i;
|
||||
symbolTableEntryType *newSymbol;
|
||||
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
valueType *newValue();
|
||||
|
||||
for (i=0; predefinedSymbolTable[i].symbolName!=NULL; i++) {
|
||||
newSymbol = lookupOrEnterSymbol(predefinedSymbolTable[i].
|
||||
symbolName, DEFINE_SYMBOL);
|
||||
newSymbol->context->value = newValue(ABSOLUTE_VALUE,
|
||||
predefinedSymbolTable[i].symbolValue,
|
||||
EXPRESSION_OPND);
|
||||
newSymbol->context->attributes |= DEFINED_VARIABLE_ATT;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
installCommandLineDefineSymbols()
|
||||
{
|
||||
int i;
|
||||
symbolTableEntryType *newSymbol;
|
||||
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
valueType *newValue();
|
||||
|
||||
while (commandLineDefines != NULL) {
|
||||
newSymbol = lookupOrEnterSymbol(commandLineDefines->name,
|
||||
DEFINE_SYMBOL);
|
||||
newSymbol->context->value = newValue(ABSOLUTE_VALUE,
|
||||
commandLineDefines->value, EXPRESSION_OPND);
|
||||
newSymbol->context->attributes |= DEFINED_VARIABLE_ATT;
|
||||
commandLineDefines = commandLineDefines->nextDefine;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
createHashTables()
|
||||
{
|
||||
opcodeTableEntryType *newOpcodeEntry;
|
||||
keywordTableEntryType *newKeywordEntry;
|
||||
conditionTableEntryType *newConditionEntry;
|
||||
|
||||
newOpcodeEntry = theOpcodes;
|
||||
while (newOpcodeEntry->mnemonic != NULL)
|
||||
hashStringEnter(newOpcodeEntry++, opcodeTable);
|
||||
|
||||
newKeywordEntry = theKeywords;
|
||||
while (newKeywordEntry->string != NULL)
|
||||
hashStringEnter(newKeywordEntry++, keywordTable);
|
||||
|
||||
newConditionEntry = theConditions;
|
||||
while (newConditionEntry->string != NULL)
|
||||
hashStringEnter(newConditionEntry++, conditionTable);
|
||||
}
|
||||
|
||||
void
|
||||
queueInputFile(name)
|
||||
char *name;
|
||||
{
|
||||
fileNameListType *newFileName;
|
||||
|
||||
newFileName = typeAlloc(fileNameListType);
|
||||
newFileName->name = name;
|
||||
newFileName->fildes = NULL;
|
||||
newFileName->openFlag = FALSE;
|
||||
newFileName->nextFileName = NULL;
|
||||
newFileName->lineNumber = 1;
|
||||
if (inputFileStack == NULL) {
|
||||
inputFileStack = bottomOfInputFileStack = newFileName;
|
||||
} else {
|
||||
bottomOfInputFileStack->nextFileName = newFileName;
|
||||
bottomOfInputFileStack = newFileName;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
openFirstInputFile()
|
||||
{
|
||||
if (inputFileStack == NULL) {
|
||||
inputFileStack = typeAlloc(fileNameListType);
|
||||
inputFileStack->name = "<standard input>";
|
||||
inputFileStack->fildes = stdin;
|
||||
inputFileStack->openFlag = TRUE;
|
||||
inputFileStack->lineNumber = 1;
|
||||
inputFileStack->nextFileName = NULL;
|
||||
} else {
|
||||
if ((inputFileStack->fildes = fopen(inputFileStack->name,
|
||||
"r")) == NULL) {
|
||||
fatalSystemError(UNABLE_TO_OPEN_INPUT_FILE_ERROR,
|
||||
inputFileStack->name);
|
||||
} else {
|
||||
inputFileStack->openFlag = TRUE;
|
||||
}
|
||||
}
|
||||
input = inputFileStack->fildes;
|
||||
currentLineNumber = inputFileStack->lineNumber;
|
||||
currentFileName = inputFileStack->name;
|
||||
currentOperandNumber = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
isDotMName(fileName)
|
||||
stringType *fileName;
|
||||
{
|
||||
int length;
|
||||
|
||||
length = strlen(fileName);
|
||||
return(length >= 2 && fileName[length - 1] == 'm' &&
|
||||
fileName[length - 2] == '.');
|
||||
}
|
||||
|
||||
bool
|
||||
parseCommandLineDefine(arg, name, value)
|
||||
char *arg;
|
||||
char **name;
|
||||
int *value;
|
||||
{
|
||||
char *ptr;
|
||||
char c;
|
||||
int base;
|
||||
int start;
|
||||
|
||||
ptr = arg;
|
||||
while ((c = *ptr++) && (ptr-arg)<MAX_NAME_SIZE && isAlphaNumeric(c))
|
||||
;
|
||||
--ptr;
|
||||
if (c=='\0') {
|
||||
*value = 1;
|
||||
} else if (c == '=') {
|
||||
*ptr++ = '\0';
|
||||
if (ptr[0] != '0') {
|
||||
base = 10;
|
||||
start = 0;
|
||||
} else if (ptr[1]=='b' || ptr[1]=='B') {
|
||||
base = 2;
|
||||
start = 2;
|
||||
} else if (ptr[1]=='q' || ptr[1]=='Q') {
|
||||
base = 4;
|
||||
start = 2;
|
||||
} else if (ptr[1]=='x' || ptr[1]=='X') {
|
||||
base = 16;
|
||||
start = 2;
|
||||
} else {
|
||||
base = 8;
|
||||
start = 1;
|
||||
}
|
||||
*value = fancyAtoI(&ptr[start], base);
|
||||
} else {
|
||||
error(BAD_COMMAND_LINE_DEFINE_ERROR, arg);
|
||||
*name = NULL;
|
||||
*value = 0;
|
||||
return(FALSE);
|
||||
}
|
||||
*name = arg;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
noteCommandLineDefine(arg)
|
||||
char *arg;
|
||||
{
|
||||
char *name;
|
||||
int value;
|
||||
commandLineDefineType *newCommandLineDefine;
|
||||
|
||||
bool parseCommandLineDefine();
|
||||
|
||||
if (parseCommandLineDefine(arg, &name, &value)) {
|
||||
newCommandLineDefine = typeAlloc(commandLineDefineType);
|
||||
newCommandLineDefine->name = name;
|
||||
newCommandLineDefine->value = value;
|
||||
newCommandLineDefine->nextDefine = commandLineDefines;
|
||||
commandLineDefines = newCommandLineDefine;
|
||||
}
|
||||
}
|
BIN
initialize.o
Normal file
BIN
initialize.o
Normal file
Binary file not shown.
542
lexer.c
Normal file
542
lexer.c
Normal file
@ -0,0 +1,542 @@
|
||||
/*
|
||||
lexer.c -- Lexical scanner for the Macross assembler
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
3-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
#include "y.tab.h"
|
||||
#include "lexerTables.h"
|
||||
|
||||
extern int yylval;
|
||||
extern int yydebug;
|
||||
|
||||
static char lineBuffer[LINE_BUFFER_SIZE] = { '\0' };
|
||||
static int lineBufferPtr = 0;
|
||||
|
||||
#define getNextChar() (lineBuffer[lineBufferPtr] ? \
|
||||
lineBuffer[lineBufferPtr++] : \
|
||||
readAnotherLine())
|
||||
/*int getNextChar() {int c;c=xgetNextChar();printf("read '%c'\n",c);return(c);}*/
|
||||
|
||||
#define oopsThatWasTheWrongChar(c) { if(lineBufferPtr) \
|
||||
lineBuffer[--lineBufferPtr] = c; }
|
||||
/*oopsThatWasTheWrongChar(c)char c;{printf("ungetting '%c'\n", c);xoopsThatWasTheWrongChar(c);}*/
|
||||
|
||||
#define isAlphabetic(c) (alphabeticCharacterTable[c])
|
||||
#define isNumeric(c) (numericCharacterTable[c])
|
||||
#define isAlphaNumeric(c) (alphaNumericCharacterTable[c])
|
||||
|
||||
int
|
||||
yylex()
|
||||
{
|
||||
int result;
|
||||
|
||||
result = lexer();
|
||||
if (yydebug) {
|
||||
printf("lexer returns ");
|
||||
printToken(result);
|
||||
printf(", value=%d (0x%x)\n", yylval, yylval);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
lexer()
|
||||
{
|
||||
char c;
|
||||
|
||||
char skipWhitespaceAndComments();
|
||||
|
||||
if ((c = skipWhitespaceAndComments()) == EOF)
|
||||
return(lexLiteral(c));
|
||||
else
|
||||
return((*lexDispatchTable[c])(c));
|
||||
}
|
||||
|
||||
void
|
||||
initializeLexDispatchTable()
|
||||
{
|
||||
int c;
|
||||
int lexIdentifier();
|
||||
int lexNumber();
|
||||
int lexLiteral();
|
||||
int lexCharacterConstant();
|
||||
int lexStringConstant();
|
||||
int lexOperator();
|
||||
|
||||
for (c = 0; c < LEX_DISPATCH_TABLE_SIZE; c++) {
|
||||
if (isAlphabetic(c) || c=='$')
|
||||
lexDispatchTable[c] = lexIdentifier;
|
||||
else if (isNumeric(c))
|
||||
lexDispatchTable[c] = lexNumber;
|
||||
else if (isMacrossLiteralCharacter(c))
|
||||
lexDispatchTable[c] = lexLiteral;
|
||||
else if (c == '\'')
|
||||
lexDispatchTable[c] = lexCharacterConstant;
|
||||
else if (c == '"')
|
||||
lexDispatchTable[c] = lexStringConstant;
|
||||
else
|
||||
lexDispatchTable[c] = lexOperator;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
isMacrossLiteralCharacter(c)
|
||||
char c;
|
||||
{
|
||||
return(c==':' || c==',' || c=='@' || c=='#' ||
|
||||
c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' ||
|
||||
c=='\n' || c==EOF);
|
||||
}
|
||||
|
||||
void
|
||||
snarfAlphanumericString(c, buffer)
|
||||
char c;
|
||||
char *buffer;
|
||||
{
|
||||
char *bufferPtr;
|
||||
|
||||
bufferPtr = buffer;
|
||||
do {
|
||||
if (bufferPtr < &buffer[MAX_NAME_SIZE])
|
||||
*bufferPtr++ = c;
|
||||
c = getNextChar();
|
||||
} while (c!=EOF && isAlphaNumeric(c));
|
||||
*bufferPtr = '\0';
|
||||
oopsThatWasTheWrongChar(c);
|
||||
}
|
||||
|
||||
char nameBuffer[MAX_NAME_SIZE+1];
|
||||
|
||||
int
|
||||
lexIdentifier(c)
|
||||
char c;
|
||||
{
|
||||
char *saveString();
|
||||
int hashValue;
|
||||
|
||||
snarfAlphanumericString(c, nameBuffer);
|
||||
hashValue = hashString(nameBuffer);
|
||||
if (yylval = lookupOpcode(nameBuffer, hashValue))
|
||||
return(Opcode);
|
||||
else if (yylval = lookupKeyword(nameBuffer, hashValue))
|
||||
return(yylval);
|
||||
else if ((yylval = lookupConditionCode(nameBuffer, hashValue)) !=
|
||||
(int)NOT_FOUND_COND)
|
||||
return(ConditionCode);
|
||||
else if (yylval = lookupMacroName(nameBuffer, hashValue))
|
||||
return(MacroName);
|
||||
else {
|
||||
yylval = (int) saveString(nameBuffer);
|
||||
return(Identifier);
|
||||
}
|
||||
}
|
||||
|
||||
char numberBuffer[MAX_NAME_SIZE+1];
|
||||
|
||||
int
|
||||
lexNumber(c)
|
||||
char c;
|
||||
{
|
||||
int base;
|
||||
int start;
|
||||
|
||||
snarfAlphanumericString(c, numberBuffer);
|
||||
if (numberBuffer[0] != '0') {
|
||||
base = 10;
|
||||
start = 0;
|
||||
} else if (numberBuffer[1]=='b' || numberBuffer[1]=='B') {
|
||||
base = 2;
|
||||
start = 2;
|
||||
} else if (numberBuffer[1]=='q' || numberBuffer[1]=='Q') {
|
||||
base = 4;
|
||||
start = 2;
|
||||
} else if (numberBuffer[1]=='x' || numberBuffer[1]=='X') {
|
||||
base = 16;
|
||||
start = 2;
|
||||
} else {
|
||||
base = 8;
|
||||
start = 1;
|
||||
}
|
||||
yylval = fancyAtoI(&numberBuffer[start], base);
|
||||
return(Number);
|
||||
}
|
||||
|
||||
int
|
||||
fancyAtoI(buffer, base)
|
||||
char *buffer;
|
||||
int base;
|
||||
{
|
||||
int value;
|
||||
int digit;
|
||||
char c;
|
||||
|
||||
value = 0;
|
||||
while (*buffer != '\0') {
|
||||
if ((digit = digitValue(c = *buffer++)) >= base) {
|
||||
error(DIGIT_OUT_OF_RADIX_ERROR, c, base);
|
||||
return(0);
|
||||
}
|
||||
value = value*base + digit;
|
||||
}
|
||||
return(value);
|
||||
}
|
||||
|
||||
int
|
||||
digitValue(c)
|
||||
char c;
|
||||
{
|
||||
if (isNumeric(c))
|
||||
return(c - '0');
|
||||
else
|
||||
return(toLowerCase(c) - 'a' + 10);
|
||||
}
|
||||
|
||||
int
|
||||
lexLiteral(c)
|
||||
char c;
|
||||
{
|
||||
static bool passedEnd = FALSE;
|
||||
|
||||
yylval = 0;
|
||||
if (c == '\n') {
|
||||
return(EOL);
|
||||
} else if (c == EOF) {
|
||||
if (passedEnd) {
|
||||
return(0);
|
||||
} else {
|
||||
passedEnd = TRUE;
|
||||
return(ENDFILE);
|
||||
}
|
||||
} else {
|
||||
return(c);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
lexCharacterConstant()
|
||||
{
|
||||
char c;
|
||||
|
||||
yylval = getStringCharacter(input);
|
||||
if (getNextChar() != '\'') {
|
||||
error(UNCLOSED_CHARACTER_CONSTANT_ERROR);
|
||||
while ((c = getNextChar())!='\'' && c!='\n' && c!=EOF)
|
||||
;
|
||||
}
|
||||
return(Number);
|
||||
}
|
||||
|
||||
bool escaped; /* true if last string character read was an escape
|
||||
code. */
|
||||
int
|
||||
getStringCharacter(input)
|
||||
FILE *input;
|
||||
{
|
||||
char c;
|
||||
char *numberPtr;
|
||||
int result;
|
||||
char controlCharacter();
|
||||
|
||||
escaped = FALSE;
|
||||
c = getNextChar();
|
||||
if (c == '\\') {
|
||||
escaped = TRUE;
|
||||
c = getNextChar();
|
||||
if (c == '^')
|
||||
return(controlCharacter(getNextChar()));
|
||||
else if ('0'<=c && c<='7') {
|
||||
numberPtr = numberBuffer;
|
||||
while ('0'<=c && c<='7') {
|
||||
*numberPtr++ = c;
|
||||
c = getNextChar();
|
||||
}
|
||||
*numberPtr = '\0';
|
||||
oopsThatWasTheWrongChar(c);
|
||||
result = fancyAtoI(numberBuffer, 8);
|
||||
if (result > 0377)
|
||||
error(OCTAL_CHARACTER_TOO_BIG_ERROR, result);
|
||||
return (result % 0377);
|
||||
} else
|
||||
return(escapeCodes[c]);
|
||||
} else
|
||||
return(c);
|
||||
}
|
||||
|
||||
char stringBuffer[MAX_NAME_SIZE + 1];
|
||||
|
||||
int
|
||||
lexStringConstant()
|
||||
{
|
||||
char *stringPtr;
|
||||
char c;
|
||||
|
||||
stringPtr = stringBuffer;
|
||||
while (((c = getStringCharacter(input))!='"' && c!='\n' && c!=EOF)
|
||||
|| escaped)
|
||||
*stringPtr++ = c;
|
||||
*stringPtr = '\0';
|
||||
if (c=='\n' || c==EOF)
|
||||
error(UNCLOSED_STRING_CONSTANT_ERROR);
|
||||
yylval = (int)saveString(stringBuffer);
|
||||
return(TextString);
|
||||
}
|
||||
|
||||
int
|
||||
lexOperator(firstC)
|
||||
char firstC;
|
||||
{
|
||||
char secondC;
|
||||
char thirdC;
|
||||
int op;
|
||||
int oper;
|
||||
|
||||
secondC = getNextChar();
|
||||
for (op=0; operatorTable[op].first!='\0'; op++) {
|
||||
if (operatorTable[op].first==firstC &&
|
||||
operatorTable[op].second==secondC)
|
||||
break;
|
||||
else if (operatorTable[op].first==firstC &&
|
||||
operatorTable[op].second=='\0') {
|
||||
oopsThatWasTheWrongChar(secondC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (operatorTable[op].first == '\0') {
|
||||
error(UNRECOGNIZED_SOMETHING_OR_OTHER_ERROR, firstC);
|
||||
return(yylex());
|
||||
}
|
||||
/* kludge to deal with the two three-character operators: */
|
||||
if ((oper=operatorTable[op].token)==RIGHT_SHIFT || oper==LEFT_SHIFT) {
|
||||
thirdC = getNextChar();
|
||||
if (thirdC == '=') {
|
||||
yylval = (int)((oper==RIGHT_SHIFT) ?
|
||||
RIGHT_SHIFT_ASSIGN : LEFT_SHIFT_ASSIGN);
|
||||
return(ASSIGN);
|
||||
} else
|
||||
oopsThatWasTheWrongChar(thirdC);
|
||||
}
|
||||
yylval = (int)operatorTable[op].value;
|
||||
return(operatorTable[op].token);
|
||||
}
|
||||
|
||||
char
|
||||
controlCharacter(c)
|
||||
char c;
|
||||
{
|
||||
#define CONTROL_CHARACTER_MASK (~0100)
|
||||
|
||||
return(c & CONTROL_CHARACTER_MASK);
|
||||
}
|
||||
|
||||
char
|
||||
skipWhitespaceAndComments()
|
||||
{
|
||||
char c;
|
||||
|
||||
while ((c=getNextChar())==' ' || c=='\t' || c=='/') {
|
||||
if (c == '/') {
|
||||
if ((c = getNextChar()) == '*') {
|
||||
while (TRUE) {
|
||||
while ((c = getNextChar()) != '*') {
|
||||
if (c == EOF) {
|
||||
error(UNCLOSED_COMMENT_ERROR);
|
||||
return(c);
|
||||
}
|
||||
}
|
||||
if ((c = getNextChar()) == '/') {
|
||||
break;
|
||||
} else if (c == '*') {
|
||||
oopsThatWasTheWrongChar(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
oopsThatWasTheWrongChar(c);
|
||||
return('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c == ';') {
|
||||
while ((c = getNextChar()) != '\n') {
|
||||
if (c == EOF) {
|
||||
error(UNCLOSED_LINE_COMMENT_ERROR);
|
||||
return(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(c);
|
||||
}
|
||||
|
||||
int
|
||||
popInputFileStack()
|
||||
{
|
||||
fileNameListType *oldFile;
|
||||
|
||||
if (inputFileStack->nextFileName == NULL)
|
||||
return(EOF);
|
||||
oldFile = inputFileStack;
|
||||
inputFileStack = inputFileStack->nextFileName;
|
||||
qfree(oldFile);
|
||||
currentLineNumber = inputFileStack->lineNumber;
|
||||
currentFileName = inputFileStack->name;
|
||||
cumulativeLineNumber--;
|
||||
fclose(input);
|
||||
if (!inputFileStack->openFlag) {
|
||||
if ((inputFileStack->fildes = fopen(inputFileStack->name,
|
||||
"r")) == NULL) {
|
||||
fatalSystemError(UNABLE_TO_OPEN_INPUT_FILE_ERROR,
|
||||
inputFileStack->name);
|
||||
} else {
|
||||
inputFileStack->openFlag = TRUE;
|
||||
}
|
||||
}
|
||||
input = inputFileStack->fildes;
|
||||
if (includeNestingDepth > 0) {
|
||||
includeNestingDepth--;
|
||||
currentLineNumber--;
|
||||
}
|
||||
return(getNextChar());
|
||||
}
|
||||
|
||||
void
|
||||
pushInputFileStack(fileName)
|
||||
stringType *fileName;
|
||||
{
|
||||
fileNameListType *newFileName;
|
||||
|
||||
inputFileStack->lineNumber = currentLineNumber;
|
||||
newFileName = typeAlloc(fileNameListType);
|
||||
if ((input = newFileName->fildes = fopen(fileName, "r")) == NULL) {
|
||||
fatalSystemError(UNABLE_TO_OPEN_INCLUDE_FILE_ERROR, fileName);
|
||||
}
|
||||
newFileName->openFlag = TRUE;
|
||||
newFileName->nextFileName = inputFileStack;
|
||||
inputFileStack = newFileName;
|
||||
currentFileName = newFileName->name = fileName;
|
||||
currentLineNumber = newFileName->lineNumber = 1;
|
||||
includeNestingDepth++;
|
||||
if (statementEvaluationDepth == 1)
|
||||
oopsThatWasTheWrongChar('\n'); /* hack for line #'s */
|
||||
}
|
||||
|
||||
void
|
||||
resynchronizeInput()
|
||||
{
|
||||
char c;
|
||||
while ((c = getNextChar())!='\n' && c!=EOF)
|
||||
;
|
||||
oopsThatWasTheWrongChar(c);
|
||||
}
|
||||
|
||||
bool longLineFlag = FALSE;
|
||||
static bool previousLongLineFlag = FALSE;
|
||||
|
||||
void
|
||||
saveLineForListing(line)
|
||||
stringType *line;
|
||||
{
|
||||
if (!previousLongLineFlag) {
|
||||
putw(currentLocationCounter.value, saveFileForPass2);
|
||||
putw(includeNestingDepth, saveFileForPass2);
|
||||
}
|
||||
previousLongLineFlag = longLineFlag;
|
||||
fputs(line, saveFileForPass2);
|
||||
}
|
||||
|
||||
void
|
||||
saveEOLForListing()
|
||||
{
|
||||
putw(-1, saveFileForPass2);
|
||||
putw(includeNestingDepth, saveFileForPass2);
|
||||
fputs("\n", saveFileForPass2);
|
||||
}
|
||||
|
||||
void
|
||||
saveIndexForListing(kindOfStatement, cumulativeLineNumber)
|
||||
statementKindType kindOfStatement;
|
||||
int cumulativeLineNumber;
|
||||
{
|
||||
if (!amExpanding() || !notListable(kindOfStatement)) {
|
||||
putw(kindOfStatement, indexFileForPass2);
|
||||
putw(currentLocationCounter.value, indexFileForPass2);
|
||||
if (amExpanding())
|
||||
putw(-cumulativeLineNumber, indexFileForPass2);
|
||||
else
|
||||
putw( cumulativeLineNumber, indexFileForPass2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
saveEndMifForListing(cumulativeLineNumber)
|
||||
int cumulativeLineNumber;
|
||||
{
|
||||
putw(MIF_STATEMENT, indexFileForPass2);
|
||||
putw(-1, indexFileForPass2);
|
||||
if (amExpanding())
|
||||
putw(-cumulativeLineNumber, indexFileForPass2);
|
||||
else
|
||||
putw(cumulativeLineNumber, indexFileForPass2);
|
||||
}
|
||||
|
||||
void
|
||||
saveListingOff()
|
||||
{
|
||||
saveIndexForListing(-1, cumulativeLineNumber);
|
||||
}
|
||||
|
||||
void
|
||||
saveListingOn()
|
||||
{
|
||||
if (currentCodeMode == ABSOLUTE_BUFFER)
|
||||
saveIndexForListing(-1, cumulativeLineNumber);
|
||||
else
|
||||
saveIndexForListing(-2, cumulativeLineNumber);
|
||||
}
|
||||
|
||||
char *
|
||||
myfgets(buffer, length, stream)
|
||||
char *buffer;
|
||||
int length;
|
||||
FILE *stream;
|
||||
{
|
||||
char *result;
|
||||
char c;
|
||||
|
||||
result = buffer;
|
||||
while (length-- > 1 && (c = getc(stream)) != EOF && c != '\n')
|
||||
*buffer++ = c;
|
||||
if (c == EOF) {
|
||||
*result = '\0';
|
||||
return(NULL);
|
||||
}
|
||||
if (length > 0)
|
||||
*buffer++ = c;
|
||||
if (length == 0 && c != '\n')
|
||||
longLineFlag = TRUE;
|
||||
else
|
||||
longLineFlag = FALSE;
|
||||
*buffer = '\0';
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
readAnotherLine()
|
||||
{
|
||||
int result;
|
||||
|
||||
if (myfgets(lineBuffer, LINE_BUFFER_SIZE, input)) {
|
||||
if (amListing())
|
||||
saveLineForListing(lineBuffer);
|
||||
lineBufferPtr = 1;
|
||||
result = lineBuffer[0];
|
||||
} else {
|
||||
result = popInputFileStack();
|
||||
}
|
||||
currentLineNumber++;
|
||||
cumulativeLineNumber++;
|
||||
return(result);
|
||||
}
|
85
lexerTables.h
Normal file
85
lexerTables.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
lexerTables.h -- Tables describing stuff the lexer needs to know.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
3-November-1984
|
||||
*/
|
||||
|
||||
struct {
|
||||
char first;
|
||||
char second;
|
||||
int token;
|
||||
assignmentKindType value;
|
||||
} operatorTable[] = {
|
||||
'!', '=', NOT_EQUAL_TO, NO_ASSIGN,
|
||||
'!', '\0', LOGICAL_NOT, NO_ASSIGN,
|
||||
'%', '=', ASSIGN, MOD_ASSIGN,
|
||||
'%', '\0', MOD, NO_ASSIGN,
|
||||
'&', '&', LOGICAL_AND, NO_ASSIGN,
|
||||
'&', '=', ASSIGN, AND_ASSIGN,
|
||||
'&', '\0', BITWISE_AND, NO_ASSIGN,
|
||||
'*', '=', ASSIGN, MUL_ASSIGN,
|
||||
'*', '\0', MUL, NO_ASSIGN,
|
||||
'+', '+', INCREMENT, NO_ASSIGN,
|
||||
'+', '=', ASSIGN, ADD_ASSIGN,
|
||||
'+', '\0', ADD, NO_ASSIGN,
|
||||
'-', '-', DECREMENT, NO_ASSIGN,
|
||||
'-', '=', ASSIGN, SUB_ASSIGN,
|
||||
'-', '\0', SUB, NO_ASSIGN,
|
||||
'.', '\0', SELECT, NO_ASSIGN,
|
||||
'/', '=', ASSIGN, DIV_ASSIGN,
|
||||
'/', '\0', DIV, NO_ASSIGN,
|
||||
'<', '<', LEFT_SHIFT, NO_ASSIGN,
|
||||
'<', '=', LESS_THAN_OR_EQUAL_TO, NO_ASSIGN,
|
||||
'<', '\0', LESS_THAN, NO_ASSIGN,
|
||||
'=', '=', EQUAL_TO, NO_ASSIGN,
|
||||
'=', '\0', ASSIGN, ASSIGN_ASSIGN,
|
||||
'>', '=', GREATER_THAN_OR_EQUAL_TO, NO_ASSIGN,
|
||||
'>', '>', RIGHT_SHIFT, NO_ASSIGN,
|
||||
'>', '\0', GREATER_THAN, NO_ASSIGN,
|
||||
'^', '=', ASSIGN, XOR_ASSIGN,
|
||||
'^', '^', LOGICAL_XOR, NO_ASSIGN,
|
||||
'^', '\0', BITWISE_XOR, NO_ASSIGN,
|
||||
'|', '=', ASSIGN, OR_ASSIGN,
|
||||
'|', '|', LOGICAL_OR, NO_ASSIGN,
|
||||
'|', '\0', BITWISE_OR, NO_ASSIGN,
|
||||
'~', '\0', BITWISE_NOT, NO_ASSIGN,
|
||||
'?', '\0', HI_BYTE, NO_ASSIGN,
|
||||
'\0', '\0', 0, NO_ASSIGN,
|
||||
};
|
||||
|
||||
char escapeCodes[256] = {
|
||||
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
|
||||
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
|
||||
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
|
||||
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
|
||||
' ', '!', '"', '#', '$', '%', '&', '\'',
|
||||
'(', ')', '*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', ':', ';', '<', '=', '>', '?',
|
||||
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
|
||||
'`', 'a', '\b', 'c', 'd', '\33', '\f', 'g',
|
||||
'h', 'i', 'j', 'k', 'l', 'm', '\n', 'o',
|
||||
'p', 'q', '\r', 's', '\t', 'u', 'v', 'w',
|
||||
'x', 'y', 'z', '{', '|', '}', '~', '\177',
|
||||
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
|
||||
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
|
||||
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
|
||||
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
|
||||
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
|
||||
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
|
||||
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
|
||||
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
|
||||
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
|
||||
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
|
||||
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
|
||||
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
|
||||
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
|
||||
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
|
||||
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
|
||||
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
|
||||
};
|
649
listing.c
Normal file
649
listing.c
Normal file
@ -0,0 +1,649 @@
|
||||
/*
|
||||
listing.c -- Routines to generate a Macross assembly listing.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
10-February-1985
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
static char lineBuffer1[LINE_BUFFER_SIZE];
|
||||
static char lineBuffer2[LINE_BUFFER_SIZE];
|
||||
static int cumulativeLineNumber = 0;
|
||||
static char macroLineBuffer[LINE_BUFFER_SIZE];
|
||||
static char nextMacroLineBuffer[LINE_BUFFER_SIZE];
|
||||
static int macroAddress;
|
||||
static int nextMacroAddress;
|
||||
static int macroDepth;
|
||||
static int nextMacroDepth;
|
||||
|
||||
void
|
||||
outputListing()
|
||||
{
|
||||
void generateListing();
|
||||
|
||||
rewind(saveFileForPass2);
|
||||
rewind(indexFileForPass2);
|
||||
rewind(macroFileForPass2);
|
||||
generateListing();
|
||||
}
|
||||
|
||||
void
|
||||
terminateListingFiles()
|
||||
{
|
||||
saveLineForListing("\n");
|
||||
saveIndexForListing(NULL_STATEMENT, cumulativeLineNumber);
|
||||
saveLineForListing("\n");
|
||||
saveIndexForListing(NULL_STATEMENT, cumulativeLineNumber);
|
||||
}
|
||||
|
||||
#define advanceSourceFile() \
|
||||
if (nextSourceAddress == -1) {\
|
||||
readSourceFileLine(&sourceAddress, &sourceDepth,\
|
||||
sourceText = lineBuffer1, saveFileForPass2);\
|
||||
readSourceFileLine(&nextSourceAddress,\
|
||||
&nextSourceDepth, nextSourceText =\
|
||||
lineBuffer2, saveFileForPass2);\
|
||||
sourceLineNumber++;\
|
||||
} else {\
|
||||
sourceAddress = nextSourceAddress;\
|
||||
sourceDepth = nextSourceDepth;\
|
||||
tempText = sourceText;\
|
||||
sourceText = nextSourceText;\
|
||||
nextSourceText = tempText;\
|
||||
if (tempText == NULL)\
|
||||
nextSourceText = (sourceText==lineBuffer1) ?\
|
||||
lineBuffer2 : lineBuffer1;\
|
||||
readSourceFileLine(&nextSourceAddress,\
|
||||
&nextSourceDepth, nextSourceText,\
|
||||
saveFileForPass2);\
|
||||
sourceLineNumber++;\
|
||||
}
|
||||
|
||||
#define advanceIndexFile() {\
|
||||
indexAddress = nextIndexAddress;\
|
||||
indexLineNumber = nextIndexLineNumber;\
|
||||
indexKind = nextIndexKind;\
|
||||
readIndexFileLine(&nextIndexKind, &nextIndexAddress,\
|
||||
&nextIndexLineNumber);\
|
||||
}
|
||||
|
||||
/* This is the most horrible piece of code I have ever written in my entire
|
||||
life -- cbm */
|
||||
void
|
||||
generateListing()
|
||||
{
|
||||
int sourceAddress;
|
||||
int sourceDepth;
|
||||
char *sourceText = lineBuffer1;
|
||||
int nextSourceAddress;
|
||||
int nextSourceDepth;
|
||||
char *nextSourceText = lineBuffer2;
|
||||
int sourceLineNumber;
|
||||
|
||||
int indexAddress;
|
||||
int indexLineNumber;
|
||||
statementKindType indexKind;
|
||||
int nextIndexAddress;
|
||||
int nextIndexLineNumber;
|
||||
statementKindType nextIndexKind;
|
||||
|
||||
bool firstLine;
|
||||
bool alreadyListingMacroExpansion;
|
||||
bool finishingListingMacroExpansion;
|
||||
bool nullMacroLine;
|
||||
int callLineNumber;
|
||||
int targetLineNumber;
|
||||
bool mifEndFlag;
|
||||
int numberOfBytesToList;
|
||||
int numberOfBytesListed;
|
||||
char *tempText;
|
||||
|
||||
void readIndexFileLine();
|
||||
void readSourceFileLine();
|
||||
|
||||
sourceLineNumber = 1;
|
||||
alreadyListingMacroExpansion = FALSE;
|
||||
readSourceFileLine(&sourceAddress, &sourceDepth, sourceText,
|
||||
saveFileForPass2);
|
||||
readSourceFileLine(&nextSourceAddress, &nextSourceDepth,
|
||||
nextSourceText, saveFileForPass2);
|
||||
if (expandMacros)
|
||||
readSourceFileLine(&nextMacroAddress, &nextMacroDepth,
|
||||
nextMacroLineBuffer, macroFileForPass2);
|
||||
readIndexFileLine(&indexKind, &indexAddress, &indexLineNumber);
|
||||
readIndexFileLine(&nextIndexKind, &nextIndexAddress,
|
||||
&nextIndexLineNumber);
|
||||
currentCodeMode = RELOCATABLE_BUFFER;
|
||||
if (indexKind == ORG_STATEMENT || indexKind == ALIGN_STATEMENT ||
|
||||
indexKind == REL_STATEMENT) {
|
||||
if (indexKind == ORG_STATEMENT) {
|
||||
currentCodeMode = ABSOLUTE_BUFFER;
|
||||
}
|
||||
advanceIndexFile();
|
||||
}
|
||||
while (!feof(saveFileForPass2) && !feof(indexFileForPass2)) {
|
||||
mifEndFlag = FALSE;
|
||||
if ((int)indexKind == -1) {
|
||||
advanceIndexFile();
|
||||
if ((int)indexKind == -1)
|
||||
currentCodeMode = ABSOLUTE_BUFFER;
|
||||
else
|
||||
currentCodeMode = RELOCATABLE_BUFFER;
|
||||
advanceIndexFile();
|
||||
sourceLineNumber = indexLineNumber;
|
||||
if (nextIndexKind == ORG_STATEMENT || nextIndexKind ==
|
||||
ALIGN_STATEMENT || nextIndexKind ==
|
||||
REL_STATEMENT) {
|
||||
if (nextIndexKind == ORG_STATEMENT) {
|
||||
currentCodeMode = ABSOLUTE_BUFFER;
|
||||
} else if (nextIndexKind == REL_STATEMENT) {
|
||||
currentCodeMode = RELOCATABLE_BUFFER;
|
||||
}
|
||||
advanceIndexFile();
|
||||
}
|
||||
}
|
||||
if (indexKind == MACRO_STATEMENT || indexKind ==
|
||||
FUNCTION_STATEMENT || indexKind ==
|
||||
STRUCT_STATEMENT) {
|
||||
while (sourceLineNumber < indexLineNumber) {
|
||||
printListingLine(0, indexAddress, sourceText,
|
||||
indexKind);
|
||||
advanceSourceFile();
|
||||
}
|
||||
} else if (!alreadyListingMacroExpansion && isBlockOpener(
|
||||
indexKind)) {
|
||||
while (sourceLineNumber < nextIndexLineNumber) {
|
||||
printListingLine(0, indexAddress, sourceText,
|
||||
indexKind);
|
||||
advanceSourceFile();
|
||||
}
|
||||
readIndexFileLine(&nextIndexKind, &nextIndexAddress,
|
||||
&nextIndexLineNumber);
|
||||
}
|
||||
while ((indexLineNumber == nextIndexLineNumber &&
|
||||
!alreadyListingMacroExpansion &&
|
||||
(int)nextIndexKind != -1 && indexKind !=
|
||||
ORG_STATEMENT) || (indexKind ==
|
||||
NULL_STATEMENT && nextSourceAddress == -1)) {
|
||||
while (nextSourceAddress == -1) {
|
||||
printListingLine(0, indexAddress, sourceText,
|
||||
indexKind);
|
||||
advanceSourceFile();
|
||||
}
|
||||
readIndexFileLine(&nextIndexKind, &nextIndexAddress,
|
||||
&nextIndexLineNumber);
|
||||
}
|
||||
if (nextIndexLineNumber >= 0) {
|
||||
targetLineNumber = alreadyListingMacroExpansion ?
|
||||
callLineNumber : sourceLineNumber;
|
||||
while (nextIndexLineNumber < targetLineNumber &&
|
||||
!isBlockOpener(indexKind)) {
|
||||
readIndexFileLine(&nextIndexKind,
|
||||
&nextIndexAddress,
|
||||
&nextIndexLineNumber);
|
||||
}
|
||||
}
|
||||
while (nextIndexAddress == -1 && !feof(indexFileForPass2)) {
|
||||
readIndexFileLine(&nextIndexKind, &nextIndexAddress,
|
||||
&nextIndexLineNumber);
|
||||
mifEndFlag = TRUE;
|
||||
}
|
||||
numberOfBytesToList = nextIndexAddress - indexAddress;
|
||||
firstLine = TRUE;
|
||||
nullMacroLine = FALSE;
|
||||
while (numberOfBytesToList > 0 || nextSourceAddress == -1 ||
|
||||
firstLine) {
|
||||
firstLine = FALSE;
|
||||
if (alreadyListingMacroExpansion) {
|
||||
if (nullMacroLine) {
|
||||
numberOfBytesListed = printListingLine(
|
||||
numberOfBytesToList, indexAddress,
|
||||
NULL, indexKind);
|
||||
nullMacroLine = FALSE;
|
||||
} else {
|
||||
numberOfBytesListed = printMacroLine(
|
||||
numberOfBytesToList, indexAddress,
|
||||
indexKind);
|
||||
}
|
||||
} else if (!feof(indexFileForPass2)) {
|
||||
numberOfBytesListed = printListingLine(
|
||||
numberOfBytesToList, indexAddress,
|
||||
sourceText, indexKind);
|
||||
}
|
||||
numberOfBytesToList -= numberOfBytesListed;
|
||||
indexAddress += numberOfBytesListed;
|
||||
if (nextSourceAddress == -1 || (sourceLineNumber <
|
||||
indexLineNumber && indexKind ==
|
||||
INSTRUCTION_STATEMENT &&
|
||||
!alreadyListingMacroExpansion)) {
|
||||
advanceSourceFile();
|
||||
firstLine = TRUE;
|
||||
} else if (!alreadyListingMacroExpansion &&
|
||||
nextIndexLineNumber >= 0) {
|
||||
sourceText = NULL;
|
||||
} else if (alreadyListingMacroExpansion &&
|
||||
numberOfBytesToList > 0) {
|
||||
nullMacroLine = TRUE;
|
||||
}
|
||||
}
|
||||
while (mifEndFlag && sourceLineNumber+1<nextIndexLineNumber
|
||||
&& !alreadyListingMacroExpansion) {
|
||||
advanceSourceFile();
|
||||
printListingLine(0, indexAddress, sourceText,
|
||||
indexKind);
|
||||
}
|
||||
if (nextIndexKind == ORG_STATEMENT || nextIndexKind ==
|
||||
ALIGN_STATEMENT || nextIndexKind ==
|
||||
REL_STATEMENT) {
|
||||
if (nextIndexKind == ORG_STATEMENT) {
|
||||
currentCodeMode = ABSOLUTE_BUFFER;
|
||||
} else if (nextIndexKind == REL_STATEMENT) {
|
||||
currentCodeMode = RELOCATABLE_BUFFER;
|
||||
}
|
||||
advanceIndexFile();
|
||||
}
|
||||
advanceIndexFile();
|
||||
if (!alreadyListingMacroExpansion)
|
||||
advanceSourceFile();
|
||||
if (indexLineNumber < 0) {
|
||||
while (nextIndexAddress == -1) {
|
||||
readIndexFileLine(&nextIndexKind,
|
||||
&nextIndexAddress,
|
||||
&nextIndexLineNumber);
|
||||
}
|
||||
if ((int)indexKind == -2) {
|
||||
indexKind = NULL_STATEMENT;
|
||||
}
|
||||
if (!alreadyListingMacroExpansion) {
|
||||
callLineNumber = sourceLineNumber;
|
||||
sourceLineNumber = -indexLineNumber;
|
||||
alreadyListingMacroExpansion = TRUE;
|
||||
}
|
||||
} else if (alreadyListingMacroExpansion) {
|
||||
alreadyListingMacroExpansion = FALSE;
|
||||
while (abs(indexLineNumber) < callLineNumber &&
|
||||
!feof(indexFileForPass2)) {
|
||||
advanceIndexFile();
|
||||
}
|
||||
sourceLineNumber = /*isBlockOpener(indexKind) ?*/
|
||||
callLineNumber /*+ 1 : indexLineNumber*/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool longLineFlag; /* defined in lexer.c */
|
||||
|
||||
int
|
||||
printMacroLine(numberOfBytes, byteAddress, kind)
|
||||
int numberOfBytes;
|
||||
int byteAddress;
|
||||
statementKindType kind;
|
||||
{
|
||||
macroAddress = nextMacroAddress;
|
||||
macroDepth = nextMacroDepth;
|
||||
strcpy(macroLineBuffer, nextMacroLineBuffer);
|
||||
readSourceFileLine(&nextMacroAddress, &nextMacroDepth,
|
||||
nextMacroLineBuffer, macroFileForPass2);
|
||||
return(printListingLine(numberOfBytes, byteAddress, macroLineBuffer,
|
||||
kind));
|
||||
}
|
||||
|
||||
void
|
||||
readSourceFileLine(sourceAddressPtr, sourceDepthPtr, lineBuffer, file)
|
||||
int *sourceAddressPtr;
|
||||
int *sourceDepthPtr;
|
||||
char lineBuffer[];
|
||||
FILE *file;
|
||||
{
|
||||
char c;
|
||||
|
||||
*sourceAddressPtr = getw(file);
|
||||
*sourceDepthPtr = getw(file);
|
||||
myfgets(lineBuffer, LINE_BUFFER_SIZE, file);
|
||||
if (longLineFlag) {
|
||||
while ((c = getc(file)) != '\n' && c != EOF)
|
||||
;
|
||||
lineBuffer[LINE_BUFFER_SIZE - 2] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
readIndexFileLine(statementKindPtr, indexAddressPtr, indexLineNumberPtr)
|
||||
statementKindType *statementKindPtr;
|
||||
int *indexAddressPtr;
|
||||
int *indexLineNumberPtr;
|
||||
{
|
||||
statementKindType statementKindRead;
|
||||
int indexAddressRead;
|
||||
int indexLineNumberRead;
|
||||
|
||||
statementKindRead = (statementKindType) getw(indexFileForPass2);
|
||||
indexAddressRead = getw(indexFileForPass2);
|
||||
indexLineNumberRead = getw(indexFileForPass2) - 1;
|
||||
if (!feof(indexFileForPass2)) {
|
||||
*statementKindPtr = statementKindRead;
|
||||
*indexAddressPtr = indexAddressRead;
|
||||
*indexLineNumberPtr = indexLineNumberRead;
|
||||
} else {
|
||||
*indexLineNumberPtr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
printListingLine(numberOfBytes, byteAddress, text, kind)
|
||||
int numberOfBytes;
|
||||
int byteAddress;
|
||||
char *text;
|
||||
statementKindType kind;
|
||||
{
|
||||
int i;
|
||||
|
||||
void tabPrint();
|
||||
|
||||
if (kind != BLOCK_STATEMENT)
|
||||
numberOfBytes = (numberOfBytes < 4) ? numberOfBytes : 4;
|
||||
|
||||
if (numberOfBytes==0 && isBlankStatement(kind))
|
||||
fprintf(listFileOutput, " ");
|
||||
else
|
||||
#if TARGET_CPU == CPU_6502
|
||||
fprintf(listFileOutput, "%04x ", byteAddress);
|
||||
#else if TARGET_CPU == CPU_68000
|
||||
fprintf(listFileOutput, "%06x ", byteAddress);
|
||||
#endif
|
||||
|
||||
if (kind != BLOCK_STATEMENT) {
|
||||
#if TARGET_CPU == CPU_6502
|
||||
for (i=0; i<numberOfBytes; i++)
|
||||
fprintf(listFileOutput, " %02x",
|
||||
getByte(byteAddress++));
|
||||
for (i=numberOfBytes; i<4; i++)
|
||||
fprintf(listFileOutput, " ");
|
||||
} else {
|
||||
fprintf(listFileOutput, " ");
|
||||
#else if TARGET_CPU == CPU_68000
|
||||
for (i=0; i<numberOfBytes; i++) {
|
||||
fprintf(listFileOutput, "%02x",
|
||||
getByte(byteAddress++));
|
||||
if (i==1) fprintf(listFileOutput, " ");
|
||||
}
|
||||
for (i=numberOfBytes; i<4; i++) {
|
||||
fprintf(listFileOutput, " ");
|
||||
if (i==1) fprintf(listFileOutput, " ");
|
||||
}
|
||||
} else {
|
||||
fprintf(listFileOutput, " ");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (text == NULL) {
|
||||
fprintf(listFileOutput, "\n");
|
||||
} else {
|
||||
fprintf(listFileOutput, " ");
|
||||
tabPrint(text);
|
||||
}
|
||||
return(numberOfBytes);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
isBlockOpener(statementKind)
|
||||
statementKindType statementKind;
|
||||
{
|
||||
return (statementKind==IF_STATEMENT ||
|
||||
statementKind==WHILE_STATEMENT ||
|
||||
statementKind==DO_WHILE_STATEMENT ||
|
||||
statementKind==DO_UNTIL_STATEMENT ||
|
||||
statementKind==CONSTRAIN_STATEMENT ||
|
||||
/* statementKind==STRUCT_STATEMENT ||*/
|
||||
statementKind==MIF_STATEMENT ||
|
||||
statementKind==MFOR_STATEMENT ||
|
||||
statementKind==MDO_WHILE_STATEMENT ||
|
||||
statementKind==MDO_UNTIL_STATEMENT ||
|
||||
statementKind==MWHILE_STATEMENT ||
|
||||
statementKind==INCLUDE_STATEMENT ||
|
||||
statementKind==GROUP_STATEMENT
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
isBlankStatement(statementKind)
|
||||
statementKindType statementKind;
|
||||
{
|
||||
return( statementKind == DEFINE_STATEMENT ||
|
||||
statementKind == NULL_STATEMENT ||
|
||||
statementKind == VARIABLE_STATEMENT ||
|
||||
statementKind == CONSTRAIN_STATEMENT ||
|
||||
statementKind == MACRO_STATEMENT ||
|
||||
statementKind == FUNCTION_STATEMENT ||
|
||||
statementKind == UNDEFINE_STATEMENT ||
|
||||
statementKind == MDEFINE_STATEMENT ||
|
||||
statementKind == MVARIABLE_STATEMENT ||
|
||||
statementKind == FRETURN_STATEMENT ||
|
||||
statementKind == UNDEFINE_STATEMENT ||
|
||||
statementKind == EXTERN_STATEMENT ||
|
||||
statementKind == START_STATEMENT ||
|
||||
statementKind == INCLUDE_STATEMENT ||
|
||||
statementKind == MIF_STATEMENT ||
|
||||
statementKind == MFOR_STATEMENT ||
|
||||
statementKind == MDO_WHILE_STATEMENT ||
|
||||
statementKind == MDO_UNTIL_STATEMENT ||
|
||||
statementKind == MWHILE_STATEMENT ||
|
||||
statementKind == PERFORM_STATEMENT
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
tabPrint(text)
|
||||
stringType *text;
|
||||
{
|
||||
int column;
|
||||
int spaces;
|
||||
|
||||
column = 0;
|
||||
while (*text != '\0') {
|
||||
if (*text == '\t') {
|
||||
for (spaces = 8 - (column % 8); spaces>0; spaces--) {
|
||||
putc(' ', listFileOutput);
|
||||
column++;
|
||||
}
|
||||
} else {
|
||||
putc(*text, listFileOutput);
|
||||
column++;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printNTimes(aChar, times)
|
||||
char aChar;
|
||||
int times;
|
||||
{
|
||||
void moreText();
|
||||
|
||||
while (times-- > 0)
|
||||
moreText("%c", aChar);
|
||||
}
|
||||
|
||||
void
|
||||
tabIndent()
|
||||
{
|
||||
printNTimes('\t', tabCount);
|
||||
}
|
||||
|
||||
static char expressionString[LINE_BUFFER_SIZE] = { '\0' };
|
||||
static char *expressionStringPtr = expressionString;
|
||||
static char expansionString[LINE_BUFFER_SIZE] = { '\0' };
|
||||
static char *expansionStringPtr = expansionString;
|
||||
static char labelString[LINE_BUFFER_SIZE] = { '\0' };
|
||||
static char *labelStringPtr = labelString;
|
||||
|
||||
bool
|
||||
labeledLine()
|
||||
{
|
||||
return(labelStringPtr != labelString);
|
||||
}
|
||||
|
||||
void
|
||||
addText(buffer, bufferPtr, format, arg1, arg2, arg3)
|
||||
char *buffer;
|
||||
char **bufferPtr;
|
||||
char *format;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
{
|
||||
sprintf(*bufferPtr, format, arg1, arg2, arg3);
|
||||
*bufferPtr = buffer + strlen(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
moreTextOptional(buffer, bufferPtr, format, arg1, arg2, arg3)
|
||||
char *buffer;
|
||||
char **bufferPtr;
|
||||
char *format;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
{
|
||||
if (buffer == NULL)
|
||||
addText(expansionString, &expansionStringPtr, format, arg1,
|
||||
arg2, arg3);
|
||||
else
|
||||
addText(buffer, bufferPtr, format, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void
|
||||
moreText(format, arg1, arg2, arg3)
|
||||
char *format;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
{
|
||||
addText(expansionString, &expansionStringPtr, format, arg1,arg2,arg3);
|
||||
}
|
||||
|
||||
void
|
||||
moreLabel(format, arg1, arg2, arg3)
|
||||
char *format;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
{
|
||||
sprintf(labelStringPtr, format, arg1, arg2, arg3);
|
||||
labelStringPtr = labelString + strlen(labelString);
|
||||
}
|
||||
|
||||
static addressType savedCurrentLocationCounterValue;
|
||||
static int savedIncludeNestingDepth;
|
||||
|
||||
void
|
||||
startLine()
|
||||
{
|
||||
printNTimes('+', macroCallDepth);
|
||||
savedCurrentLocationCounterValue = currentLocationCounter.value;
|
||||
savedIncludeNestingDepth = includeNestingDepth;
|
||||
}
|
||||
|
||||
void
|
||||
endLine()
|
||||
{
|
||||
if (amListing()) {
|
||||
putw(savedCurrentLocationCounterValue, macroFileForPass2);
|
||||
putw(savedIncludeNestingDepth, macroFileForPass2);
|
||||
fprintf(macroFileForPass2, "%s\n", expansionString);
|
||||
}
|
||||
expansionStringPtr = expansionString;
|
||||
*expansionStringPtr = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
flushExpressionString()
|
||||
{
|
||||
expressionStringPtr = expressionString;
|
||||
*expressionStringPtr = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
expandExpression(toBuffer, toBufferPtr)
|
||||
char *toBuffer;
|
||||
char **toBufferPtr;
|
||||
{
|
||||
if (toBuffer == NULL)
|
||||
moreText("%s", expressionString);
|
||||
else
|
||||
addText(toBuffer, toBufferPtr, "%s", expressionString);
|
||||
flushExpressionString();
|
||||
}
|
||||
|
||||
void
|
||||
expandNum(buffer, bufferPtr, n)
|
||||
char *buffer;
|
||||
char **bufferPtr;
|
||||
int n;
|
||||
{
|
||||
moreTextOptional(buffer, bufferPtr, "%d", n);
|
||||
}
|
||||
|
||||
void
|
||||
flushOperand(n)
|
||||
int n;
|
||||
{
|
||||
moreText("%s", operandBuffer[n]);
|
||||
operandBuffer[n][0] = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
expandOperands(op)
|
||||
int op;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (op > 0) {
|
||||
flushOperand(0);
|
||||
for (i=1; i<op; i++) {
|
||||
moreText(", ");
|
||||
flushOperand(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
expandLabel()
|
||||
{
|
||||
moreText("%s", labelString);
|
||||
labelStringPtr = labelString;
|
||||
*labelStringPtr = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
moreExpression(format, arg1, arg2, arg3)
|
||||
char *format;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
{
|
||||
sprintf(expressionStringPtr, format, arg1, arg2, arg3);
|
||||
expressionStringPtr = expressionString + strlen(expressionString);
|
||||
}
|
||||
|
||||
void
|
||||
startLineMarked()
|
||||
{
|
||||
startLine();
|
||||
if (amListing())
|
||||
saveIndexForListing(-2, cumulativeLineNumber);
|
||||
}
|
||||
|
||||
bool
|
||||
notListable(statementKind)
|
||||
statementKindType statementKind;
|
||||
{
|
||||
return(!listableStatement(statementKind) &&
|
||||
statementKind != INSTRUCTION_STATEMENT &&
|
||||
(int)statementKind != -2);
|
||||
}
|
521
lookups.c
Normal file
521
lookups.c
Normal file
@ -0,0 +1,521 @@
|
||||
/*
|
||||
lookups.c -- Routines to lookup things in tables.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
5-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/*
|
||||
These routines all do basically the same thing. Various kinds of keywords
|
||||
and so forth are stored in hash tables. The hash buckets contain linked
|
||||
lists that are sorted alphabetically.
|
||||
*/
|
||||
|
||||
conditionType
|
||||
lookupConditionCode(s, hashValue)
|
||||
char *s;
|
||||
int hashValue;
|
||||
{
|
||||
conditionTableEntryType *result;
|
||||
|
||||
genericTableEntryType *prehashedStringLookup();
|
||||
|
||||
result = (conditionTableEntryType *) prehashedStringLookup(s,
|
||||
conditionTable, hashValue);
|
||||
if (result != NULL)
|
||||
return(result->code);
|
||||
else
|
||||
return(NOT_FOUND_COND);
|
||||
}
|
||||
|
||||
int
|
||||
lookupKeyword(s, hashValue)
|
||||
char *s;
|
||||
int hashValue;
|
||||
{
|
||||
keywordTableEntryType *result;
|
||||
|
||||
genericTableEntryType *prehashedStringLookup();
|
||||
|
||||
result = (keywordTableEntryType *) prehashedStringLookup(s,
|
||||
keywordTable, hashValue);
|
||||
if (result != NULL)
|
||||
return(result->token);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
macroTableEntryType *
|
||||
lookupMacroName(s, hashValue)
|
||||
char *s;
|
||||
int hashValue;
|
||||
{
|
||||
genericTableEntryType *prehashedStringLookup();
|
||||
|
||||
return((macroTableEntryType *) prehashedStringLookup(s, macroTable,
|
||||
hashValue));
|
||||
}
|
||||
|
||||
opcodeTableEntryType *
|
||||
lookupOpcode(s, hashValue)
|
||||
char *s;
|
||||
int hashValue;
|
||||
{
|
||||
genericTableEntryType *prehashedStringLookup();
|
||||
|
||||
return((opcodeTableEntryType *) prehashedStringLookup(s,
|
||||
opcodeTable, hashValue));
|
||||
}
|
||||
|
||||
/* lookupOrEnterSymbol -- if there is an entry in the symbol table for the
|
||||
given symbol, return that entry, otherwise create a new entry for it of
|
||||
the given kind and return *that* */
|
||||
|
||||
symbolTableEntryType *
|
||||
lookupOrEnterSymbol(s, kind)
|
||||
stringType *s;
|
||||
symbolUsageKindType kind;
|
||||
{
|
||||
symbolTableEntryType *result;
|
||||
genericTableEntryType *hashStringLookup();
|
||||
genericTableEntryType *hashStringEnter();
|
||||
symbolTableEntryType *buildSymbolTableEntry();
|
||||
|
||||
if (result = (symbolTableEntryType *)hashStringLookup(s,symbolTable)){
|
||||
/* result->referenceCount++;*/
|
||||
return(result);
|
||||
} else
|
||||
return((symbolTableEntryType *)
|
||||
hashStringEnter(buildSymbolTableEntry(s, kind),
|
||||
symbolTable));
|
||||
}
|
||||
|
||||
void
|
||||
pushSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
symbolInContextType *newContext;
|
||||
|
||||
newContext = typeAlloc(symbolInContextType);
|
||||
newContext->pushedContexts = symbol->context;
|
||||
symbol->context = newContext;
|
||||
}
|
||||
|
||||
void
|
||||
popSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
symbolInContextType *deadContext;
|
||||
|
||||
deadContext = symbol->context;
|
||||
if (deadContext == NULL)
|
||||
botch("symbol pop underflow\n");
|
||||
else {
|
||||
symbol->context = deadContext->pushedContexts;
|
||||
if (freeFlag) {
|
||||
if (deadContext->value != NULL)
|
||||
freeValue(deadContext->value);
|
||||
free(deadContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macroTableEntryType *
|
||||
createMacro(macroName)
|
||||
stringType *macroName;
|
||||
{
|
||||
macroTableEntryType *result;
|
||||
symbolTableEntryType *testSymbol;
|
||||
|
||||
genericTableEntryType *hashStringLookup();
|
||||
genericTableEntryType *hashStringEnter();
|
||||
macroTableEntryType *buildMacroTableEntry();
|
||||
symbolTableEntryType *lookupOrEnterSymbol();
|
||||
|
||||
testSymbol = lookupOrEnterSymbol(macroName, MACRO_SYMBOL);
|
||||
if (testSymbol->context->usage != MACRO_SYMBOL) {
|
||||
error(SYMBOL_ALREADY_THERE_ERROR, symbName(testSymbol));
|
||||
return(NULL);
|
||||
} else if (hashStringLookup(macroName, macroTable) != NULL) {
|
||||
error(SYMBOL_ALREADY_THERE_ERROR, symbName(testSymbol));
|
||||
return(NULL);
|
||||
} else {
|
||||
result = (macroTableEntryType *)
|
||||
hashStringEnter(buildMacroTableEntry(macroName),
|
||||
macroTable);
|
||||
result->body = NULL;
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Generic table lookup utility routines
|
||||
*/
|
||||
|
||||
genericTableEntryType *
|
||||
prehashedStringLookup(s, table, hashValue)
|
||||
char *s;
|
||||
genericTableEntryType *table[];
|
||||
int hashValue;
|
||||
{
|
||||
genericTableEntryType *result;
|
||||
int test;
|
||||
|
||||
result = table[hashValue];
|
||||
while (result != NULL) {
|
||||
if ((test = strcmplc(s, result->string)) == 0)
|
||||
break;
|
||||
else if (test > 0) {
|
||||
result = NULL;
|
||||
break;
|
||||
} else {
|
||||
result = result->next;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
genericTableEntryType *
|
||||
hashStringLookup(s, table)
|
||||
char *s;
|
||||
genericTableEntryType *table[];
|
||||
{
|
||||
return(prehashedStringLookup(s, table, hashString(s)));
|
||||
}
|
||||
|
||||
genericTableEntryType *
|
||||
hashStringEnter(entry, table)
|
||||
genericTableEntryType *entry;
|
||||
genericTableEntryType *table[];
|
||||
{
|
||||
genericTableEntryType *result;
|
||||
genericTableEntryType *oldResult;
|
||||
int test;
|
||||
int hashValue;
|
||||
|
||||
hashValue = hashString(entry->string);
|
||||
result = table[hashValue];
|
||||
if (result == NULL) {
|
||||
table[hashValue] = entry;
|
||||
entry->next = NULL;
|
||||
return(entry);
|
||||
}
|
||||
oldResult = NULL;
|
||||
while (result != NULL) {
|
||||
if ((test = strcmplc(entry->string, result->string)) == 0) {
|
||||
botch("symbol table entry %s already there\n",
|
||||
entry->string);
|
||||
} else if (test > 0) {
|
||||
entry->next = result;
|
||||
if (oldResult == NULL)
|
||||
table[hashValue] = entry;
|
||||
else
|
||||
oldResult->next = entry;
|
||||
return(entry);
|
||||
} else {
|
||||
oldResult = result;
|
||||
result = result->next;
|
||||
}
|
||||
}
|
||||
if (oldResult == NULL)
|
||||
table[hashValue] = entry;
|
||||
else
|
||||
oldResult->next = entry;
|
||||
entry->next = NULL;
|
||||
return(entry);
|
||||
}
|
||||
|
||||
int
|
||||
hashString(s)
|
||||
char *s;
|
||||
{
|
||||
unsigned result;
|
||||
|
||||
result = 0;
|
||||
while (*s != '\0')
|
||||
result = (result << 1) + toLowerCase(*s++);
|
||||
return(result & HASH_TABLE_MASK);
|
||||
}
|
||||
|
||||
bool
|
||||
strcmplc(s1, s2) /* string compare in lower case */
|
||||
char *s1; /* heavily optimized version */
|
||||
char *s2;
|
||||
{
|
||||
char c1;
|
||||
int result;
|
||||
|
||||
do {
|
||||
c1 = toLowerCase(*s1++);
|
||||
|
||||
/* if result != 0, they differ */
|
||||
if (result = c1 - toLowerCase(*s2++)) {
|
||||
return(result); /* c1<c2==neg, c1>c2==pos */
|
||||
} else if (!c1) { /* if they're null, we're done */
|
||||
return(0);
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
bool
|
||||
strcmplct(s1, s2) /* For tables: s2 is already lower case */
|
||||
char *s1; /* heavily optimized version. */
|
||||
char *s2;
|
||||
{
|
||||
char c1;
|
||||
int result;
|
||||
|
||||
while (TRUE) {
|
||||
c1 = toLowerCase(*s1++);
|
||||
if (result = c1 - (*s2++)) { /* if result != 0, they differ */
|
||||
return(result); /* c1<c2==neg, c1>c2==pos */
|
||||
} else if (!c1) { /* if they're null, we're done */
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
purgeSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
symbolInContextType *context;
|
||||
|
||||
symbolInContextType *getWorkingContext();
|
||||
|
||||
if ((context = getWorkingContext(symbol)) != NULL)
|
||||
context->usage = DEAD_SYMBOL;
|
||||
}
|
||||
|
||||
void
|
||||
reincarnateSymbol(context, newUsage)
|
||||
symbolInContextType *context;
|
||||
symbolUsageKindType newUsage;
|
||||
{
|
||||
context->attributes = 0;
|
||||
dupValue(context->value, UndefinedValue);
|
||||
context->usage = newUsage;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Routines to handle assembly-time binding of symbols to contexts.
|
||||
*/
|
||||
|
||||
void
|
||||
pushBinding(symbol, newBinding, newUsage)
|
||||
symbolTableEntryType *symbol;
|
||||
valueType *newBinding;
|
||||
symbolUsageKindType newUsage;
|
||||
{
|
||||
valueType *newValue();
|
||||
|
||||
pushSymbol(symbol);
|
||||
if (newBinding == NULL)
|
||||
newBinding = newValue(FAIL, 0, EXPRESSION_OPND);
|
||||
symbol->context->value = newBinding;
|
||||
symbol->context->usage = newUsage;
|
||||
symbol->context->environmentNumber = currentEnvironment->
|
||||
environmentNumber;
|
||||
symbol->context->attributes = DEFINED_VARIABLE_ATT;
|
||||
}
|
||||
|
||||
void
|
||||
popBinding(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
popSymbol(symbol);
|
||||
}
|
||||
|
||||
int /* returns number of bindings completed, negative this if failure */
|
||||
bindMacroArguments(argumentList, parameterList, macroName)
|
||||
argumentDefinitionListType *argumentList;
|
||||
operandListType *parameterList;
|
||||
stringType *macroName;
|
||||
{
|
||||
int numberBound;
|
||||
bool arrayTag;
|
||||
int arrayLength;
|
||||
valueType **arrayContents;
|
||||
int i;
|
||||
|
||||
valueType *newValue();
|
||||
|
||||
if (argumentList == NULL)
|
||||
arrayTag = FALSE;
|
||||
else
|
||||
arrayTag = ((argumentListHeadType *)argumentList)->arrayTag;
|
||||
numberBound = 1;
|
||||
while (argumentList!=NULL && (!arrayTag || argumentList->
|
||||
nextArgument!=NULL) && parameterList!=NULL) {
|
||||
pushBinding(argumentList->theArgument, newValue(OPERAND_VALUE,
|
||||
parameterList, EXPRESSION_OPND), ARGUMENT_SYMBOL);
|
||||
argumentList = argumentList->nextArgument;
|
||||
parameterList = parameterList->nextOperand;
|
||||
numberBound++;
|
||||
}
|
||||
if (!arrayTag) {
|
||||
if (parameterList != NULL) {
|
||||
error(TOO_MANY_ARGUMENTS_TO_MACRO_ERROR, macroName,
|
||||
numberBound-1);
|
||||
return(-numberBound);
|
||||
}
|
||||
while (argumentList != NULL) {
|
||||
pushBinding(argumentList->theArgument, newValue(FAIL,
|
||||
0, EXPRESSION_OPND), ARGUMENT_SYMBOL);
|
||||
argumentList = argumentList->nextArgument;
|
||||
numberBound++;
|
||||
}
|
||||
} else {
|
||||
if (parameterList == NULL) {
|
||||
while (argumentList->nextArgument != NULL) {
|
||||
pushBinding(argumentList->theArgument,
|
||||
newValue(FAIL, 0, EXPRESSION_OPND),
|
||||
ARGUMENT_SYMBOL);
|
||||
argumentList = argumentList->nextArgument;
|
||||
numberBound++;
|
||||
}
|
||||
}
|
||||
arrayLength = countParameters(parameterList);
|
||||
pushBinding(argumentList->theArgument, newValue(ARRAY_VALUE,
|
||||
allocArray(arrayLength, &arrayContents),
|
||||
EXPRESSION_OPND), ARGUMENT_SYMBOL);
|
||||
for (i=0; i<arrayLength; ++i) {
|
||||
arrayContents[i] = newValue(OPERAND_VALUE,
|
||||
parameterList, EXPRESSION_OPND);
|
||||
parameterList = parameterList->nextOperand;
|
||||
}
|
||||
numberBound++;
|
||||
}
|
||||
return(numberBound);
|
||||
}
|
||||
|
||||
int /* returns number of bindings completed, negative this if failure */
|
||||
bindFunctionArguments(argumentList, parameterList, functionName)
|
||||
argumentDefinitionListType *argumentList;
|
||||
operandListType *parameterList;
|
||||
stringType *functionName;
|
||||
{
|
||||
valueType *argument;
|
||||
bool arrayTag;
|
||||
int arrayLength;
|
||||
valueType **arrayContents;
|
||||
int i;
|
||||
int numberBound;
|
||||
valueType *firstArgument;
|
||||
environmentType *saveEnvironment;
|
||||
|
||||
valueType *evaluateOperand();
|
||||
valueType *newValue();
|
||||
|
||||
if (argumentList == NULL)
|
||||
arrayTag = FALSE;
|
||||
else
|
||||
arrayTag = ((argumentListHeadType *)argumentList)->arrayTag;
|
||||
numberBound = 1;
|
||||
firstArgument = NULL;
|
||||
while (argumentList!=NULL && (!arrayTag || argumentList->
|
||||
nextArgument!=NULL) && parameterList!=NULL) {
|
||||
saveEnvironment = currentEnvironment;
|
||||
currentEnvironment = currentEnvironment->previousEnvironment;
|
||||
argument = evaluateOperand(parameterList, NO_FIXUP);
|
||||
currentEnvironment = saveEnvironment;
|
||||
if (firstArgument == NULL)
|
||||
firstArgument = argument;
|
||||
if (isUsable(argument)) {
|
||||
pushBinding(argumentList->theArgument, argument,
|
||||
ARGUMENT_SYMBOL);
|
||||
argumentList = argumentList->nextArgument;
|
||||
parameterList = parameterList->nextOperand;
|
||||
expand((argumentList!=NULL && parameterList!=NULL) ?
|
||||
moreExpression(", ") : 0);
|
||||
numberBound++;
|
||||
} else {
|
||||
if (isUndefined(argument))
|
||||
resultOfLastFunctionCall =
|
||||
newValue(UNDEFINED_VALUE, 0,
|
||||
firstArgument->addressMode);
|
||||
return(-numberBound);
|
||||
}
|
||||
}
|
||||
if (!arrayTag) {
|
||||
if (parameterList != NULL) {
|
||||
error(TOO_MANY_ARGUMENTS_TO_FUNCTION_ERROR,
|
||||
functionName, numberBound - 1);
|
||||
return(-numberBound);
|
||||
}
|
||||
while (argumentList != NULL) {
|
||||
pushBinding(argumentList->theArgument, newValue(FAIL,
|
||||
0, EXPRESSION_OPND), ARGUMENT_SYMBOL);
|
||||
argumentList = argumentList->nextArgument;
|
||||
numberBound++;
|
||||
}
|
||||
} else {
|
||||
if (parameterList == NULL) {
|
||||
while (argumentList->nextArgument != NULL) {
|
||||
pushBinding(argumentList->theArgument,
|
||||
newValue(FAIL, 0, EXPRESSION_OPND),
|
||||
ARGUMENT_SYMBOL);
|
||||
argumentList = argumentList->nextArgument;
|
||||
numberBound++;
|
||||
}
|
||||
}
|
||||
arrayLength = countParameters(parameterList);
|
||||
pushBinding(argumentList->theArgument, newValue(ARRAY_VALUE,
|
||||
allocArray(arrayLength, &arrayContents),
|
||||
EXPRESSION_OPND), ARGUMENT_SYMBOL);
|
||||
numberBound++;
|
||||
for (i=0; i<arrayLength; ++i) {
|
||||
saveEnvironment = currentEnvironment;
|
||||
currentEnvironment = currentEnvironment->
|
||||
previousEnvironment;
|
||||
argument = evaluateOperand(parameterList, NO_FIXUP);
|
||||
currentEnvironment = saveEnvironment;
|
||||
if (firstArgument == NULL)
|
||||
firstArgument = argument;
|
||||
if (isUsable(argument)) {
|
||||
arrayContents[i] = argument;
|
||||
parameterList = parameterList->nextOperand;
|
||||
} else {
|
||||
if (isUndefined(argument))
|
||||
resultOfLastFunctionCall =
|
||||
newValue(UNDEFINED_VALUE, 0,
|
||||
firstArgument->addressMode);
|
||||
return(-numberBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(numberBound);
|
||||
}
|
||||
|
||||
void
|
||||
unbindArguments(argumentList, numberToUnbind)
|
||||
argumentDefinitionListType *argumentList;
|
||||
int numberToUnbind;
|
||||
{
|
||||
while (argumentList != NULL && numberToUnbind-- > 0) {
|
||||
popBinding(argumentList->theArgument);
|
||||
argumentList = argumentList->nextArgument;
|
||||
}
|
||||
if (numberToUnbind > 0)
|
||||
botch("binding count larger than number of bindings\n");
|
||||
}
|
||||
|
||||
void
|
||||
unbindLocalVariables(identifierList)
|
||||
identifierListType *identifierList;
|
||||
{
|
||||
identifierListType *deadEntry;
|
||||
|
||||
while (identifierList != NULL) {
|
||||
popBinding(identifierList->theSymbol);
|
||||
deadEntry = identifierList;
|
||||
identifierList = identifierList->nextIdentifier;
|
||||
qfree(deadEntry);
|
||||
}
|
||||
}
|
151
macrossGlobals.h
Normal file
151
macrossGlobals.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
macrossGlobals.h -- Global variable definitions for the Macross
|
||||
assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
1-November-1984
|
||||
|
||||
*/
|
||||
|
||||
bool backwardsCompatibleIfFlag;
|
||||
bool beneathFunction;
|
||||
commandLineDefineType *commandLineDefines;
|
||||
int cumulativeLineNumber;
|
||||
environmentType *currentEnvironment;
|
||||
int currentFieldOffset;
|
||||
char *currentFileName;
|
||||
char *lastErrorFile;
|
||||
stringType *currentFunctionName;
|
||||
int currentLabelTagNumber;
|
||||
int currentLineNumber;
|
||||
int lastErrorLine;
|
||||
identifierListType *currentLocalVariableList;
|
||||
valueType currentLocationCounter;
|
||||
int currentOperandNumber;
|
||||
int currentReferenceDepth;
|
||||
bool debug;
|
||||
bool emitPrint;
|
||||
bool expandMacros;
|
||||
bool errorFlag;
|
||||
bool expressionFailed;
|
||||
bool finishOperand;
|
||||
operandKindType fixupAddressMode[MAX_NUMBER_OF_OPERANDS];
|
||||
operandKindType newFixupAddressMode;
|
||||
fixupListType *fixupList;
|
||||
bool freeFlag;
|
||||
bool freturnExit;
|
||||
bool generatingFixup;
|
||||
environmentType globalEnvironment;
|
||||
int hackFlag;
|
||||
bool haveUserStartAddress;
|
||||
bool fixupStartAddress;
|
||||
int includeNestingDepth;
|
||||
FILE *indexFileForPass2;
|
||||
FILE *input;
|
||||
fileNameListType *inputFileStack;
|
||||
FILE *listFileOutput;
|
||||
int listingControlCounter;
|
||||
bool listingOn;
|
||||
int macroCallDepth;
|
||||
FILE *macroFileForPass2;
|
||||
int macroOrFunctionNestingDepth;
|
||||
structInstanceType *newStruct;
|
||||
int nextEnvironmentNumber;
|
||||
int nextLabelTagNumber;
|
||||
FILE *objectFileOutput;
|
||||
char operandBuffer[MAX_NUMBER_OF_OPERANDS][LINE_BUFFER_SIZE];
|
||||
char pass2IndexFileName[];
|
||||
char pass2SourceFileName[];
|
||||
char pass2MacroExpansionFileName[];
|
||||
expressionType *pendingFixup[MAX_NUMBER_OF_OPERANDS];
|
||||
bool performingFixups;
|
||||
bool positionIndependentCodeMode;
|
||||
bool produceLinkableObject;
|
||||
addressType relocatableHighWaterMark;
|
||||
reservationListType *reservationList;
|
||||
valueType *resultOfLastFunctionCall;
|
||||
valueType savedRelocatableCurrentLocationCounter;
|
||||
FILE *saveFileForPass2;
|
||||
bool showAllSymbolsFlag;
|
||||
bool sideEffectFlag;
|
||||
bool standaloneExpansionFlag;
|
||||
valueType *startAddress;
|
||||
int statementEvaluationDepth;
|
||||
int statementListNestingDepth;
|
||||
int structNestingDepth;
|
||||
FILE *symbolDumpFileOutput;
|
||||
bool symbolTableDumpOn;
|
||||
int tabCount;
|
||||
addressType targetOffset;
|
||||
bool terseErrorMessages;
|
||||
valueType *UndefinedValue;
|
||||
symbolUsageKindType unknownSymbolTag;
|
||||
|
||||
#define DEFAULT_OBJECT_FILE_NAME "m.out"
|
||||
|
||||
#define LEX_DISPATCH_TABLE_SIZE 128
|
||||
int (*lexDispatchTable[128])();
|
||||
|
||||
#define HASH_TABLE_SIZE 512
|
||||
#define HASH_TABLE_MASK 0x1FF
|
||||
|
||||
struct {
|
||||
stringType *functionName;
|
||||
valueType *(*functionEntry)();
|
||||
bool isSpecialFunction;
|
||||
int ordinal;
|
||||
} builtInFunctionTable[];
|
||||
|
||||
struct {
|
||||
stringType *symbolName;
|
||||
int symbolValue;
|
||||
} predefinedSymbolTable[];
|
||||
|
||||
macroTableEntryType *macroTable[HASH_TABLE_SIZE];
|
||||
|
||||
opcodeTableEntryType *opcodeTable[HASH_TABLE_SIZE];
|
||||
|
||||
opcodeTableEntryType theOpcodes[];
|
||||
|
||||
keywordTableEntryType *keywordTable[HASH_TABLE_SIZE];
|
||||
|
||||
keywordTableEntryType theKeywords[];
|
||||
|
||||
conditionTableEntryType *conditionTable[HASH_TABLE_SIZE];
|
||||
|
||||
conditionTableEntryType theConditions[];
|
||||
|
||||
symbolTableEntryType *symbolTable[HASH_TABLE_SIZE];
|
||||
|
||||
int operandClassTable[];
|
||||
|
||||
void (*instructionActionTable[])();
|
||||
|
||||
int validSymbolValues[NUM_OF_SYM_USAGES];
|
||||
|
||||
byte structScratchBuffer[MAXIMUM_ALLOWED_STRUCT_SIZE];
|
||||
|
||||
codeRegionType absoluteCodeRegion;
|
||||
codeRegionType relocatableCodeRegion;
|
||||
codeRegionType *codeRegions[2];
|
||||
codeBufferKindType currentCodeMode;
|
||||
codeBufferType *emptyBuffer; /* ??? */
|
||||
codeBreakType *codeBreakList;
|
||||
codeBreakType *lastCodeBreak;
|
||||
|
||||
expressionReferenceListType *expressionReferenceList[3];
|
||||
expressionReferenceListType *referencesToNote[MAX_NUMBER_OF_OPERANDS];
|
||||
int numberOfReferencesInList[3];
|
||||
functionDefinitionType *externalFunctionList;
|
||||
functionDefinitionType *endOfExternalFunctionList;
|
||||
int externalFunctionCount;
|
||||
|
||||
char alphabeticCharacterTable[128];
|
||||
char alphaNumericCharacterTable[128];
|
||||
char lowerCaseCharacterTable[128];
|
||||
char numericCharacterTable[128];
|
||||
|
||||
int expressionBufferSize;
|
||||
#define EXPRESSION_BUFFER_LIMIT 500
|
||||
byte expressionBuffer[EXPRESSION_BUFFER_LIMIT];
|
BIN
macrossTables.o
Normal file
BIN
macrossTables.o
Normal file
Binary file not shown.
405
macrossTables_6502.c
Normal file
405
macrossTables_6502.c
Normal file
@ -0,0 +1,405 @@
|
||||
/*
|
||||
macrossTables.c -- Define the contents of various tables and values
|
||||
of various initialized global variables.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
5-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
/* All those NULLs are used to string together lists after this all gets
|
||||
hashed */
|
||||
conditionTableEntryType theConditions[] = {
|
||||
"always", NULL, ALWAYS_COND,
|
||||
"carry", NULL, CARRY_COND,
|
||||
"equal", NULL, ZERO_COND,
|
||||
"geq", NULL, GEQ_COND,
|
||||
"greater", NULL, GT_COND,
|
||||
"gt", NULL, GT_COND,
|
||||
"leq", NULL, LEQ_COND,
|
||||
"less", NULL, LT_COND,
|
||||
"lt", NULL, LT_COND,
|
||||
"minus", NULL, NEGATIVE_COND,
|
||||
"negative", NULL, NEGATIVE_COND,
|
||||
"neq", NULL, NOT_ZERO_COND,
|
||||
"never", NULL, NEVER_COND,
|
||||
"not_carry", NULL, NOT_CARRY_COND, /* for dragon */
|
||||
"not_equal", NULL, NOT_ZERO_COND, /* for dragon */
|
||||
"not_overflow", NULL, NOT_OVERFLOW_COND, /* for dragon */
|
||||
"not_zero", NULL, NOT_ZERO_COND, /* for dragon */
|
||||
"overflow", NULL, OVERFLOW_COND,
|
||||
"plus", NULL, NOT_NEGATIVE_COND,
|
||||
"positive", NULL, NOT_NEGATIVE_COND,
|
||||
"sgeq", NULL, SGEQ_COND,
|
||||
"sgt", NULL, SGT_COND,
|
||||
"sleq", NULL, SLEQ_COND,
|
||||
"slt", NULL, SLT_COND,
|
||||
"sneq", NULL, NOT_ZERO_COND,
|
||||
"zero", NULL, ZERO_COND,
|
||||
NULL, NULL, NEVER_COND,
|
||||
};
|
||||
|
||||
/* All those NULLs are used to string together lists after this all gets
|
||||
hashed */
|
||||
keywordTableEntryType theKeywords[] = {
|
||||
"a", NULL, A,
|
||||
"align", NULL, ALIGN,
|
||||
"assert", NULL, ASSERT,
|
||||
"block", NULL, BLOCK,
|
||||
"byte", NULL, BYTE,
|
||||
"constrain", NULL, CONSTRAIN,
|
||||
"dbyte", NULL, DBYTE,
|
||||
"define", NULL, DEFINE,
|
||||
"do", NULL, DO,
|
||||
"else", NULL, ELSE,
|
||||
"elseif", NULL, ELSEIF,
|
||||
"extern", NULL, EXTERN,
|
||||
"freturn", NULL, FRETURN,
|
||||
"function", NULL, FUNCTION,
|
||||
"here", NULL, HERE,
|
||||
"if", NULL, IF,
|
||||
"include", NULL, INCLUDE,
|
||||
"long", NULL, LONG,
|
||||
"macro", NULL, MACRO,
|
||||
"mcase", NULL, MCASE,
|
||||
"mdefault", NULL, MDEFAULT,
|
||||
"mdefine", NULL, MDEFINE,
|
||||
"mdo", NULL, MDO,
|
||||
"melse", NULL, MELSE,
|
||||
"melseif", NULL, MELSEIF,
|
||||
"mfor", NULL, MFOR,
|
||||
"mif", NULL, MIF,
|
||||
"mswitch", NULL, MSWITCH,
|
||||
"muntil", NULL, MUNTIL,
|
||||
"mvariable", NULL, MVARIABLE,
|
||||
"mwhile", NULL, MWHILE,
|
||||
"org", NULL, ORG,
|
||||
"rel", NULL, REL,
|
||||
"start", NULL, START,
|
||||
"string", NULL, STRING,
|
||||
"struct", NULL, STRUCT,
|
||||
"target", NULL, TARGET,
|
||||
"undefine", NULL, UNDEFINE,
|
||||
"until", NULL, UNTIL,
|
||||
"variable", NULL, VARIABLE,
|
||||
"while", NULL, WHILE,
|
||||
"word", NULL, WORD,
|
||||
"x", NULL, X,
|
||||
"y", NULL, Y,
|
||||
NULL, NULL, 0,
|
||||
};
|
||||
|
||||
#define HASH_TABLE_SIZE 509
|
||||
|
||||
macroTableEntryType *macroTable[HASH_TABLE_SIZE];
|
||||
|
||||
opcodeTableEntryType *opcodeTable[HASH_TABLE_SIZE];
|
||||
|
||||
symbolTableEntryType *symbolTable[HASH_TABLE_SIZE];
|
||||
|
||||
keywordTableEntryType *keywordTable[HASH_TABLE_SIZE];
|
||||
|
||||
conditionTableEntryType *conditionTable[HASH_TABLE_SIZE];
|
||||
|
||||
/* All those NULLs are used to string together lists after this all gets
|
||||
hashed. */
|
||||
opcodeTableEntryType theOpcodes[] = {
|
||||
"adc", NULL, 0x61, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"and", NULL, 0x21, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"asl", NULL, 0x02, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
|
||||
"bcc", NULL, 0x90, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"bcs", NULL, 0xB0, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"beq", NULL, 0xF0, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"bit", NULL, 0x24, DIR_1, DIR_1_CLASS_BITS, 1, 1, 0,
|
||||
"bmi", NULL, 0x30, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"bne", NULL, 0xD0, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"bpl", NULL, 0x10, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"brk", NULL, 0x00, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"bvc", NULL, 0x50, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"bvs", NULL, 0x70, RELATIVE, REL_CLASS_BITS, 1, 1, 0,
|
||||
"clc", NULL, 0x18, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"cld", NULL, 0xD8, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"cli", NULL, 0x58, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"clv", NULL, 0xB8, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"cmp", NULL, 0xC1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"cpx", NULL, 0xE0, IMM_DIR, IMM_DIR_CLASS_BITS, 1, 1, 0,
|
||||
"cpy", NULL, 0xC0, IMM_DIR, IMM_DIR_CLASS_BITS, 1, 1, 0,
|
||||
"dec", NULL, 0xC6, DIR_X_2, DIR_X_2_CLASS_BITS, 1, 1, 0,
|
||||
"dex", NULL, 0xCA, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"dey", NULL, 0x88, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"eor", NULL, 0x41, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"inc", NULL, 0xE6, DIR_X_2, DIR_X_2_CLASS_BITS, 1, 1, 0,
|
||||
"inx", NULL, 0xE8, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"iny", NULL, 0xC8, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"jmp", NULL, 0x4C, DIR_INDIR, DIR_INDIR_CLASS_BITS, 1, 1, 0,
|
||||
"jsr", NULL, 0x20, DIR_2, DIR_2_CLASS_BITS, 1, 1, 0,
|
||||
"lda", NULL, 0xA1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"ldx", NULL, 0xA2, IMM_DIR_Y, IMM_DIR_Y_CLASS_BITS, 1, 1, 0,
|
||||
"ldy", NULL, 0xA0, IMM_DIR_X, IMM_DIR_X_CLASS_BITS, 1, 1, 0,
|
||||
"lsr", NULL, 0x42, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
|
||||
"nop", NULL, 0xEA, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"ora", NULL, 0x01, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"pha", NULL, 0x48, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"php", NULL, 0x08, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"pla", NULL, 0x68, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"plp", NULL, 0x28, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"rol", NULL, 0x22, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
|
||||
"ror", NULL, 0x62, DIR_X_1, DIR_X_1_CLASS_BITS, 1, 1, 0,
|
||||
"rti", NULL, 0x40, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"rts", NULL, 0x60, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"sbc", NULL, 0xE1, IMM_INDEX, IMM_INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"sec", NULL, 0x38, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"sed", NULL, 0xF8, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"sei", NULL, 0x78, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"sta", NULL, 0x81, INDEX, INDEX_CLASS_BITS, 1, 1, 0,
|
||||
"stx", NULL, 0x86, DIR_Y, DIR_Y_CLASS_BITS, 1, 1, 0,
|
||||
"sty", NULL, 0x84, DIR_X_3, DIR_X_3_CLASS_BITS, 1, 1, 0,
|
||||
"tax", NULL, 0xAA, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"tay", NULL, 0xA8, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"tsx", NULL, 0xBA, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"txa", NULL, 0x8A, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"txs", NULL, 0x9A, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
"tya", NULL, 0x98, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
NULL, NULL, 0x00, NONE, NONE_CLASS_BITS, 0, 0, 0,
|
||||
};
|
||||
|
||||
int operandClassTable[] = { /* indexed by operandKindType */
|
||||
EXPRESSION_OPND_BIT,
|
||||
IMMEDIATE_OPND_BIT,
|
||||
INDIRECT_OPND_BIT,
|
||||
A_REGISTER_OPND_BIT,
|
||||
X_REGISTER_OPND_BIT,
|
||||
Y_REGISTER_OPND_BIT,
|
||||
POST_INDEXED_Y_OPND_BIT,
|
||||
PRE_INDEXED_X_OPND_BIT,
|
||||
X_INDEXED_OPND_BIT,
|
||||
Y_INDEXED_OPND_BIT,
|
||||
X_SELECTED_OPND_BIT,
|
||||
Y_SELECTED_OPND_BIT,
|
||||
PRE_SELECTED_X_OPND_BIT,
|
||||
STRING_OPND_BIT,
|
||||
BLOCK_OPND_BIT,
|
||||
};
|
||||
|
||||
int actionsRelative();
|
||||
int actionsDir1();
|
||||
int actionsDir2();
|
||||
int actionsDirIndir();
|
||||
int actionsDirX1();
|
||||
int actionsDirX2();
|
||||
int actionsDirX3();
|
||||
int actionsDirY();
|
||||
int actionsImmDir();
|
||||
int actionsImmDirX();
|
||||
int actionsImmDirY();
|
||||
int actionsNone();
|
||||
int actionsIndex();
|
||||
int actionsImmIndex();
|
||||
|
||||
/* indexed by opcodeClass */
|
||||
int (*instructionActionTable[])() = {
|
||||
actionsRelative,
|
||||
actionsDir1,
|
||||
actionsDir2,
|
||||
actionsDirIndir,
|
||||
actionsDirX1,
|
||||
actionsDirX2,
|
||||
actionsDirX3,
|
||||
actionsDirY,
|
||||
actionsImmDir,
|
||||
actionsImmDirX,
|
||||
actionsImmDirY,
|
||||
actionsNone,
|
||||
actionsIndex,
|
||||
actionsImmIndex,
|
||||
};
|
||||
|
||||
/* indexed by symbolUsageKindType */
|
||||
int validSymbolValues[NUM_OF_SYM_USAGES] = {
|
||||
/* STRUCT_NAME_SYMBOL */ STRUCT_VALUE_BIT,
|
||||
/* STRUCT_FIELD_SYMBOL */ FIELD_VALUE_BIT,
|
||||
/* MACRO_SYMBOL */ MACRO_VALUE_BIT,
|
||||
/* ARGUMENT_SYMBOL */ OPERAND_VALUE_BIT,
|
||||
/* LABEL_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT,
|
||||
/* EXTERNAL_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT |
|
||||
UNDEFINED_VALUE_BIT,
|
||||
/* VARIABLE_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT |
|
||||
UNDEFINED_VALUE_BIT |
|
||||
STRING_VALUE_BIT | OPERAND_VALUE_BIT |
|
||||
CONDITION_VALUE_BIT,
|
||||
/* MVARIABLE_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT |
|
||||
UNDEFINED_VALUE_BIT |
|
||||
STRING_VALUE_BIT | OPERAND_VALUE_BIT |
|
||||
CONDITION_VALUE_BIT,
|
||||
/* UNKNOWN_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
/* FUNCTION_SYMBOL */ FUNCTION_VALUE_BIT,
|
||||
/* BUILT_IN_FUNCTION_SYMBOL */ BUILT_IN_FUNCTION_VALUE_BIT,
|
||||
/* NESTED_UNKNOWN_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
/* DEFINE_SYMBOL */ OPERAND_VALUE_BIT,
|
||||
/* MDEFINE_SYMBOL */ OPERAND_VALUE_BIT,
|
||||
/* UNKNOWN_FUNCTION_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
/* UNKNOWN_MACRO_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
};
|
||||
|
||||
/* indexed by valueKindType */
|
||||
int valueBitTable[] = {
|
||||
ABSOLUTE_VALUE_BIT,
|
||||
DATA_VALUE_BIT,
|
||||
RELOCATABLE_VALUE_BIT,
|
||||
BSS_VALUE_BIT,
|
||||
STRUCT_VALUE_BIT,
|
||||
FIELD_VALUE_BIT,
|
||||
MACRO_VALUE_BIT,
|
||||
OPERAND_VALUE_BIT,
|
||||
STRING_VALUE_BIT,
|
||||
CONDITION_VALUE_BIT,
|
||||
UNDEFINED_VALUE_BIT,
|
||||
FUNCTION_VALUE_BIT,
|
||||
BLOCK_VALUE_BIT,
|
||||
BUILT_IN_FUNCTION_VALUE_BIT,
|
||||
ARRAY_VALUE_BIT,
|
||||
FAIL_BIT,
|
||||
};
|
||||
|
||||
|
||||
codeRegionType absoluteCodeRegion;
|
||||
codeRegionType relocatableCodeRegion;
|
||||
codeRegionType *codeRegions[2] = {
|
||||
&absoluteCodeRegion,
|
||||
&relocatableCodeRegion
|
||||
};
|
||||
|
||||
/* A predefined undefined value so we don't have to make a new one every
|
||||
time we need one */
|
||||
valueType undefinedValueValue = { UNDEFINED_VALUE, 0,
|
||||
EXPRESSION_OPND };
|
||||
valueType *UndefinedValue = &undefinedValueValue;
|
||||
|
||||
valueType *addressModeBIF();
|
||||
valueType *applyBIF();
|
||||
valueType *arrayLengthBIF();
|
||||
valueType *atasciiBIF();
|
||||
valueType *atasciiColorBIF();
|
||||
valueType *debugModeOffBIF();
|
||||
valueType *debugModeOnBIF();
|
||||
valueType *emitModeOffBIF();
|
||||
valueType *emitModeOnBIF();
|
||||
valueType *isAbsoluteValueBIF();
|
||||
valueType *isARegisterBIF();
|
||||
valueType *isBlockBIF();
|
||||
valueType *isBuiltInFunctionBIF();
|
||||
valueType *isConditionCodeBIF();
|
||||
valueType *isDefinedBIF();
|
||||
valueType *isDirectModeBIF();
|
||||
valueType *isExternalBIF();
|
||||
valueType *isFieldBIF();
|
||||
valueType *isFunctionBIF();
|
||||
valueType *isImmediateModeBIF();
|
||||
valueType *isIndexedModeBIF();
|
||||
valueType *isIndirectModeBIF();
|
||||
valueType *isPostIndexedModeBIF();
|
||||
valueType *isPreIndexedModeBIF();
|
||||
valueType *isRelocatableValueBIF();
|
||||
valueType *isStringBIF();
|
||||
valueType *isStructBIF();
|
||||
valueType *isSymbolBIF();
|
||||
valueType *isXIndexedModeBIF();
|
||||
valueType *isXRegisterBIF();
|
||||
valueType *isYIndexedModeBIF();
|
||||
valueType *isYRegisterBIF();
|
||||
valueType *listingOffBIF();
|
||||
valueType *listingOnBIF();
|
||||
valueType *makeArrayBIF();
|
||||
valueType *nthCharBIF();
|
||||
valueType *printfBIF();
|
||||
valueType *strcatBIF();
|
||||
valueType *strcmpBIF();
|
||||
valueType *strcmplcBIF();
|
||||
valueType *strlenBIF();
|
||||
valueType *substrBIF();
|
||||
valueType *symbolDefineBIF();
|
||||
valueType *symbolLookupBIF();
|
||||
valueType *symbolNameBIF();
|
||||
valueType *symbolUsageBIF();
|
||||
valueType *valueTypeBIF();
|
||||
|
||||
/* Used to initialize symbols representing built-in functions */
|
||||
struct {
|
||||
stringType *functionName;
|
||||
valueType *(*functionEntry)();
|
||||
bool isSpecialFunction;
|
||||
int ordinal;
|
||||
} builtInFunctionTable[] = {
|
||||
"addressMode", addressModeBIF, FALSE, -1,
|
||||
"apply", applyBIF, FALSE, -1,
|
||||
"arrayLength", arrayLengthBIF, FALSE, -1,
|
||||
"atascii", atasciiBIF, FALSE, 0,
|
||||
"atasciiColor", atasciiColorBIF, FALSE, 1,
|
||||
"debugModeOff", debugModeOffBIF, FALSE, -1,
|
||||
"debugModeOn", debugModeOnBIF, FALSE, -1,
|
||||
"emitModeOff", emitModeOffBIF, FALSE, -1,
|
||||
"emitModeOn", emitModeOnBIF, FALSE, -1,
|
||||
"isAbsoluteValue", isAbsoluteValueBIF, FALSE, 2,
|
||||
"isARegister", isARegisterBIF, FALSE, -1,
|
||||
"isBlock", isBlockBIF, FALSE, -1,
|
||||
"isBuiltInFunction", isBuiltInFunctionBIF, FALSE, -1,
|
||||
"isConditionCode", isConditionCodeBIF, FALSE, 3,
|
||||
"isDefined", isDefinedBIF, TRUE, 4,
|
||||
"isDirectMode", isDirectModeBIF, FALSE, -1,
|
||||
"isExternal", isExternalBIF, TRUE, 5,
|
||||
"isField", isFieldBIF, FALSE, -1,
|
||||
"isFunction", isFunctionBIF, FALSE, -1,
|
||||
"isImmediateMode", isImmediateModeBIF, FALSE, -1,
|
||||
"isIndexedMode", isIndexedModeBIF, FALSE, -1,
|
||||
"isIndirectMode", isIndirectModeBIF, FALSE, -1,
|
||||
"isPostIndexedMode", isPostIndexedModeBIF, FALSE, -1,
|
||||
"isPreIndexedMode", isPreIndexedModeBIF, FALSE, -1,
|
||||
"isRelocatableValue", isRelocatableValueBIF, FALSE, -1,
|
||||
"isString", isStringBIF, FALSE, -1,
|
||||
"isStruct", isStructBIF, FALSE, -1,
|
||||
"isSymbol", isSymbolBIF, TRUE, -1,
|
||||
"isXIndexedMode", isXIndexedModeBIF, FALSE, -1,
|
||||
"isXRegister", isXRegisterBIF, FALSE, -1,
|
||||
"isYIndexedMode", isYIndexedModeBIF, FALSE, -1,
|
||||
"isYRegister", isYRegisterBIF, FALSE, -1,
|
||||
"listingOff", listingOffBIF, FALSE, -1,
|
||||
"listingOn", listingOnBIF, FALSE, -1,
|
||||
"makeArray", makeArrayBIF, FALSE, -1,
|
||||
"nthChar", nthCharBIF, FALSE, 6,
|
||||
"printf", printfBIF, FALSE, 7,
|
||||
"strcat", strcatBIF, FALSE, 8,
|
||||
"strcmp", strcmpBIF, FALSE, 9,
|
||||
"strcmplc", strcmplcBIF, FALSE, 10,
|
||||
"strlen", strlenBIF, FALSE, 11,
|
||||
"substr", substrBIF, FALSE, 12,
|
||||
"symbolDefine", symbolDefineBIF, FALSE, -1,
|
||||
"symbolLookup", symbolLookupBIF, FALSE, 13,
|
||||
"symbolName", symbolNameBIF, TRUE, 14,
|
||||
"symbolUsage", symbolUsageBIF, TRUE, -1,
|
||||
"valueType", valueTypeBIF, FALSE, -1,
|
||||
NULL, NULL, FALSE, -1,
|
||||
};
|
||||
|
||||
/* Used to initialize predefined symbols */
|
||||
struct {
|
||||
stringType *symbolName;
|
||||
int symbolValue;
|
||||
} predefinedSymbolTable[] = {
|
||||
"FALSE", 0,
|
||||
"NULL", 0,
|
||||
"TRUE", 1,
|
||||
NULL, 0,
|
||||
};
|
||||
|
||||
/* These define the temporary files used to hold scratch data used in the
|
||||
generation of listings. The "XXXXXX"s get blasted by 'mktemp' */
|
||||
char pass2SourceFileName[] = "/tmp/zsourceXXXXXX";
|
||||
char pass2IndexFileName[] = "/tmp/zindexXXXXXX";
|
||||
char pass2MacroExpansionFileName[] = "/tmp/zmacroXXXXXX";
|
608
macrossTables_68000.c
Normal file
608
macrossTables_68000.c
Normal file
@ -0,0 +1,608 @@
|
||||
/*
|
||||
macrossTables.c -- Define the contents of various tables and values
|
||||
of various initialized global variables.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
5-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
/* All those NULLs are used to string together lists after this all gets
|
||||
hashed */
|
||||
conditionTableEntryType theConditions[] = {
|
||||
"always", NULL, ALWAYS_COND,
|
||||
"carry", NULL, CARRY_COND,
|
||||
"equal", NULL, EQUAL_COND,
|
||||
"geq", NULL, GEQ_COND,
|
||||
"greater", NULL, GT_COND,
|
||||
"gt", NULL, GT_COND,
|
||||
"high", NULL, HIGH_COND,
|
||||
"high_same", NULL, NOT_CARRY_COND,
|
||||
"hs", NULL, NOT_CARRY_COND,
|
||||
"less", NULL, LT_COND,
|
||||
"leq", NULL, LEQ_COND,
|
||||
"low", NULL, CARRY_COND,
|
||||
"low_same", NULL, LOW_OR_SAME_COND,
|
||||
"ls", NULL, LOW_OR_SAME_COND,
|
||||
"lt", NULL, LT_COND,
|
||||
"minus", NULL, MINUS_COND,
|
||||
"negative", NULL, MINUS_COND,
|
||||
"neq", NULL, NOT_EQUAL_COND,
|
||||
"never", NULL, NEVER_COND,
|
||||
"not_carry", NULL, NOT_CARRY_COND, /* for dragon */
|
||||
"not_equal", NULL, NOT_EQUAL_COND, /* for dragon */
|
||||
"not_overflow", NULL, NOT_OVERFLOW_COND, /* for dragon */
|
||||
"not_zero", NULL, NOT_EQUAL_COND, /* for dragon */
|
||||
"overflow", NULL, OVERFLOW_COND,
|
||||
"plus", NULL, PLUS_COND,
|
||||
"positive", NULL, PLUS_COND,
|
||||
"zero", NULL, EQUAL_COND,
|
||||
NULL, NULL, NEVER_COND,
|
||||
};
|
||||
|
||||
/* All those NULLs are used to string together lists after this all gets
|
||||
hashed */
|
||||
keywordTableEntryType theKeywords[] = {
|
||||
"a0", NULL, A0,
|
||||
"a1", NULL, A1,
|
||||
"a2", NULL, A2,
|
||||
"a3", NULL, A3,
|
||||
"a4", NULL, A4,
|
||||
"a5", NULL, A5,
|
||||
"a6", NULL, A6,
|
||||
"a7", NULL, A7,
|
||||
"align", NULL, ALIGN,
|
||||
"assert", NULL, ASSERT,
|
||||
"block", NULL, BLOCK,
|
||||
"byte", NULL, BYTE,
|
||||
"cc", NULL, CCR,
|
||||
"ccr", NULL, CCR,
|
||||
"constrain", NULL, CONSTRAIN,
|
||||
"d0", NULL, D0,
|
||||
"d1", NULL, D1,
|
||||
"d2", NULL, D2,
|
||||
"d3", NULL, D3,
|
||||
"d4", NULL, D4,
|
||||
"d5", NULL, D5,
|
||||
"d6", NULL, D6,
|
||||
"d7", NULL, D7,
|
||||
"dbyte", NULL, DBYTE,
|
||||
"define", NULL, DEFINE,
|
||||
"dfc", NULL, DFC,
|
||||
"do", NULL, DO,
|
||||
"else", NULL, ELSE,
|
||||
"elseif", NULL, ELSEIF,
|
||||
"extern", NULL, EXTERN,
|
||||
"freturn", NULL, FRETURN,
|
||||
"function", NULL, FUNCTION,
|
||||
"here", NULL, HERE,
|
||||
"if", NULL, IF,
|
||||
"include", NULL, INCLUDE,
|
||||
"l", NULL, L,
|
||||
"long", NULL, LONG,
|
||||
"macro", NULL, MACRO,
|
||||
"mcase", NULL, MCASE,
|
||||
"mdefault", NULL, MDEFAULT,
|
||||
"mdefine", NULL, MDEFINE,
|
||||
"mdo", NULL, MDO,
|
||||
"melse", NULL, MELSE,
|
||||
"melseif", NULL, MELSEIF,
|
||||
"mfor", NULL, MFOR,
|
||||
"mif", NULL, MIF,
|
||||
"mswitch", NULL, MSWITCH,
|
||||
"muntil", NULL, MUNTIL,
|
||||
"mvariable", NULL, MVARIABLE,
|
||||
"mwhile", NULL, MWHILE,
|
||||
"org", NULL, ORG,
|
||||
"pc", NULL, PC,
|
||||
"rel", NULL, REL,
|
||||
"sfc", NULL, SFC,
|
||||
"sr", NULL, SR,
|
||||
"start", NULL, START,
|
||||
"string", NULL, STRING,
|
||||
"struct", NULL, STRUCT,
|
||||
"target", NULL, TARGET,
|
||||
"undefine", NULL, UNDEFINE,
|
||||
"until", NULL, UNTIL,
|
||||
"usp", NULL, USP,
|
||||
"variable", NULL, VARIABLE,
|
||||
"vbr", NULL, VBR,
|
||||
"w", NULL, W,
|
||||
"while", NULL, WHILE,
|
||||
"word", NULL, WORD,
|
||||
NULL, NULL, 0,
|
||||
};
|
||||
|
||||
#define HASH_TABLE_SIZE 509
|
||||
|
||||
macroTableEntryType *macroTable[HASH_TABLE_SIZE];
|
||||
|
||||
opcodeTableEntryType *opcodeTable[HASH_TABLE_SIZE];
|
||||
|
||||
symbolTableEntryType *symbolTable[HASH_TABLE_SIZE];
|
||||
|
||||
keywordTableEntryType *keywordTable[HASH_TABLE_SIZE];
|
||||
|
||||
conditionTableEntryType *conditionTable[HASH_TABLE_SIZE];
|
||||
|
||||
/* All those NULLs are used to string together lists after this all gets
|
||||
hashed. */
|
||||
opcodeTableEntryType theOpcodes[] = {
|
||||
/* mnemonic, next, opcode, class, allowed modes, min#operands, max#operands,
|
||||
subclass/alternate opcode */
|
||||
"abcd", NULL, 0xC100, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"addb", NULL, 0xD000, CLASS_II, CLASS_II_BITS, 2, 2, 0x0600,
|
||||
"addl", NULL, 0xD080, CLASS_II, CLASS_II_BITS, 2, 2, 0x0680,
|
||||
"addqb",NULL, 0x5000, CLASS_III, CLASS_III_BITS, 2, 2, 0,
|
||||
"addql",NULL, 0x5080, CLASS_III, CLASS_III_BITS, 2, 2, 0,
|
||||
"addqw",NULL, 0x5040, CLASS_III, CLASS_III_BITS, 2, 2, 0,
|
||||
"addw", NULL, 0xD040, CLASS_II, CLASS_II_BITS, 2, 2, 0x0640,
|
||||
"addxb",NULL, 0xD100, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"addxl",NULL, 0xD180, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"addxw",NULL, 0xD140, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"andb", NULL, 0xC000, CLASS_IV, CLASS_IV_BITS, 2, 2, 0x0200,
|
||||
"andl", NULL, 0xC080, CLASS_IV, CLASS_IV_BITS, 2, 2, 0x0280,
|
||||
"andw", NULL, 0xC040, CLASS_IV, CLASS_IV_BITS, 2, 2, 0x0240,
|
||||
"aslb", NULL, 0xE100, CLASS_V, CLASS_V_BITS, 1, 2, 00,
|
||||
"asll", NULL, 0xE180, CLASS_V, CLASS_V_BITS, 1, 2, 00,
|
||||
"aslw", NULL, 0xE140, CLASS_V, CLASS_V_BITS, 1, 2, 00,
|
||||
"asrb", NULL, 0xE000, CLASS_V, CLASS_V_BITS, 1, 2, 00,
|
||||
"asrl", NULL, 0xE080, CLASS_V, CLASS_V_BITS, 1, 2, 00,
|
||||
"asrw", NULL, 0xE040, CLASS_V, CLASS_V_BITS, 1, 2, 00,
|
||||
"bcc", NULL, 0x64, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bchg", NULL, 0x0040, CLASS_VII, CLASS_VII_BITS, 2, 2, 0,
|
||||
"bclr", NULL, 0x0080, CLASS_VII, CLASS_VII_BITS, 2, 2, 0,
|
||||
"bcs", NULL, 0x65, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"beq", NULL, 0x67, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bge", NULL, 0x6C, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bgt", NULL, 0x6E, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bhi", NULL, 0x62, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"ble", NULL, 0x6F, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bls", NULL, 0x63, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"blt", NULL, 0x6D, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bmi", NULL, 0x6B, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bne", NULL, 0x66, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bpl", NULL, 0x6A, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bra", NULL, 0x60, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bset", NULL, 0x00C0, CLASS_VII, CLASS_VII_BITS, 2, 2, 0,
|
||||
"bsr", NULL, 0x61, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"btst", NULL, 0x0000, CLASS_VII, CLASS_VII_BITS, 2, 2, 0,
|
||||
"bvc", NULL, 0x68, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"bvs", NULL, 0x69, CLASS_VI, CLASS_VI_BITS, 1, 1, 0,
|
||||
"chk", NULL, 0x4180, CLASS_VIII, CLASS_VIII_BITS,2, 2, 0,
|
||||
"clrb", NULL, 0x4200, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"clrl", NULL, 0x4280, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"clrw", NULL, 0x4240, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"cmpb", NULL, 0x0000, CLASS_X, CLASS_X_BITS, 2, 2, 0x0000,
|
||||
"cmpl", NULL, 0x0080, CLASS_X, CLASS_X_BITS, 2, 2, 0xB1C0,
|
||||
"cmpmb",NULL, 0xB108, CLASS_XI, CLASS_XI_BITS, 2, 2, 0,
|
||||
"cmpml",NULL, 0xB188, CLASS_XI, CLASS_XI_BITS, 2, 2, 0,
|
||||
"cmpmw",NULL, 0xB148, CLASS_XI, CLASS_XI_BITS, 2, 2, 0,
|
||||
"cmpw", NULL, 0x0040, CLASS_X, CLASS_X_BITS, 2, 2, 0xB0C0,
|
||||
"dbcc", NULL, 0x54C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbcs", NULL, 0x55C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbeq", NULL, 0x57C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbf", NULL, 0x51C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbge", NULL, 0x5CC8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbgt", NULL, 0x5EC8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbhi", NULL, 0x52C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dble", NULL, 0x5FC8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbls", NULL, 0x53C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dblt", NULL, 0x5DC8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbmi", NULL, 0x5BC8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbne", NULL, 0x56C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbpl", NULL, 0x5BC8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbra", NULL, 0x50C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbt", NULL, 0x50C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbvc", NULL, 0x58C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"dbvs", NULL, 0x59C8, CLASS_XII, CLASS_XII_BITS, 2, 2, 0,
|
||||
"divs", NULL, 0x81C0, CLASS_VIII, CLASS_VIII_BITS,2, 2, 0,
|
||||
"divu", NULL, 0x80C0, CLASS_VIII, CLASS_VIII_BITS,2, 2, 0,
|
||||
"eorb", NULL, 0xB100, CLASS_XIII, CLASS_XIII_BITS,2, 2, 0x0A00,
|
||||
"eorl", NULL, 0xB180, CLASS_XIII, CLASS_XIII_BITS,2, 2, 0x0A80,
|
||||
"eorw", NULL, 0xB140, CLASS_XIII, CLASS_XIII_BITS,2, 2, 0x0A40,
|
||||
"exg", NULL, 0xC100, CLASS_XIV, CLASS_XIV_BITS, 2, 2, 0,
|
||||
"extl", NULL, 0x48C0, CLASS_XV, CLASS_XV_BITS, 1, 1, 0,
|
||||
"extw", NULL, 0x4880, CLASS_XV, CLASS_XV_BITS, 1, 1, 0,
|
||||
"illegal",NULL, 0x4AFC, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"jmp", NULL, 0x4EC0, CLASS_XVII, CLASS_XVII_BITS,1, 1, 0,
|
||||
"jsr", NULL, 0x4E80, CLASS_XVII, CLASS_XVII_BITS,1, 1, 0,
|
||||
"lea", NULL, 0x41C0, CLASS_XVIII, CLASS_XVIII_BITS,2, 2, 0,
|
||||
"link", NULL, 0x4E50, CLASS_XIX, CLASS_XIX_BITS, 2, 2, 0,
|
||||
"lslb", NULL, 0xE100, CLASS_V, CLASS_V_BITS, 1, 2, 01,
|
||||
"lsll", NULL, 0xE180, CLASS_V, CLASS_V_BITS, 1, 2, 01,
|
||||
"lslw", NULL, 0xE140, CLASS_V, CLASS_V_BITS, 1, 2, 01,
|
||||
"lsrb", NULL, 0xE000, CLASS_V, CLASS_V_BITS, 1, 2, 01,
|
||||
"lsrl", NULL, 0xE080, CLASS_V, CLASS_V_BITS, 1, 2, 01,
|
||||
"lsrw", NULL, 0xE040, CLASS_V, CLASS_V_BITS, 1, 2, 01,
|
||||
"movb", NULL, 0x1000, CLASS_XX, CLASS_XX_BITS, 2, 2, 0x0000,
|
||||
"moveb",NULL, 0x1000, CLASS_XX, CLASS_XX_BITS, 2, 2, 0x0000,
|
||||
"movel",NULL, 0x2000, CLASS_XX, CLASS_XX_BITS, 2, 2, 0x2040,
|
||||
"moveml",NULL, 0x48C0, CLASS_XXI, CLASS_XXI_BITS, 2, 17, 0,
|
||||
"movemw",NULL, 0x4880, CLASS_XXI, CLASS_XXI_BITS, 2, 17, 0,
|
||||
"movepl",NULL, 0x0148, CLASS_XXII, CLASS_XXII_BITS,2, 2, 0,
|
||||
"movepw",NULL, 0x0108, CLASS_XXII, CLASS_XXII_BITS,2, 2, 0,
|
||||
"moveq",NULL, 0x70, CLASS_XXIII, CLASS_XXIII_BITS,2, 2, 0,
|
||||
"movesb",NULL, 0x0E00, CLASS_XXIV, CLASS_XXIV_BITS,2, 2, 0,
|
||||
"movesl",NULL, 0x0E80, CLASS_XXIV, CLASS_XXIV_BITS,2, 2, 0,
|
||||
"movesw",NULL, 0x0E40, CLASS_XXIV, CLASS_XXIV_BITS,2, 2, 0,
|
||||
"movew",NULL, 0x3000, CLASS_XX, CLASS_XX_BITS, 2, 2, 0x3040,
|
||||
"movl", NULL, 0x2000, CLASS_XX, CLASS_XX_BITS, 2, 2, 0x2040,
|
||||
"movml",NULL, 0x48C0, CLASS_XXI, CLASS_XXI_BITS, 2, 17, 0,
|
||||
"movmw",NULL, 0x4880, CLASS_XXI, CLASS_XXI_BITS, 2, 17, 0,
|
||||
"movpl",NULL, 0x0148, CLASS_XXII, CLASS_XXII_BITS,2, 2, 0,
|
||||
"movpw",NULL, 0x0108, CLASS_XXII, CLASS_XXII_BITS,2, 2, 0,
|
||||
"movq", NULL, 0x70, CLASS_XXIII, CLASS_XXIII_BITS,2, 2, 0,
|
||||
"movsb",NULL, 0x0E00, CLASS_XXIV, CLASS_XXIV_BITS,2, 2, 0,
|
||||
"movsl",NULL, 0x0E80, CLASS_XXIV, CLASS_XXIV_BITS,2, 2, 0,
|
||||
"movsw",NULL, 0x0E40, CLASS_XXIV, CLASS_XXIV_BITS,2, 2, 0,
|
||||
"movw", NULL, 0x3000, CLASS_XX, CLASS_XX_BITS, 2, 2, 0x3040,
|
||||
"muls", NULL, 0xC1C0, CLASS_VIII, CLASS_VIII_BITS,2, 2, 0,
|
||||
"mulu", NULL, 0xC0C0, CLASS_VIII, CLASS_VIII_BITS,2, 2, 0,
|
||||
"nbcd", NULL, 0x4800, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"negb", NULL, 0x4400, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"negl", NULL, 0x4480, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"negw", NULL, 0x4440, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"negxb",NULL, 0x4000, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"negxl",NULL, 0x4080, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"negxw",NULL, 0x4040, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"nop", NULL, 0x4E71, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"notb", NULL, 0x4600, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"notl", NULL, 0x4680, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"notw", NULL, 0x4640, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"orb", NULL, 0x8000, CLASS_IV, CLASS_IV_BITS, 2, 2, 0x0000,
|
||||
"orl", NULL, 0x8080, CLASS_IV, CLASS_IV_BITS, 2, 2, 0x0080,
|
||||
"orw", NULL, 0x8040, CLASS_IV, CLASS_IV_BITS, 2, 2, 0x0040,
|
||||
"pea", NULL, 0x4840, CLASS_XVII, CLASS_XVII_BITS,1, 1, 0,
|
||||
"reset",NULL, 0x4E70, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"rolb", NULL, 0xE100, CLASS_V, CLASS_V_BITS, 1, 2, 02,
|
||||
"roll", NULL, 0xE180, CLASS_V, CLASS_V_BITS, 1, 2, 02,
|
||||
"rolw", NULL, 0xE140, CLASS_V, CLASS_V_BITS, 1, 2, 02,
|
||||
"rorb", NULL, 0xE000, CLASS_V, CLASS_V_BITS, 1, 2, 02,
|
||||
"rorl", NULL, 0xE080, CLASS_V, CLASS_V_BITS, 1, 2, 02,
|
||||
"rorw", NULL, 0xE040, CLASS_V, CLASS_V_BITS, 1, 2, 02,
|
||||
"roxlb",NULL, 0xE100, CLASS_V, CLASS_V_BITS, 1, 2, 03,
|
||||
"roxll",NULL, 0xE180, CLASS_V, CLASS_V_BITS, 1, 2, 03,
|
||||
"roxlw",NULL, 0xE140, CLASS_V, CLASS_V_BITS, 1, 2, 03,
|
||||
"roxrb",NULL, 0xE000, CLASS_V, CLASS_V_BITS, 1, 2, 03,
|
||||
"roxrl",NULL, 0xE080, CLASS_V, CLASS_V_BITS, 1, 2, 03,
|
||||
"roxrw",NULL, 0xE040, CLASS_V, CLASS_V_BITS, 1, 2, 03,
|
||||
"rtd", NULL, 0x4E74, CLASS_XXV, CLASS_XXV_BITS, 1, 1, 0,
|
||||
"rte", NULL, 0x4E73, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"rtr", NULL, 0x4E77, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"rts", NULL, 0x4E75, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"sbcd", NULL, 0x8100, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"scc", NULL, 0x54C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"scs", NULL, 0x55C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"seq", NULL, 0x57C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"sf", NULL, 0x51C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"sge", NULL, 0x5CC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"sgt", NULL, 0x5EC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"shi", NULL, 0x52C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"sle", NULL, 0x5FC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"sls", NULL, 0x53C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"slt", NULL, 0x5DC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"smi", NULL, 0x5BC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"sne", NULL, 0x56C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"spl", NULL, 0x5AC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"st", NULL, 0x50C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"stop", NULL, 0x4E72, CLASS_XXVII, CLASS_XXVII_BITS,1, 1, 0,
|
||||
"subb", NULL, 0x9000, CLASS_II, CLASS_II_BITS, 2, 2, 0x0400,
|
||||
"subl", NULL, 0x9080, CLASS_II, CLASS_II_BITS, 2, 2, 0x0480,
|
||||
"subqb",NULL, 0x5100, CLASS_III, CLASS_III_BITS, 2, 2, 0,
|
||||
"subql",NULL, 0x5180, CLASS_III, CLASS_III_BITS, 2, 2, 0,
|
||||
"subqw",NULL, 0x5140, CLASS_III, CLASS_III_BITS, 2, 2, 0,
|
||||
"subw", NULL, 0x9040, CLASS_II, CLASS_II_BITS, 2, 2, 0x0440,
|
||||
"subxb",NULL, 0x9100, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"subxl",NULL, 0x9180, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"subxw",NULL, 0x9140, CLASS_I, CLASS_I_BITS, 2, 2, 0,
|
||||
"svc", NULL, 0x58C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"svs", NULL, 0x59C0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"swap", NULL, 0x4840, CLASS_XV, CLASS_XV_BITS, 1, 1, 0,
|
||||
"tas", NULL, 0x4AC0, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"trap", NULL, 0x4E40, CLASS_XXVIII, CLASS_XXVIII_BITS,1,1, 0,
|
||||
"trapv",NULL, 0x4E76, CLASS_XVI, CLASS_XVI_BITS, 0, 0, 0,
|
||||
"tstb", NULL, 0x4A00, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"tstl", NULL, 0x4A80, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"tstw", NULL, 0x4A40, CLASS_IX, CLASS_IX_BITS, 1, 1, 0,
|
||||
"unlk", NULL, 0x4E58, CLASS_XXVI, CLASS_XXVI_BITS,1, 1, 0,
|
||||
NULL, NULL, 0x0000, CLASS_XVI, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
int operandClassTable[] = { /* indexed by operandKindType */
|
||||
EXPRESSION_OPND_BIT,
|
||||
STRING_OPND_BIT,
|
||||
BLOCK_OPND_BIT,
|
||||
D_REGISTER_OPND_BIT,
|
||||
A_REGISTER_OPND_BIT,
|
||||
A_REGISTER_INDIRECT_OPND_BIT,
|
||||
POSTINCREMENT_OPND_BIT,
|
||||
PREDECREMENT_OPND_BIT,
|
||||
DISPLACEMENT_OPND_BIT,
|
||||
INDEXED_OPND_BIT,
|
||||
PC_DISPLACEMENT_OPND_BIT,
|
||||
PC_INDEXED_OPND_BIT,
|
||||
IMMEDIATE_OPND_BIT,
|
||||
ABSOLUTE_SHORT_OPND_BIT,
|
||||
ABSOLUTE_LONG_OPND_BIT,
|
||||
CC_REGISTER_OPND_BIT,
|
||||
STATUS_REGISTER_OPND_BIT,
|
||||
USP_REGISTER_OPND_BIT,
|
||||
CONTROL_REGISTER_OPND_BIT,
|
||||
SELECTED_OPND_BIT,
|
||||
INDEX_SELECTED_OPND_BIT,
|
||||
};
|
||||
|
||||
int actionsClassI();
|
||||
int actionsClassII();
|
||||
int actionsClassIII();
|
||||
int actionsClassIV();
|
||||
int actionsClassV();
|
||||
int actionsClassVI();
|
||||
int actionsClassVII();
|
||||
int actionsClassVIII();
|
||||
int actionsClassIX();
|
||||
int actionsClassX();
|
||||
int actionsClassXI();
|
||||
int actionsClassXII();
|
||||
int actionsClassXIII();
|
||||
int actionsClassXIV();
|
||||
int actionsClassXV();
|
||||
int actionsClassXVI();
|
||||
int actionsClassXVII();
|
||||
int actionsClassXVIII();
|
||||
int actionsClassXIX();
|
||||
int actionsClassXX();
|
||||
int actionsClassXXI();
|
||||
int actionsClassXXII();
|
||||
int actionsClassXXIII();
|
||||
int actionsClassXXIV();
|
||||
int actionsClassXXV();
|
||||
int actionsClassXXVI();
|
||||
int actionsClassXXVII();
|
||||
int actionsClassXXVIII();
|
||||
|
||||
/* indexed by opcodeClass */
|
||||
int (*instructionActionTable[])() = {
|
||||
actionsClassI,
|
||||
actionsClassII,
|
||||
actionsClassIII,
|
||||
actionsClassIV,
|
||||
actionsClassV,
|
||||
actionsClassVI,
|
||||
actionsClassVII,
|
||||
actionsClassVIII,
|
||||
actionsClassIX,
|
||||
actionsClassX,
|
||||
actionsClassXI,
|
||||
actionsClassXII,
|
||||
actionsClassXIII,
|
||||
actionsClassXIV,
|
||||
actionsClassXV,
|
||||
actionsClassXVI,
|
||||
actionsClassXVII,
|
||||
actionsClassXVIII,
|
||||
actionsClassXIX,
|
||||
actionsClassXX,
|
||||
actionsClassXXI,
|
||||
actionsClassXXII,
|
||||
actionsClassXXIII,
|
||||
actionsClassXXIV,
|
||||
actionsClassXXV,
|
||||
actionsClassXXVI,
|
||||
actionsClassXXVII,
|
||||
actionsClassXXVIII,
|
||||
};
|
||||
|
||||
/* indexed by symbolUsageKindType */
|
||||
int validSymbolValues[NUM_OF_SYM_USAGES] = {
|
||||
/* STRUCT_NAME_SYMBOL */ STRUCT_VALUE_BIT,
|
||||
/* STRUCT_FIELD_SYMBOL */ FIELD_VALUE_BIT,
|
||||
/* MACRO_SYMBOL */ MACRO_VALUE_BIT,
|
||||
/* ARGUMENT_SYMBOL */ OPERAND_VALUE_BIT,
|
||||
/* LABEL_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT,
|
||||
/* EXTERNAL_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT |
|
||||
UNDEFINED_VALUE_BIT,
|
||||
/* VARIABLE_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT |
|
||||
UNDEFINED_VALUE_BIT |
|
||||
STRING_VALUE_BIT | OPERAND_VALUE_BIT |
|
||||
CONDITION_VALUE_BIT,
|
||||
/* MVARIABLE_SYMBOL */ ABSOLUTE_VALUE_BIT | RELOCATABLE_VALUE_BIT |
|
||||
DATA_VALUE_BIT | BSS_VALUE_BIT |
|
||||
UNDEFINED_VALUE_BIT |
|
||||
STRING_VALUE_BIT | OPERAND_VALUE_BIT |
|
||||
CONDITION_VALUE_BIT,
|
||||
/* UNKNOWN_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
/* FUNCTION_SYMBOL */ FUNCTION_VALUE_BIT,
|
||||
/* BUILT_IN_FUNCTION_SYMBOL */ BUILT_IN_FUNCTION_VALUE_BIT,
|
||||
/* NESTED_UNKNOWN_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
/* DEFINE_SYMBOL */ OPERAND_VALUE_BIT,
|
||||
/* MDEFINE_SYMBOL */ OPERAND_VALUE_BIT,
|
||||
/* UNKNOWN_FUNCTION_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
/* UNKNOWN_MACRO_SYMBOL */ UNDEFINED_VALUE_BIT,
|
||||
};
|
||||
|
||||
/* indexed by valueKindType */
|
||||
int valueBitTable[] = {
|
||||
ABSOLUTE_VALUE_BIT,
|
||||
DATA_VALUE_BIT,
|
||||
RELOCATABLE_VALUE_BIT,
|
||||
BSS_VALUE_BIT,
|
||||
STRUCT_VALUE_BIT,
|
||||
FIELD_VALUE_BIT,
|
||||
MACRO_VALUE_BIT,
|
||||
OPERAND_VALUE_BIT,
|
||||
STRING_VALUE_BIT,
|
||||
CONDITION_VALUE_BIT,
|
||||
UNDEFINED_VALUE_BIT,
|
||||
FUNCTION_VALUE_BIT,
|
||||
BLOCK_VALUE_BIT,
|
||||
BUILT_IN_FUNCTION_VALUE_BIT,
|
||||
ARRAY_VALUE_BIT,
|
||||
FAIL_BIT,
|
||||
};
|
||||
|
||||
|
||||
codeRegionType absoluteCodeRegion;
|
||||
codeRegionType relocatableCodeRegion;
|
||||
codeRegionType *codeRegions[2] = {
|
||||
&absoluteCodeRegion,
|
||||
&relocatableCodeRegion
|
||||
};
|
||||
|
||||
/* A predefined undefined value so we don't have to make a new one every
|
||||
time we need one */
|
||||
valueType undefinedValueValue = { UNDEFINED_VALUE, 0,
|
||||
EXPRESSION_OPND };
|
||||
valueType *UndefinedValue = &undefinedValueValue;
|
||||
|
||||
valueType *addressModeBIF();
|
||||
valueType *applyBIF();
|
||||
valueType *atasciiBIF();
|
||||
valueType *atasciiColorBIF();
|
||||
valueType *debugModeOffBIF();
|
||||
valueType *debugModeOnBIF();
|
||||
valueType *emitModeOffBIF();
|
||||
valueType *emitModeOnBIF();
|
||||
valueType *getAddressRegisterBIF();
|
||||
valueType *getDataRegisterBIF();
|
||||
valueType *getIndexRegisterBIF();
|
||||
valueType *getRegisterBIF();
|
||||
valueType *getWLBIF();
|
||||
valueType *isARegisterBIF();
|
||||
valueType *isAbsoluteLongModeBIF();
|
||||
valueType *isAbsoluteModeBIF();
|
||||
valueType *isAbsoluteShortModeBIF();
|
||||
valueType *isAbsoluteValueBIF();
|
||||
valueType *isBlockBIF();
|
||||
valueType *isBuiltInFunctionBIF();
|
||||
valueType *isCCRegisterBIF();
|
||||
valueType *isConditionCodeBIF();
|
||||
valueType *isControlRegisterBIF();
|
||||
valueType *isDFCRegisterBIF();
|
||||
valueType *isDRegisterBIF();
|
||||
valueType *isDefinedBIF();
|
||||
valueType *isDisplacementModeBIF();
|
||||
valueType *isExternalBIF();
|
||||
valueType *isFieldBIF();
|
||||
valueType *isFunctionBIF();
|
||||
valueType *isImmediateModeBIF();
|
||||
valueType *isIndexedModeBIF();
|
||||
valueType *isIndirectModeBIF();
|
||||
valueType *isPCDisplacementModeBIF();
|
||||
valueType *isPCIndexedModeBIF();
|
||||
valueType *isPostincrementModeBIF();
|
||||
valueType *isPredecrementModeBIF();
|
||||
valueType *isRelocatableValueBIF();
|
||||
valueType *isSFCRegisterBIF();
|
||||
valueType *isStatusRegisterBIF();
|
||||
valueType *isStringBIF();
|
||||
valueType *isStructBIF();
|
||||
valueType *isSymbolBIF();
|
||||
valueType *isUSPBIF();
|
||||
valueType *isVBRegisterBIF();
|
||||
valueType *listingOffBIF();
|
||||
valueType *listingOnBIF();
|
||||
valueType *nthCharBIF();
|
||||
valueType *printfBIF();
|
||||
valueType *strcatBIF();
|
||||
valueType *strcmpBIF();
|
||||
valueType *strcmplcBIF();
|
||||
valueType *strlenBIF();
|
||||
valueType *substrBIF();
|
||||
valueType *symbolDefineBIF();
|
||||
valueType *symbolLookupBIF();
|
||||
valueType *symbolNameBIF();
|
||||
valueType *symbolUsageBIF();
|
||||
valueType *valueTypeBIF();
|
||||
|
||||
/* Used to initialize symbols representing built-in functions */
|
||||
struct {
|
||||
stringType *functionName;
|
||||
valueType *(*functionEntry)();
|
||||
bool isSpecialFunction;
|
||||
} builtInFunctionTable[] = {
|
||||
"addressMode", addressModeBIF, FALSE,
|
||||
"apply", applyBIF, FALSE,
|
||||
"atascii", atasciiBIF, FALSE,
|
||||
"atasciiColor", atasciiColorBIF, FALSE,
|
||||
"debugModeOff", debugModeOffBIF, FALSE,
|
||||
"debugModeOn", debugModeOnBIF, FALSE,
|
||||
"emitModeOff", emitModeOffBIF, FALSE,
|
||||
"emitModeOn", emitModeOnBIF, FALSE,
|
||||
"getAddressRegister", getAddressRegisterBIF, FALSE,
|
||||
"getDataRegister", getDataRegisterBIF, FALSE,
|
||||
"getIndexRegister", getIndexRegisterBIF, FALSE,
|
||||
"getRegister", getRegisterBIF, FALSE,
|
||||
"getWL", getWLBIF, FALSE,
|
||||
"isARegister", isARegisterBIF, FALSE,
|
||||
"isAbsoluteLongMode", isAbsoluteLongModeBIF, FALSE,
|
||||
"isAbsoluteMode", isAbsoluteModeBIF, FALSE,
|
||||
"isAbsoluteShortMode", isAbsoluteShortModeBIF, FALSE,
|
||||
"isAbsoluteValue", isAbsoluteValueBIF, FALSE,
|
||||
"isBlock", isBlockBIF, FALSE,
|
||||
"isBuiltInFunction", isBuiltInFunctionBIF, FALSE,
|
||||
"isCCRegister", isCCRegisterBIF, FALSE,
|
||||
"isConditionCode", isConditionCodeBIF, FALSE,
|
||||
"isControlRegister", isControlRegisterBIF, FALSE,
|
||||
"isDFCRegister", isDFCRegisterBIF, FALSE,
|
||||
"isDRegister", isDRegisterBIF, FALSE,
|
||||
"isDefined", isDefinedBIF, TRUE,
|
||||
"isDisplacementMode", isDisplacementModeBIF, FALSE,
|
||||
"isExternal", isExternalBIF, TRUE,
|
||||
"isField", isFieldBIF, FALSE,
|
||||
"isFunction", isFunctionBIF, FALSE,
|
||||
"isImmediateMode", isImmediateModeBIF, FALSE,
|
||||
"isIndexedMode", isIndexedModeBIF, FALSE,
|
||||
"isIndirectMode", isIndirectModeBIF, FALSE,
|
||||
"isPCDisplacementMode", isPCDisplacementModeBIF,FALSE,
|
||||
"isPCIndexedMode", isPCIndexedModeBIF, FALSE,
|
||||
"isPostincrementMode", isPostincrementModeBIF, FALSE,
|
||||
"isPredecrementMode", isPredecrementModeBIF, FALSE,
|
||||
"isRelocatableValue", isRelocatableValueBIF, FALSE,
|
||||
"isSFCRegister", isSFCRegisterBIF, FALSE,
|
||||
"isStatusRegister", isStatusRegisterBIF, FALSE,
|
||||
"isString", isStringBIF, FALSE,
|
||||
"isStruct", isStructBIF, FALSE,
|
||||
"isSymbol", isSymbolBIF, TRUE,
|
||||
"isUSP", isUSPBIF, FALSE,
|
||||
"isVBRegister", isVBRegisterBIF, FALSE,
|
||||
"listingOff", listingOffBIF, FALSE,
|
||||
"listingOn", listingOnBIF, FALSE,
|
||||
"nthChar", nthCharBIF, FALSE,
|
||||
"printf", printfBIF, FALSE,
|
||||
"strcat", strcatBIF, FALSE,
|
||||
"strcmp", strcmpBIF, FALSE,
|
||||
"strcmplc", strcmplcBIF, FALSE,
|
||||
"strlen", strlenBIF, FALSE,
|
||||
"substr", substrBIF, FALSE,
|
||||
"symbolDefine", symbolDefineBIF, FALSE,
|
||||
"symbolLookup", symbolLookupBIF, FALSE,
|
||||
"symbolName", symbolNameBIF, TRUE,
|
||||
"symbolUsage", symbolUsageBIF, TRUE,
|
||||
"valueType", valueTypeBIF, FALSE,
|
||||
NULL, NULL, FALSE,
|
||||
};
|
||||
|
||||
/* Used to initialize predefined symbols */
|
||||
struct {
|
||||
stringType *symbolName;
|
||||
int symbolValue;
|
||||
} predefinedSymbolTable[] = {
|
||||
"FALSE", 0,
|
||||
"NULL", 0,
|
||||
"TRUE", 1,
|
||||
NULL, 0,
|
||||
};
|
||||
|
||||
/* These define the temporary files used to hold scratch data used in the
|
||||
generation of listings. The "XXXXXX"s get blasted by 'mktemp' */
|
||||
char pass2SourceFileName[] = "/tmp/zsourceXXXXXX";
|
||||
char pass2IndexFileName[] = "/tmp/zindexXXXXXX";
|
||||
char pass2MacroExpansionFileName[] = "/tmp/zmacroXXXXXX";
|
1070
macrossTypes.h
Normal file
1070
macrossTypes.h
Normal file
File diff suppressed because it is too large
Load Diff
1202
macross_6502.y
Normal file
1202
macross_6502.y
Normal file
File diff suppressed because it is too large
Load Diff
1362
macross_68000.y
Normal file
1362
macross_68000.y
Normal file
File diff suppressed because it is too large
Load Diff
37
main.c
Normal file
37
main.c
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
main.c -- Top level of the Macross assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
5-December-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char end;
|
||||
char *sbrk();
|
||||
|
||||
fflush(stdout);
|
||||
initializeStuff(argc, argv);
|
||||
yyparse();
|
||||
finishUp();
|
||||
if (emitPrint)
|
||||
printf("storage high water mark 0x%x == %d\n", sbrk(0) - &end,
|
||||
sbrk(0) - &end);
|
||||
if (errorFlag)
|
||||
chokePukeAndDie();
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
printVersion()
|
||||
{
|
||||
printf("Macross %s version 4.20.\n", TARGET_CPU_STRING);
|
||||
}
|
||||
|
331
malloc.c
Normal file
331
malloc.c
Normal file
@ -0,0 +1,331 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)malloc.c 1.2 (Lucasfilm) 84/10/17";
|
||||
/* from malloc.c 4.3 (Berkeley) 9/16/83 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* malloc.c (Caltech) 2/21/82
|
||||
* Chris Kingsley, kingsley@cit-20.
|
||||
*
|
||||
* This is a very fast storage allocator. It allocates blocks of a small
|
||||
* number of different sizes, and keeps free lists of each size. Blocks that
|
||||
* don't exactly fit are passed up to the next larger size. In this
|
||||
* implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
|
||||
* This is designed for use in a program that uses vast quantities of memory,
|
||||
* but bombs when it runs out.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define NULL 0
|
||||
|
||||
/*
|
||||
* The overhead on a block is at least 4 bytes. When free, this space
|
||||
* contains a pointer to the next free block, and the bottom two bits must
|
||||
* be zero. When in use, the first byte is set to MAGIC, and the second
|
||||
* byte is the size index. The remaining bytes are for alignment.
|
||||
* If range checking is enabled and the size of the block fits
|
||||
* in two bytes, then the top two bytes hold the size of the requested block
|
||||
* plus the range checking words, and the header word MINUS ONE.
|
||||
*/
|
||||
union overhead {
|
||||
union overhead *ov_next; /* when free */
|
||||
struct {
|
||||
u_char ovu_magic; /* magic number */
|
||||
u_char ovu_index; /* bucket # */
|
||||
#ifdef RCHECK
|
||||
u_short ovu_size; /* actual block size */
|
||||
u_int ovu_rmagic; /* range magic number */
|
||||
#endif
|
||||
} ovu;
|
||||
#define ov_magic ovu.ovu_magic
|
||||
#define ov_index ovu.ovu_index
|
||||
#define ov_size ovu.ovu_size
|
||||
#define ov_rmagic ovu.ovu_rmagic
|
||||
};
|
||||
|
||||
#define MAGIC 0xff /* magic # on accounting info */
|
||||
#define RMAGIC 0x55555555 /* magic # on range info */
|
||||
#ifdef RCHECK
|
||||
#define RSLOP sizeof (u_int)
|
||||
#else
|
||||
#define RSLOP 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* nextf[i] is the pointer to the next free block of size 2^(i+3). The
|
||||
* smallest allocatable block is 8 bytes. The overhead information
|
||||
* precedes the data area returned to the user.
|
||||
*/
|
||||
#define NBUCKETS 30
|
||||
static union overhead *nextf[NBUCKETS];
|
||||
extern char *sbrk();
|
||||
|
||||
#ifdef MSTATS
|
||||
/*
|
||||
* nmalloc[i] is the difference between the number of mallocs and frees
|
||||
* for a given block size.
|
||||
*/
|
||||
static u_int nmalloc[NBUCKETS];
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef debug
|
||||
#define ASSERT(p) if (!(p)) botch("p"); else
|
||||
static
|
||||
botch(s)
|
||||
char *s;
|
||||
{
|
||||
|
||||
printf("assertion botched: %s\n", s);
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
#define ASSERT(p)
|
||||
#endif
|
||||
|
||||
char *
|
||||
malloc(nbytes)
|
||||
register unsigned nbytes;
|
||||
{
|
||||
register union overhead *p;
|
||||
register int bucket = 0;
|
||||
register unsigned shiftr;
|
||||
|
||||
/*
|
||||
* Convert amount of memory requested into
|
||||
* closest block size stored in hash buckets
|
||||
* which satisfies request. Account for
|
||||
* space used per block for accounting.
|
||||
*/
|
||||
nbytes += sizeof (union overhead) + RSLOP;
|
||||
nbytes = (nbytes + 3) &~ 3;
|
||||
shiftr = (nbytes - 1) >> 2;
|
||||
/* apart from this loop, this is O(1) */
|
||||
while (shiftr >>= 1)
|
||||
bucket++;
|
||||
/*
|
||||
* If nothing in hash bucket right now,
|
||||
* request more memory from the system.
|
||||
*/
|
||||
if (nextf[bucket] == NULL)
|
||||
morecore(bucket);
|
||||
if ((p = (union overhead *)nextf[bucket]) == NULL)
|
||||
return (NULL);
|
||||
/* remove from linked list */
|
||||
nextf[bucket] = nextf[bucket]->ov_next;
|
||||
p->ov_magic = MAGIC;
|
||||
p->ov_index= bucket;
|
||||
#ifdef MSTATS
|
||||
nmalloc[bucket]++;
|
||||
#endif
|
||||
#ifdef RCHECK
|
||||
/*
|
||||
* Record allocated size of block and
|
||||
* bound space with magic numbers.
|
||||
*/
|
||||
if (nbytes <= 0x10000)
|
||||
p->ov_size = nbytes - 1;
|
||||
p->ov_rmagic = RMAGIC;
|
||||
*((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
|
||||
#endif
|
||||
return ((char *)(p + 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate more memory to the indicated bucket.
|
||||
*/
|
||||
static
|
||||
morecore(bucket)
|
||||
register bucket;
|
||||
{
|
||||
register union overhead *op;
|
||||
register int rnu; /* 2^rnu bytes will be requested */
|
||||
register int nblks; /* become nblks blocks of the desired size */
|
||||
register int siz;
|
||||
|
||||
if (nextf[bucket])
|
||||
return;
|
||||
/*
|
||||
* Insure memory is allocated
|
||||
* on a page boundary. Should
|
||||
* make getpageize call?
|
||||
*/
|
||||
op = (union overhead *)sbrk(0);
|
||||
if ((int)op & 0x3ff)
|
||||
sbrk(1024 - ((int)op & 0x3ff));
|
||||
/* take 2k unless the block is bigger than that */
|
||||
/* rnu = (bucket <= 8) ? 11 : bucket + 3; */
|
||||
rnu = (bucket <= 10) ? 13 : bucket + 3; /* now grab 8k 'cbm' */
|
||||
nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
|
||||
if (rnu < bucket)
|
||||
rnu = bucket;
|
||||
op = (union overhead *)sbrk(1 << rnu);
|
||||
/* no more room! */
|
||||
if ((int)op == -1)
|
||||
return;
|
||||
/*
|
||||
* Round up to minimum allocation size boundary
|
||||
* and deduct from block count to reflect.
|
||||
*/
|
||||
if ((int)op & 7) {
|
||||
op = (union overhead *)(((int)op + 8) &~ 7);
|
||||
nblks--;
|
||||
}
|
||||
/*
|
||||
* Add new memory allocated to that on
|
||||
* free list for this hash bucket.
|
||||
*/
|
||||
nextf[bucket] = op;
|
||||
siz = 1 << (bucket + 3);
|
||||
while (--nblks > 0) {
|
||||
op->ov_next = (union overhead *)((caddr_t)op + siz);
|
||||
op = (union overhead *)((caddr_t)op + siz);
|
||||
}
|
||||
}
|
||||
|
||||
free(cp)
|
||||
char *cp;
|
||||
{
|
||||
register int size;
|
||||
register union overhead *op;
|
||||
|
||||
if (cp == NULL)
|
||||
return;
|
||||
op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
|
||||
#ifdef debug
|
||||
ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
|
||||
#else
|
||||
if (op->ov_magic != MAGIC)
|
||||
return; /* sanity */
|
||||
#endif
|
||||
#ifdef RCHECK
|
||||
ASSERT(op->ov_rmagic == RMAGIC);
|
||||
if (op->ov_index <= 13)
|
||||
ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
|
||||
#endif
|
||||
ASSERT(op->ov_index < NBUCKETS);
|
||||
size = op->ov_index;
|
||||
op->ov_next = nextf[size];
|
||||
nextf[size] = op;
|
||||
#ifdef MSTATS
|
||||
nmalloc[size]--;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* When a program attempts "storage compaction" as mentioned in the
|
||||
* old malloc man page, it realloc's an already freed block. Usually
|
||||
* this is the last block it freed; occasionally it might be farther
|
||||
* back. We have to search all the free lists for the block in order
|
||||
* to determine its bucket: 1st we make one pass thru the lists
|
||||
* checking only the first block in each; if that fails we search
|
||||
* ``realloc_srchlen'' blocks in each list for a match (the variable
|
||||
* is extern so the caller can modify it). If that fails we just copy
|
||||
* however many bytes was given to realloc() and hope it's not huge.
|
||||
*/
|
||||
int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
|
||||
|
||||
char *
|
||||
realloc(cp, nbytes)
|
||||
char *cp;
|
||||
unsigned nbytes;
|
||||
{
|
||||
register u_int onb;
|
||||
union overhead *op;
|
||||
char *res;
|
||||
register int i;
|
||||
int was_alloced = 0;
|
||||
|
||||
if (cp == NULL)
|
||||
return (malloc(nbytes));
|
||||
op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
|
||||
if (op->ov_magic == MAGIC) {
|
||||
was_alloced++;
|
||||
i = op->ov_index;
|
||||
} else {
|
||||
/*
|
||||
* Already free, doing "compaction".
|
||||
*
|
||||
* Search for the old block of memory on the
|
||||
* free list. First, check the most common
|
||||
* case (last element free'd), then (this failing)
|
||||
* the last ``realloc_srchlen'' items free'd.
|
||||
* If all lookups fail, then assume the size of
|
||||
* the memory block being realloc'd is the
|
||||
* smallest possible.
|
||||
*/
|
||||
if ((i = findbucket(op, 1)) < 0 &&
|
||||
(i = findbucket(op, realloc_srchlen)) < 0)
|
||||
i = 0;
|
||||
}
|
||||
onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
|
||||
/* avoid the copy if same size block */
|
||||
if (was_alloced &&
|
||||
nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
|
||||
return(cp);
|
||||
if ((res = malloc(nbytes)) == NULL)
|
||||
return (NULL);
|
||||
if (cp != res) /* common optimization */
|
||||
bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
|
||||
if (was_alloced)
|
||||
free(cp);
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search ``srchlen'' elements of each free list for a block whose
|
||||
* header starts at ``freep''. If srchlen is -1 search the whole list.
|
||||
* Return bucket number, or -1 if not found.
|
||||
*/
|
||||
static
|
||||
findbucket(freep, srchlen)
|
||||
union overhead *freep;
|
||||
int srchlen;
|
||||
{
|
||||
register union overhead *p;
|
||||
register int i, j;
|
||||
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
j = 0;
|
||||
for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
|
||||
if (p == freep)
|
||||
return (i);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef MSTATS
|
||||
/*
|
||||
* mstats - print out statistics about malloc
|
||||
*
|
||||
* Prints two lines of numbers, one showing the length of the free list
|
||||
* for each size category, the second showing the number of mallocs -
|
||||
* frees for each size category.
|
||||
*/
|
||||
mstats(s)
|
||||
char *s;
|
||||
{
|
||||
register int i, j;
|
||||
register union overhead *p;
|
||||
int totfree = 0,
|
||||
totused = 0;
|
||||
|
||||
fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
|
||||
;
|
||||
fprintf(stderr, " %d", j);
|
||||
totfree += j * (1 << (i + 3));
|
||||
}
|
||||
fprintf(stderr, "\nused:\t");
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
fprintf(stderr, " %d", nmalloc[i]);
|
||||
totused += nmalloc[i] * (1 << (i + 3));
|
||||
}
|
||||
fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
|
||||
totused, totfree);
|
||||
}
|
||||
#endif
|
51
notes68/1.am
Normal file
51
notes68/1.am
Normal file
@ -0,0 +1,51 @@
|
||||
Address Modes
|
||||
-------------
|
||||
Notation
|
||||
Number Motorola Name Motorola Sun Sun Name
|
||||
------ ------------- -------- --- --------
|
||||
1 Data Register Direct Dn Dn Register
|
||||
|
||||
2 Address Register Direct An An Register
|
||||
|
||||
3 Address Register Indirect (An) An@ Register
|
||||
Deferred
|
||||
|
||||
4 Address Register Indirect w/ (An)+ An@+ Postincrement
|
||||
Postincrement
|
||||
|
||||
5 Address Register Indirect w/ -(An) An@- Predecrement
|
||||
Predecrement
|
||||
|
||||
6 Address Register Indirect w/ d(An) An@(d) Displacement
|
||||
Displacement
|
||||
|
||||
7 Address Register Indirect w/ d(An,Rx.W) An@(d,Rx:W) Word Index
|
||||
Index d(An,Rx.L) An@(d,Rx:L) Long Index
|
||||
|
||||
8 Program Counter w/ Displacement d(PC) PC@(d) PC Displacement
|
||||
|
||||
9 Program Counter w/ Index d(PC,Rx.W) PC@(d,Rx:W) PC Word
|
||||
Index
|
||||
d(PC,Rx.L) PC@(d,Rx:L) PC Long
|
||||
Index
|
||||
|
||||
10 Immediate #xxx #xxx Immediate
|
||||
|
||||
11 Absolute Short xxx.W xxx:W Absolute Short
|
||||
|
||||
12 Absolute Long xxx.L xxx:L Absolute Long
|
||||
|
||||
13 -- -- xxx Normal
|
||||
|
||||
14 (condition code register) CCR CC --
|
||||
|
||||
15 (status register) SR SR --
|
||||
|
||||
16 Implied
|
||||
|
||||
17 (user stack pointer) USP USP --
|
||||
|
||||
18 (control register) SFC SFC --
|
||||
DFC DFC
|
||||
VBR VBR
|
||||
|
45
notes68/2.amg
Normal file
45
notes68/2.amg
Normal file
@ -0,0 +1,45 @@
|
||||
Address Mode Groups
|
||||
-------------------
|
||||
ID Mode set Mnemonic
|
||||
-- -------- --------
|
||||
A 1 DATA_REGISTER
|
||||
|
||||
B 2 ADDRESS_REGISTER
|
||||
|
||||
C 4 POSTINCREMENT
|
||||
|
||||
D 5 PREDECREMENT
|
||||
|
||||
E 6 DISPLACEMENT
|
||||
|
||||
F 10 IMMEDIATE
|
||||
|
||||
G 13 NORMAL
|
||||
|
||||
H 14 CONDITION_CODE_REGISTER
|
||||
|
||||
I 15 STATUS_REGISTER
|
||||
|
||||
J 16 (no operand at all!)
|
||||
|
||||
K 17 USER_STACK_POINTER
|
||||
|
||||
L { 17-18 } CONTROL_REGISTER
|
||||
|
||||
M { 1-2 } REGISTER
|
||||
|
||||
N { 1-7, 11-13 } STORABLE
|
||||
|
||||
O { 1-13 } FULL_EA
|
||||
|
||||
P { 1, 3-7, 11-13 } STORABLE_NO_A_REGISTER
|
||||
|
||||
Q { 1, 3-13 } FULL_EA_NO_A_REG
|
||||
|
||||
R { 3-4, 6-9, 11-13 } MISC_1
|
||||
|
||||
S { 3-7, 11-13 } STORABLE_NO_REGISTER
|
||||
|
||||
T { 3, 5-7, 11-13 } MISC_2
|
||||
|
||||
U { 3, 6-9, 11-13 } MISC_3
|
60
notes68/3.os
Normal file
60
notes68/3.os
Normal file
@ -0,0 +1,60 @@
|
||||
Operand Sets
|
||||
------------
|
||||
1 A
|
||||
2 AA
|
||||
3 AE
|
||||
4 AG
|
||||
5 AP
|
||||
6 AS
|
||||
|
||||
7 B
|
||||
8 BF
|
||||
9 BK
|
||||
|
||||
10 CC
|
||||
|
||||
11 DD
|
||||
|
||||
12 EA
|
||||
|
||||
13 F
|
||||
14 FA
|
||||
15 FH
|
||||
16 FI
|
||||
17 FN
|
||||
18 FP
|
||||
|
||||
19 G
|
||||
|
||||
20 HP
|
||||
|
||||
21 IP
|
||||
|
||||
22 J
|
||||
|
||||
23 KB
|
||||
|
||||
24 LM
|
||||
|
||||
25 ML
|
||||
26 MM
|
||||
27 MP
|
||||
28 MS
|
||||
29 M*T
|
||||
|
||||
30 OA
|
||||
31 OB
|
||||
|
||||
32 P
|
||||
|
||||
33 QA
|
||||
34 QH
|
||||
35 QI
|
||||
|
||||
36 RM*
|
||||
|
||||
37 S
|
||||
38 SM
|
||||
|
||||
39 U
|
||||
40 UB
|
115
notes68/4.ic
Normal file
115
notes68/4.ic
Normal file
@ -0,0 +1,115 @@
|
||||
Instruction Classes
|
||||
-------------------
|
||||
i ABCD - | AA
|
||||
ADDX bwl | DD
|
||||
SBCD - |
|
||||
SUBX bwl |
|
||||
|
||||
ii ADD bwl | AS
|
||||
SUB bwl | FP __I
|
||||
| OA
|
||||
| OB __A
|
||||
|
||||
iii ADDQ bwl | FN
|
||||
SUBQ bwl |
|
||||
|
||||
iv AND bwl | AS
|
||||
OR bwl | FH __CCR
|
||||
| FI __SR
|
||||
| FN __I
|
||||
| GA
|
||||
|
||||
v ASL bwl | AA
|
||||
ASR bwl | FA
|
||||
LSL bwl | S
|
||||
LSR bwl |
|
||||
ROL bwl |
|
||||
ROR bwl |
|
||||
ROXL bwl |
|
||||
ROXR bwl |
|
||||
|
||||
vi Bcc - | G
|
||||
BRA - |
|
||||
BSR - |
|
||||
|
||||
vii BCHG - | AP
|
||||
BCLR - | FP
|
||||
BSET - |
|
||||
BTST - |
|
||||
|
||||
viii CHK - | QA
|
||||
DIVS - |
|
||||
DIVU - |
|
||||
MULS - |
|
||||
MULU - |
|
||||
|
||||
ix CLR bwl | P
|
||||
NBCD - |
|
||||
NEG bwl |
|
||||
NEGX bwl |
|
||||
NOT bwl |
|
||||
Scc - |
|
||||
TAS - |
|
||||
TST bwl |
|
||||
|
||||
x CMP bwl | FP __I
|
||||
| OA
|
||||
| OB __A
|
||||
|
||||
xi CMPM bwl | CC
|
||||
|
||||
xii DBcc - | AG
|
||||
|
||||
xiii EOR bwl | AP
|
||||
| FH __CCR
|
||||
| FI __SR
|
||||
| FP __I
|
||||
|
||||
xiv EXG - | MM
|
||||
|
||||
xv EXT bwl | A
|
||||
SWAP - |
|
||||
|
||||
xvi ILLEGAL - | J
|
||||
NOP - |
|
||||
RESET - |
|
||||
RTE - |
|
||||
RTR - |
|
||||
RTS - |
|
||||
TRAPV - |
|
||||
|
||||
xvii JMP - | U
|
||||
JSR - |
|
||||
PEA - |
|
||||
|
||||
xviii LEA - | UB
|
||||
|
||||
xix LINK - | BF
|
||||
|
||||
xx MOV bwl | BK __USP
|
||||
| HP CCR__
|
||||
| IP SR__
|
||||
| KB __USP
|
||||
| LM __C
|
||||
| ML __C
|
||||
| OB __I
|
||||
| OP
|
||||
| QH __CCR
|
||||
| QI __SR
|
||||
|
||||
xxi MOVEM wl | M*T
|
||||
| RM*
|
||||
|
||||
xxii MOVEP wl | AE
|
||||
| EA
|
||||
|
||||
xxiii MOVEQ - | FA
|
||||
|
||||
xxiv MOVS bwl | MS
|
||||
| SM
|
||||
|
||||
xxv RTD - | F
|
||||
STOP - |
|
||||
TRAP - |
|
||||
|
||||
xxvi UNLK - | B
|
612
object.c
Normal file
612
object.c
Normal file
@ -0,0 +1,612 @@
|
||||
/*
|
||||
object.c -- Routines to output object files for the Macross assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
20-November-1984
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
static int symbolTableSize;
|
||||
static int symbolTableStringSize;
|
||||
bool encodingFunction;
|
||||
|
||||
void
|
||||
outputObjectFile()
|
||||
{
|
||||
void outputPartition();
|
||||
void outputReferenceInfo();
|
||||
void outputSymbolTableInfo();
|
||||
void outputAbsoluteCode();
|
||||
void outputRelocatableCode();
|
||||
void outputReservations();
|
||||
void outputExpressions();
|
||||
void outputFunctions();
|
||||
void dumpSymbolTable();
|
||||
void enumerateAndCountSymbols();
|
||||
|
||||
if (debug || emitPrint)
|
||||
printCodeBuffers();
|
||||
outputPartition();
|
||||
outputAbsoluteCode();
|
||||
if (produceLinkableObject) {
|
||||
outputPartition();
|
||||
outputRelocatableCode();
|
||||
outputPartition();
|
||||
outputReservations();
|
||||
outputPartition();
|
||||
enumerateAndCountSymbols();
|
||||
outputReferenceInfo();
|
||||
outputSymbolTableInfo();
|
||||
outputExpressions();
|
||||
outputFunctions();
|
||||
}
|
||||
if (symbolTableDumpOn)
|
||||
dumpSymbolTable();
|
||||
fclose(objectFileOutput);
|
||||
}
|
||||
|
||||
void
|
||||
outputWord(aWord)
|
||||
int aWord;
|
||||
{
|
||||
putc(aWord & 0xFF, objectFileOutput);
|
||||
putc((aWord >> 8) & 0xFF, objectFileOutput);
|
||||
}
|
||||
|
||||
void
|
||||
outputPartition()
|
||||
{
|
||||
outputWord(0xFFFF);
|
||||
}
|
||||
|
||||
void
|
||||
outputBigword(bigword)
|
||||
unsigned long bigword;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i<=4; i++) {
|
||||
putc(bigword & 0xFF, objectFileOutput);
|
||||
bigword >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputByte(aByte)
|
||||
byte aByte;
|
||||
{
|
||||
putc(aByte, objectFileOutput);
|
||||
}
|
||||
|
||||
void
|
||||
outputString(string)
|
||||
stringType *string;
|
||||
{
|
||||
do {
|
||||
putc(*string, objectFileOutput);
|
||||
} while (*string++ != '\0');
|
||||
}
|
||||
|
||||
void
|
||||
outputStartAddress(startAddress)
|
||||
addressType startAddress;
|
||||
{
|
||||
outputWord(startAddress);
|
||||
if (produceLinkableObject) {
|
||||
outputWord(startAddress - 3);
|
||||
outputByte(0);
|
||||
} else {
|
||||
outputWord(startAddress);
|
||||
outputByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputRelocatableCode()
|
||||
{
|
||||
int i;
|
||||
addressType codeStartAddress;
|
||||
addressType codeEndAddress;
|
||||
|
||||
void outputPseudoSegment();
|
||||
void outputBreak();
|
||||
|
||||
if (haveUserStartAddress && !fixupStartAddress && startAddress->
|
||||
kindOfValue == RELOCATABLE_VALUE)
|
||||
outputStartAddress(startAddress->value);
|
||||
else if (haveUserStartAddress && fixupStartAddress)
|
||||
outputStartAddress(0xFFFE);
|
||||
if (relocatableHighWaterMark < 0)
|
||||
return;
|
||||
codeEndAddress = -1;
|
||||
do {
|
||||
codeStartAddress = codeEndAddress + 1;
|
||||
while (codeBreakList != NULL && codeBreakList->breakAddress
|
||||
== codeStartAddress) {
|
||||
outputBreak(codeBreakList);
|
||||
codeBreakList = codeBreakList->nextBreak;
|
||||
}
|
||||
if (codeBreakList == NULL)
|
||||
codeEndAddress = relocatableHighWaterMark;
|
||||
else
|
||||
codeEndAddress = codeBreakList->breakAddress - 1;
|
||||
outputPseudoSegment(codeStartAddress, codeEndAddress);
|
||||
} while (codeEndAddress < relocatableHighWaterMark);
|
||||
}
|
||||
|
||||
void
|
||||
outputBreak(codeBreak)
|
||||
codeBreakType *codeBreak;
|
||||
{
|
||||
switch (codeBreak->kindOfBreak) {
|
||||
case BREAK_BREAK:
|
||||
case END_CONSTRAIN_BREAK:
|
||||
/* do nothing */
|
||||
break;
|
||||
|
||||
case ALIGN_BREAK:
|
||||
outputWord(codeBreak->breakAddress);
|
||||
outputWord(codeBreak->breakAddress - 2);
|
||||
outputWord(codeBreak->breakData);
|
||||
break;
|
||||
|
||||
case CONSTRAIN_BREAK:
|
||||
outputWord(codeBreak->breakAddress);
|
||||
outputWord(codeBreak->breakAddress - 1);
|
||||
outputWord(codeBreak->breakData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputAbsoluteCode()
|
||||
{
|
||||
int i;
|
||||
int startSegment;
|
||||
int endSegment;
|
||||
int nextSegment;
|
||||
void outputOneCodeBuffer();
|
||||
|
||||
if (haveUserStartAddress && !fixupStartAddress && startAddress->
|
||||
kindOfValue==ABSOLUTE_VALUE)
|
||||
outputStartAddress(startAddress->value);
|
||||
for (startSegment=0; startSegment<CODE_BUFFERS_IN_ADDRESS_SPACE;
|
||||
startSegment = endSegment + 1) {
|
||||
endSegment = startSegment;
|
||||
nextSegment = endSegment + 1;
|
||||
while (nextSegment < CODE_BUFFERS_IN_ADDRESS_SPACE &&
|
||||
absoluteCodeRegion.codeSegments[nextSegment]
|
||||
!= NULL && absoluteCodeRegion.codeSegments[
|
||||
endSegment] != NULL && absoluteCodeRegion.
|
||||
codeSegments[endSegment]->codeEndAddress+1 ==
|
||||
absoluteCodeRegion.codeSegments[nextSegment]
|
||||
->codeStartAddress) {
|
||||
++endSegment;
|
||||
++nextSegment;
|
||||
}
|
||||
if (absoluteCodeRegion.codeSegments[startSegment] != NULL) {
|
||||
outputWord(absoluteCodeRegion.codeSegments[
|
||||
startSegment]->codeStartAddress);
|
||||
outputWord(absoluteCodeRegion.codeSegments[
|
||||
endSegment]->codeEndAddress);
|
||||
for (i=startSegment; i<=endSegment; ++i)
|
||||
outputOneCodeBuffer(absoluteCodeRegion.
|
||||
codeSegments[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputOneCodeBuffer(segment)
|
||||
codeSegmentType *segment;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (segment != NULL) {
|
||||
/* outputWord(segment->codeStartAddress);
|
||||
outputWord(segment->codeEndAddress);*/
|
||||
for (i=bufferPosition(segment->codeStartAddress); i<=
|
||||
bufferPosition(segment->codeEndAddress); i++)
|
||||
outputByte((*segment->codeBuffer)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputPseudoSegment(codeStartAddress, codeEndAddress)
|
||||
addressType codeStartAddress;
|
||||
addressType codeEndAddress;
|
||||
{
|
||||
int startSegment;
|
||||
int endSegment;
|
||||
int startPosition;
|
||||
int endPosition;
|
||||
int originalStartPosition;
|
||||
int ultimateEndPosition;
|
||||
int position;
|
||||
int segment;
|
||||
codeSegmentType *segmentPtr;
|
||||
|
||||
void outputWord();
|
||||
void outputByte();
|
||||
|
||||
outputWord(codeStartAddress);
|
||||
outputWord(codeEndAddress);
|
||||
startSegment = bufferNumber(codeStartAddress);
|
||||
endSegment = bufferNumber(codeEndAddress);
|
||||
originalStartPosition = bufferPosition(codeStartAddress);
|
||||
ultimateEndPosition = bufferPosition(codeEndAddress);
|
||||
for (segment=startSegment; segment<=endSegment; segment++) {
|
||||
segmentPtr = relocatableCodeRegion.codeSegments[segment];
|
||||
startPosition = (segment == startSegment) ?
|
||||
originalStartPosition : 0;
|
||||
endPosition = (segment == endSegment) ? ultimateEndPosition :
|
||||
CODE_BUFFER_SIZE - 1;
|
||||
for(position=startPosition; position<=endPosition; position++)
|
||||
outputByte((*segmentPtr->codeBuffer)[position]);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
isObjectSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
return(symbol != NULL && symbol->context->value != NULL &&
|
||||
symbol->context->value->kindOfValue != FUNCTION_VALUE &&
|
||||
symbol->context->value->kindOfValue != BUILT_IN_FUNCTION_VALUE
|
||||
&& symbol->context->value->kindOfValue != MACRO_VALUE &&
|
||||
((isExternal(symbol) && symbol->context->value->kindOfValue
|
||||
!= UNDEFINED_VALUE) || symbol->referenceCount > 0));
|
||||
/* return(symbol != NULL && symbol->context->value != NULL &&
|
||||
(symbol->context->value->kindOfValue == RELOCATABLE_VALUE ||
|
||||
symbol->context->value->kindOfValue == ABSOLUTE_VALUE ||
|
||||
isExternal(symbol)));*/
|
||||
}
|
||||
|
||||
void
|
||||
enumerateAndCountSymbols()
|
||||
{
|
||||
int i;
|
||||
symbolTableEntryType *symb;
|
||||
|
||||
symbolTableSize = 0;
|
||||
symbolTableStringSize = 0;
|
||||
for (i=0; i<HASH_TABLE_SIZE; i++)
|
||||
for (symb=symbolTable[i]; symb!=NULL; symb=symb->nextSymbol)
|
||||
if (isObjectSymbol(symb)) {
|
||||
symbolTableStringSize += strlen(symb->symbolName) + 1;
|
||||
symb->ordinal = symbolTableSize++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enumerateAndCountReferences()
|
||||
{
|
||||
int result;
|
||||
int codeMode;
|
||||
expressionReferenceListType *theReferences;
|
||||
|
||||
result = 0;
|
||||
for (codeMode=0; codeMode<=1; codeMode++) {
|
||||
theReferences = expressionReferenceList[codeMode];
|
||||
while (theReferences != NULL) {
|
||||
theReferences->relocation.referenceExpression = result++;
|
||||
theReferences = theReferences->nextReference;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
outputReference(reference)
|
||||
expressionReferenceType *reference;
|
||||
{
|
||||
byte funnyByte;
|
||||
bigWord funnyWord;
|
||||
|
||||
/* This nonsense is to maintain byte-order and bit-order independence
|
||||
across host machines so that Macross object files will be
|
||||
portable. */
|
||||
funnyByte = reference->referenceMode |
|
||||
(reference->referenceRelative << 1) |
|
||||
(reference->referenceExternal << 2) |
|
||||
(reference->referenceKind << 3);
|
||||
funnyWord = ((reference->referenceAddress) & 0xFFFFFF) |
|
||||
(funnyByte << 24);
|
||||
outputBigword(funnyWord);
|
||||
outputBigword(reference->referenceExpression);
|
||||
|
||||
}
|
||||
|
||||
static int referenceCount;
|
||||
|
||||
void
|
||||
outputReferenceInfo()
|
||||
{
|
||||
expressionReferenceListType *theReferences;
|
||||
int codeMode;
|
||||
|
||||
outputBigword(referenceCount = enumerateAndCountReferences());
|
||||
|
||||
for (codeMode=0; codeMode<=1; codeMode++) {
|
||||
theReferences = expressionReferenceList[codeMode];
|
||||
while (theReferences != NULL) {
|
||||
outputReference(&(theReferences->relocation));
|
||||
theReferences = theReferences->nextReference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputOneSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
byte symbolClass;
|
||||
valueType *symbolValue;
|
||||
valueType *evaluateIdentifier();
|
||||
|
||||
if (symbol->context->usage == DEFINE_SYMBOL)
|
||||
symbolValue = evaluateIdentifier(symbol, FALSE, NO_FIXUP_OK);
|
||||
else
|
||||
symbolValue = symbol->context->value;
|
||||
if (symbolValue->kindOfValue == ABSOLUTE_VALUE)
|
||||
symbolClass = SYMBOL_ABSOLUTE;
|
||||
else if (symbolValue->kindOfValue == RELOCATABLE_VALUE)
|
||||
symbolClass = SYMBOL_RELOCATABLE;
|
||||
else
|
||||
symbolClass = SYMBOL_UNDEFINED;
|
||||
if (isExternal(symbol))
|
||||
symbolClass |= SYMBOL_EXTERNAL;
|
||||
else if (symbolClass == SYMBOL_UNDEFINED)
|
||||
symbolClass = SYMBOL_ABSOLUTE;
|
||||
outputByte(symbolClass);
|
||||
outputBigword(symbolValue->value);
|
||||
outputString(symbol->symbolName);
|
||||
}
|
||||
|
||||
void
|
||||
outputSymbolTableInfo()
|
||||
{
|
||||
int i;
|
||||
symbolTableEntryType *symb;
|
||||
|
||||
outputBigword(symbolTableSize);
|
||||
outputBigword(symbolTableStringSize);
|
||||
for (i=0; i<HASH_TABLE_SIZE; i++)
|
||||
for (symb=symbolTable[i]; symb!=NULL; symb=symb->nextSymbol)
|
||||
if (isObjectSymbol(symb))
|
||||
outputOneSymbol(symb);
|
||||
}
|
||||
|
||||
int
|
||||
symbolCompare(symbol1, symbol2)
|
||||
symbolTableEntryType **symbol1;
|
||||
symbolTableEntryType **symbol2;
|
||||
{
|
||||
return(strcmplc((*symbol1)->symbolName, (*symbol2)->symbolName));
|
||||
}
|
||||
|
||||
bool
|
||||
shouldDumpSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
return(symbolTableDumpOn == 2
|
||||
|| (symbol->context->usage != BUILT_IN_FUNCTION_SYMBOL
|
||||
&& (symbol->context->usage != DEFINE_SYMBOL
|
||||
|| symbol->context->referenceCount != 0
|
||||
|| showAllSymbolsFlag
|
||||
)
|
||||
&& symbol->symbolName[0] != '$'
|
||||
&& symbol->symbolName[0] != '_'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
dumpSymbolTable()
|
||||
{
|
||||
int i;
|
||||
symbolTableEntryType *symb;
|
||||
symbolTableEntryType **symbolVector;
|
||||
int numberOfSymbols;
|
||||
int symbolPtr;
|
||||
valueType *value;
|
||||
|
||||
valueType *evaluateIdentifier();
|
||||
void printValueTersely();
|
||||
|
||||
numberOfSymbols = 0;
|
||||
for (i=0; i<HASH_TABLE_SIZE; i++)
|
||||
for (symb=symbolTable[i]; symb!=NULL; symb=symb->nextSymbol) {
|
||||
if (symb->context != NULL && symb->context->value != NULL &&
|
||||
(symb->context->value->kindOfValue !=
|
||||
UNDEFINED_VALUE || symb->context->usage ==
|
||||
LABEL_SYMBOL || symb->context->usage ==
|
||||
EXTERNAL_SYMBOL || symb->context->usage ==
|
||||
UNKNOWN_SYMBOL || symb->context->usage ==
|
||||
NESTED_UNKNOWN_SYMBOL)) {
|
||||
if (shouldDumpSymbol(symb)) {
|
||||
numberOfSymbols++;
|
||||
}
|
||||
}
|
||||
}
|
||||
symbolVector = (symbolTableEntryType **)malloc(
|
||||
sizeof(symbolTableEntryType *) * numberOfSymbols);
|
||||
symbolPtr = 0;
|
||||
for (i=0; i<HASH_TABLE_SIZE; i++)
|
||||
for (symb=symbolTable[i]; symb!=NULL; symb=symb->nextSymbol) {
|
||||
if (symb->context != NULL && symb->context->value != NULL &&
|
||||
(symb->context->value->kindOfValue !=
|
||||
UNDEFINED_VALUE || symb->context->usage ==
|
||||
LABEL_SYMBOL || symb->context->usage ==
|
||||
EXTERNAL_SYMBOL || symb->context->usage ==
|
||||
UNKNOWN_SYMBOL || symb->context->usage ==
|
||||
NESTED_UNKNOWN_SYMBOL)) {
|
||||
if (shouldDumpSymbol(symb)) {
|
||||
symbolVector[symbolPtr++] = symb;
|
||||
}
|
||||
}
|
||||
}
|
||||
qsort(symbolVector, numberOfSymbols, sizeof(symbolTableEntryType *),
|
||||
symbolCompare);
|
||||
for (symbolPtr=0; symbolPtr<numberOfSymbols; symbolPtr++) {
|
||||
symb = symbolVector[symbolPtr];
|
||||
if (hackFlag != 0) {
|
||||
if (hackableSymbol(symb) && (isExternal(symb) ||
|
||||
hackFlag == 1)) {
|
||||
value = evaluateIdentifier(symb, TRUE,
|
||||
NO_FIXUP_OK);
|
||||
fprintf(symbolDumpFileOutput,
|
||||
"define %s = 0x%x\n", symb->
|
||||
symbolName, value->value);
|
||||
}
|
||||
} else if (symb->context->usage == FUNCTION_SYMBOL) {
|
||||
fprintf(symbolDumpFileOutput, "%-20s = FUNCTION\n",
|
||||
symb->symbolName);
|
||||
} else if (symbolTableDumpOn == 2 || symb->context->usage !=
|
||||
BUILT_IN_FUNCTION_SYMBOL) {
|
||||
value = evaluateIdentifier(symb, TRUE, NO_FIXUP_OK);
|
||||
fprintf(symbolDumpFileOutput, "%-20s = ", symb->
|
||||
symbolName);
|
||||
printValueTersely(value);
|
||||
fprintf(symbolDumpFileOutput, " [%d]", symb->
|
||||
context->referenceCount - 1);
|
||||
if (isExternal(symb))
|
||||
fprintf(symbolDumpFileOutput, " ext");
|
||||
fprintf(symbolDumpFileOutput, "\n");
|
||||
}
|
||||
}
|
||||
free(symbolVector);
|
||||
}
|
||||
|
||||
bool
|
||||
hackableSymbol(symbol)
|
||||
symbolTableEntryType *symbol;
|
||||
{
|
||||
return(symbol->context->usage == DEFINE_SYMBOL || symbol->context->
|
||||
usage == LABEL_SYMBOL);
|
||||
}
|
||||
|
||||
void
|
||||
printValueTersely(value)
|
||||
valueType *value;
|
||||
{
|
||||
static char *valueKindTable[NUM_OF_VALUE_KINDS] = {
|
||||
"ABS",
|
||||
"DAT",
|
||||
"REL",
|
||||
"BSS",
|
||||
"STT",
|
||||
"FLD",
|
||||
"MAC",
|
||||
"OPN",
|
||||
"STR",
|
||||
"CND",
|
||||
"UND",
|
||||
"FUN",
|
||||
"BLK",
|
||||
"BIF",
|
||||
"FAL",
|
||||
};
|
||||
|
||||
if (value != NULL)
|
||||
fprintf(symbolDumpFileOutput, "%s: %#6x %d", valueKindTable[
|
||||
(int)value->kindOfValue], value->value, value->value);
|
||||
else
|
||||
fprintf(symbolDumpFileOutput, "(no value)");
|
||||
}
|
||||
|
||||
void
|
||||
outputReservations()
|
||||
{
|
||||
while (reservationList != NULL) {
|
||||
outputWord(reservationList->startAddress);
|
||||
outputWord(reservationList->blockSize);
|
||||
reservationList = reservationList->nextReservation;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputExpressionBuffer()
|
||||
{
|
||||
int i;
|
||||
|
||||
outputBigword(expressionBufferSize);
|
||||
if (debug || emitPrint)
|
||||
printExpressionBuffer();
|
||||
for (i=0; i<expressionBufferSize; ++i)
|
||||
outputByte(expressionBuffer[i]);
|
||||
}
|
||||
|
||||
void
|
||||
outputOneExpression(expression)
|
||||
expressionType *expression;
|
||||
{
|
||||
expressionType *newExpression;
|
||||
|
||||
expressionType *generateFixupExpression();
|
||||
bool encodeExpression();
|
||||
|
||||
expressionBufferSize = 0;
|
||||
if (expression == NULL) {
|
||||
encodeRelocatableNumber(0);
|
||||
outputExpressionBuffer();
|
||||
} else {
|
||||
newExpression = generateFixupExpression(expression);
|
||||
freeExpression(expression);
|
||||
if (encodeExpression(newExpression))
|
||||
outputExpressionBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputExpressions()
|
||||
{
|
||||
int codeMode;
|
||||
expressionReferenceListType *theReferences;
|
||||
|
||||
encodingFunction = FALSE;
|
||||
outputBigword(referenceCount);
|
||||
for (codeMode=0; codeMode<=1; codeMode++) {
|
||||
theReferences = expressionReferenceList[codeMode];
|
||||
while (theReferences != NULL) {
|
||||
outputOneExpression(theReferences->expressionReferenced);
|
||||
theReferences = theReferences->nextReference;
|
||||
}
|
||||
}
|
||||
if (haveUserStartAddress && fixupStartAddress)
|
||||
outputOneExpression(startAddress);
|
||||
}
|
||||
|
||||
void
|
||||
outputOneFunction(function)
|
||||
functionDefinitionType *function;
|
||||
{
|
||||
argumentDefinitionListType *argumentList;
|
||||
bool encodeBlock();
|
||||
int countArguments();
|
||||
|
||||
outputByte((byte)countArguments(function));
|
||||
argumentList = function->arguments;
|
||||
while (argumentList != NULL) {
|
||||
outputBigword(argumentList->theArgument->ordinal);
|
||||
argumentList = argumentList->nextArgument;
|
||||
}
|
||||
expressionBufferSize = 0;
|
||||
if (encodeBlock(function->body))
|
||||
outputExpressionBuffer();
|
||||
}
|
||||
|
||||
void
|
||||
outputFunctions()
|
||||
{
|
||||
outputBigword(externalFunctionCount);
|
||||
encodingFunction = TRUE;
|
||||
while (externalFunctionCount-- > 0) {
|
||||
outputOneFunction(externalFunctionList);
|
||||
externalFunctionList = externalFunctionList->
|
||||
nextExternalFunction;
|
||||
}
|
||||
}
|
59
operandBody_6502.h
Normal file
59
operandBody_6502.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
operandBody_6502.h -- Define parser tree types for 6502 operands.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
18-April-1985
|
||||
*/
|
||||
|
||||
typedef stringType stringOperandBodyType;
|
||||
|
||||
typedef expressionType xIndexedOperandBodyType;
|
||||
|
||||
typedef expressionType yIndexedOperandBodyType;
|
||||
|
||||
typedef expressionType preIndexedXOperandBodyType;
|
||||
|
||||
typedef expressionType postIndexedYOperandBodyType;
|
||||
|
||||
typedef nullType yRegisterOperandBodyType;
|
||||
|
||||
typedef nullType xRegisterOperandBodyType;
|
||||
|
||||
typedef nullType aRegisterOperandBodyType;
|
||||
|
||||
typedef expressionType immediateOperandBodyType;
|
||||
|
||||
typedef expressionType indirectOperandBodyType;
|
||||
|
||||
typedef expressionType expressionOperandBodyType;
|
||||
|
||||
typedef BlockType blockOperandBodyType;
|
||||
|
||||
typedef selectionListType xSelectedOperandBodyType;
|
||||
|
||||
typedef selectionListType ySelectedOperandBodyType;
|
||||
|
||||
typedef selectionListType preSelectedOperandBodyType;
|
||||
|
||||
#define BlockOperandBodyType anyOldThing /* kludge */
|
||||
/* doing above right confuses compiler as it is a forward reference inside
|
||||
yon union: */
|
||||
|
||||
typedef union {
|
||||
expressionOperandBodyType *expressionUnion;
|
||||
immediateOperandBodyType *immediateUnion;
|
||||
indirectOperandBodyType *indirectUnion;
|
||||
aRegisterOperandBodyType *aRegisterUnion;
|
||||
xRegisterOperandBodyType *xRegisterUnion;
|
||||
yRegisterOperandBodyType *yRegisterUnion;
|
||||
postIndexedYOperandBodyType *postIndexedYUnion;
|
||||
preIndexedXOperandBodyType *preIndexedXUnion;
|
||||
xIndexedOperandBodyType *xIndexedUnion;
|
||||
yIndexedOperandBodyType *yIndexedUnion;
|
||||
xSelectedOperandBodyType *xSelectedUnion;
|
||||
ySelectedOperandBodyType *ySelectedUnion;
|
||||
preSelectedOperandBodyType *preSelectedUnion;
|
||||
stringOperandBodyType *stringUnion;
|
||||
BlockOperandBodyType *blockUnion;
|
||||
} operandBodyType;
|
81
operandBody_68000.h
Normal file
81
operandBody_68000.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
operandBody_68000.h -- Define parser tree types for 68000 operands.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
25-April-1985
|
||||
*/
|
||||
|
||||
typedef expressionType expressionOperandBodyType;
|
||||
|
||||
typedef stringType stringOperandBodyType;
|
||||
|
||||
typedef BlockType blockOperandBodyType;
|
||||
|
||||
typedef nullType dRegisterOperandBodyType;
|
||||
|
||||
typedef nullType aRegisterOperandBodyType;
|
||||
|
||||
typedef nullType aRegisterIndirectOperandBodyType;
|
||||
|
||||
typedef nullType postincrementOperandBodyType;
|
||||
|
||||
typedef nullType predecrementOperandBodyType;
|
||||
|
||||
typedef expressionType displacementOperandBodyType;
|
||||
|
||||
typedef selectionListType selectedOperandBodyType;
|
||||
|
||||
typedef expressionType indexedOperandBodyType;
|
||||
|
||||
typedef selectionListType indexSelectedOperandBodyType;
|
||||
|
||||
typedef expressionType pcDisplacementOperandBodyType;
|
||||
|
||||
typedef expressionType pcIndexedOperandBodyType;
|
||||
|
||||
typedef expressionType immediateOperandBodyType;
|
||||
|
||||
typedef expressionType absoluteShortOperandBodyType;
|
||||
|
||||
typedef expressionType absoluteLongOperandBodyType;
|
||||
|
||||
typedef nullType ccRegisterOperandBodyType;
|
||||
|
||||
typedef nullType statusRegisterOperandBodyType;
|
||||
|
||||
typedef nullType uspRegisterOperandBodyType;
|
||||
|
||||
typedef nullType controlRegisterOperandBodyType;
|
||||
|
||||
#define BlockOperandBodyType anyOldThing /* kludge */
|
||||
/* doing above right confuses compiler as it is a forward reference inside
|
||||
yon union: */
|
||||
|
||||
typedef union {
|
||||
expressionOperandBodyType *expressionUnion;
|
||||
stringOperandBodyType *stringUnion;
|
||||
BlockOperandBodyType *blockUnion;
|
||||
dRegisterOperandBodyType *dRegisterUnion;
|
||||
aRegisterOperandBodyType *aRegisterUnion;
|
||||
aRegisterIndirectOperandBodyType *aRegisterIndirectUnion;
|
||||
postincrementOperandBodyType *postincrementUnion;
|
||||
predecrementOperandBodyType *predecrementUnion;
|
||||
displacementOperandBodyType *displacementUnion;
|
||||
selectedOperandBodyType *selectionUnion;
|
||||
indexedOperandBodyType *indexedUnion;
|
||||
indexSelectedOperandBodyType *indexSelectedUnion;
|
||||
pcDisplacementOperandBodyType *pcDisplacementUnion;
|
||||
pcIndexedOperandBodyType *pcIndexedUnion;
|
||||
immediateOperandBodyType *immediateUnion;
|
||||
absoluteShortOperandBodyType *absoluteShortUnion;
|
||||
absoluteLongOperandBodyType *absoluteLongUnion;
|
||||
ccRegisterOperandBodyType *ccRegisterUnion;
|
||||
statusRegisterOperandBodyType *statusRegisterUnion;
|
||||
uspRegisterOperandBodyType *uspRegisterUnion;
|
||||
controlRegisterOperandBodyType *controlRegisterUnion;
|
||||
} operandBodyType;
|
||||
|
||||
#define SFC_REGISTER 0
|
||||
#define DFC_REGISTER 1
|
||||
#define VBR_REGISTER 2
|
80
operandDefs_6502.h
Normal file
80
operandDefs_6502.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
operandDefs_6502.h -- Define operand types and flag bits for 6502.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
18-April-1985
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
EXPRESSION_OPND, IMMEDIATE_OPND, INDIRECT_OPND,
|
||||
A_REGISTER_OPND, X_REGISTER_OPND, Y_REGISTER_OPND,
|
||||
POST_INDEXED_Y_OPND, PRE_INDEXED_X_OPND, X_INDEXED_OPND,
|
||||
Y_INDEXED_OPND, X_SELECTED_OPND, Y_SELECTED_OPND,
|
||||
PRE_SELECTED_X_OPND, STRING_OPND, BLOCK_OPND
|
||||
} operandKindType;
|
||||
|
||||
#define operandKindField(op) op
|
||||
|
||||
/* Opcodes: */
|
||||
/* In the opcode table we want to have information that tells which possible
|
||||
address modes the corresponding instruction can utilize. The
|
||||
instruction set of the 6502 breaks up into classes of instructions, such
|
||||
that all of the instructions in a class accept the same address modes.
|
||||
We encode the instructions by class and the classes by permissible address
|
||||
modes. This helps us reduce errors in construction of the opcode table,
|
||||
since getting one instruction of a given class right means getting all the
|
||||
others right too. */
|
||||
typedef enum {
|
||||
RELATIVE, DIR_1, DIR_2, DIR_INDIR, DIR_X_1, DIR_X_2, DIR_X_3,
|
||||
DIR_Y, IMM_DIR, IMM_DIR_X, IMM_DIR_Y, NONE, INDEX, IMM_INDEX
|
||||
} addressClassType;
|
||||
|
||||
#define NO_OPND_BIT 0x0000
|
||||
#define EXPRESSION_OPND_BIT 0x0001
|
||||
#define IMMEDIATE_OPND_BIT 0x0002
|
||||
#define INDIRECT_OPND_BIT 0x0004
|
||||
#define A_REGISTER_OPND_BIT 0x0008
|
||||
#define X_REGISTER_OPND_BIT 0x0010
|
||||
#define Y_REGISTER_OPND_BIT 0x0020
|
||||
#define POST_INDEXED_Y_OPND_BIT 0x0040
|
||||
#define PRE_INDEXED_X_OPND_BIT 0x0080
|
||||
#define X_INDEXED_OPND_BIT 0x0100
|
||||
#define Y_INDEXED_OPND_BIT 0x0200
|
||||
#define X_SELECTED_OPND_BIT 0x0400
|
||||
#define Y_SELECTED_OPND_BIT 0x0800
|
||||
#define PRE_SELECTED_X_OPND_BIT 0x1000
|
||||
#define STRING_OPND_BIT 0x2000
|
||||
#define BLOCK_OPND_BIT 0x4000
|
||||
#define ANY_OPND_BITS 0xFFFF
|
||||
|
||||
#define REL_CLASS_BITS EXPRESSION_OPND_BIT
|
||||
#define DIR_1_CLASS_BITS EXPRESSION_OPND_BIT
|
||||
#define DIR_2_CLASS_BITS EXPRESSION_OPND_BIT
|
||||
#define DIR_INDIR_CLASS_BITS EXPRESSION_OPND_BIT | INDIRECT_OPND_BIT
|
||||
#define DIR_X_1_CLASS_BITS EXPRESSION_OPND_BIT | X_INDEXED_OPND_BIT | \
|
||||
X_SELECTED_OPND_BIT | A_REGISTER_OPND_BIT
|
||||
#define DIR_X_2_CLASS_BITS EXPRESSION_OPND_BIT | X_INDEXED_OPND_BIT | \
|
||||
X_SELECTED_OPND_BIT
|
||||
#define DIR_X_3_CLASS_BITS EXPRESSION_OPND_BIT | X_INDEXED_OPND_BIT | \
|
||||
X_SELECTED_OPND_BIT
|
||||
#define DIR_Y_CLASS_BITS EXPRESSION_OPND_BIT | Y_INDEXED_OPND_BIT | \
|
||||
Y_SELECTED_OPND_BIT
|
||||
#define IMM_DIR_CLASS_BITS EXPRESSION_OPND_BIT | IMMEDIATE_OPND_BIT
|
||||
#define IMM_DIR_X_CLASS_BITS EXPRESSION_OPND_BIT | IMMEDIATE_OPND_BIT | \
|
||||
X_INDEXED_OPND_BIT | X_SELECTED_OPND_BIT
|
||||
#define IMM_DIR_Y_CLASS_BITS EXPRESSION_OPND_BIT | IMMEDIATE_OPND_BIT | \
|
||||
Y_INDEXED_OPND_BIT | Y_SELECTED_OPND_BIT
|
||||
#define NONE_CLASS_BITS NO_OPND_BIT
|
||||
#define IMM_INDEX_CLASS_BITS X_INDEXED_OPND_BIT | Y_INDEXED_OPND_BIT | \
|
||||
X_SELECTED_OPND_BIT | Y_SELECTED_OPND_BIT | \
|
||||
IMMEDIATE_OPND_BIT | PRE_INDEXED_X_OPND_BIT |\
|
||||
POST_INDEXED_Y_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT | PRE_SELECTED_X_OPND_BIT
|
||||
#define INDEX_CLASS_BITS X_INDEXED_OPND_BIT | Y_INDEXED_OPND_BIT | \
|
||||
X_SELECTED_OPND_BIT | Y_SELECTED_OPND_BIT | \
|
||||
PRE_INDEXED_X_OPND_BIT | \
|
||||
POST_INDEXED_Y_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT | PRE_SELECTED_X_OPND_BIT
|
||||
|
||||
#define MAX_NUMBER_OF_OPERANDS 1
|
279
operandDefs_68000.h
Normal file
279
operandDefs_68000.h
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
operandDefs_68000.h -- Define operand types and flag bits for 68000.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
25-April-1985
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
EXPRESSION_OPND, STRING_OPND, BLOCK_OPND, D_REGISTER_OPND,
|
||||
A_REGISTER_OPND, A_REGISTER_INDIRECT_OPND, POSTINCREMENT_OPND,
|
||||
PREDECREMENT_OPND, DISPLACEMENT_OPND, INDEXED_OPND,
|
||||
PC_DISPLACEMENT_OPND, PC_INDEXED_OPND, IMMEDIATE_OPND,
|
||||
ABSOLUTE_SHORT_OPND, ABSOLUTE_LONG_OPND, CC_REGISTER_OPND,
|
||||
STATUS_REGISTER_OPND, USP_REGISTER_OPND,
|
||||
CONTROL_REGISTER_OPND, SELECTED_OPND, INDEX_SELECTED_OPND,
|
||||
} operandKindType;
|
||||
|
||||
/*** Hack warning ***/
|
||||
|
||||
/* We know that enumerated types are actually just ints. Some of the address
|
||||
modes require some additional information in the form of one or two
|
||||
register numbers. We want to still encode this information in one int.
|
||||
Therefor, we are going to OR some bits representing the register into the
|
||||
higher-order bits of the type word, thus violating the principle of
|
||||
enumerated types (it's just that the 'enum' syntax above is so much cleaner
|
||||
than a bunch of '#define's) */
|
||||
|
||||
#define getRegisterField(op, n) ((((int)op)>>(8+(n-1)*4)) & 0xF)
|
||||
#define setRegisterField(op, n, r) (op=((int)op | \
|
||||
(((r)&0xF)<<(8+((n)-1)*4))))
|
||||
|
||||
#define getAddressRegister(op) (getRegisterField(op, 1) - 8)
|
||||
#define getDataRegister(op) getRegisterField(op, 1)
|
||||
#define getRegister(op) getRegisterField(op, 1)
|
||||
#define getIndexRegister(op) getRegisterField(op, 2)
|
||||
#define getWL(op) (((int)op >> 16) & 1)
|
||||
|
||||
#define setAddressRegister(op, r) setRegisterField(op, 1, (int)r + 8)
|
||||
#define setDataRegister(op, r) setRegisterField(op, 1, (int)r)
|
||||
#define setRegister(op, r) setRegisterField(op, 1, (int)r)
|
||||
#define setIndexRegister(op, r) setRegisterField(op, 2, (int)r)
|
||||
#define setWL(op, wl) (op = ((int)op | (((wl) & 1) << 16)))
|
||||
|
||||
#define operandKindField(op) (operandKindType)((int)op & 0xFF)
|
||||
|
||||
/* Opcodes: */
|
||||
/* In the opcode table we want to have information that tells which possible
|
||||
address modes the corresponding instruction can utilize. The
|
||||
instruction set of the 68000 breaks up into classes of instructions, such
|
||||
that all of the instructions in a class accept the same address modes.
|
||||
We encode the instructions by class and the classes by permissible address
|
||||
modes. This helps us reduce errors in construction of the opcode table,
|
||||
since getting one instruction of a given class right means getting all the
|
||||
others right too. Ordinarily we'd give each class a nice mnemonic name,
|
||||
but the 68000 has 26 idiosyncratic classes and a unique name for each
|
||||
would confuse more than it would help. */
|
||||
|
||||
typedef enum {
|
||||
CLASS_I, CLASS_II, CLASS_III, CLASS_IV, CLASS_V, CLASS_VI,
|
||||
CLASS_VII, CLASS_VIII, CLASS_IX, CLASS_X, CLASS_XI, CLASS_XII,
|
||||
CLASS_XIII, CLASS_XIV, CLASS_XV, CLASS_XVI, CLASS_XVII,
|
||||
CLASS_XVIII, CLASS_XIX, CLASS_XX, CLASS_XXI, CLASS_XXII,
|
||||
CLASS_XXIII, CLASS_XXIV, CLASS_XXV, CLASS_XXVI, CLASS_XXVII,
|
||||
CLASS_XXVIII,
|
||||
} addressClassType;
|
||||
|
||||
/* The various address modes as required by the various instructions manage to
|
||||
sort themselves into a number of independent groups. We will give these
|
||||
groups names to facilitate operand address mode checking */
|
||||
|
||||
#define NO_OPND_BIT 0x000000
|
||||
#define EXPRESSION_OPND_BIT 0x000001
|
||||
#define STRING_OPND_BIT 0x000002
|
||||
#define BLOCK_OPND_BIT 0x000004
|
||||
#define D_REGISTER_OPND_BIT 0x000008
|
||||
#define A_REGISTER_OPND_BIT 0x000010
|
||||
#define A_REGISTER_INDIRECT_OPND_BIT 0x000020
|
||||
#define POSTINCREMENT_OPND_BIT 0x000040
|
||||
#define PREDECREMENT_OPND_BIT 0x000080
|
||||
#define DISPLACEMENT_OPND_BIT 0x000100
|
||||
#define INDEXED_OPND_BIT 0x000200
|
||||
#define PC_DISPLACEMENT_OPND_BIT 0x000400
|
||||
#define PC_INDEXED_OPND_BIT 0x000800
|
||||
#define IMMEDIATE_OPND_BIT 0x001000
|
||||
#define ABSOLUTE_SHORT_OPND_BIT 0x002000
|
||||
#define ABSOLUTE_LONG_OPND_BIT 0x004000
|
||||
#define CC_REGISTER_OPND_BIT 0x008000
|
||||
#define STATUS_REGISTER_OPND_BIT 0x010000
|
||||
#define USP_REGISTER_OPND_BIT 0x020000
|
||||
#define CONTROL_REGISTER_OPND_BIT 0x040000
|
||||
#define SELECTED_OPND_BIT 0x080000
|
||||
#define INDEX_SELECTED_OPND_BIT 0x100000
|
||||
#define ANY_OPND_BITS 0xFFFFFF
|
||||
|
||||
#define D_REGISTER_GROUP_BITS D_REGISTER_OPND_BIT
|
||||
#define GROUP_A D_REGISTER_GROUP_BITS
|
||||
|
||||
#define A_REGISTER_GROUP_BITS A_REGISTER_OPND_BIT
|
||||
#define GROUP_B A_REGISTER_GROUP_BITS
|
||||
|
||||
#define POSTINCREMENT_GROUP_BITS POSTINCREMENT_OPND_BIT
|
||||
#define GROUP_C POSTINCREMENT_GROUP_BITS
|
||||
|
||||
#define PREDECREMENT_GROUP_BITS PREDECREMENT_OPND_BIT
|
||||
#define GROUP_D PREDECREMENT_GROUP_BITS
|
||||
|
||||
#define DISPLACEMENT_GROUP_BITS (DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT)
|
||||
#define GROUP_E DISPLACEMENT_GROUP_BITS
|
||||
|
||||
#define IMMEDIATE_GROUP_BITS IMMEDIATE_OPND_BIT
|
||||
#define GROUP_F IMMEDIATE_GROUP_BITS
|
||||
|
||||
#define NORMAL_GROUP_BITS EXPRESSION_OPND_BIT
|
||||
#define GROUP_G NORMAL_GROUP_BITS
|
||||
|
||||
#define CC_REGISTER_GROUP_BITS CC_REGISTER_OPND_BIT
|
||||
#define GROUP_H CC_REGISTER_GROUP_BITS
|
||||
|
||||
#define STATUS_REGISTER_GROUP_BITS STATUS_REGISTER_OPND_BIT
|
||||
#define GROUP_I STATUS_REGISTER_GROUP_BITS
|
||||
|
||||
#define IMPLIED_GROUP_BITS NO_OPND_BIT
|
||||
#define GROUP_J IMPLIED_GROUP_BITS
|
||||
|
||||
#define USP_REGISTER_GROUP_BITS USP_REGISTER_OPND_BIT
|
||||
#define GROUP_K USP_REGISTER_GROUP_BITS
|
||||
|
||||
#define CONTROL_REGISTER_GROUP_BITS (USP_REGISTER_OPND_BIT | \
|
||||
CONTROL_REGISTER_OPND_BIT)
|
||||
#define GROUP_L CONTROL_REGISTER_GROUP_BITS
|
||||
|
||||
#define REGISTER_GROUP_BITS (D_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_OPND_BIT)
|
||||
#define GROUP_M REGISTER_GROUP_BITS
|
||||
|
||||
#define STORABLE_GROUP_BITS (D_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
POSTINCREMENT_OPND_BIT | \
|
||||
PREDECREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_N STORABLE_GROUP_BITS
|
||||
|
||||
#define FULL_EA_GROUP_BITS (D_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
POSTINCREMENT_OPND_BIT | \
|
||||
PREDECREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
PC_DISPLACEMENT_OPND_BIT | \
|
||||
PC_INDEXED_OPND_BIT | \
|
||||
IMMEDIATE_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_O FULL_EA_GROUP_BITS
|
||||
|
||||
#define STORABLE_NO_A_REGISTER_GROUP_BITS \
|
||||
(D_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
POSTINCREMENT_OPND_BIT | \
|
||||
PREDECREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_P STORABLE_NO_A_REGISTER_GROUP_BITS
|
||||
|
||||
#define FULL_EA_NO_A_REGISTER_GROUP_BITS (D_REGISTER_OPND_BIT | \
|
||||
A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
POSTINCREMENT_OPND_BIT | \
|
||||
PREDECREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
PC_DISPLACEMENT_OPND_BIT | \
|
||||
PC_INDEXED_OPND_BIT | \
|
||||
IMMEDIATE_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_Q FULL_EA_NO_A_REGISTER_GROUP_BITS
|
||||
|
||||
#define MISC_1_GROUP_BITS (A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
POSTINCREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
PC_DISPLACEMENT_OPND_BIT | \
|
||||
PC_INDEXED_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_R MISC_1_GROUP_BITS
|
||||
|
||||
#define STORABLE_NO_REGISTER_GROUP_BITS (A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
POSTINCREMENT_OPND_BIT | \
|
||||
PREDECREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_S STORABLE_NO_REGISTER_GROUP_BITS
|
||||
|
||||
#define MISC_2_GROUP_BITS (A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
PREDECREMENT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_T MISC_2_GROUP_BITS
|
||||
|
||||
#define MISC_3_GROUP_BITS (A_REGISTER_INDIRECT_OPND_BIT | \
|
||||
DISPLACEMENT_OPND_BIT | \
|
||||
SELECTED_OPND_BIT | \
|
||||
INDEXED_OPND_BIT | \
|
||||
INDEX_SELECTED_OPND_BIT | \
|
||||
PC_DISPLACEMENT_OPND_BIT | \
|
||||
PC_INDEXED_OPND_BIT | \
|
||||
ABSOLUTE_SHORT_OPND_BIT | \
|
||||
ABSOLUTE_LONG_OPND_BIT | \
|
||||
EXPRESSION_OPND_BIT)
|
||||
#define GROUP_U MISC_3_GROUP_BITS
|
||||
|
||||
#define CLASS_I_BITS (GROUP_A | GROUP_D)
|
||||
#define CLASS_II_BITS (GROUP_A | GROUP_B | GROUP_F | GROUP_O | \
|
||||
GROUP_P | GROUP_S)
|
||||
#define CLASS_III_BITS (GROUP_F | GROUP_N)
|
||||
#define CLASS_IV_BITS (GROUP_A | GROUP_F | GROUP_H | GROUP_I | \
|
||||
GROUP_P | GROUP_Q | GROUP_S)
|
||||
#define CLASS_V_BITS (GROUP_A | GROUP_F | GROUP_S)
|
||||
#define CLASS_VI_BITS GROUP_G
|
||||
#define CLASS_VII_BITS (GROUP_A | GROUP_F | GROUP_P)
|
||||
#define CLASS_VIII_BITS (GROUP_A | GROUP_Q)
|
||||
#define CLASS_IX_BITS GROUP_P
|
||||
#define CLASS_X_BITS (GROUP_A | GROUP_B | GROUP_F | GROUP_O | GROUP_P)
|
||||
#define CLASS_XI_BITS GROUP_C
|
||||
#define CLASS_XII_BITS (GROUP_A | GROUP_G)
|
||||
#define CLASS_XIII_BITS (GROUP_A | GROUP_F | GROUP_H | GROUP_I | GROUP_P)
|
||||
#define CLASS_XIV_BITS GROUP_M
|
||||
#define CLASS_XV_BITS GROUP_A
|
||||
#define CLASS_XVI_BITS GROUP_J
|
||||
#define CLASS_XVII_BITS GROUP_U
|
||||
#define CLASS_XVIII_BITS (GROUP_B | GROUP_U)
|
||||
#define CLASS_XIX_BITS (GROUP_B | GROUP_F)
|
||||
#define CLASS_XX_BITS (GROUP_B | GROUP_H | GROUP_I | GROUP_K | \
|
||||
GROUP_L | GROUP_M | GROUP_O | GROUP_Q)
|
||||
#define CLASS_XXI_BITS (GROUP_M | GROUP_R | GROUP_T)
|
||||
#define CLASS_XXII_BITS (GROUP_A | GROUP_E)
|
||||
#define CLASS_XXIII_BITS (GROUP_A | GROUP_F)
|
||||
#define CLASS_XXIV_BITS (GROUP_M | GROUP_S)
|
||||
#define CLASS_XXV_BITS GROUP_F
|
||||
#define CLASS_XXVI_BITS GROUP_B
|
||||
#define CLASS_XXVII_BITS GROUP_F
|
||||
#define CLASS_XXVIII_BITS GROUP_F
|
||||
|
||||
#define MAX_NUMBER_OF_OPERANDS 17
|
BIN
operandStuffSD.o
Normal file
BIN
operandStuffSD.o
Normal file
Binary file not shown.
389
operandStuffSD_6502.c
Normal file
389
operandStuffSD_6502.c
Normal file
@ -0,0 +1,389 @@
|
||||
/*
|
||||
operandStuff_6502.c -- Various target processor routines to handle
|
||||
operands in the Macross assembler (6502 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
23-April-1985
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/* corresponds to routines in buildStuff2.c */
|
||||
|
||||
operandType *
|
||||
buildOperand(kindOfOperand, arg)
|
||||
operandKindType kindOfOperand;
|
||||
anyOldThing *arg;
|
||||
{
|
||||
operandType *result;
|
||||
|
||||
result = typeAlloc(operandType);
|
||||
result->kindOfOperand = kindOfOperand;
|
||||
result->nextOperand = NULL;
|
||||
switch (kindOfOperand) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
result->theOperand.expressionUnion =
|
||||
(expressionOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case IMMEDIATE_OPND:
|
||||
result->theOperand.immediateUnion =
|
||||
(immediateOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case INDIRECT_OPND:
|
||||
result->theOperand.indirectUnion =
|
||||
(indirectOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
result->theOperand.aRegisterUnion =
|
||||
(aRegisterOperandBodyType *) NULL;
|
||||
break;
|
||||
|
||||
case X_REGISTER_OPND:
|
||||
result->theOperand.xRegisterUnion =
|
||||
(xRegisterOperandBodyType *) NULL;
|
||||
break;
|
||||
|
||||
case Y_REGISTER_OPND:
|
||||
result->theOperand.yRegisterUnion =
|
||||
(yRegisterOperandBodyType *) NULL;
|
||||
break;
|
||||
|
||||
case POST_INDEXED_Y_OPND:
|
||||
result->theOperand.postIndexedYUnion =
|
||||
(postIndexedYOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case PRE_INDEXED_X_OPND:
|
||||
result->theOperand.preIndexedXUnion =
|
||||
(preIndexedXOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case X_INDEXED_OPND:
|
||||
result->theOperand.xIndexedUnion =
|
||||
(xIndexedOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case Y_INDEXED_OPND:
|
||||
result->theOperand.yIndexedUnion =
|
||||
(yIndexedOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case X_SELECTED_OPND:
|
||||
result->theOperand.xSelectedUnion =
|
||||
(xSelectedOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case Y_SELECTED_OPND:
|
||||
result->theOperand.ySelectedUnion =
|
||||
(ySelectedOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case PRE_SELECTED_X_OPND:
|
||||
result->theOperand.preSelectedUnion =
|
||||
(preSelectedOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
result->theOperand.stringUnion =
|
||||
(stringOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
result->theOperand.blockUnion = (BlockOperandBodyType *) arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("unknown operand kind: %d\n", kindOfOperand);
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* corresponds to routines in fixups.c */
|
||||
|
||||
operandListType *
|
||||
duplicateOperandForFixup(operand, isSpecialFunctionOperand)
|
||||
operandListType *operand;
|
||||
bool isSpecialFunctionOperand;
|
||||
{
|
||||
operandListType *result;
|
||||
|
||||
expressionType *duplicateExpressionForFixup();
|
||||
|
||||
result = typeAlloc(operandListType);
|
||||
result->kindOfOperand = operand->kindOfOperand;
|
||||
result->nextOperand = NULL;
|
||||
if (operand->kindOfOperand != EXPRESSION_OPND)
|
||||
newFixupAddressMode = operand->kindOfOperand;
|
||||
switch (operand->kindOfOperand) {
|
||||
case EXPRESSION_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case INDIRECT_OPND:
|
||||
case POST_INDEXED_Y_OPND:
|
||||
case PRE_INDEXED_X_OPND:
|
||||
case X_INDEXED_OPND:
|
||||
case Y_INDEXED_OPND:
|
||||
result->theOperand.expressionUnion =
|
||||
duplicateExpressionForFixup(operand->theOperand,
|
||||
FALSE, isSpecialFunctionOperand);
|
||||
break;
|
||||
case X_SELECTED_OPND:
|
||||
case Y_SELECTED_OPND:
|
||||
case PRE_SELECTED_X_OPND:
|
||||
result->theOperand.expressionUnion =
|
||||
duplicateExpressionForFixup(operand->theOperand,
|
||||
FALSE, isSpecialFunctionOperand);
|
||||
break;
|
||||
case A_REGISTER_OPND:
|
||||
case X_REGISTER_OPND:
|
||||
case Y_REGISTER_OPND:
|
||||
result->theOperand = operand->theOperand;
|
||||
break;
|
||||
case STRING_OPND:
|
||||
result->theOperand = operand->theOperand;
|
||||
break;
|
||||
case BLOCK_OPND:
|
||||
error(CANT_FORWARD_REFERENCE_BLOCK_ERROR);
|
||||
result = NULL;
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* corresponds to routines in garbage.c */
|
||||
|
||||
#define nullFree(thing) if (thing == NULL) return;
|
||||
|
||||
void
|
||||
freeOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
nullFree(operand);
|
||||
switch (operand->kindOfOperand) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case INDIRECT_OPND:
|
||||
case POST_INDEXED_Y_OPND:
|
||||
case PRE_INDEXED_X_OPND:
|
||||
case X_INDEXED_OPND:
|
||||
case Y_INDEXED_OPND:
|
||||
freeExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
case X_REGISTER_OPND:
|
||||
case Y_REGISTER_OPND:
|
||||
break;
|
||||
|
||||
case X_SELECTED_OPND:
|
||||
case Y_SELECTED_OPND:
|
||||
case PRE_SELECTED_X_OPND:
|
||||
freeSelectionList(operand->theOperand);
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
freeString(operand->theOperand);
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
freeBlock(operand->theOperand);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("bad operand kind in freeOperand %d\n",
|
||||
operand->kindOfOperand);
|
||||
break;
|
||||
}
|
||||
freeOperand(operand->nextOperand);
|
||||
free(operand);
|
||||
}
|
||||
|
||||
/* corresponds to routines in listing.c */
|
||||
|
||||
void
|
||||
expandOperand(addressMode)
|
||||
operandKindType addressMode;
|
||||
{
|
||||
switch (addressMode) {
|
||||
case IMMEDIATE_OPND: moreText("#"); break;
|
||||
case INDIRECT_OPND: moreText("@"); break;
|
||||
case POST_INDEXED_Y_OPND: moreText("y[@"); break;
|
||||
case PRE_INDEXED_X_OPND: moreText("@x["); break;
|
||||
case X_INDEXED_OPND: moreText("x["); break;
|
||||
case Y_INDEXED_OPND: moreText("y["); break;
|
||||
case A_REGISTER_OPND: moreText("a"); break;
|
||||
case X_REGISTER_OPND: moreText("x"); break;
|
||||
case Y_REGISTER_OPND: moreText("y"); break;
|
||||
case X_SELECTED_OPND: moreText("x"); break;
|
||||
case Y_SELECTED_OPND: moreText("y"); break;
|
||||
case PRE_SELECTED_X_OPND: moreText("@x"); break;
|
||||
default: break;
|
||||
}
|
||||
expandExpression(NULL);
|
||||
if (addressMode == POST_INDEXED_Y_OPND ||
|
||||
addressMode == PRE_INDEXED_X_OPND ||
|
||||
addressMode == X_INDEXED_OPND ||
|
||||
addressMode == Y_INDEXED_OPND)
|
||||
moreText("]");
|
||||
}
|
||||
|
||||
/* corresponds to routines in expressionSemantics.c */
|
||||
|
||||
#define nullEvaluate(thing) if (thing==NULL) return(NULL);
|
||||
#define fail(err) if (!expressionFailed) {\
|
||||
error(err);\
|
||||
expressionFailed = TRUE;\
|
||||
}
|
||||
#define fail1(err,arg) if (!expressionFailed) {\
|
||||
error(err,arg);\
|
||||
expressionFailed = TRUE;\
|
||||
}
|
||||
#define fail2(err,arg1,arg2) if (!expressionFailed) {\
|
||||
error(err,arg1,arg2);\
|
||||
expressionFailed = TRUE;\
|
||||
}
|
||||
|
||||
#define qfree2(a,b) if (freeFlag) { free(a); free(b); }
|
||||
|
||||
#define expansionOff() {saveExpansion=expandMacros; expandMacros=FALSE;}
|
||||
#define forceExpansion() {saveExpansion=expandMacros; expandMacros=TRUE;}
|
||||
#define expansionOn() expandMacros=saveExpansion;
|
||||
|
||||
valueType *
|
||||
evaluateOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
valueType *result;
|
||||
bool saveExpansion;
|
||||
expressionType *expression;
|
||||
|
||||
valueType *evaluateExpression();
|
||||
valueType *evaluateSelectionList();
|
||||
valueType *newValue();
|
||||
|
||||
nullEvaluate(operand);
|
||||
if (operand->kindOfOperand != EXPRESSION_OPND)
|
||||
newFixupAddressMode = operand->kindOfOperand;
|
||||
switch (operand->kindOfOperand) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case INDIRECT_OPND:
|
||||
case POST_INDEXED_Y_OPND:
|
||||
case PRE_INDEXED_X_OPND:
|
||||
case X_INDEXED_OPND:
|
||||
case Y_INDEXED_OPND:
|
||||
result = evaluateExpression(operand->theOperand,
|
||||
performingFixups ? NO_FIXUP : OPERAND_FIXUP);
|
||||
if (operand->kindOfOperand != EXPRESSION_OPND) {
|
||||
if (result->addressMode != EXPRESSION_OPND) {
|
||||
error(BAD_ADDRESS_MODE_ERROR);
|
||||
result->kindOfValue = FAIL;
|
||||
} else {
|
||||
result->addressMode = operand->kindOfOperand;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
case X_REGISTER_OPND:
|
||||
case Y_REGISTER_OPND:
|
||||
result = newValue(UNDEFINED_VALUE, 0, operand->
|
||||
kindOfOperand);
|
||||
break;
|
||||
|
||||
case X_SELECTED_OPND:
|
||||
case Y_SELECTED_OPND:
|
||||
case PRE_SELECTED_X_OPND:
|
||||
result = evaluateSelectionList(operand->theOperand);
|
||||
if (result->addressMode != EXPRESSION_OPND) {
|
||||
error(BAD_ADDRESS_MODE_ERROR);
|
||||
result->kindOfValue = FAIL;
|
||||
} else {
|
||||
result->addressMode = operand->kindOfOperand;
|
||||
}
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
result = newValue(STRING_VALUE, operand->theOperand,
|
||||
STRING_OPND);
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
if (standaloneExpansionFlag)
|
||||
forceExpansion();
|
||||
sideEffectFlag = TRUE;
|
||||
assembleBlock(operand->theOperand);
|
||||
expansionOn();
|
||||
result = newValue(FAIL, 0, BLOCK_OPND);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("bad operand kind in evaluateOperand %d\n",
|
||||
operand->kindOfOperand);
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* from parserMisc.c */
|
||||
|
||||
conditionType
|
||||
invertConditionCode(conditionCode)
|
||||
conditionType conditionCode;
|
||||
{
|
||||
#define cc (int)conditionCode
|
||||
|
||||
if ((int)CARRY_COND<=cc && cc<=(int)ALWAYS_COND)
|
||||
return((conditionType)
|
||||
(cc - (int)CARRY_COND + (int)NOT_CARRY_COND));
|
||||
else if ((int)NOT_CARRY_COND<=cc && cc<=(int)NEVER_COND)
|
||||
return((conditionType)
|
||||
(cc + (int)CARRY_COND - (int)NOT_CARRY_COND));
|
||||
else
|
||||
botch("invertConditionCode given %d, not a condition code\n");
|
||||
}
|
||||
|
||||
/* from semanticMisc.c */
|
||||
|
||||
bool
|
||||
shouldParenthesize(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
expressionTermKindType kind;
|
||||
|
||||
switch(operand->kindOfOperand) {
|
||||
case EXPRESSION_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case INDIRECT_OPND:
|
||||
case POST_INDEXED_Y_OPND:
|
||||
case PRE_INDEXED_X_OPND:
|
||||
case X_INDEXED_OPND:
|
||||
case Y_INDEXED_OPND:
|
||||
kind = operand->theOperand.expressionUnion->kindOfTerm;
|
||||
return (kind==UNOP_EXPR || kind==BINOP_EXPR || kind==
|
||||
ASSIGN_EXPR);
|
||||
break;
|
||||
|
||||
case X_SELECTED_OPND:
|
||||
case Y_SELECTED_OPND:
|
||||
case PRE_SELECTED_X_OPND:
|
||||
return(TRUE);
|
||||
break;
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
case X_REGISTER_OPND:
|
||||
case Y_REGISTER_OPND:
|
||||
case STRING_OPND:
|
||||
case BLOCK_OPND:
|
||||
return(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
559
operandStuffSD_68000.c
Normal file
559
operandStuffSD_68000.c
Normal file
@ -0,0 +1,559 @@
|
||||
/*
|
||||
operandStuff_68000.c -- Various target processor routines to handle
|
||||
operands in the Macross assembler (68000 version).
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
26-April-1985
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
|
||||
/* corresponds to routines in buildStuff2.c */
|
||||
|
||||
operandType *
|
||||
buildOperand(kindOfOperand, arg1, arg2, arg3, arg4)
|
||||
operandKindType kindOfOperand;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
int arg4;
|
||||
{
|
||||
operandType *result;
|
||||
|
||||
result = typeAlloc(operandType);
|
||||
result->kindOfOperand = kindOfOperand;
|
||||
result->nextOperand = NULL;
|
||||
switch (kindOfOperand) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
result->theOperand.expressionUnion =
|
||||
(expressionOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
result->theOperand.stringUnion =
|
||||
(stringOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
result->theOperand.blockUnion = (BlockOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case D_REGISTER_OPND:
|
||||
result->theOperand.dRegisterUnion =
|
||||
(dRegisterOperandBodyType *) NULL;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case A_REGISTER_OPND:
|
||||
result->theOperand.aRegisterUnion =
|
||||
(aRegisterOperandBodyType *) NULL;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
result->theOperand.aRegisterIndirectUnion =
|
||||
(aRegisterIndirectOperandBodyType *) NULL;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case POSTINCREMENT_OPND:
|
||||
result->theOperand.postincrementUnion =
|
||||
(postincrementOperandBodyType *) NULL;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case PREDECREMENT_OPND:
|
||||
result->theOperand.predecrementUnion =
|
||||
(predecrementOperandBodyType *) NULL;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case DISPLACEMENT_OPND:
|
||||
result->theOperand.displacementUnion =
|
||||
(displacementOperandBodyType *) arg2;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case SELECTED_OPND:
|
||||
result->theOperand.selectionUnion =
|
||||
(selectedOperandBodyType *) arg2;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
case INDEXED_OPND:
|
||||
result->theOperand.indexedUnion =
|
||||
(indexedOperandBodyType *) arg1;
|
||||
setRegister(result->kindOfOperand, arg2);
|
||||
setIndexRegister(result->kindOfOperand, arg3);
|
||||
setWL(result->kindOfOperand, (int)arg4);
|
||||
break;
|
||||
|
||||
case INDEX_SELECTED_OPND:
|
||||
result->theOperand.indexSelectedUnion =
|
||||
(indexSelectedOperandBodyType *) arg1;
|
||||
setRegister(result->kindOfOperand, arg2);
|
||||
setIndexRegister(result->kindOfOperand, arg3);
|
||||
setWL(result->kindOfOperand, (int)arg4);
|
||||
break;
|
||||
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
result->theOperand.pcDisplacementUnion =
|
||||
(pcDisplacementOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case PC_INDEXED_OPND:
|
||||
result->theOperand.pcIndexedUnion =
|
||||
(pcIndexedOperandBodyType *) arg1;
|
||||
setIndexRegister(result->kindOfOperand, arg2);
|
||||
setWL(result->kindOfOperand, (int)arg3);
|
||||
break;
|
||||
|
||||
case IMMEDIATE_OPND:
|
||||
result->theOperand.immediateUnion =
|
||||
(immediateOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
result->theOperand.absoluteShortUnion =
|
||||
(absoluteShortOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
result->theOperand.absoluteLongUnion =
|
||||
(absoluteLongOperandBodyType *) arg1;
|
||||
break;
|
||||
|
||||
case CC_REGISTER_OPND:
|
||||
result->theOperand.ccRegisterUnion =
|
||||
(ccRegisterOperandBodyType *) NULL;
|
||||
break;
|
||||
|
||||
case STATUS_REGISTER_OPND:
|
||||
result->theOperand.statusRegisterUnion =
|
||||
(statusRegisterOperandBodyType *) NULL;
|
||||
break;
|
||||
|
||||
case USP_REGISTER_OPND:
|
||||
result->theOperand.uspRegisterUnion =
|
||||
(uspRegisterOperandBodyType *) NULL;
|
||||
break;
|
||||
|
||||
case CONTROL_REGISTER_OPND:
|
||||
result->theOperand.controlRegisterUnion =
|
||||
(controlRegisterOperandBodyType *) NULL;
|
||||
setRegister(result->kindOfOperand, arg1);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("unknown operand kind: %d\n", kindOfOperand);
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* corresponds to routines in fixups.c */
|
||||
|
||||
operandListType *
|
||||
duplicateOperandForFixup(operand, isSpecialFunctionOperand)
|
||||
operandListType *operand;
|
||||
bool isSpecialFunctionOperand;
|
||||
{
|
||||
operandListType *result;
|
||||
|
||||
expressionType *duplicateExpressionForFixup();
|
||||
|
||||
result = typeAlloc(operandListType);
|
||||
result->kindOfOperand = operand->kindOfOperand;
|
||||
result->nextOperand = NULL;
|
||||
if (operand->kindOfOperand != EXPRESSION_OPND)
|
||||
newFixupAddressMode = operand->kindOfOperand;
|
||||
switch (operandKindField(operand->kindOfOperand)) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
case DISPLACEMENT_OPND:
|
||||
case SELECTED_OPND:
|
||||
case INDEXED_OPND:
|
||||
case INDEX_SELECTED_OPND:
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
case PC_INDEXED_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
result->theOperand.expressionUnion =
|
||||
duplicateExpressionForFixup(operand->theOperand,
|
||||
FALSE, isSpecialFunctionOperand);
|
||||
break;
|
||||
case D_REGISTER_OPND:
|
||||
case A_REGISTER_OPND:
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
case POSTINCREMENT_OPND:
|
||||
case PREDECREMENT_OPND:
|
||||
case CC_REGISTER_OPND:
|
||||
case STATUS_REGISTER_OPND:
|
||||
case USP_REGISTER_OPND:
|
||||
case CONTROL_REGISTER_OPND:
|
||||
result->theOperand = operand->theOperand;
|
||||
break;
|
||||
case STRING_OPND:
|
||||
result->theOperand = operand->theOperand;
|
||||
break;
|
||||
case BLOCK_OPND:
|
||||
error(CANT_FORWARD_REFERENCE_BLOCK_ERROR);
|
||||
result = NULL;
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* corresponds to routines in garbage.c */
|
||||
|
||||
#define nullFree(thing) if (thing == NULL) return;
|
||||
|
||||
void
|
||||
freeOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
nullFree(operand);
|
||||
switch (operandKindField(operand->kindOfOperand)) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
case DISPLACEMENT_OPND:
|
||||
case INDEXED_OPND:
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
case PC_INDEXED_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
freeExpression(operand->theOperand);
|
||||
break;
|
||||
|
||||
case D_REGISTER_OPND:
|
||||
case A_REGISTER_OPND:
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
case POSTINCREMENT_OPND:
|
||||
case PREDECREMENT_OPND:
|
||||
case CC_REGISTER_OPND:
|
||||
case STATUS_REGISTER_OPND:
|
||||
case USP_REGISTER_OPND:
|
||||
case CONTROL_REGISTER_OPND:
|
||||
break;
|
||||
|
||||
case SELECTED_OPND:
|
||||
case INDEX_SELECTED_OPND:
|
||||
freeSelectionList(operand->theOperand);
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
freeString(operand->theOperand);
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
freeBlock(operand->theOperand);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("bad operand kind in freeOperand %d\n",
|
||||
operand->kindOfOperand);
|
||||
break;
|
||||
}
|
||||
freeOperand(operand->nextOperand);
|
||||
free(operand);
|
||||
}
|
||||
|
||||
/* corresponds to routines in listing.c */
|
||||
|
||||
void
|
||||
expandOperand(addressMode, buffer)
|
||||
operandKindType addressMode;
|
||||
char *buffer;
|
||||
{
|
||||
char *bufferPtr;
|
||||
|
||||
bufferPtr = buffer;
|
||||
switch (operandKindField(addressMode)) {
|
||||
case D_REGISTER_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "d");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
break;
|
||||
case A_REGISTER_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
break;
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "[a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
moreTextOptional(buffer, &bufferPtr, "]");
|
||||
break;
|
||||
case POSTINCREMENT_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "[a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
moreTextOptional(buffer, &bufferPtr, "]+");
|
||||
break;
|
||||
case PREDECREMENT_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "-[a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
moreTextOptional(buffer, &bufferPtr, "]");
|
||||
break;
|
||||
case IMMEDIATE_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "#");
|
||||
break;
|
||||
case CC_REGISTER_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "ccr");
|
||||
break;
|
||||
case STATUS_REGISTER_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "sr");
|
||||
break;
|
||||
case USP_REGISTER_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "usp");
|
||||
break;
|
||||
case CONTROL_REGISTER_OPND:
|
||||
if (getRegister(addressMode) == 1)
|
||||
moreTextOptional(buffer, &bufferPtr, "sfc");
|
||||
else if (getRegister(addressMode) == 2)
|
||||
moreTextOptional(buffer, &bufferPtr, "dfc");
|
||||
else
|
||||
moreTextOptional(buffer, &bufferPtr, "vbr");
|
||||
break;
|
||||
case SELECTED_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
break;
|
||||
case INDEX_SELECTED_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
if (getIndexRegister(addressMode)<8) {
|
||||
moreTextOptional(buffer, &bufferPtr, "[a");
|
||||
expandNum(buffer, &bufferPtr,
|
||||
getIndexRegister(addressMode));
|
||||
} else {
|
||||
moreTextOptional(buffer, &bufferPtr, "[d");
|
||||
expandNum(buffer, &bufferPtr,
|
||||
getIndexRegister(addressMode)-8);
|
||||
}
|
||||
moreTextOptional(buffer, &bufferPtr, "]");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
expandExpression(buffer, &bufferPtr);
|
||||
switch(operandKindField(addressMode)) {
|
||||
case DISPLACEMENT_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "[a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
moreTextOptional(buffer, &bufferPtr, "]");
|
||||
break;
|
||||
case INDEXED_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "[a");
|
||||
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
||||
moreTextOptional(buffer, &bufferPtr, ",");
|
||||
if (getIndexRegister(addressMode)<8) {
|
||||
moreTextOptional(buffer, &bufferPtr, "a");
|
||||
expandNum(buffer, &bufferPtr,
|
||||
getIndexRegister(addressMode));
|
||||
} else {
|
||||
moreTextOptional(buffer, &bufferPtr, "d");
|
||||
expandNum(buffer, &bufferPtr,
|
||||
getIndexRegister(addressMode)-8);
|
||||
}
|
||||
moreTextOptional(buffer, &bufferPtr, ".");
|
||||
if (getWL(addressMode))
|
||||
moreTextOptional(buffer, &bufferPtr, "l]");
|
||||
else
|
||||
moreTextOptional(buffer, &bufferPtr, "w]");
|
||||
break;
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "[pc]");
|
||||
break;
|
||||
case PC_INDEXED_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, "[pc,");
|
||||
if (getIndexRegister(addressMode)<8) {
|
||||
moreTextOptional(buffer, &bufferPtr, "a");
|
||||
expandNum(buffer, &bufferPtr,
|
||||
getIndexRegister(addressMode));
|
||||
} else {
|
||||
moreTextOptional(buffer, &bufferPtr, "d");
|
||||
expandNum(buffer, &bufferPtr,
|
||||
getIndexRegister(addressMode)-8);
|
||||
}
|
||||
moreTextOptional(buffer, &bufferPtr, ".");
|
||||
if (getWL(addressMode))
|
||||
moreTextOptional(buffer, &bufferPtr, "l]");
|
||||
else
|
||||
moreTextOptional(buffer, &bufferPtr, "w]");
|
||||
break;
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, ".w");
|
||||
break;
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
moreTextOptional(buffer, &bufferPtr, ".l");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* corresponds to routines in expressionSemantics.c */
|
||||
|
||||
#define nullEvaluate(thing) if (thing==NULL) return(NULL);
|
||||
#define fail(err) if (!expressionFailed) {\
|
||||
error(err);\
|
||||
expressionFailed = TRUE;\
|
||||
}
|
||||
#define fail1(err,arg) if (!expressionFailed) {\
|
||||
error(err,arg);\
|
||||
expressionFailed = TRUE;\
|
||||
}
|
||||
#define fail2(err,arg1,arg2) if (!expressionFailed) {\
|
||||
error(err,arg1,arg2);\
|
||||
expressionFailed = TRUE;\
|
||||
}
|
||||
|
||||
#define qfree2(a,b) if (freeFlag) { free(a); free(b); }
|
||||
|
||||
#define expansionOff() {saveExpansion=expandMacros; expandMacros=FALSE;}
|
||||
#define forceExpansion() {saveExpansion=expandMacros; expandMacros=TRUE;}
|
||||
#define expansionOn() expandMacros=saveExpansion;
|
||||
|
||||
valueType *
|
||||
evaluateOperand(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
valueType *result;
|
||||
bool saveExpansion;
|
||||
expressionType *expression;
|
||||
|
||||
valueType *evaluateExpression();
|
||||
valueType *evaluateSelectionList();
|
||||
valueType *newValue();
|
||||
|
||||
nullEvaluate(operand);
|
||||
if (operand->kindOfOperand != EXPRESSION_OPND)
|
||||
newFixupAddressMode = operand->kindOfOperand;
|
||||
switch (operandKindField(operand->kindOfOperand)) {
|
||||
|
||||
case EXPRESSION_OPND:
|
||||
case DISPLACEMENT_OPND:
|
||||
case INDEXED_OPND:
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
case PC_INDEXED_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
result = evaluateExpression(operand->theOperand,
|
||||
performingFixups ? NO_FIXUP : OPERAND_FIXUP);
|
||||
if (operand->kindOfOperand != EXPRESSION_OPND) {
|
||||
if (result->addressMode != EXPRESSION_OPND) {
|
||||
error(BAD_ADDRESS_MODE_ERROR);
|
||||
result->kindOfValue = FAIL;
|
||||
} else {
|
||||
result->addressMode = operand->kindOfOperand;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SELECTED_OPND:
|
||||
case INDEX_SELECTED_OPND:
|
||||
result = evaluateSelectionList(operand->theOperand);
|
||||
if (result->addressMode != EXPRESSION_OPND) {
|
||||
error(BAD_ADDRESS_MODE_ERROR);
|
||||
result->kindOfValue = FAIL;
|
||||
} else {
|
||||
result->addressMode = operand->kindOfOperand;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_REGISTER_OPND:
|
||||
case A_REGISTER_OPND:
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
case POSTINCREMENT_OPND:
|
||||
case PREDECREMENT_OPND:
|
||||
case CC_REGISTER_OPND:
|
||||
case STATUS_REGISTER_OPND:
|
||||
case USP_REGISTER_OPND:
|
||||
case CONTROL_REGISTER_OPND:
|
||||
result = newValue(ABSOLUTE_VALUE, 0, operand->
|
||||
kindOfOperand);
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
result = newValue(STRING_VALUE, operand->theOperand,
|
||||
STRING_OPND);
|
||||
break;
|
||||
|
||||
case BLOCK_OPND:
|
||||
if (standaloneExpansionFlag)
|
||||
forceExpansion();
|
||||
assembleBlock(operand->theOperand);
|
||||
expansionOn();
|
||||
result = newValue(FAIL, 0, BLOCK_OPND);
|
||||
break;
|
||||
|
||||
default:
|
||||
botch("bad operand kind in evaluateOperand %d\n",
|
||||
operand->kindOfOperand);
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* from parserMisc.c */
|
||||
|
||||
conditionType
|
||||
invertConditionCode(conditionCode)
|
||||
conditionType conditionCode;
|
||||
{
|
||||
#define cc (int)conditionCode
|
||||
|
||||
if ((int)CARRY_COND<=cc && cc<=(int)ALWAYS_COND)
|
||||
return((conditionType)
|
||||
(cc - (int)CARRY_COND + (int)NOT_CARRY_COND));
|
||||
else if ((int)NOT_CARRY_COND<=cc && cc<=(int)NEVER_COND)
|
||||
return((conditionType)
|
||||
(cc + (int)CARRY_COND - (int)NOT_CARRY_COND));
|
||||
else
|
||||
botch("invertConditionCode given %d, not a condition code\n");
|
||||
}
|
||||
|
||||
/* from semanticMisc.c */
|
||||
|
||||
bool
|
||||
shouldParenthesize(operand)
|
||||
operandType *operand;
|
||||
{
|
||||
expressionTermKindType kind;
|
||||
|
||||
switch(operandKindField(operand->kindOfOperand)) {
|
||||
case EXPRESSION_OPND:
|
||||
case DISPLACEMENT_OPND:
|
||||
case INDEXED_OPND:
|
||||
case PC_DISPLACEMENT_OPND:
|
||||
case PC_INDEXED_OPND:
|
||||
case IMMEDIATE_OPND:
|
||||
case ABSOLUTE_SHORT_OPND:
|
||||
case ABSOLUTE_LONG_OPND:
|
||||
kind = operand->theOperand.expressionUnion->kindOfTerm;
|
||||
return (kind==UNOP_EXPR || kind==BINOP_EXPR || kind==
|
||||
ASSIGN_EXPR);
|
||||
break;
|
||||
|
||||
case STRING_OPND:
|
||||
case BLOCK_OPND:
|
||||
case D_REGISTER_OPND:
|
||||
case A_REGISTER_OPND:
|
||||
case A_REGISTER_INDIRECT_OPND:
|
||||
case POSTINCREMENT_OPND:
|
||||
case PREDECREMENT_OPND:
|
||||
case CC_REGISTER_OPND:
|
||||
case STATUS_REGISTER_OPND:
|
||||
case USP_REGISTER_OPND:
|
||||
case CONTROL_REGISTER_OPND:
|
||||
case SELECTED_OPND:
|
||||
case INDEX_SELECTED_OPND:
|
||||
return(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
165
opt/Makefile
Normal file
165
opt/Makefile
Normal file
@ -0,0 +1,165 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
# to make for another target CPU, redefine PROC to the name of the target
|
||||
# processor, e.g., 68000
|
||||
PROC =6502
|
||||
|
||||
OBJECTS = y.tab.o actions.o buildStuff1.o buildStuff2.o\
|
||||
buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o\
|
||||
emitBranch.o emitStuff.o encode.o errorStuff.o expressionSemantics.o fixups.o\
|
||||
garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o\
|
||||
malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o\
|
||||
statementSemantics.o structSemantics.o tokenStrings.o
|
||||
|
||||
SOURCES = macross_$(PROC).y actions_$(PROC).c buildStuff1.c buildStuff2.c\
|
||||
buildStuff3.c builtInFunctions.c builtInFunsSD_$(PROC).c debugPrint.c\
|
||||
debugPrintSD_$(PROC).c emitBranch_$(PROC).c emitStuff.c encode.c errorStuff.c\
|
||||
expressionSemantics.c fixups.c garbage.c initialize.c lexer.c listing.c\
|
||||
lookups.c macrossTables_$(PROC).c main.c malloc.c object.c\
|
||||
operandStuffSD_$(PROC).c parserMisc.c semanticMisc.c statementSemantics.c\
|
||||
structSemantics.c tokenStrings_$(PROC).c lexerTables.h macrossGlobals.h\
|
||||
macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h driver.c
|
||||
|
||||
HEADERS = macrossTypes.h macrossGlobals.h
|
||||
|
||||
.c.o:
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) $*.c
|
||||
|
||||
.c.run:
|
||||
cc -o $* $*.c
|
||||
|
||||
macross: $(OBJECTS)
|
||||
cc -O -o macross $(OBJECTS)
|
||||
|
||||
driver: driver.c
|
||||
cc -o driver driver.c
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross; make macross >&errorfyle)" &
|
||||
|
||||
install: macross
|
||||
cp macross macross_tmp
|
||||
strip macross_tmp
|
||||
cp /u1/gg/bin/macross_$(PROC) /u1/gg/bin/macross_$(PROC).old
|
||||
cp macross_tmp /u1/gg/bin/macross_$(PROC)
|
||||
rm macross_tmp
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/mycroft/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/shem/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/weyr/u1/gg/bin
|
||||
|
||||
dinstall: driver
|
||||
cp driver /u1/gg/bin/driver_tmp
|
||||
strip /u1/gg/bin/driver_tmp
|
||||
mv /u1/gg/bin/driver_tmp /u1/gg/bin/driver/macross
|
||||
cp /u1/gg/bin/driver /net/mycroft/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/shem/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/driver /net/weyr/u1/gg/bin/macross
|
||||
|
||||
change:
|
||||
rm *.o
|
||||
rm *.tab.*
|
||||
cp Makefile_68000 Makefile
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
cp $? /net/kessel/u0/chip/macross
|
||||
cp $? /net/kessel/u0/chip/macross/prof
|
||||
cp $? ..
|
||||
date >.mark
|
||||
date >/net/kessel/u0/chip/macross/.mark
|
||||
date >/net/kessel/u0/chip/macross/prof/.mark
|
||||
date >../.mark
|
||||
|
||||
macrossTypes.h: macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h
|
||||
|
||||
actions.o: actions_$(PROC).c $(HEADERS)
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) actions_$(PROC).c
|
||||
mv actions_$(PROC).o actions.o
|
||||
|
||||
buildStuff1.o: buildStuff1.c $(HEADERS)
|
||||
|
||||
buildStuff2.o: buildStuff2.c $(HEADERS)
|
||||
|
||||
buildStuff3.o: buildStuff3.c $(HEADERS)
|
||||
|
||||
builtInFunctions.o: builtInFunctions.c $(HEADERS)
|
||||
|
||||
builtInFunsSD.o: builtInFunsSD_$(PROC).c $(HEADERS)
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) builtInFunsSD_$(PROC).c
|
||||
mv builtInFunsSD_$(PROC).o builtInFunsSD.o
|
||||
|
||||
debugPrint.o: debugPrint.c y.tab.h $(HEADERS)
|
||||
|
||||
debugPrintSD.o: debugPrintSD_$(PROC).c y.tab.h $(HEADERS)
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) debugPrintSD_$(PROC).c
|
||||
mv debugPrintSD_$(PROC).o debugPrintSD.o
|
||||
|
||||
emitBranch.o: emitBranch_$(PROC).c $(HEADERS)
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) emitBranch_$(PROC).c
|
||||
mv emitBranch_$(PROC).o emitBranch.o
|
||||
|
||||
emitStuff.o: emitStuff.c $(HEADERS)
|
||||
cc -c -O -DBYTESWAPPED -DTARGET_CPU=CPU_$(PROC) emitStuff.c
|
||||
|
||||
encode.o: encode.c $(HEADERS)
|
||||
|
||||
errorStuff.o: errorStuff.c $(HEADERS)
|
||||
|
||||
expressionSemantics.o: expressionSemantics.c y.tab.h $(HEADERS)
|
||||
|
||||
fixups.o: fixups.c $(HEADERS)
|
||||
|
||||
garbage.o: garbage.c y.tab.h $(HEADERS)
|
||||
|
||||
initialize.o: initialize.c $(HEADERS)
|
||||
|
||||
lexer.o: lexer.c lexerTables.h y.tab.h $(HEADERS)
|
||||
|
||||
listing.o: listing.c $(HEADERS)
|
||||
|
||||
lookups.o: lookups.c $(HEADERS)
|
||||
|
||||
macrossTables.o: macrossTables_$(PROC).c y.tab.h macrossTypes.h
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) macrossTables_$(PROC).c
|
||||
mv macrossTables_$(PROC).o macrossTables.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
|
||||
main.o: main.c $(HEADERS)
|
||||
|
||||
object.o: object.c $(HEADERS)
|
||||
|
||||
operandStuffSD.o: operandStuffSD_$(PROC).c $(HEADERS)
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) operandStuffSD_$(PROC).c
|
||||
mv operandStuffSD_$(PROC).o operandStuffSD.o
|
||||
|
||||
parserMisc.o: parserMisc.c y.tab.h $(HEADERS)
|
||||
|
||||
semanticMisc.o: semanticMisc.c $(HEADERS)
|
||||
|
||||
statementSemantics.o: statementSemantics.c $(HEADERS)
|
||||
|
||||
structSemantics.o: structSemantics.c $(HEADERS)
|
||||
|
||||
tokenStrings.o: tokenStrings_$(PROC).c $(HEADERS)
|
||||
cc -c -O -DTARGET_CPU=CPU_$(PROC) tokenStrings_$(PROC).c
|
||||
mv tokenStrings_$(PROC).o tokenStrings.o
|
||||
|
||||
y.tab.o: y.tab.c $(HEADERS)
|
||||
cc -c -O -DYYDEBUG -DTARGET_CPU=CPU_$(PROC) y.tab.c
|
||||
|
||||
y.tab.c y.tab.h: macross_$(PROC).y
|
||||
yacc -d macross_$(PROC).y
|
||||
|
||||
y.output: macross_$(PROC).y
|
||||
yacc -vd macross_$(PROC).y
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o y.output y.tab.c y.tab.h macross
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
162
opt/Makefile_6502
Normal file
162
opt/Makefile_6502
Normal file
@ -0,0 +1,162 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
# to make for another target CPU, redefine PROC to the name of the target
|
||||
# processor, e.g., 68000
|
||||
PROC =6502
|
||||
|
||||
OBJECTS = y.tab.o actions.o buildStuff1.o buildStuff2.o\
|
||||
buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o\
|
||||
emitBranch.o emitStuff.o errorStuff.o expressionSemantics.o fixups.o\
|
||||
garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o\
|
||||
malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o\
|
||||
statementSemantics.o structSemantics.o tokenStrings.o
|
||||
|
||||
SOURCES = macross_$(PROC).y actions_$(PROC).c buildStuff1.c buildStuff2.c\
|
||||
buildStuff3.c builtInFunctions.c builtInFunsSD_$(PROC).c debugPrint.c\
|
||||
debugPrintSD_$(PROC).c emitBranch_$(PROC).c emitStuff.c errorStuff.c\
|
||||
expressionSemantics.c fixups.c garbage.c initialize.c lexer.c listing.c\
|
||||
lookups.c macrossTables_$(PROC).c main.c malloc.c object.c\
|
||||
operandStuffSD_$(PROC).c parserMisc.c semanticMisc.c statementSemantics.c\
|
||||
structSemantics.c tokenStrings_$(PROC).c lexerTables.h macrossGlobals.h\
|
||||
macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h driver.c
|
||||
|
||||
HEADERS = macrossTypes.h macrossGlobals.h
|
||||
|
||||
.c.o:
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) $*.c
|
||||
|
||||
.c.run:
|
||||
cc -O -o $* $*.c
|
||||
|
||||
macross: $(OBJECTS)
|
||||
cc -O -o macross $(OBJECTS)
|
||||
|
||||
driver: driver.c
|
||||
cc -O -o driver driver.c
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross; make macross >&errorfyle)" &
|
||||
|
||||
install: macross
|
||||
cp macross /u1/gg/bin/macross_tmp
|
||||
strip /u1/gg/bin/macross_tmp
|
||||
mv /u1/gg/bin/macross_$(PROC) /u1/gg/bin/macross_$(PROC).old
|
||||
mv /u1/gg/bin/macross_tmp /u1/gg/bin/macross_$(PROC)
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/mycroft/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/shem/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/weyr/u1/gg/bin
|
||||
|
||||
dinstall: driver
|
||||
cp driver /u1/gg/bin/driver_tmp
|
||||
strip /u1/gg/bin/driver_tmp
|
||||
mv /u1/gg/bin/driver_tmp /u1/gg/bin/macross
|
||||
cp /u1/gg/bin/macross /net/mycroft/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/macross /net/shem/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/macross /net/weyr/u1/gg/bin/macross
|
||||
|
||||
change:
|
||||
rm *.o
|
||||
rm *.tab.*
|
||||
cp Makefile_68000 Makefile
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
cp $? /net/kessel/u0/chip/macross
|
||||
cp $? /net/kessel/u0/chip/macross/prof
|
||||
cp $? ..
|
||||
date >.mark
|
||||
date >/net/kessel/u0/chip/macross/.mark
|
||||
date >/net/kessel/u0/chip/macross/prof/.mark
|
||||
date >../.mark
|
||||
|
||||
macrossTypes.h: macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h
|
||||
|
||||
actions.o: actions_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) actions_$(PROC).c
|
||||
mv actions_$(PROC).o actions.o
|
||||
|
||||
buildStuff1.o: buildStuff1.c $(HEADERS)
|
||||
|
||||
buildStuff2.o: buildStuff2.c $(HEADERS)
|
||||
|
||||
buildStuff3.o: buildStuff3.c $(HEADERS)
|
||||
|
||||
builtInFunctions.o: builtInFunctions.c $(HEADERS)
|
||||
|
||||
builtInFunsSD.o: builtInFunsSD_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) builtInFunsSD_$(PROC).c
|
||||
mv builtInFunsSD_$(PROC).o builtInFunsSD.o
|
||||
|
||||
debugPrint.o: debugPrint.c y.tab.h $(HEADERS)
|
||||
|
||||
debugPrintSD.o: debugPrintSD_$(PROC).c y.tab.h $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) debugPrintSD_$(PROC).c
|
||||
mv debugPrintSD_$(PROC).o debugPrintSD.o
|
||||
|
||||
emitBranch.o: emitBranch_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) emitBranch_$(PROC).c
|
||||
mv emitBranch_$(PROC).o emitBranch.o
|
||||
|
||||
emitStuff.o: emitStuff.c $(HEADERS)
|
||||
cc -O -c -DBYTESWAPPED -DTARGET_CPU=CPU_$(PROC) emitStuff.c
|
||||
|
||||
errorStuff.o: errorStuff.c $(HEADERS)
|
||||
|
||||
expressionSemantics.o: expressionSemantics.c y.tab.h $(HEADERS)
|
||||
|
||||
fixups.o: fixups.c $(HEADERS)
|
||||
|
||||
garbage.o: garbage.c y.tab.h $(HEADERS)
|
||||
|
||||
initialize.o: initialize.c $(HEADERS)
|
||||
|
||||
lexer.o: lexer.c lexerTables.h y.tab.h $(HEADERS)
|
||||
|
||||
listing.o: listing.c $(HEADERS)
|
||||
|
||||
lookups.o: lookups.c $(HEADERS)
|
||||
|
||||
macrossTables.o: macrossTables_$(PROC).c y.tab.h macrossTypes.h
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) macrossTables_$(PROC).c
|
||||
mv macrossTables_$(PROC).o macrossTables.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
|
||||
main.o: main.c $(HEADERS)
|
||||
|
||||
object.o: object.c $(HEADERS)
|
||||
|
||||
operandStuffSD.o: operandStuffSD_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) operandStuffSD_$(PROC).c
|
||||
mv operandStuffSD_$(PROC).o operandStuffSD.o
|
||||
|
||||
parserMisc.o: parserMisc.c y.tab.h $(HEADERS)
|
||||
|
||||
semanticMisc.o: semanticMisc.c $(HEADERS)
|
||||
|
||||
statementSemantics.o: statementSemantics.c $(HEADERS)
|
||||
|
||||
structSemantics.o: structSemantics.c $(HEADERS)
|
||||
|
||||
tokenStrings.o: tokenStrings_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) tokenStrings_$(PROC).c
|
||||
mv tokenStrings_$(PROC).o tokenStrings.o
|
||||
|
||||
y.tab.o: y.tab.c $(HEADERS)
|
||||
cc -O -c -DYYDEBUG -DTARGET_CPU=CPU_$(PROC) y.tab.c
|
||||
|
||||
y.tab.c y.tab.h: macross_$(PROC).y
|
||||
yacc -d macross_$(PROC).y
|
||||
|
||||
y.output: macross_$(PROC).y
|
||||
yacc -vd macross_$(PROC).y
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o y.output y.tab.c y.tab.h macross
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
162
opt/Makefile_68000
Normal file
162
opt/Makefile_68000
Normal file
@ -0,0 +1,162 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
# to make for another target CPU, redefine PROC to the name of the target
|
||||
# processor, e.g., 68000
|
||||
PROC =68000
|
||||
|
||||
OBJECTS = y.tab.o actions.o buildStuff1.o buildStuff2.o\
|
||||
buildStuff3.o builtInFunctions.o builtInFunsSD.o debugPrint.o debugPrintSD.o\
|
||||
emitBranch.o emitStuff.o errorStuff.o expressionSemantics.o fixups.o\
|
||||
garbage.o initialize.o lexer.o listing.o lookups.o macrossTables.o main.o\
|
||||
malloc.o object.o operandStuffSD.o parserMisc.o semanticMisc.o\
|
||||
statementSemantics.o structSemantics.o tokenStrings.o
|
||||
|
||||
SOURCES = macross_$(PROC).y actions_$(PROC).c buildStuff1.c buildStuff2.c\
|
||||
buildStuff3.c builtInFunctions.c builtInFunsSD_$(PROC).c debugPrint.c\
|
||||
debugPrintSD_$(PROC).c emitBranch_$(PROC).c emitStuff.c errorStuff.c\
|
||||
expressionSemantics.c fixups.c garbage.c initialize.c lexer.c listing.c\
|
||||
lookups.c macrossTables_$(PROC).c main.c malloc.c object.c\
|
||||
operandStuffSD_$(PROC).c parserMisc.c semanticMisc.c statementSemantics.c\
|
||||
structSemantics.c tokenStrings_$(PROC).c lexerTables.h macrossGlobals.h\
|
||||
macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h driver.c
|
||||
|
||||
HEADERS = macrossTypes.h macrossGlobals.h
|
||||
|
||||
.c.o:
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) $*.c
|
||||
|
||||
.c.run:
|
||||
cc -O -o $* $*.c
|
||||
|
||||
macross: $(OBJECTS)
|
||||
cc -O -o macross $(OBJECTS)
|
||||
|
||||
driver: driver.c
|
||||
cc -O -o driver driver.c
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross; make macross >&errorfyle)" &
|
||||
|
||||
install: macross
|
||||
cp macross /u1/gg/bin/macross_tmp
|
||||
strip /u1/gg/bin/macross_tmp
|
||||
mv /u1/gg/bin/macross_$(PROC) /u1/gg/bin/macross_$(PROC).old
|
||||
mv /u1/gg/bin/macross_tmp /u1/gg/bin/macross_$(PROC)
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/mycroft/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/shem/u1/gg/bin
|
||||
cp /u1/gg/bin/macross_$(PROC) /net/weyr/u1/gg/bin
|
||||
|
||||
dinstall: driver
|
||||
cp driver /u1/gg/bin/driver_tmp
|
||||
strip /u1/gg/bin/driver_tmp
|
||||
mv /u1/gg/bin/driver_tmp /u1/gg/bin/macross
|
||||
cp /u1/gg/bin/macross /net/mycroft/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/macross /net/shem/u1/gg/bin/macross
|
||||
cp /u1/gg/bin/macross /net/weyr/u1/gg/bin/macross
|
||||
|
||||
change:
|
||||
rm *.o
|
||||
rm *.tab.*
|
||||
cp Makefile_6502 Makefile
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
cp $? /net/kessel/u0/chip/macross
|
||||
cp $? /net/kessel/u0/chip/macross/prof
|
||||
cp $? ..
|
||||
date >.mark
|
||||
date >/net/kessel/u0/chip/macross/.mark
|
||||
date >/net/kessel/u0/chip/macross/prof/.mark
|
||||
date >../.mark
|
||||
|
||||
macrossTypes.h: macrossTypes.h operandDefs_$(PROC).h operandBody_$(PROC).h\
|
||||
conditionDefs_$(PROC).h
|
||||
|
||||
actions.o: actions_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) actions_$(PROC).c
|
||||
mv actions_$(PROC).o actions.o
|
||||
|
||||
buildStuff1.o: buildStuff1.c $(HEADERS)
|
||||
|
||||
buildStuff2.o: buildStuff2.c $(HEADERS)
|
||||
|
||||
buildStuff3.o: buildStuff3.c $(HEADERS)
|
||||
|
||||
builtInFunctions.o: builtInFunctions.c $(HEADERS)
|
||||
|
||||
builtInFunsSD.o: builtInFunsSD_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) builtInFunsSD_$(PROC).c
|
||||
mv builtInFunsSD_$(PROC).o builtInFunsSD.o
|
||||
|
||||
debugPrint.o: debugPrint.c y.tab.h $(HEADERS)
|
||||
|
||||
debugPrintSD.o: debugPrintSD_$(PROC).c y.tab.h $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) debugPrintSD_$(PROC).c
|
||||
mv debugPrintSD_$(PROC).o debugPrintSD.o
|
||||
|
||||
emitBranch.o: emitBranch_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) emitBranch_$(PROC).c
|
||||
mv emitBranch_$(PROC).o emitBranch.o
|
||||
|
||||
emitStuff.o: emitStuff.c $(HEADERS)
|
||||
cc -O -c -DBYTESWAPPED -DTARGET_CPU=CPU_$(PROC) emitStuff.c
|
||||
|
||||
errorStuff.o: errorStuff.c $(HEADERS)
|
||||
|
||||
expressionSemantics.o: expressionSemantics.c y.tab.h $(HEADERS)
|
||||
|
||||
fixups.o: fixups.c $(HEADERS)
|
||||
|
||||
garbage.o: garbage.c y.tab.h $(HEADERS)
|
||||
|
||||
initialize.o: initialize.c $(HEADERS)
|
||||
|
||||
lexer.o: lexer.c lexerTables.h y.tab.h $(HEADERS)
|
||||
|
||||
listing.o: listing.c $(HEADERS)
|
||||
|
||||
lookups.o: lookups.c $(HEADERS)
|
||||
|
||||
macrossTables.o: macrossTables_$(PROC).c y.tab.h macrossTypes.h
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) macrossTables_$(PROC).c
|
||||
mv macrossTables_$(PROC).o macrossTables.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
|
||||
main.o: main.c $(HEADERS)
|
||||
|
||||
object.o: object.c $(HEADERS)
|
||||
|
||||
operandStuffSD.o: operandStuffSD_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) operandStuffSD_$(PROC).c
|
||||
mv operandStuffSD_$(PROC).o operandStuffSD.o
|
||||
|
||||
parserMisc.o: parserMisc.c y.tab.h $(HEADERS)
|
||||
|
||||
semanticMisc.o: semanticMisc.c $(HEADERS)
|
||||
|
||||
statementSemantics.o: statementSemantics.c $(HEADERS)
|
||||
|
||||
structSemantics.o: structSemantics.c $(HEADERS)
|
||||
|
||||
tokenStrings.o: tokenStrings_$(PROC).c $(HEADERS)
|
||||
cc -O -c -DTARGET_CPU=CPU_$(PROC) tokenStrings_$(PROC).c
|
||||
mv tokenStrings_$(PROC).o tokenStrings.o
|
||||
|
||||
y.tab.o: y.tab.c $(HEADERS)
|
||||
cc -O -c -DYYDEBUG -DTARGET_CPU=CPU_$(PROC) y.tab.c
|
||||
|
||||
y.tab.c y.tab.h: macross_$(PROC).y
|
||||
yacc -d macross_$(PROC).y
|
||||
|
||||
y.output: macross_$(PROC).y
|
||||
yacc -vd macross_$(PROC).y
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o y.output y.tab.c y.tab.h macross
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
128
parserMisc.c
Normal file
128
parserMisc.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
parserMisc.c -- Miscellaneous parser support routines for the Macross
|
||||
assembler.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
3-November-1984
|
||||
|
||||
*/
|
||||
|
||||
#include "macrossTypes.h"
|
||||
#include "macrossGlobals.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
statementType *
|
||||
addLabelToStatement(labelList, statement)
|
||||
labelListType *labelList;
|
||||
statementType *statement;
|
||||
{
|
||||
statementType *newStatement();
|
||||
|
||||
if (statement == NULL)
|
||||
statement = newStatement(NULL_STATEMENT, NULL);
|
||||
statement->labels = labelList;
|
||||
return(statement);
|
||||
}
|
||||
|
||||
void
|
||||
botch(message, arg1, arg2, arg3)
|
||||
char *message;
|
||||
anyOldThing *arg1;
|
||||
anyOldThing *arg2;
|
||||
anyOldThing *arg3;
|
||||
{
|
||||
printf("Macross horrible terrible internal botch: ");
|
||||
printf(message, arg1, arg2, arg3);
|
||||
chokePukeAndDie();
|
||||
}
|
||||
|
||||
void
|
||||
checkDefineAssignmentOperator(assignmentOperator)
|
||||
assignmentKindType assignmentOperator;
|
||||
{
|
||||
if (assignmentOperator != ASSIGN_ASSIGN)
|
||||
puntOnError(DEFINE_ASSIGNMENT_WRONG_ERROR);
|
||||
}
|
||||
|
||||
statementType *
|
||||
convertDefineToMdefine(defineStatement)
|
||||
statementType *defineStatement;
|
||||
{
|
||||
if (defineStatement->kindOfStatement != DEFINE_STATEMENT)
|
||||
botch("convertDefineToMdefine got statement kind: %d\n",
|
||||
defineStatement->kindOfStatement);
|
||||
defineStatement->kindOfStatement = MDEFINE_STATEMENT;
|
||||
return(defineStatement);
|
||||
}
|
||||
|
||||
ifStatementBodyType *
|
||||
extractIfBody(ifStatement)
|
||||
statementType *ifStatement;
|
||||
{
|
||||
ifStatementBodyType *result;
|
||||
|
||||
result = ifStatement->statementBody.ifUnion;
|
||||
if (ifStatement->labels != NULL)
|
||||
botch("extract if body with non-null labels\n");
|
||||
else if (ifStatement->nextStatement != NULL)
|
||||
botch("extract if body with non-null next\n");
|
||||
else
|
||||
qfree(ifStatement);
|
||||
return(result);
|
||||
}
|
||||
|
||||
mifStatementBodyType *
|
||||
extractMifBody(mifStatement)
|
||||
statementType *mifStatement;
|
||||
{
|
||||
mifStatementBodyType *result;
|
||||
|
||||
result = mifStatement->statementBody.mifUnion;
|
||||
if (mifStatement->labels != NULL)
|
||||
botch("extract mif body with non-null labels\n");
|
||||
else if (mifStatement->nextStatement != NULL)
|
||||
botch("extract mif body with non-null next\n");
|
||||
else
|
||||
qfree(mifStatement);
|
||||
return(result);
|
||||
}
|
||||
|
||||
stringType *
|
||||
extractString(textExpression)
|
||||
operandType *textExpression;
|
||||
{
|
||||
stringType *result;
|
||||
|
||||
if (textExpression->kindOfOperand != STRING_OPND)
|
||||
botch("extract string got handed an opnd kind: %d\n",
|
||||
textExpression->kindOfOperand);
|
||||
result = textExpression->theOperand.stringUnion;
|
||||
qfree(textExpression);
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
popMacroOrFunctionNestingDepth()
|
||||
{
|
||||
if (--macroOrFunctionNestingDepth == 0)
|
||||
unknownSymbolTag = UNKNOWN_SYMBOL;
|
||||
}
|
||||
|
||||
void
|
||||
pushMacroOrFunctionNestingDepth()
|
||||
{
|
||||
macroOrFunctionNestingDepth++;
|
||||
unknownSymbolTag = NESTED_UNKNOWN_SYMBOL;
|
||||
}
|
||||
|
||||
char *
|
||||
saveString(s)
|
||||
char *s;
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = (char *)malloc(strlen(s)+1);
|
||||
strcpy(result, s);
|
||||
return(result);
|
||||
}
|
BIN
parserMisc.o
Normal file
BIN
parserMisc.o
Normal file
Binary file not shown.
1337
semanticMisc.c
Normal file
1337
semanticMisc.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
semanticMisc.o
Normal file
BIN
semanticMisc.o
Normal file
Binary file not shown.
1
slinky/.mark
Normal file
1
slinky/.mark
Normal file
@ -0,0 +1 @@
|
||||
Fri Jun 6 14:51:43 PDT 1986
|
8
slinky/DOC
Normal file
8
slinky/DOC
Normal file
@ -0,0 +1,8 @@
|
||||
/u0/chip/macross/slinky:
|
||||
This directory contains the source to Slinky. Here's what's here:
|
||||
|
||||
DOC - This file
|
||||
Makefile - Makefile to compile it
|
||||
*.c, *.h - source files
|
||||
opt/ - directory for optimized version, as mentioned in
|
||||
documentation above for /u0/chip/macross/opt
|
77
slinky/Makefile
Normal file
77
slinky/Makefile
Normal file
@ -0,0 +1,77 @@
|
||||
.SUFFIXES: .o .c .h .run
|
||||
|
||||
OBJECTS = builtins.o debugPrint.o errorStuff.o expr.o initialize.o\
|
||||
instantiate.o link.o main.o map.o poke.o read.o relocate.o slinkyTables.o\
|
||||
write.o
|
||||
|
||||
SOURCES = builtins.c debugPrint.c errorStuff.c expr.c initialize.c\
|
||||
instantiate.c link.c main.c map.c poke.c read.c relocate.c slinkyTables.c\
|
||||
write.c slinkyExpressions.h slinkyGlobals.h slinkyTypes.h y.tab.h
|
||||
|
||||
.c.o:
|
||||
cc -c -g $*.c
|
||||
|
||||
.c.run:
|
||||
cc -o $* $*.c
|
||||
|
||||
slinky: $(OBJECTS)
|
||||
cc -g -o slinky $(OBJECTS)
|
||||
|
||||
update: .mark
|
||||
kessel "(cd /u0/chip/macross/slinky; make slinky >&errorfyle)" &
|
||||
|
||||
move: .mark
|
||||
|
||||
.mark: $(SOURCES)
|
||||
# cp $? /net/kessel/u0/chip/macross/slinky
|
||||
cp $? /net/kessel/u0/chip/macross/slinky
|
||||
# cp $? /net/kessel/u0/chip/macross/slinky/prof
|
||||
cp $? /net/kessel/u0/chip/macross/slinky/prof
|
||||
cp $? opt
|
||||
date >.mark
|
||||
# date >/net/kessel/u0/chip/macross/slinky/.mark
|
||||
date >/net/kessel/u0/chip/macross/slinky/.mark
|
||||
# date >/net/kessel/u0/chip/macross/slinky/prof/.mark
|
||||
date >/net/kessel/u0/chip/macross/slinky/prof/.mark
|
||||
date >opt/.mark
|
||||
|
||||
install: slinky
|
||||
cp slinky /u1/gg/bin/slinky_tmp
|
||||
strip /u1/gg/bin/slinky_tmp
|
||||
mv /u1/gg/bin/slinky /u1/gg/bin/sliny.old
|
||||
mv /u1/gg/bin/slinky_tmp /u1/gg/bin/slinky
|
||||
|
||||
builtins.o: builtins.c slinkyGlobals.h slinkyTypes.h slinkyExpressions.h
|
||||
|
||||
debugPrint.o: debugPrint.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
errorStuff.o: errorStuff.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
expr.o: expr.c slinkyExpressions.h slinkyGlobals.h slinkyTypes.h y.tab.h
|
||||
|
||||
initialize.o: initialize.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
instantiate.o: instantiate.c slinkyGlobals.h slinkyTypes.h slinkyExpressions.h
|
||||
|
||||
link.o: link.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
main.o: main.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
map.o: map.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
poke.o: poke.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
read.o: read.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
relocate.o: relocate.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
slinkyTables.o: slinkyTables.c slinkyTypes.h
|
||||
|
||||
write.o: write.c slinkyGlobals.h slinkyTypes.h
|
||||
|
||||
cleanup:
|
||||
/bin/rm -f *.o slinky
|
||||
|
||||
love:
|
||||
@echo "Not war?"
|
||||
|
431
slinky/builtins.c
Normal file
431
slinky/builtins.c
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
builtins.c -- Built-in functions for the Slinky linker
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
14-November-1985
|
||||
*/
|
||||
|
||||
#include "slinkyTypes.h"
|
||||
#include "slinkyGlobals.h"
|
||||
#include "slinkyExpressions.h"
|
||||
#include <strings.h>
|
||||
|
||||
#define getSymbol() ((symbolType *)getNumber())
|
||||
|
||||
void
|
||||
tooFewArgs(argCount, name)
|
||||
int argCount;
|
||||
stringType *name;
|
||||
{
|
||||
error(TOO_FEW_ARGUMENTS_TO_BIF_ERROR, name);
|
||||
while (argCount-- > 0)
|
||||
skipExpression();
|
||||
}
|
||||
|
||||
void
|
||||
tooManyArgs(argCount, name)
|
||||
int argCount;
|
||||
stringType *name;
|
||||
{
|
||||
error(TOO_MANY_ARGUMENTS_TO_BIF_ERROR, name);
|
||||
while (argCount-- > 0)
|
||||
skipExpression();
|
||||
}
|
||||
|
||||
/*
|
||||
The built-in-functions themselves: pointers to these are loaded into the
|
||||
builtInFunctionTable at linker compile time. These are all known within
|
||||
the Macross assembler: each symbol of the form "xxx" is assigned a pointer
|
||||
to "xxxBIF" (BIF == Built-In-Function).
|
||||
*/
|
||||
|
||||
/* The two ATASCII related BIF's refer to this table -- This really only
|
||||
makes sense for the 6502 version, but is harmless in other versions. */
|
||||
static char atasciiTable[] = { /* 0xFFs will become 0x00s on output */
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0xFF,
|
||||
};
|
||||
|
||||
/* Convert a string to ATASCII */
|
||||
stringType *
|
||||
atasciiBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *string;
|
||||
stringType *newString;
|
||||
int i;
|
||||
|
||||
if (argCount == 0) {
|
||||
return("");
|
||||
} else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "atascii");
|
||||
return("");
|
||||
} else {
|
||||
string = (stringType *)evaluateExpression();
|
||||
newString = (stringType *)malloc(strlen(string)+1);
|
||||
for (i=0; string[i]!='\0'; i++)
|
||||
newString[i] = atasciiTable[string[i]];
|
||||
newString[i] = '\0';
|
||||
return(newString);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a string to ATASCII while setting high-order color bits */
|
||||
stringType *
|
||||
atasciiColorBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *string;
|
||||
stringType *newString;
|
||||
int color;
|
||||
int i;
|
||||
byte testChar;
|
||||
|
||||
if (argCount == 0) {
|
||||
return("");
|
||||
} else if (argCount == 1) {
|
||||
return(atasciiBIF(argCount));
|
||||
} else if (argCount > 2) {
|
||||
tooManyArgs(argCount, "atasciiColor");
|
||||
return("");
|
||||
} else {
|
||||
string = (stringType *)evaluateExpression();
|
||||
color = (evaluateExpression() & 0x03) << 6;
|
||||
newString = (stringType *)malloc(strlen(string)+1);
|
||||
for (i=0; string[i]!='\0'; i++) {
|
||||
testChar = atasciiTable[string[i]];
|
||||
if (testChar == 0xFF)
|
||||
testChar = 0;
|
||||
testChar = (testChar & 0x3F) | color;
|
||||
if (testChar == 0)
|
||||
testChar = 0xFF;
|
||||
newString[i] = testChar;
|
||||
}
|
||||
newString[i] = '\0';
|
||||
return(newString);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an operand is absolute (as opposed to relocatable) */
|
||||
bool
|
||||
isAbsoluteValueBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
if (argCount > 1)
|
||||
tooManyArgs(argCount, "isAbsoluteValue");
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* Check if operand is a condition code */
|
||||
bool
|
||||
isConditionCodeBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
bool result;
|
||||
|
||||
if (argCount == 0)
|
||||
return(FALSE);
|
||||
else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "isConditionCode");
|
||||
return(FALSE);
|
||||
}
|
||||
result = (*pc == CONDITION_CODE_TAG);
|
||||
skipExpression();
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* Check if a symbol is defined */
|
||||
bool
|
||||
isDefinedBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
symbolType *symbol;
|
||||
|
||||
if (argCount == 0)
|
||||
return(FALSE);
|
||||
else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "isDefined");
|
||||
return(FALSE);
|
||||
}
|
||||
if (*pc != IDENTIFIER_TAG) {
|
||||
skipExpression();
|
||||
return(TRUE);
|
||||
}
|
||||
pc++; /* skip tag */
|
||||
symbol = getSymbol();
|
||||
return((symbol->symbolClass & ~SYMBOL_EXTERNAL) != 0);
|
||||
}
|
||||
|
||||
/* Check if a symbol is externally visible */
|
||||
bool
|
||||
isExternalBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
symbolType *symbol;
|
||||
|
||||
if (argCount == 0)
|
||||
return(FALSE);
|
||||
else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "isExternal");
|
||||
return(FALSE);
|
||||
}
|
||||
if (*pc != IDENTIFIER_TAG) {
|
||||
skipExpression();
|
||||
return(TRUE);
|
||||
}
|
||||
pc++; /* skip tag */
|
||||
symbol = getSymbol();
|
||||
return((symbol->symbolClass & SYMBOL_EXTERNAL) != 0);
|
||||
}
|
||||
|
||||
/* Return the Nth character of a string (as an integer) */
|
||||
int
|
||||
nthCharBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *string;
|
||||
int position;
|
||||
|
||||
if (argCount > 2) {
|
||||
tooManyArgs(argCount, "nthChar");
|
||||
return(0);
|
||||
} else if (argCount != 2) {
|
||||
tooFewArgs(argCount, "nthChar");
|
||||
return(0);
|
||||
}
|
||||
string = (stringType *)evaluateExpression();
|
||||
position = evaluateExpression();
|
||||
if (position >= strlen(string)) {
|
||||
error(BAD_POSITION_ARGUMENT_TO_NTH_CHAR_ERROR);
|
||||
return(0);
|
||||
}
|
||||
return(string[position]);
|
||||
}
|
||||
|
||||
/* Pass stuff through to stdio's 'printf' function */
|
||||
int
|
||||
printfBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *formatString;
|
||||
int argument[20];
|
||||
int i;
|
||||
|
||||
if (argCount < 1) {
|
||||
tooFewArgs(argCount, "printf");
|
||||
return(0);
|
||||
} else if (argCount > 21) {
|
||||
tooManyArgs(argCount, "printf");
|
||||
return(0);
|
||||
}
|
||||
formatString = (stringType *)evaluateExpression();
|
||||
argCount--;
|
||||
for (i=0; i<argCount; ++i)
|
||||
argument[i] = evaluateExpression();
|
||||
/* cretinous hack */
|
||||
return(printf(formatString, argument[0], argument[1], argument[2],
|
||||
argument[3], argument[4], argument[5], argument[6],
|
||||
argument[7], argument[8], argument[9], argument[10],
|
||||
argument[11], argument[12], argument[13],
|
||||
argument[14], argument[15], argument[16],
|
||||
argument[17], argument[18], argument[19]));
|
||||
}
|
||||
|
||||
/* Concatenate two strings */
|
||||
stringType *
|
||||
strcatBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *string1;
|
||||
stringType *string2;
|
||||
stringType *newString;
|
||||
|
||||
if (argCount == 0)
|
||||
return("");
|
||||
else if (argCount == 1)
|
||||
return((stringType *)evaluateExpression());
|
||||
else if (argCount > 2) {
|
||||
tooManyArgs(argCount, "strcat");
|
||||
return("");
|
||||
}
|
||||
string1 = (stringType *)evaluateExpression();
|
||||
string2 = (stringType *)evaluateExpression();
|
||||
newString = (stringType *)malloc(strlen(string1)+strlen(string2)+1);
|
||||
strcpy(newString, string1);
|
||||
strcat(newString, string2);
|
||||
return(newString);
|
||||
}
|
||||
|
||||
/* Compare two strings */
|
||||
int
|
||||
strcmpBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *string1;
|
||||
stringType *string2;
|
||||
|
||||
if (argCount < 2) {
|
||||
tooFewArgs(argCount, "strcmp");
|
||||
return(0);
|
||||
} else if (argCount > 2) {
|
||||
tooManyArgs(argCount, "strcmp");
|
||||
return(0);
|
||||
}
|
||||
string1 = (stringType *)evaluateExpression();
|
||||
string2 = (stringType *)evaluateExpression();
|
||||
return(strcmp(string1, string2));
|
||||
}
|
||||
|
||||
/* Compare two strings in a case-independent fashion */
|
||||
int
|
||||
strcmplcBIF(argCount)
|
||||
int argCount;
|
||||
|
||||
{
|
||||
stringType *string1;
|
||||
stringType *string2;
|
||||
|
||||
if (argCount < 2) {
|
||||
tooFewArgs(argCount, "strcmplc");
|
||||
return(0);
|
||||
} else if (argCount > 2) {
|
||||
tooManyArgs(argCount, "strcmplc");
|
||||
return(0);
|
||||
}
|
||||
string1 = (stringType *)evaluateExpression();
|
||||
string2 = (stringType *)evaluateExpression();
|
||||
return(strcmplc(string1, string2));
|
||||
}
|
||||
|
||||
/* Return the length of a string */
|
||||
int
|
||||
strlenBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
if (argCount < 1)
|
||||
return(0);
|
||||
else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "strlen");
|
||||
return(0);
|
||||
}
|
||||
return(strlen(evaluateExpression()));
|
||||
}
|
||||
|
||||
/* Return a substring of a string */
|
||||
char *
|
||||
substrBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
stringType *string;
|
||||
int start;
|
||||
int length;
|
||||
stringType *newString;
|
||||
int originalLength;
|
||||
bool backwards;
|
||||
|
||||
if (argCount < 1)
|
||||
return("");
|
||||
else if (argCount == 1)
|
||||
return((stringType *)evaluateExpression());
|
||||
else if (argCount > 3) {
|
||||
tooManyArgs(argCount, "substr");
|
||||
return("");
|
||||
}
|
||||
string = (stringType *)evaluateExpression();
|
||||
originalLength = strlen(string);
|
||||
start = evaluateExpression();
|
||||
if (start < 0) {
|
||||
start = -start - 1;
|
||||
backwards = TRUE;
|
||||
} else
|
||||
backwards = FALSE;
|
||||
if (argCount == 2) {
|
||||
length = originalLength - start;
|
||||
if (backwards)
|
||||
length = -length;
|
||||
} else {
|
||||
length = evaluateExpression();
|
||||
}
|
||||
if (length < 0) {
|
||||
length = -length;
|
||||
if (backwards)
|
||||
start = start + length - 1;
|
||||
else
|
||||
start = start - length + 1;
|
||||
}
|
||||
if (backwards)
|
||||
start = originalLength - start - 1;
|
||||
if (originalLength <= start || originalLength < length + start ||
|
||||
start < 0 ){
|
||||
error(BAD_SUBSTRING_INDICES_ERROR);
|
||||
return("");
|
||||
}
|
||||
newString = (stringType *)malloc(length+1);
|
||||
strncpy(newString, string+start, length);
|
||||
newString[length] = '\0';
|
||||
return(newString);
|
||||
}
|
||||
|
||||
/* Turn a string into a symbol and return its value */
|
||||
addressType
|
||||
symbolLookupBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
symbolType *symbol;
|
||||
stringType *symbolName;
|
||||
symbolType *lookupGlobalSymbol();
|
||||
|
||||
if (argCount < 1) {
|
||||
tooFewArgs(argCount, "symbolLookup");
|
||||
return(0);
|
||||
} else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "symbolLookup");
|
||||
return(0);
|
||||
}
|
||||
symbol = lookupGlobalSymbol(symbolName = (stringType *)
|
||||
evaluateExpression());
|
||||
if (symbol == NULL) {
|
||||
error(SYMBOL_NOT_FOUND_IN_SYMBOL_LOOKUP_ERROR, symbolName);
|
||||
return(0);
|
||||
} else
|
||||
return(symbol->symbolValue);
|
||||
}
|
||||
|
||||
/* Turn a symbol into a string */
|
||||
stringType *
|
||||
symbolNameBIF(argCount)
|
||||
int argCount;
|
||||
{
|
||||
symbolType *symbol;
|
||||
|
||||
if (argCount < 1) {
|
||||
tooFewArgs(argCount, "symbolName");
|
||||
return(NULL);
|
||||
} else if (argCount > 1) {
|
||||
tooManyArgs(argCount, "symbolName");
|
||||
return(NULL);
|
||||
}
|
||||
if (*pc != IDENTIFIER_TAG) {
|
||||
error(SYMBOL_NAME_ARG_IS_NOT_SYMBOL_ERROR);
|
||||
skipExpression();
|
||||
return("");
|
||||
}
|
||||
pc++;
|
||||
symbol = getSymbol();
|
||||
return(symbol->symbolName);
|
||||
}
|
BIN
slinky/builtins.o
Normal file
BIN
slinky/builtins.o
Normal file
Binary file not shown.
124
slinky/debugPrint.c
Normal file
124
slinky/debugPrint.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
debugPrint.c -- Routines to dump stuff out in readable form for
|
||||
debugging the Slinky linker.
|
||||
|
||||
Chip Morningstar -- Lucasfilm Ltd.
|
||||
|
||||
18-March-1985
|
||||
|
||||
*/
|
||||
|
||||
#include "slinkyTypes.h"
|
||||
#include "slinkyGlobals.h"
|
||||
|
||||
|
||||
static char *modeStrings[2] = {
|
||||
"abs",
|
||||
"rel",
|
||||
};
|
||||
|
||||
static char *kindStrings[3] = {
|
||||
"byte",
|
||||
"word",
|
||||
"dbyt",
|
||||
};
|
||||
|
||||
static char *pcrelStrings[2] = {
|
||||
" ",
|
||||
"pcrel",
|
||||
};
|
||||
|
||||
static char *externalStrings[2] = {
|
||||
" ",
|
||||
"extern",
|
||||
};
|
||||
|
||||
static char *symbolStrings[6] = {
|
||||
"und ", /* 0x00 */
|
||||
"und ext", /* 0x01 */
|
||||
"abs ", /* 0x02 */
|
||||
"abs ext", /* 0x03 */
|
||||
"rel ", /* 0x04 */
|
||||
"rel ext", /* 0x05 */
|
||||
};
|
||||
|
||||
void
|
||||
printCode(startAddress, endAddress, mode)
|
||||
int startAddress;
|
||||
int endAddress;
|
||||
int mode;
|
||||
{
|
||||
printf(" Code: 0x%04x:0x%04x %s\n", startAddress, endAddress,
|
||||
modeStrings[mode]);
|
||||
}
|
||||
|
||||
void
|
||||
printReference(reference)
|
||||
expressionReferenceType *reference;
|
||||
{
|
||||
printf(" Ref : 0x%04x (%s %s %s %s) expression #%d\n", reference->
|
||||
referenceAddress, modeStrings[reference->referenceMode],
|
||||
pcrelStrings[reference->referenceRelative], externalStrings[
|
||||
reference->referenceExternal], kindStrings[reference->
|
||||
referenceKind], reference->referenceExpression.inFile);
|
||||
}
|
||||
|
||||
void
|
||||
printReferenceFixup(reference)
|
||||
expressionReferenceType *reference;
|
||||
{
|
||||
printf(" Ref : 0x%04x (%s %s %s %s) expression=0x%x\n",
|
||||
reference->referenceAddress, modeStrings[reference->
|
||||
referenceMode],pcrelStrings[reference->referenceRelative],
|
||||
externalStrings[reference->referenceExternal], kindStrings[
|
||||
reference->referenceKind], reference->referenceExpression.
|
||||
inCore);
|
||||
}
|
||||
|
||||
void
|
||||
printSymbol(symbolTag, symbol)
|
||||
int symbolTag;
|
||||
symbolType *symbol;
|
||||
{
|
||||
printf(" Symb: %3d %s 0x%04x \"%s\"\n", symbolTag, symbolStrings[
|
||||
symbol->symbolClass], symbol->symbolValue,
|
||||
symbol->symbolName);
|
||||
}
|
||||
|
||||
void
|
||||
printLoadMapSymbol(symbol)
|
||||
symbolType *symbol;
|
||||
{
|
||||
fprintf(mapFileOutput, "%-20s 0x%04x %s ", symbol->symbolName,
|
||||
symbol->symbolValue, symbolStrings[symbol->symbolClass]);
|
||||
}
|
||||
|
||||
void
|
||||
printGlobalSymbols()
|
||||
{
|
||||
int symbolCount;
|
||||
|
||||
printf("Globals:\n");
|
||||
printf(" %d global symbols\n", globalSymbolCount);
|
||||
for (symbolCount=0; symbolCount<globalSymbolCount; symbolCount++) {
|
||||
printf(" Gsym: %3d \"%s\"\n", symbolCount,
|
||||
globalSymbolTable[symbolCount]->symbolName);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printExpression(expression, length)
|
||||
expressionPCType expression;
|
||||
int length;
|
||||
{
|
||||
int line;
|
||||
int i;
|
||||
|
||||
printf("expression length = %d:\n", length);
|
||||
for (line=0; line<length; line+=16) {
|
||||
printf(" %4x:", line);
|
||||
for (i=line; i<line+16 && i<length; i++)
|
||||
printf(" %2x", expression[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
BIN
slinky/debugPrint.o
Normal file
BIN
slinky/debugPrint.o
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user