mirror of
https://github.com/zellyn/go6502.git
synced 2025-02-07 02:30:38 +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"
|
||||
|
||||
type Context interface {
|
||||
Set(name string, value uint16)
|
||||
Get(name string) (uint16, bool)
|
||||
Set(name string, value int64)
|
||||
Get(name string) (int64, bool)
|
||||
SetAddr(uint16)
|
||||
GetAddr() uint16
|
||||
DivZero() *uint16
|
||||
@ -44,7 +44,7 @@ type SimpleContext struct {
|
||||
}
|
||||
|
||||
type symbolValue struct {
|
||||
v uint16
|
||||
v int64
|
||||
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 == "*" {
|
||||
return sc.GetAddr(), true
|
||||
return int64(sc.GetAddr()), true
|
||||
}
|
||||
sc.fix()
|
||||
s, found := sc.symbols[name]
|
||||
@ -71,7 +71,7 @@ func (sc *SimpleContext) GetAddr() uint16 {
|
||||
return sc.addr
|
||||
}
|
||||
|
||||
func (sc *SimpleContext) Set(name string, value uint16) {
|
||||
func (sc *SimpleContext) Set(name string, value int64) {
|
||||
sc.fix()
|
||||
s, found := sc.symbols[name]
|
||||
if found && s.v != value {
|
||||
|
@ -57,7 +57,7 @@ type E struct {
|
||||
Right *E
|
||||
Op Operator
|
||||
Text string
|
||||
Val uint16
|
||||
Val int64
|
||||
}
|
||||
|
||||
func (e E) String() string {
|
||||
@ -106,7 +106,7 @@ func (e *E) Width() uint16 {
|
||||
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 {
|
||||
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 {
|
||||
return 0, ln.Errorf("divizion by zero")
|
||||
}
|
||||
return *z, nil
|
||||
return int64(*z), nil
|
||||
}
|
||||
return l / r, nil
|
||||
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.
|
||||
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)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
|
@ -37,17 +37,24 @@ func New(sets opcodes.Set) *As65 {
|
||||
"EQU": {inst.TypeEqu, a.ParseEquate, inst.VarEquNormal},
|
||||
"EPZ": {inst.TypeEqu, a.ParseEquate, inst.VarEquPageZero},
|
||||
"DFB": {inst.TypeData, a.ParseData, inst.VarBytes},
|
||||
"DW": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||
"DDB": {inst.TypeData, a.ParseData, inst.VarWordsBe},
|
||||
"ASC": {inst.TypeData, a.ParseAscii, inst.VarAscii},
|
||||
"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
|
||||
|
||||
"ds": {inst.TypeData, a.ParseData, inst.VarBytesZero},
|
||||
"rmb": {inst.TypeData, a.ParseData, inst.VarBytesZero},
|
||||
|
||||
"dw": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||
"fcw": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||
"fdb": {inst.TypeData, a.ParseData, inst.VarWordsLe},
|
||||
|
||||
"DDB": {inst.TypeData, a.ParseData, inst.VarWordsBe},
|
||||
"ASC": {inst.TypeData, a.ParseAscii, inst.VarAscii},
|
||||
"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{
|
||||
|
@ -166,10 +166,10 @@ func (a *Base) handleLabel(ctx context.Context, in inst.I) error {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
ctx.Set(in.Label, addr)
|
||||
ctx.Set(in.Label, int64(addr))
|
||||
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.Final = true
|
||||
in.Addr = val
|
||||
in.Addr = uint16(val)
|
||||
return in, nil
|
||||
}
|
||||
|
||||
@ -488,7 +488,7 @@ func (a *Base) ParseBlockStorage(ctx context.Context, in inst.I, lp *lines.Parse
|
||||
}
|
||||
|
||||
in.Final = true
|
||||
in.Width = val
|
||||
in.Width = uint16(val)
|
||||
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:
|
||||
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)
|
||||
}
|
||||
s := lp.Emit()
|
||||
i, err := strconv.ParseUint(s, 16, 16)
|
||||
i, err := strconv.ParseInt(s, 16, 64)
|
||||
if err != nil {
|
||||
return &expr.E{}, in.Errorf("invalid hex number: %s: %s", s, err)
|
||||
}
|
||||
ex.Op = expr.OpLeaf
|
||||
ex.Val = uint16(i)
|
||||
ex.Val = i
|
||||
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)
|
||||
}
|
||||
s := lp.Emit()
|
||||
i, err := strconv.ParseUint(s, 2, 16)
|
||||
i, err := strconv.ParseInt(s, 2, 64)
|
||||
if err != nil {
|
||||
return &expr.E{}, in.Errorf("invalid binary number: %s: %s", s, err)
|
||||
}
|
||||
ex.Op = expr.OpLeaf
|
||||
ex.Val = uint16(i)
|
||||
ex.Val = i
|
||||
return top, nil
|
||||
}
|
||||
|
||||
// Decimal
|
||||
if lp.AcceptRun(Digits) {
|
||||
s := lp.Emit()
|
||||
i, err := strconv.ParseUint(s, 10, 16)
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return &expr.E{}, in.Errorf("invalid number: %s: %s", s, err)
|
||||
}
|
||||
ex.Op = expr.OpLeaf
|
||||
ex.Val = uint16(i)
|
||||
ex.Val = i
|
||||
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")
|
||||
}
|
||||
ex.Op = expr.OpLeaf
|
||||
ex.Val = uint16(c)
|
||||
ex.Val = int64(c)
|
||||
if strings.Contains(a.InvCharChars, quote[:1]) {
|
||||
ex.Val |= 0x80
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
|
||||
in.Width = 2
|
||||
in.Var = inst.VarOpBranch
|
||||
if valKnown {
|
||||
b, err := RelativeAddr(c, in, val)
|
||||
b, err := RelativeAddr(c, in, uint16(val))
|
||||
if err != nil {
|
||||
return in, err
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ func TestSimpleCommonFunctions(t *testing.T) {
|
||||
{aa, " beq $2343", "{beq $2343}", "f0fc"},
|
||||
{aa, " beq $2345", "{beq $2345}", "f0fe"},
|
||||
{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/ind $1234}", "6c3412"},
|
||||
{aa, " lda #$12", "{lda/imm (lsb $0012)}", "a912"},
|
||||
|
@ -45,6 +45,7 @@ const (
|
||||
VarMixed // Bytes or words (LE), depending on individual expression widths
|
||||
VarWordsLe // Data: expressions, but forced to one word per, little-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
|
||||
VarAsciiFlip // Data: from ASCII strings, high bit clear, except last char
|
||||
VarAsciiHi // Data: from ASCII strings, high bit set
|
||||
@ -68,7 +69,7 @@ type I struct {
|
||||
Width uint16 // width in bytes
|
||||
Final bool // Do we know the actual bytes yet?
|
||||
Op byte // Opcode
|
||||
Value uint16 // For Equates, the value
|
||||
Value int64 // For Equates, the value
|
||||
DeclaredLine uint16 // Line number listed in file
|
||||
Line *lines.Line // Line object for this line
|
||||
Addr uint16 // Current memory address
|
||||
@ -103,6 +104,8 @@ func (i I) TypeString() string {
|
||||
return "data"
|
||||
case VarBytes:
|
||||
return "data/b"
|
||||
case VarBytesZero:
|
||||
return "data/bz"
|
||||
case VarWordsLe:
|
||||
return "data/wle"
|
||||
case VarWordsBe:
|
||||
@ -235,7 +238,7 @@ func (i *I) computeBlock(c context.Context, final bool) (bool, error) {
|
||||
if err == nil {
|
||||
i.Value = val
|
||||
i.Final = true
|
||||
i.Width = val
|
||||
i.Width = uint16(val)
|
||||
} else {
|
||||
if final {
|
||||
return false, i.Errorf("block storage with unknown size")
|
||||
@ -254,7 +257,7 @@ func (i *I) computeMustKnow(c context.Context) error {
|
||||
case TypeTarget:
|
||||
return errors.New("Target not implemented yet.")
|
||||
case TypeOrg:
|
||||
c.SetAddr(val)
|
||||
c.SetAddr(uint16(val))
|
||||
case TypeEqu:
|
||||
c.Set(i.Label, val)
|
||||
// Don't handle labels.
|
||||
@ -286,7 +289,7 @@ func (i *I) computeOp(c context.Context) error {
|
||||
if offset < -128 {
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user