Use int64 for intermediate results internally

This commit is contained in:
Zellyn Hunter 2016-05-10 05:57:17 -04:00
parent f193a52183
commit 9c0bcea95d
7 changed files with 65 additions and 38 deletions

View File

@ -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 {

View File

@ -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:

View File

@ -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{

View File

@ -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
}

View File

@ -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
}

View File

@ -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"},

View File

@ -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