Gopher2600/hardware/cpu/register/register.go
steve eb17bc1f63 o registers
- replaced both register implementations with just one that uses
    32 bit integers as the underlying implementation. very smart and
    very quick by comparison to the bit array implementation.
2020-01-05 18:58:26 +00:00

295 lines
6.6 KiB
Go

package register
import (
"fmt"
"reflect"
)
// Register is an array of of type bit, used for register representation
type Register struct {
value uint32
size uint
label string
signBit uint32
vbit uint32
mask uint32
hexformat string
binformat string
}
// NewRegister is the preferred method of initialisation for Register
func NewRegister(value interface{}, size int, label string) (*Register, error) {
if size != 8 && size != 16 {
return nil, fmt.Errorf("unsupport bit size (%d)", size)
}
r := new(Register)
switch value := value.(type) {
case *Register:
r.value = value.value
case int:
r.value = uint32(value)
case uint8:
r.value = uint32(value)
case uint16:
r.value = uint32(value)
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(value)))
}
r.size = uint(size)
r.label = label
if size == 8 {
r.signBit = 0x00000080
r.vbit = 0x00000040
r.mask = 0x000000FF
r.hexformat = "0x%02x"
r.binformat = "%08b"
} else if size == 16 {
r.signBit = 0x00008000
r.vbit = 0x00004000
r.mask = 0x0000FFFF
r.hexformat = "0x%04x"
r.binformat = "%016b"
}
return r, nil
}
// Size returns the number of bits in register
func (r Register) Size() int {
return 8
}
// Label returns the label assigned to the register
func (r Register) Label() string {
return r.label
}
// IsNegative checks the sign bit of the register
func (r Register) IsNegative() bool {
return r.value&r.signBit == r.signBit
}
// IsZero checks if register is zero
func (r Register) IsZero() bool {
return r.value == 0
}
// IsBitV is used by the BIT instruction and returns the state of Bit6 (the bit
// next to the sign bit. it's a bit odd because it is only ever used by the BIT
// instruction and the BIT instruction only ever uses 8 bit registers.
// none-the-less, we've generalised it so it can be used with 16 bit registers
// too (for completion)
func (r Register) IsBitV() bool {
return r.value&r.vbit == r.vbit
}
func (r Register) String() string {
return fmt.Sprintf("%s: %d [%s] %s", r.label, r.ToUint(), r.ToHex(), r.ToBits())
}
// ToString returns the string representation of an aribtrary value
func (r Register) ToString(v interface{}) string {
vr, err := NewRegister(v, r.Size(), r.Label())
if err != nil {
return err.Error()
}
return fmt.Sprintf("%v", vr)
}
// ToBits returns the register as bit pattern (of '0' and '1')
func (r Register) ToBits() string {
return fmt.Sprintf(r.binformat, r.value)
}
// ToHex returns value as hexidecimal string
func (r Register) ToHex() string {
return fmt.Sprintf(r.hexformat, r.ToUint())
}
// ToUint returns value of type uint, regardless of register size
func (r Register) ToUint() uint {
return uint(r.value)
}
// ToUint8 returns value of type uint16, regardless of register size
func (r Register) ToUint8() uint8 {
return uint8(r.value)
}
// ToUint16 returns value of type uint16, regardless of register size
func (r Register) ToUint16() uint16 {
return uint16(r.value)
}
// Load value into register
func (r *Register) Load(v interface{}) {
switch v := v.(type) {
case *Register:
r.value = v.value & r.mask
case int:
r.value = uint32(v) & r.mask
case uint8:
r.value = uint32(v) & r.mask
case uint16:
r.value = uint32(v) & r.mask
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(v)))
}
}
// Add value to register. Returns carry and overflow states
func (r *Register) Add(v interface{}, carry bool) (bool, bool) {
var preNeg, postNeg bool
preNeg = r.IsNegative()
switch v := v.(type) {
case *Register:
r.value += v.value
if carry == true {
r.value++
}
postNeg = v.IsNegative()
case int:
r.value += uint32(v)
if carry == true {
r.value++
}
postNeg = uint32(v)&r.signBit == r.signBit
case uint8:
r.value += uint32(v)
if carry == true {
r.value++
}
postNeg = uint32(v)&r.signBit == r.signBit
case uint16:
r.value += uint32(v)
if carry == true {
r.value++
}
postNeg = uint32(v)&r.signBit == r.signBit
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(v)))
}
carry = ^r.mask&r.value != 0
overflow := !r.IsNegative() && preNeg && postNeg
if carry {
r.value &= r.mask
}
return carry, overflow
}
// Subtract value from register. Returns carry and overflow states
func (r *Register) Subtract(v interface{}, carry bool) (bool, bool) {
var val int
switch v := v.(type) {
case *Register:
val = int(v.value)
case int:
val = v
case uint8:
val = int(v)
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(v)))
}
val = ^val
val++
val &= int(r.mask)
return r.Add(val, !carry)
}
// AND value with register
func (r *Register) AND(v interface{}) {
switch v := v.(type) {
case *Register:
r.value &= v.value
case int:
r.value &= uint32(v)
case uint8:
r.value &= uint32(v)
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(v)))
}
r.value &= r.mask
}
// ASL (arithmetic shift left) shifts register one bit to the left. Returns
// the most significant bit as it was before the shift. If we think of the
// ASL operation as a multiply by two then the return value is the carry bit.
func (r *Register) ASL() bool {
carry := r.IsNegative()
r.value <<= 1
r.value &= r.mask
return carry
}
// EOR (exclusive or) value with register
func (r *Register) EOR(v interface{}) {
switch v := v.(type) {
case *Register:
r.value ^= v.value
case int:
r.value ^= uint32(v)
case uint8:
r.value ^= uint32(v)
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(v)))
}
r.value &= r.mask
}
// LSR (logical shift right) shifts register one bit to the rigth.
// the least significant bit as it was before the shift. If we think of
// the ASL operation as a division by two then the return value is the carry bit.
func (r *Register) LSR() bool {
carry := r.value&1 == 1
r.value >>= 1
r.value &= r.mask
return carry
}
// ORA (non-exclusive or) value with register
func (r *Register) ORA(v interface{}) {
switch v := v.(type) {
case *Register:
r.value |= v.value
case int:
r.value |= uint32(v)
case uint8:
r.value |= uint32(v)
default:
panic(fmt.Sprintf("unsupported value type (%s)", reflect.TypeOf(v)))
}
r.value &= r.mask
}
// ROL rotates register 1 bit to the left. Returns new carry status.
func (r *Register) ROL(carry bool) bool {
retCarry := r.IsNegative()
r.value <<= 1
if carry == true {
r.value |= 1
}
r.value &= r.mask
return retCarry
}
// ROR rotates register 1 bit to the right. Returns new carry status.
func (r *Register) ROR(carry bool) bool {
retCarry := r.value&1 == 1
r.value >>= 1
if carry == true {
r.value |= r.signBit
}
r.value &= r.mask
return retCarry
}