mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-05-20 05:40:49 -04:00
4c530bf7a7
- 6502 implementation is basically correct but does not handle - interrupts - pre-fetch cycle - anything less fine grained than instruction stepping - memory sub-system sketched in o retroactive adding of GPL copyright notice
194 lines
4.5 KiB
Go
194 lines
4.5 KiB
Go
package cpu
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
)
|
|
|
|
// Register is the bit representation of the all CPU registers (with the exception of
|
|
// the status register.
|
|
type Register []bit
|
|
|
|
// note that in the 6502, all arithmetic and bitwise operations are carried out on 8 bit
|
|
// registers, with a special increment for the PC register. for this emulation, those
|
|
// operations can be performed on 16 bit registers too, for convenience. principally, this
|
|
// means the PC register, but we also perform 16 bit addition on temporary registers when
|
|
// indexing. in the latter case, care must be taken to detect 8 bit overflow, or page-faults
|
|
// as we call them, manually.
|
|
//
|
|
// pageFault = indexedAddress & 0xFF00 != preIndexedAddress & 0xFF00
|
|
|
|
func (r Register) String() string {
|
|
return fmt.Sprintf("%s (%d)", r.ToBits(), r.ToUint())
|
|
}
|
|
|
|
// Load value into register
|
|
func (r Register) Load(v interface{}) {
|
|
b, err := generateRegister(v, len(r))
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
copy(r, b)
|
|
}
|
|
|
|
// Add value to register. Returns carry and overflow states
|
|
func (r Register) Add(v interface{}, carry bool) (bool, bool) {
|
|
b, err := generateRegister(v, len(r))
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
sign := r[0]
|
|
|
|
i := len(b) - 1
|
|
|
|
for i >= 0 {
|
|
if r[i] == false && b[i] == false && carry == false { // 0 0 0
|
|
r[i] = false
|
|
carry = false
|
|
} else if r[i] == false && b[i] == false && carry == true { // 0 0 1
|
|
r[i] = true
|
|
carry = false
|
|
} else if r[i] == false && b[i] == true && carry == false { // 0 1 0
|
|
r[i] = true
|
|
carry = false
|
|
} else if r[i] == false && b[i] == true && carry == true { // 0 1 1
|
|
r[i] = false
|
|
carry = true
|
|
} else if r[i] == true && b[i] == false && carry == false { // 1 0 0
|
|
r[i] = true
|
|
carry = false
|
|
} else if r[i] == true && b[i] == false && carry == true { // 1 0 1
|
|
r[i] = false
|
|
carry = true
|
|
} else if r[i] == true && b[i] == true && carry == false { // 1 1 0
|
|
r[i] = false
|
|
carry = true
|
|
} else if r[i] == true && b[i] == true && carry == true { // 1 1 1
|
|
r[i] = true
|
|
carry = true
|
|
}
|
|
|
|
i--
|
|
}
|
|
|
|
overflow := sign == true && b[0] == true && r[0] == false
|
|
|
|
return carry, overflow
|
|
}
|
|
|
|
// Subtract value from register. Returns carry and overflow states
|
|
//
|
|
// Note that carry flag is opposite of what you might expect when subtracting
|
|
// on the 6502/6507
|
|
func (r Register) Subtract(v interface{}, carry bool) (bool, bool) {
|
|
b, err := generateRegister(v, len(r))
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
// generate two's complement
|
|
i := 0
|
|
for i < len(b) {
|
|
b[i] = !b[i]
|
|
i++
|
|
}
|
|
b.Add(1, false)
|
|
|
|
return r.Add(b, !carry)
|
|
}
|
|
|
|
// EOR - XOR Register with value
|
|
func (r Register) EOR(v interface{}) {
|
|
b, err := generateRegister(v, len(r))
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
i := 0
|
|
for i < len(r) {
|
|
r[i] = (r[i] || b[i]) && r[i] != b[i]
|
|
i++
|
|
}
|
|
}
|
|
|
|
// ORA - OR Register with value
|
|
func (r Register) ORA(v interface{}) {
|
|
b, err := generateRegister(v, len(r))
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
i := 0
|
|
for i < len(r) {
|
|
r[i] = r[i] || b[i]
|
|
i++
|
|
}
|
|
}
|
|
|
|
// AND register with value
|
|
func (r Register) AND(v interface{}) {
|
|
b, err := generateRegister(v, len(r))
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
i := 0
|
|
for i < len(r) {
|
|
r[i] = r[i] && b[i]
|
|
i++
|
|
}
|
|
}
|
|
|
|
// ROR rotates register 1 bit to the right. Returns new carry status.
|
|
func (r Register) ROR(carry bool) bool {
|
|
rcarry := bool(r[len(r)-1])
|
|
copy(r[1:], r[:len(r)-1])
|
|
r[0] = bit(carry)
|
|
return rcarry
|
|
}
|
|
|
|
// ROL rotates register 1 bit to the left. Returns new carry status.
|
|
func (r Register) ROL(carry bool) bool {
|
|
rcarry := bool(r[0])
|
|
copy(r[:len(r)-1], r[1:])
|
|
r[len(r)-1] = bit(carry)
|
|
return rcarry
|
|
}
|
|
|
|
// 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 {
|
|
rcarry := bool(r[0])
|
|
copy(r[:len(r)-1], r[1:])
|
|
r[len(r)-1] = bit(false)
|
|
return rcarry
|
|
}
|
|
|
|
// 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 {
|
|
rcarry := bool(r[len(r)-1])
|
|
copy(r[1:], r[:len(r)-1])
|
|
r[0] = bit(false)
|
|
return rcarry
|
|
}
|
|
|
|
// IsNegative checks the sign bit of the register
|
|
func (r Register) IsNegative() bool {
|
|
return bool(r[0])
|
|
}
|
|
|
|
// IsZero checks if register is all zero bits
|
|
func (r Register) IsZero() bool {
|
|
for b := range r {
|
|
if r[b] == true {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|