mirror of
https://github.com/zellyn/go6502.git
synced 2025-02-10 21:30:42 +00:00
Got intbasic.asm compiling
This commit is contained in:
parent
8f04a118ab
commit
a9f4d9b8ff
@ -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
|
|
||||||
|
|
11
asm/asm.go
11
asm/asm.go
@ -44,6 +44,9 @@ func (a *Assembler) Load(filename string, prefix int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// if line.Parse != nil {
|
||||||
|
// fmt.Fprintf("PLUGH: %s\n", line.Text())
|
||||||
|
// }
|
||||||
if done {
|
if done {
|
||||||
lineSources = lineSources[1:]
|
lineSources = lineSources[1:]
|
||||||
continue
|
continue
|
||||||
@ -53,6 +56,11 @@ func (a *Assembler) Load(filename string, prefix int) error {
|
|||||||
// we're in an inactive ifdef branch
|
// we're in an inactive ifdef branch
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := in.FixLabels(a.Flavor); err != nil {
|
if err := in.FixLabels(a.Flavor); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -79,7 +87,7 @@ func (a *Assembler) Load(filename string, prefix int) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return in.Errorf(`unknown macro: "%s"`, in.Command)
|
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 {
|
if err != nil {
|
||||||
return in.Errorf(`error calling macro "%s": %v`, m.Name, err)
|
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
|
m.Locals[in2.Label] = true
|
||||||
}
|
}
|
||||||
if err == nil && in2.Type == inst.TypeMacroEnd {
|
if err == nil && in2.Type == inst.TypeMacroEnd {
|
||||||
|
m.Lines = append(m.Lines, line.Parse.Text())
|
||||||
a.Macros[m.Name] = m
|
a.Macros[m.Name] = m
|
||||||
a.Flavor.AddMacroName(m.Name)
|
a.Flavor.AddMacroName(m.Name)
|
||||||
return nil
|
return nil
|
||||||
|
@ -81,7 +81,6 @@ func main() {
|
|||||||
fmt.Fprintf(os.Stderr, "Error trying to determine prefix length for file '%s'", *infile, err)
|
fmt.Fprintf(os.Stderr, "Error trying to determine prefix length for file '%s'", *infile, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "Prefix guessed to be %d\n", p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.AssembleWithPrefix(*infile, p); err != nil {
|
if err := a.AssembleWithPrefix(*infile, p); err != nil {
|
7
asm/cmd/a2as/runtest.sh
Executable file
7
asm/cmd/a2as/runtest.sh
Executable 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
|
||||||
|
|
180
asm/cmd/starbang/starbang.go
Normal file
180
asm/cmd/starbang/starbang.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,7 @@ func New() *Merlin {
|
|||||||
"=": {inst.TypeEqu, m.ParseEquate, inst.EquNormal},
|
"=": {inst.TypeEqu, m.ParseEquate, inst.EquNormal},
|
||||||
"HEX": {inst.TypeData, m.ParseHexString, inst.DataBytes},
|
"HEX": {inst.TypeData, m.ParseHexString, inst.DataBytes},
|
||||||
"DFB": {inst.TypeData, m.ParseData, inst.DataBytes},
|
"DFB": {inst.TypeData, m.ParseData, inst.DataBytes},
|
||||||
|
"DB": {inst.TypeData, m.ParseData, inst.DataBytes},
|
||||||
"DA": {inst.TypeData, m.ParseData, inst.DataWordsLe},
|
"DA": {inst.TypeData, m.ParseData, inst.DataWordsLe},
|
||||||
"DDB": {inst.TypeData, m.ParseData, inst.DataWordsBe},
|
"DDB": {inst.TypeData, m.ParseData, inst.DataWordsBe},
|
||||||
"ASC": {inst.TypeData, m.ParseAscii, inst.DataAscii},
|
"ASC": {inst.TypeData, m.ParseAscii, inst.DataAscii},
|
||||||
|
@ -249,6 +249,43 @@ func TestMultiline(t *testing.T) {
|
|||||||
" PMC M1($43;$44",
|
" PMC M1($43;$44",
|
||||||
" M1 $44",
|
" M1 $44",
|
||||||
}, nil, "eae642d000eae643d000eae644d000ea", nil, true},
|
}, 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 {
|
for i, tt := range tests {
|
||||||
|
@ -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) {
|
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 the width is not known, we better have a ZeroPage alternative.
|
||||||
if !i.WidthKnown && (i.ZeroOp == 0 || i.ZeroMode == 0) {
|
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.
|
// An op with no args would be final already, so we must have an Expression.
|
||||||
if len(i.Exprs) == 0 {
|
if len(i.Exprs) == 0 {
|
||||||
|
@ -13,7 +13,7 @@ type M struct {
|
|||||||
Locals map[string]bool // labels that should be scoped to macro invocation
|
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
|
var ls []string
|
||||||
context := lines.Context{Filename: "macro:" + m.Name, Parent: in.Line, MacroCall: macroCall, MacroLocals: m.Locals}
|
context := lines.Context{Filename: "macro:" + m.Name, Parent: in.Line, MacroCall: macroCall, MacroLocals: m.Locals}
|
||||||
for _, line := range m.Lines {
|
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)
|
ls = append(ls, subbed)
|
||||||
}
|
}
|
||||||
return lines.NewSimpleLineSource(context, ls, 0), nil
|
return lines.NewSimpleLineSource(context, ls, prefix), nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user