mirror of
https://github.com/zellyn/go6502.git
synced 2025-02-12 04:30:30 +00:00
Use int64 for intermediate results internally
This commit is contained in:
parent
f193a52183
commit
9c0bcea95d
@ -3,8 +3,8 @@ package context
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type Context interface {
|
type Context interface {
|
||||||
Set(name string, value uint16)
|
Set(name string, value int64)
|
||||||
Get(name string) (uint16, bool)
|
Get(name string) (int64, bool)
|
||||||
SetAddr(uint16)
|
SetAddr(uint16)
|
||||||
GetAddr() uint16
|
GetAddr() uint16
|
||||||
DivZero() *uint16
|
DivZero() *uint16
|
||||||
@ -44,7 +44,7 @@ type SimpleContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type symbolValue struct {
|
type symbolValue struct {
|
||||||
v uint16
|
v int64
|
||||||
changed bool // Did the value ever change?
|
changed bool // Did the value ever change?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,9 +54,9 @@ func (sc *SimpleContext) fix() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *SimpleContext) Get(name string) (uint16, bool) {
|
func (sc *SimpleContext) Get(name string) (int64, bool) {
|
||||||
if name == "*" {
|
if name == "*" {
|
||||||
return sc.GetAddr(), true
|
return int64(sc.GetAddr()), true
|
||||||
}
|
}
|
||||||
sc.fix()
|
sc.fix()
|
||||||
s, found := sc.symbols[name]
|
s, found := sc.symbols[name]
|
||||||
@ -71,7 +71,7 @@ func (sc *SimpleContext) GetAddr() uint16 {
|
|||||||
return sc.addr
|
return sc.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *SimpleContext) Set(name string, value uint16) {
|
func (sc *SimpleContext) Set(name string, value int64) {
|
||||||
sc.fix()
|
sc.fix()
|
||||||
s, found := sc.symbols[name]
|
s, found := sc.symbols[name]
|
||||||
if found && s.v != value {
|
if found && s.v != value {
|
||||||
|
@ -57,7 +57,7 @@ type E struct {
|
|||||||
Right *E
|
Right *E
|
||||||
Op Operator
|
Op Operator
|
||||||
Text string
|
Text string
|
||||||
Val uint16
|
Val int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e E) String() string {
|
func (e E) String() string {
|
||||||
@ -106,7 +106,7 @@ func (e *E) Width() uint16 {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *E) Eval(ctx context.Context, ln *lines.Line) (uint16, error) {
|
func (e *E) Eval(ctx context.Context, ln *lines.Line) (int64, error) {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return 0, errors.New("cannot Eval() nil expression")
|
return 0, errors.New("cannot Eval() nil expression")
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ func (e *E) Eval(ctx context.Context, ln *lines.Line) (uint16, error) {
|
|||||||
if z == nil {
|
if z == nil {
|
||||||
return 0, ln.Errorf("divizion by zero")
|
return 0, ln.Errorf("divizion by zero")
|
||||||
}
|
}
|
||||||
return *z, nil
|
return int64(*z), nil
|
||||||
}
|
}
|
||||||
return l / r, nil
|
return l / r, nil
|
||||||
case OpAnd:
|
case OpAnd:
|
||||||
@ -194,7 +194,7 @@ func (e *E) Eval(ctx context.Context, ln *lines.Line) (uint16, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckedEval calls Eval, but also turns UnknownLabelErrors into labelMissing booleans.
|
// CheckedEval calls Eval, but also turns UnknownLabelErrors into labelMissing booleans.
|
||||||
func (e *E) CheckedEval(ctx context.Context, ln *lines.Line) (val uint16, labelMissing bool, err error) {
|
func (e *E) CheckedEval(ctx context.Context, ln *lines.Line) (val int64, labelMissing bool, err error) {
|
||||||
val, err = e.Eval(ctx, ln)
|
val, err = e.Eval(ctx, ln)
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
|
@ -37,17 +37,24 @@ func New(sets opcodes.Set) *As65 {
|
|||||||
"EQU": {inst.TypeEqu, a.ParseEquate, inst.VarEquNormal},
|
"EQU": {inst.TypeEqu, a.ParseEquate, inst.VarEquNormal},
|
||||||
"EPZ": {inst.TypeEqu, a.ParseEquate, inst.VarEquPageZero},
|
"EPZ": {inst.TypeEqu, a.ParseEquate, inst.VarEquPageZero},
|
||||||
"DFB": {inst.TypeData, a.ParseData, inst.VarBytes},
|
"DFB": {inst.TypeData, a.ParseData, inst.VarBytes},
|
||||||
"DW": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
|
||||||
"DDB": {inst.TypeData, a.ParseData, inst.VarWordsBe},
|
"ds": {inst.TypeData, a.ParseData, inst.VarBytesZero},
|
||||||
"ASC": {inst.TypeData, a.ParseAscii, inst.VarAscii},
|
"rmb": {inst.TypeData, a.ParseData, inst.VarBytesZero},
|
||||||
"DCI": {inst.TypeData, a.ParseAscii, inst.VarAsciiFlip},
|
|
||||||
"HEX": {inst.TypeData, a.ParseHexString, inst.VarBytes},
|
"dw": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||||
"PAGE": {inst.TypeNone, nil, 0}, // New page
|
"fcw": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||||
"TITLE": {inst.TypeNone, nil, 0}, // Title
|
"fdb": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||||
"SBTL": {inst.TypeNone, nil, 0}, // Subtitle
|
|
||||||
"SKP": {inst.TypeNone, nil, 0}, // Skip lines
|
"DDB": {inst.TypeData, a.ParseData, inst.VarWordsBe},
|
||||||
"REP": {inst.TypeNone, nil, 0}, // Repeat character
|
"ASC": {inst.TypeData, a.ParseAscii, inst.VarAscii},
|
||||||
"CHR": {inst.TypeNone, nil, 0}, // Set repeated character
|
"DCI": {inst.TypeData, a.ParseAscii, inst.VarAsciiFlip},
|
||||||
|
"HEX": {inst.TypeData, a.ParseHexString, inst.VarBytes},
|
||||||
|
"PAGE": {inst.TypeNone, nil, 0}, // New page
|
||||||
|
"TITLE": {inst.TypeNone, nil, 0}, // Title
|
||||||
|
"SBTL": {inst.TypeNone, nil, 0}, // Subtitle
|
||||||
|
"SKP": {inst.TypeNone, nil, 0}, // Skip lines
|
||||||
|
"REP": {inst.TypeNone, nil, 0}, // Repeat character
|
||||||
|
"CHR": {inst.TypeNone, nil, 0}, // Set repeated character
|
||||||
}
|
}
|
||||||
|
|
||||||
a.EquateDirectives = map[string]bool{
|
a.EquateDirectives = map[string]bool{
|
||||||
|
@ -166,10 +166,10 @@ func (a *Base) handleLabel(ctx context.Context, in inst.I) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lval, lok := ctx.Get(in.Label)
|
lval, lok := ctx.Get(in.Label)
|
||||||
if lok && addr != lval {
|
if lok && int64(addr) != lval {
|
||||||
return in.Errorf("Trying to set label '%s' to $%04x, but it already has value $%04x", in.Label, addr, lval)
|
return in.Errorf("Trying to set label '%s' to $%04x, but it already has value $%04x", in.Label, addr, lval)
|
||||||
}
|
}
|
||||||
ctx.Set(in.Label, addr)
|
ctx.Set(in.Label, int64(addr))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +432,7 @@ func (a *Base) ParseOrg(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I
|
|||||||
}
|
}
|
||||||
in.Width = 0
|
in.Width = 0
|
||||||
in.Final = true
|
in.Final = true
|
||||||
in.Addr = val
|
in.Addr = uint16(val)
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +488,7 @@ func (a *Base) ParseBlockStorage(ctx context.Context, in inst.I, lp *lines.Parse
|
|||||||
}
|
}
|
||||||
|
|
||||||
in.Final = true
|
in.Final = true
|
||||||
in.Width = val
|
in.Width = uint16(val)
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,6 +554,22 @@ func (a *Base) ParseData(ctx context.Context, in inst.I, lp *lines.Parse) (inst.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case inst.VarBytesZero:
|
||||||
|
in.Final = true
|
||||||
|
if len(in.Exprs) != 1 {
|
||||||
|
return in, in.Errorf("%v expected one expression (length); got %d", in.Command, len(in.Exprs))
|
||||||
|
}
|
||||||
|
val, err := in.Exprs[0].Eval(ctx, in.Line)
|
||||||
|
if err != nil {
|
||||||
|
in.Final = false
|
||||||
|
in.Data = nil
|
||||||
|
} else {
|
||||||
|
in.Final = true
|
||||||
|
in.Width = uint16(val)
|
||||||
|
for i := int(val); i > 0; i-- {
|
||||||
|
in.Data = append(in.Data, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return in, in.Errorf("Unknown Var(%d) with ParseData for %s", in.Var, in.Command)
|
return in, in.Errorf("Unknown Var(%d) with ParseData for %s", in.Var, in.Command)
|
||||||
}
|
}
|
||||||
@ -738,12 +754,12 @@ func (a *Base) ParseTerm(ctx context.Context, in inst.I, lp *lines.Parse) (*expr
|
|||||||
return &expr.E{}, in.Errorf("expecting hex number, found '%c' (%d)", c, c)
|
return &expr.E{}, in.Errorf("expecting hex number, found '%c' (%d)", c, c)
|
||||||
}
|
}
|
||||||
s := lp.Emit()
|
s := lp.Emit()
|
||||||
i, err := strconv.ParseUint(s, 16, 16)
|
i, err := strconv.ParseInt(s, 16, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &expr.E{}, in.Errorf("invalid hex number: %s: %s", s, err)
|
return &expr.E{}, in.Errorf("invalid hex number: %s: %s", s, err)
|
||||||
}
|
}
|
||||||
ex.Op = expr.OpLeaf
|
ex.Op = expr.OpLeaf
|
||||||
ex.Val = uint16(i)
|
ex.Val = i
|
||||||
return top, nil
|
return top, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,24 +770,24 @@ func (a *Base) ParseTerm(ctx context.Context, in inst.I, lp *lines.Parse) (*expr
|
|||||||
return &expr.E{}, in.Errorf("expecting binary number, found '%c' (%d)", c, c)
|
return &expr.E{}, in.Errorf("expecting binary number, found '%c' (%d)", c, c)
|
||||||
}
|
}
|
||||||
s := lp.Emit()
|
s := lp.Emit()
|
||||||
i, err := strconv.ParseUint(s, 2, 16)
|
i, err := strconv.ParseInt(s, 2, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &expr.E{}, in.Errorf("invalid binary number: %s: %s", s, err)
|
return &expr.E{}, in.Errorf("invalid binary number: %s: %s", s, err)
|
||||||
}
|
}
|
||||||
ex.Op = expr.OpLeaf
|
ex.Op = expr.OpLeaf
|
||||||
ex.Val = uint16(i)
|
ex.Val = i
|
||||||
return top, nil
|
return top, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decimal
|
// Decimal
|
||||||
if lp.AcceptRun(Digits) {
|
if lp.AcceptRun(Digits) {
|
||||||
s := lp.Emit()
|
s := lp.Emit()
|
||||||
i, err := strconv.ParseUint(s, 10, 16)
|
i, err := strconv.ParseInt(s, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &expr.E{}, in.Errorf("invalid number: %s: %s", s, err)
|
return &expr.E{}, in.Errorf("invalid number: %s: %s", s, err)
|
||||||
}
|
}
|
||||||
ex.Op = expr.OpLeaf
|
ex.Op = expr.OpLeaf
|
||||||
ex.Val = uint16(i)
|
ex.Val = i
|
||||||
return top, nil
|
return top, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,7 +800,7 @@ func (a *Base) ParseTerm(ctx context.Context, in inst.I, lp *lines.Parse) (*expr
|
|||||||
return &expr.E{}, in.Errorf("end of line after quote")
|
return &expr.E{}, in.Errorf("end of line after quote")
|
||||||
}
|
}
|
||||||
ex.Op = expr.OpLeaf
|
ex.Op = expr.OpLeaf
|
||||||
ex.Val = uint16(c)
|
ex.Val = int64(c)
|
||||||
if strings.Contains(a.InvCharChars, quote[:1]) {
|
if strings.Contains(a.InvCharChars, quote[:1]) {
|
||||||
ex.Val |= 0x80
|
ex.Val |= 0x80
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
|
|||||||
in.Width = 2
|
in.Width = 2
|
||||||
in.Var = inst.VarOpBranch
|
in.Var = inst.VarOpBranch
|
||||||
if valKnown {
|
if valKnown {
|
||||||
b, err := RelativeAddr(c, in, val)
|
b, err := RelativeAddr(c, in, uint16(val))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return in, err
|
return in, err
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ func TestSimpleCommonFunctions(t *testing.T) {
|
|||||||
{aa, " beq $2343", "{beq $2343}", "f0fc"},
|
{aa, " beq $2343", "{beq $2343}", "f0fc"},
|
||||||
{aa, " beq $2345", "{beq $2345}", "f0fe"},
|
{aa, " beq $2345", "{beq $2345}", "f0fe"},
|
||||||
{aa, " beq $2347", "{beq $2347}", "f000"},
|
{aa, " beq $2347", "{beq $2347}", "f000"},
|
||||||
// {aa, " dw $1234", "{data/wle $1234}", "3412"},
|
{aa, " dw $1234", "{data/wle $1234}", "3412"},
|
||||||
|
{aa, " ds 5", "{data/bz $0005}", "0000000000"},
|
||||||
{aa, " jmp $1234", "{jmp/abs $1234}", "4c3412"},
|
{aa, " jmp $1234", "{jmp/abs $1234}", "4c3412"},
|
||||||
{aa, " jmp ($1234)", "{jmp/ind $1234}", "6c3412"},
|
{aa, " jmp ($1234)", "{jmp/ind $1234}", "6c3412"},
|
||||||
{aa, " lda #$12", "{lda/imm (lsb $0012)}", "a912"},
|
{aa, " lda #$12", "{lda/imm (lsb $0012)}", "a912"},
|
||||||
|
@ -45,6 +45,7 @@ const (
|
|||||||
VarMixed // Bytes or words (LE), depending on individual expression widths
|
VarMixed // Bytes or words (LE), depending on individual expression widths
|
||||||
VarWordsLe // Data: expressions, but forced to one word per, little-endian
|
VarWordsLe // Data: expressions, but forced to one word per, little-endian
|
||||||
VarWordsBe // Data: expressions, but forced to one word per, big-endian
|
VarWordsBe // Data: expressions, but forced to one word per, big-endian
|
||||||
|
VarBytesZero // Data: a run of zeros
|
||||||
VarAscii // Data: from ASCII strings, high bit clear
|
VarAscii // Data: from ASCII strings, high bit clear
|
||||||
VarAsciiFlip // Data: from ASCII strings, high bit clear, except last char
|
VarAsciiFlip // Data: from ASCII strings, high bit clear, except last char
|
||||||
VarAsciiHi // Data: from ASCII strings, high bit set
|
VarAsciiHi // Data: from ASCII strings, high bit set
|
||||||
@ -68,7 +69,7 @@ type I struct {
|
|||||||
Width uint16 // width in bytes
|
Width uint16 // width in bytes
|
||||||
Final bool // Do we know the actual bytes yet?
|
Final bool // Do we know the actual bytes yet?
|
||||||
Op byte // Opcode
|
Op byte // Opcode
|
||||||
Value uint16 // For Equates, the value
|
Value int64 // For Equates, the value
|
||||||
DeclaredLine uint16 // Line number listed in file
|
DeclaredLine uint16 // Line number listed in file
|
||||||
Line *lines.Line // Line object for this line
|
Line *lines.Line // Line object for this line
|
||||||
Addr uint16 // Current memory address
|
Addr uint16 // Current memory address
|
||||||
@ -103,6 +104,8 @@ func (i I) TypeString() string {
|
|||||||
return "data"
|
return "data"
|
||||||
case VarBytes:
|
case VarBytes:
|
||||||
return "data/b"
|
return "data/b"
|
||||||
|
case VarBytesZero:
|
||||||
|
return "data/bz"
|
||||||
case VarWordsLe:
|
case VarWordsLe:
|
||||||
return "data/wle"
|
return "data/wle"
|
||||||
case VarWordsBe:
|
case VarWordsBe:
|
||||||
@ -235,7 +238,7 @@ func (i *I) computeBlock(c context.Context, final bool) (bool, error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
i.Value = val
|
i.Value = val
|
||||||
i.Final = true
|
i.Final = true
|
||||||
i.Width = val
|
i.Width = uint16(val)
|
||||||
} else {
|
} else {
|
||||||
if final {
|
if final {
|
||||||
return false, i.Errorf("block storage with unknown size")
|
return false, i.Errorf("block storage with unknown size")
|
||||||
@ -254,7 +257,7 @@ func (i *I) computeMustKnow(c context.Context) error {
|
|||||||
case TypeTarget:
|
case TypeTarget:
|
||||||
return errors.New("Target not implemented yet.")
|
return errors.New("Target not implemented yet.")
|
||||||
case TypeOrg:
|
case TypeOrg:
|
||||||
c.SetAddr(val)
|
c.SetAddr(uint16(val))
|
||||||
case TypeEqu:
|
case TypeEqu:
|
||||||
c.Set(i.Label, val)
|
c.Set(i.Label, val)
|
||||||
// Don't handle labels.
|
// Don't handle labels.
|
||||||
@ -286,7 +289,7 @@ func (i *I) computeOp(c context.Context) error {
|
|||||||
if offset < -128 {
|
if offset < -128 {
|
||||||
return i.Errorf("%s cannot jump back %d (max -128) from $%04x to $%04x", i.Command, offset, curr+2, val)
|
return i.Errorf("%s cannot jump back %d (max -128) from $%04x to $%04x", i.Command, offset, curr+2, val)
|
||||||
}
|
}
|
||||||
val = uint16(offset)
|
val = int64(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.Final = true
|
i.Final = true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user