Got intbasic.asm compiling

This commit is contained in:
Zellyn Hunter 2014-07-31 16:33:10 -07:00
parent 8f04a118ab
commit a9f4d9b8ff
9 changed files with 241 additions and 12 deletions

View File

@ -1,7 +0,0 @@
go run a2as.go --in ../../../goapple2/source/redbook/monitor.asm --out monitor.rom --flavor redbooka --listing monitor.lst --prefix=-1
go run a2as.go --in ../../../goapple2/source/redbook/miniasm.asm --out miniasm.rom --flavor redbooka --listing miniasm.lst --prefix=-1
go run a2as.go --in ../../../goapple2/source/redbook/sweet16.asm --out sweet16.rom --flavor redbooka --listing sweet16.lst --prefix=-1
go run a2as.go --in ../../../goapple2/source/redbook/fp.asm --out fp.rom --flavor redbookb --listing fp.lst --prefix=-1
go run a2as.go --in ../../../goapple2/source/redbook/misc-f699.asm --out misc-f699.rom --flavor redbooka --listing misc-f699.lst --prefix=0
# go run a2as.go --in ../../../goapple2/source/redbook/intbasic.asm --out intbasic.rom --flavor redbook --listing intbasic.lst --prefix=-1

View File

@ -44,6 +44,9 @@ func (a *Assembler) Load(filename string, prefix int) error {
if err != nil {
return err
}
// if line.Parse != nil {
// fmt.Fprintf("PLUGH: %s\n", line.Text())
// }
if done {
lineSources = lineSources[1:]
continue
@ -53,6 +56,11 @@ func (a *Assembler) Load(filename string, prefix int) error {
// we're in an inactive ifdef branch
continue
}
if err != nil {
return err
}
if err := in.FixLabels(a.Flavor); err != nil {
return err
}
@ -79,7 +87,7 @@ func (a *Assembler) Load(filename string, prefix int) error {
if !ok {
return in.Errorf(`unknown macro: "%s"`, in.Command)
}
subLs, err := m.LineSource(a.Flavor, in, macroCall)
subLs, err := m.LineSource(a.Flavor, in, macroCall, prefix)
if err != nil {
return in.Errorf(`error calling macro "%s": %v`, m.Name, err)
}
@ -170,6 +178,7 @@ func (a *Assembler) readMacro(in inst.I, ls lines.LineSource) error {
m.Locals[in2.Label] = true
}
if err == nil && in2.Type == inst.TypeMacroEnd {
m.Lines = append(m.Lines, line.Parse.Text())
a.Macros[m.Name] = m
a.Flavor.AddMacroName(m.Name)
return nil

View File

@ -81,7 +81,6 @@ func main() {
fmt.Fprintf(os.Stderr, "Error trying to determine prefix length for file '%s'", *infile, err)
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "Prefix guessed to be %d\n", p)
}
if err := a.AssembleWithPrefix(*infile, p); err != nil {

7
asm/cmd/a2as/runtest.sh Executable file
View File

@ -0,0 +1,7 @@
go run a2as.go --in ../../../../goapple2/source/redbook/monitor.asm --out monitor.rom --flavor redbooka --listing monitor.lst --prefix=-1
go run a2as.go --in ../../../../goapple2/source/redbook/miniasm.asm --out miniasm.rom --flavor redbooka --listing miniasm.lst --prefix=-1
go run a2as.go --in ../../../../goapple2/source/redbook/sweet16.asm --out sweet16.rom --flavor redbooka --listing sweet16.lst --prefix=-1
go run a2as.go --in ../../../../goapple2/source/redbook/fp.asm --out fp.rom --flavor redbookb --listing fp.lst --prefix=-1
go run a2as.go --in ../../../../goapple2/source/redbook/misc-f699.asm --out misc-f699.rom --flavor redbooka --listing misc-f699.lst --prefix=0
go run a2as.go --in ../../../../goapple2/source/redbook/intbasic.asm --out intbasic.rom --flavor merlin --listing intbasic.lst --prefix=-1

View File

@ -0,0 +1,180 @@
package main
import (
"bufio"
"fmt"
"os"
"regexp"
)
var re = regexp.MustCompile(`^([ ]*)([0-9]+)([ ]+)\*![ ]*(ENDIF|IF|LOOP|UNTIL|WHILE)(?: <(..)>)?$`)
type stackEntry struct {
command string
label string
lineNum int
endLabel string
}
var labelNum int
func makeLabel() string {
labelNum++
return fmt.Sprintf("LABEL%d", labelNum)
}
func printLine(space1, line, space2, label, text string) (int, error) {
return printLineN("5", space1, line, space2, label, text)
}
func printLine2(space1, line, space2, label, text string) (int, error) {
return printLineN("7", space1, line, space2, label, text)
}
func printLineN(units, space1, line, space2, label, text string) (int, error) {
out := fmt.Sprintf("%s%s%s%s", space1, line[:len(line)-1], units, space2)
if label != "" {
out = out + label
}
if text != "" {
out = out + " " + text
}
return fmt.Printf("%s\n", out)
}
func branch(test string) string {
switch test {
case "CC":
return "BCC"
case "CS":
return "BCS"
case "EQ":
return "BEQ"
case "HS":
return "BCS"
case "LO":
return "BCC"
case "MI":
return "BMI"
case "NE":
return "BNE"
case "PL":
return "BPL"
}
return "B??"
}
func branchOpposite(test string) string {
switch test {
case "CC":
return "BCS"
case "CS":
return "BCC"
case "EQ":
return "BNE"
case "HS":
return "BCC"
case "LO":
return "BCS"
case "MI":
return "BPL"
case "NE":
return "BEQ"
case "PL":
return "BMI"
}
return "B??"
}
func process(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
scanner := bufio.NewScanner(file)
var stack []stackEntry
lineNum := 0
for scanner.Scan() {
line := scanner.Text()
lineNum++
fmt.Println(line)
groups := re.FindStringSubmatch(line)
lastLabel := ""
if groups == nil {
lastLabel = ""
continue
}
space1, line, space2, command, test := groups[1], groups[2], groups[3], groups[4], groups[5]
_ = test
last := &stackEntry{command: "(none)"}
if len(stack) > 0 {
last = &stack[len(stack)-1]
}
switch command {
case "LOOP":
if lastLabel == "" {
lastLabel = makeLabel()
}
printLine(space1, line, space2, lastLabel, "")
stack = append(stack, stackEntry{command: command, label: lastLabel, lineNum: lineNum})
case "UNTIL":
if last.command != "LOOP" {
return fmt.Errorf("%d: %s found with no corresponding LOOP. Last command: %s/%d", lineNum, command, last.command, last.lineNum)
}
br := branchOpposite(test)
cmd := fmt.Sprintf("%s %s", br, last.label)
printLine(space1, line, space2, "", cmd)
// If we had a WHILE, we need an endlabel printed
if last.endLabel != "" {
printLine2(space1, line, space2, last.endLabel, "")
lastLabel = last.endLabel
}
stack = stack[:len(stack)-1]
case "WHILE":
if last.command != "LOOP" {
return fmt.Errorf("%d: %s found with no corresponding LOOP. Last command: %s/%d", lineNum, command, last.command, last.lineNum)
}
if last.endLabel == "" {
last.endLabel = makeLabel()
}
br := branchOpposite(test)
cmd := fmt.Sprintf("%s %s", br, last.endLabel)
printLine(space1, line, space2, "", cmd)
case "IF":
lastLabel = ""
label := makeLabel()
stack = append(stack, stackEntry{command: command, label: label, lineNum: lineNum})
cmd := fmt.Sprintf("%s %s", branchOpposite(test), label)
printLine(space1, line, space2, "", cmd)
case "ENDIF":
if last.command != "IF" {
return fmt.Errorf("%d: %s found with no corresponding IF. Last command: %s/%d", lineNum, command, last.command, last.lineNum)
}
printLine(space1, line, space2, last.label, "")
lastLabel = last.label
stack = stack[:len(stack)-1]
default:
return fmt.Errorf("%d: unknown command: %s", lineNum, command)
}
}
if err = scanner.Err(); err != nil {
return err
}
return nil
}
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: starbang <input file>\n")
os.Exit(1)
}
if err := process(os.Args[1]); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
}

View File

@ -45,6 +45,7 @@ func New() *Merlin {
"=": {inst.TypeEqu, m.ParseEquate, inst.EquNormal},
"HEX": {inst.TypeData, m.ParseHexString, inst.DataBytes},
"DFB": {inst.TypeData, m.ParseData, inst.DataBytes},
"DB": {inst.TypeData, m.ParseData, inst.DataBytes},
"DA": {inst.TypeData, m.ParseData, inst.DataWordsLe},
"DDB": {inst.TypeData, m.ParseData, inst.DataWordsBe},
"ASC": {inst.TypeData, m.ParseAscii, inst.DataAscii},

View File

@ -249,6 +249,43 @@ func TestMultiline(t *testing.T) {
" PMC M1($43;$44",
" M1 $44",
}, nil, "eae642d000eae643d000eae644d000ea", nil, true},
// Merlin: macros in other files
{mm, "macro in include", []string{
" ORG $E000",
" USE MACROS",
"PROMPT = $0033",
" INCW PROMPT",
" NOP",
}, map[string][]string{
"T.MACROS": {
"* Increment word",
"INCW MAC",
" INC ]1",
" BNE INCW_END",
" INC ]1+1",
"INCW_END EOM",
},
}, "e633d002e634ea", nil, true},
// Merlin: macros override the 3+1 zero-page rule
{mm, "macro vs zero page override", []string{
" USE MACROS",
"A1 = $0033",
"A2 = $0035",
" CMPW A1;A2",
" NOP",
}, map[string][]string{
"T.MACROS": {
"* Compare word",
"CMPW MAC",
" LDA ]1",
" CMP ]2",
" LDA ]1+1",
" SBC ]2+1",
" EOM",
},
}, "a533c535a534e536ea", nil, true},
}
for i, tt := range tests {

View File

@ -373,7 +373,10 @@ func (i *I) computeMustKnow(c context.Context, setWidth bool, final bool) (bool,
func (i *I) computeOp(c context.Context, setWidth bool, final bool) (bool, error) {
// If the width is not known, we better have a ZeroPage alternative.
if !i.WidthKnown && (i.ZeroOp == 0 || i.ZeroMode == 0) {
panic(fmt.Sprintf("Reached computeOp for '%s' with no ZeroPage alternative, i.Command"))
if i.Line.Context != nil && i.Line.Context.Parent != nil {
fmt.Println(i.Line.Context.Parent.Sprintf("foo"))
}
panic(i.Sprintf("Reached computeOp for '%s' with no ZeroPage alternative: %#v [%s]", i.Command, i, i.Line.Text()))
}
// An op with no args would be final already, so we must have an Expression.
if len(i.Exprs) == 0 {

View File

@ -13,7 +13,7 @@ type M struct {
Locals map[string]bool // labels that should be scoped to macro invocation
}
func (m M) LineSource(flavor flavors.F, in inst.I, macroCall int) (lines.LineSource, error) {
func (m M) LineSource(flavor flavors.F, in inst.I, macroCall int, prefix int) (lines.LineSource, error) {
var ls []string
context := lines.Context{Filename: "macro:" + m.Name, Parent: in.Line, MacroCall: macroCall, MacroLocals: m.Locals}
for _, line := range m.Lines {
@ -24,5 +24,5 @@ func (m M) LineSource(flavor flavors.F, in inst.I, macroCall int) (lines.LineSou
}
ls = append(ls, subbed)
}
return lines.NewSimpleLineSource(context, ls, 0), nil
return lines.NewSimpleLineSource(context, ls, prefix), nil
}