109 lines
2.1 KiB
Go
109 lines
2.1 KiB
Go
package optimizer
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// parseHexOrDec parses an ACME-style number: $ff or 255.
|
|
// Returns -1 if s is not a parseable simple number (e.g. label references, <label, >label).
|
|
func parseHexOrDec(s string) int {
|
|
if strings.HasPrefix(s, "$") {
|
|
v, err := strconv.ParseInt(s[1:], 16, 16)
|
|
if err != nil {
|
|
return -1
|
|
}
|
|
return int(v)
|
|
}
|
|
// Strip trailing characters after the number (e.g., ",y" in "5,y")
|
|
if idx := strings.IndexAny(s, ",)"); idx >= 0 {
|
|
s = s[:idx]
|
|
}
|
|
v, err := strconv.ParseInt(s, 10, 16)
|
|
if err != nil {
|
|
return -1
|
|
}
|
|
return int(v)
|
|
}
|
|
|
|
// isSimpleNumber returns true if s is a plain hex/dec number (no label refs, <, >, etc.)
|
|
func isSimpleNumber(s string) bool {
|
|
return parseHexOrDec(s) >= 0
|
|
}
|
|
|
|
type asmLine struct {
|
|
text string
|
|
isLabel bool
|
|
isCode bool
|
|
isComment bool
|
|
optMarker bool
|
|
opcode string
|
|
operand string
|
|
}
|
|
|
|
func parseLines(lines []string) []asmLine {
|
|
var result []asmLine
|
|
for _, l := range lines {
|
|
al := asmLine{text: l}
|
|
|
|
if l == "" {
|
|
result = append(result, al)
|
|
continue
|
|
}
|
|
|
|
if strings.HasPrefix(l, "; @@OPT:") {
|
|
al.optMarker = true
|
|
al.isComment = true
|
|
result = append(result, al)
|
|
continue
|
|
}
|
|
|
|
if strings.HasPrefix(l, ";") {
|
|
al.isComment = true
|
|
result = append(result, al)
|
|
continue
|
|
}
|
|
|
|
if l[0] == '\t' {
|
|
al.isCode = true
|
|
parts := strings.Fields(l)
|
|
if len(parts) > 0 {
|
|
al.opcode = strings.ToLower(parts[0])
|
|
}
|
|
if len(parts) > 1 {
|
|
al.operand = parts[1]
|
|
}
|
|
} else {
|
|
al.isLabel = true
|
|
}
|
|
|
|
result = append(result, al)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// stripOptMarkers removes @@OPT comment lines from the output
|
|
func stripOptMarkers(lines []asmLine) []asmLine {
|
|
var result []asmLine
|
|
for _, l := range lines {
|
|
if l.optMarker {
|
|
continue
|
|
}
|
|
result = append(result, l)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func linesToString(lines []asmLine) []string {
|
|
var result []string
|
|
for _, l := range lines {
|
|
result = append(result, l.text)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// skipJmpMarker returns true if the line is an @@OPT comment (to be skipped in pass logic)
|
|
func skipJmpMarker(line asmLine) bool {
|
|
return line.optMarker
|
|
}
|
|
|