Skip to content

Commit

Permalink
new supervisor handler
Browse files Browse the repository at this point in the history
  • Loading branch information
jenska committed Oct 29, 2018
1 parent 14b50ac commit ade4fbb
Show file tree
Hide file tree
Showing 8 changed files with 438 additions and 115 deletions.
205 changes: 173 additions & 32 deletions cpu/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,184 @@ import (
"log"
)

func set(instructions []Instruction, index int, f Instruction) {
if instructions[index] != nil {
panic("opcode already in use")
}
instructions[index] = f
}
type Instruction func() int

func registerM68KInstructions(c *M68K) {
func init68000InstructionSet(c *M68K) {
log.Println("register M68K instruction set")

log.Println("\tmoveq")
moveq := func(opcode int) int {
c.D[(opcode>>9)&0x7] = Data(int8(opcode & 0xff))
moveq := func() int {
c.D[(c.opcode>>9)&0x7] = Data(int8(c.opcode & 0xff))
return 4
}
base := 0x7000
for reg := 0; reg < 8; reg++ {
for imm := 0; imm < 256; imm++ {
set(c.instructions, base+(reg<<9)+imm, moveq)
}
}

log.Println("\tunknown")
unknown := func(opcode int) int {
if opcode&0xf000 == 0xf000 {
c.RaiseException(LineF)
} else if opcode&0xa000 == 0xa000 {
c.RaiseException(LineA)
} else {
c.RaiseException(IllegalInstruction)
}
return 34
}
for i := range c.instructions {
if c.instructions[i] == nil {
c.instructions[i] = unknown
}
}
or := func() int { return 0 }
and := func() int { return 0 }
btst := func() int { return 0 } // movep
bchg := func() int { return 0 }
bclr := func() int { return 0 }
bset := func() int { return 0 }
sub := func() int { return 0 }
add := func() int { return 0 }
eor := func() int { return 0 }
cmp := func() int { return 0 }
neg := func() int { return 0 }
chk := func() int { return 0 }
lea := func() int { return 0 }
not := func() int { return 0 }
clr := func() int { return 0 }
nbcd := func() int { return 0 }
swap := func() int { return 0 }
tst := func() int { return 0 }
tas := func() int { return 0 }
ext := func() int { return 0 } // movem
movem := func() int { return 0 }
move := func() int { return 0 }
link := func() int { return 0 } // unlk, move
jsr := func() int { return 0 }
jmp := func() int { return 0 }
addq := func() int { return 0 }
subq := func() int { return 0 }
dbcc := func() int { return 0 } // scc
bsr := func() int { return 0 }
bcc := func() int { return 0 }
divu := func() int { return 0 }
divs := func() int { return 0 }
mulu := func() int { return 0 }
muls := func() int { return 0 }
exg := func() int { return 0 } // and
abcd := func() int { return 0 } // and
xsr := func() int { return 0 } // ror, lsr, asr
xsl := func() int { return 0 } // rol, lsl, asl
linea := func() int { return c.RaiseException(LineA) }
linef := func() int { return c.RaiseException(LineF) }

c.instructions = []Instruction{
or, or, or, nil, btst, bchg, bclr, bset, /* 0000 */
and, and, and, nil, btst, bchg, bclr, bset, /* 0200 */
sub, sub, sub, nil, btst, bchg, bclr, bset, /* 0400 */
add, add, add, nil, btst, bchg, bclr, bset, /* 0600 */
btst, bchg, bclr, bset, btst, bchg, bclr, bset, /* 0800 */
eor, eor, eor, nil, btst, bchg, bclr, bset, /* 0A00 */
cmp, cmp, cmp, nil, btst, bchg, bclr, bset, /* 0C00 */
move, move, move, nil, btst, bchg, bclr, bset, /* 0E00 */
move, nil, move, move, move, move, move, move, /* 1000 */
move, nil, move, move, move, move, move, move, /* 1200 */
move, nil, move, move, move, move, move, move, /* 1400 */
move, nil, move, move, move, move, move, move, /* 1600 */
move, nil, move, move, move, move, move, move, /* 1800 */
move, nil, move, move, move, move, move, move, /* 1A00 */
move, nil, move, move, move, move, move, move, /* 1C00 */
move, nil, move, move, move, move, move, move, /* 1E00 */
move, move, move, move, move, move, move, move, /* 2000 */
move, move, move, move, move, move, move, move, /* 2200 */
move, move, move, move, move, move, move, move, /* 2400 */
move, move, move, move, move, move, move, move, /* 2600 */
move, move, move, move, move, move, move, move, /* 2800 */
move, move, move, move, move, move, move, move, /* 2A00 */
move, move, move, move, move, move, move, move, /* 2C00 */
move, move, move, move, move, move, move, move, /* 2E00 */
move, move, move, move, move, move, move, move, /* 3000 */
move, move, move, move, move, move, move, move, /* 3200 */
move, move, move, move, move, move, move, move, /* 3400 */
move, move, move, move, move, move, move, move, /* 3600 */
move, move, move, move, move, move, move, move, /* 3800 */
move, move, move, move, move, move, move, move, /* 3A00 */
move, move, move, move, move, move, move, move, /* 3C00 */
move, move, move, move, move, move, move, move, /* 3E00 */
neg, neg, neg, move, nil, nil, chk, lea, /* 4000 */
clr, clr, clr, move, nil, nil, chk, lea, /* 4200 */
neg, neg, neg, move, nil, nil, chk, lea, /* 4400 */
not, not, not, move, nil, nil, chk, lea, /* 4600 */
nbcd, swap, ext, ext, nil, nil, chk, lea, /* 4800 */
tst, tst, tst, tas, nil, nil, chk, lea, /* 4A00 */
nil, nil, movem, movem, nil, nil, chk, lea, /* 4C00 */
nil, link, jsr, jmp, nil, nil, chk, lea, /* 4E00 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5000 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5200 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5400 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5600 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5800 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5A00 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5C00 */
addq, addq, addq, dbcc, subq, subq, subq, dbcc, /* 5E00 */
bcc, bcc, bcc, bcc, bsr, bsr, bsr, bsr, /* 6000 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6200 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6400 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6600 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6800 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6A00 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6C00 */
bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc, /* 6E00 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7000 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7200 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7400 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7600 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7800 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7A00 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7C00 */
moveq, moveq, moveq, moveq, nil, nil, nil, nil, /* 7E00 */
or, or, or, divu, or, or, or, divs, /* 8000 */
or, or, or, divu, or, or, or, divs, /* 8200 */
or, or, or, divu, or, or, or, divs, /* 8400 */
or, or, or, divu, or, or, or, divs, /* 8600 */
or, or, or, divu, or, or, or, divs, /* 8800 */
or, or, or, divu, or, or, or, divs, /* 8A00 */
or, or, or, divu, or, or, or, divs, /* 8C00 */
or, or, or, divu, or, or, or, divs, /* 8E00 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9000 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9200 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9400 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9600 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9800 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9A00 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9C00 */
sub, sub, sub, sub, sub, sub, sub, sub, /* 9E00 */
linea, linea, linea, linea, linea, linea, linea, linea, /* A000 */
linea, linea, linea, linea, linea, linea, linea, linea,
linea, linea, linea, linea, linea, linea, linea, linea,
linea, linea, linea, linea, linea, linea, linea, linea,
linea, linea, linea, linea, linea, linea, linea, linea,
linea, linea, linea, linea, linea, linea, linea, linea,
linea, linea, linea, linea, linea, linea, linea, linea,
linea, linea, linea, linea, linea, linea, linea, linea,
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* B000 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* B200 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* B400 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* B600 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* B800 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* BA00 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* BC00 */
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, /* BE00 */
and, and, and, mulu, abcd, exg, exg, muls, /* C000 */
and, and, and, mulu, abcd, exg, exg, muls, /* C200 */
and, and, and, mulu, abcd, exg, exg, muls, /* C400 */
and, and, and, mulu, abcd, exg, exg, muls, /* C600 */
and, and, and, mulu, abcd, exg, exg, muls, /* C800 */
and, and, and, mulu, abcd, exg, exg, muls, /* CA00 */
and, and, and, mulu, abcd, exg, exg, muls, /* CC00 */
and, and, and, mulu, abcd, exg, exg, muls, /* CE00 */
add, add, add, add, add, add, add, add, /* D000 */
add, add, add, add, add, add, add, add, /* D200 */
add, add, add, add, add, add, add, add, /* D400 */
add, add, add, add, add, add, add, add, /* D600 */
add, add, add, add, add, add, add, add, /* D800 */
add, add, add, add, add, add, add, add, /* DA00 */
add, add, add, add, add, add, add, add, /* DC00 */
add, add, add, add, add, add, add, add, /* DE00 */
xsr, xsr, xsr, xsr, xsl, xsl, xsl, xsl, /* E000 */
xsr, xsr, xsr, xsr, xsl, xsl, xsl, xsl, /* E200 */
xsr, xsr, xsr, xsr, xsl, xsl, xsl, xsl, /* E400 */
xsr, xsr, xsr, xsr, xsl, xsl, xsl, xsl, /* E600 */
xsr, xsr, xsr, nil, xsl, xsl, xsl, nil, /* E800 */
xsr, xsr, xsr, nil, xsl, xsl, xsl, nil, /* EA00 */
xsr, xsr, xsr, nil, xsl, xsl, xsl, nil, /* EC00 */
xsr, xsr, xsr, nil, xsl, xsl, xsl, nil, /* EE00 */
linef, linef, linef, linef, linef, linef, linef, linef, /* F000 */
linef, linef, linef, linef, linef, linef, linef, linef,
linef, linef, linef, linef, linef, linef, linef, linef,
linef, linef, linef, linef, linef, linef, linef, linef,
linef, linef, linef, linef, linef, linef, linef, linef,
linef, linef, linef, linef, linef, linef, linef, linef,
linef, linef, linef, linef, linef, linef, linef, linef,
linef, linef, linef, linef, linef, linef, linef, linef}
}
32 changes: 25 additions & 7 deletions cpu/m68k.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ type (
Read(address Address, operand *Operand) (int, error)
Write(address Address, operand *Operand, value int) error
Reset()
SetSuperVisorFlag(*bool)
}

Instruction func(opcode int) int

M68K struct {
// registers
A [8]Address
D [8]Data
SR StatusRegister
PC Address
SSP, USP Address
opcode int
bus AddressBus

opcodeAddr Address
opcode int

bus AddressBus

instructions []Instruction
}
Expand All @@ -30,11 +32,27 @@ type (
func NewCPU(addressBus AddressBus) M68K {
result := M68K{bus: addressBus}
result.instructions = make([]Instruction, 0x10000)
registerM68KInstructions(&result)
init68000InstructionSet(&result)
result.Reset()
return result
}

func (c *M68K) Step() int {
c.opcodeAddr = c.PC
if opcode, err := c.bus.Read(c.PC, Word); err == nil {
c.opcode = opcode
c.PC += Address(Word.size)

if instruction := c.instructions[opcode>>6]; instruction != nil {
return instruction()
} else {
return c.RaiseException(IllegalInstruction)
}
} else {
panic("bus error")
}
}

func (c *M68K) Reset() {
c.SR.Set(0x2700)
c.bus.Reset()
Expand All @@ -47,7 +65,7 @@ func (c *M68K) Reset() {
c.SSP, c.PC = sp, pc
}

func (c *M68K) RaiseException(x Exception) {
func (c *M68K) RaiseException(x Exception) int {
oldSR := c.SR
if !c.SR.S {
c.SR.S = true
Expand All @@ -64,7 +82,7 @@ func (c *M68K) RaiseException(x Exception) {
} else {
c.PC = xaddr
}

return 34
}

func (c *M68K) Halt() {
Expand Down
6 changes: 3 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ func main() {
}

bus := mem.NewAddressBus(
mem.NewProtectedRAM(0, 1024, nil),
mem.NewRAM(1024, 1023*1024),
mem.NewProtectedRAM(0, 2048),
mem.NewRAM(2048, 1024*1024),
mem.NewROM(startROM, data),
)
cpu.NewCPU(bus)

cpu.NewCPU(bus)
util.Dump(bus, startROM, 128)
}
22 changes: 16 additions & 6 deletions mem/addrmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ type (
ResetHandler func()

AddressArea struct {
start cpu.Address
end cpu.Address
read MemoryReader
write MemoryWriter
reset ResetHandler
start cpu.Address
end cpu.Address
read MemoryReader
write MemoryWriter
reset ResetHandler
parent *addressMap
}

addressMap struct {
areas []AddressArea
cache *AddressArea
sv *bool
}
)

Expand Down Expand Up @@ -60,6 +62,10 @@ func (a *addressMap) Write(address cpu.Address, operand *cpu.Operand, value int)
return BusError(address)
}

func (a *addressMap) SetSuperVisorFlag(flag *bool) {
a.sv = flag
}

func (a *addressMap) Reset() {
for _, area := range a.areas {
if area.reset != nil {
Expand All @@ -69,5 +75,9 @@ func (a *addressMap) Reset() {
}

func NewAddressBus(areas ...AddressArea) cpu.AddressBus {
return &addressMap{areas: areas, cache: &areas[0]}
result := &addressMap{areas: areas, cache: &areas[0]}
for _, area := range areas {
area.parent = result
}
return result
}
5 changes: 2 additions & 3 deletions mem/ram.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,18 @@ func NewRAM(start cpu.Address, size uint) AddressArea {
},
read: func(address cpu.Address, operand *cpu.Operand) (int, error) {
if address >= start && address < end {

return operand.Read(ram[address-start:]), nil
}
return 0, BusError(address)
},
}
}

func NewProtectedRAM(start cpu.Address, size uint, sr *cpu.StatusRegister) AddressArea {
func NewProtectedRAM(start cpu.Address, size uint) AddressArea {
area := NewRAM(start, size)
protectedWrite := area.write
area.write = func(address cpu.Address, operand *cpu.Operand, value int) error {
if sr.S {
if area.parent.sv == nil || *area.parent.sv == true {
return protectedWrite(address, operand, value)
}
return cpu.SuperVisorException(address)
Expand Down
2 changes: 1 addition & 1 deletion util/disam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestDisasmMoveq(t *testing.T) {
panic(fmt.Sprintf("invalid read %s", err))
}

instruction := opcodes[opcode](bus, start)
instruction := opcodes[opcode>>6](bus, start)
assert.Equal(t, "moveq", instruction.instruction)
assert.Equal(t, 2, instruction.Size())
start += cpu.Address(instruction.Size())
Expand Down
Loading

0 comments on commit ade4fbb

Please sign in to comment.