diff --git a/cpu.go b/cpu.go index cc63174..e31ef9d 100644 --- a/cpu.go +++ b/cpu.go @@ -8,6 +8,10 @@ type ErrInvalidOpcode struct{} func (e ErrInvalidOpcode) Error() string { return "invalid opcode" } +type ErrBreak struct{} + +func (e ErrBreak) Error() string { return "EBREAK" } + type CPUState struct { Registers [32]uint32 Pc uint32 @@ -485,7 +489,20 @@ func (c *CPUState) Step() error { case 0b1110011: // ECALL/EBREAK - panic("todo") + if opcode == 0b00000000000000000000000001110011 { + // ECALL + err := c.w.Syscall() + if err != nil { + return err + } + + } else if opcode == 0b00000000000100000000000001110011 { + // EBREAK + return ErrBreak{} + + } else { + return ErrInvalidOpcode{} + } default: return ErrInvalidOpcode{} diff --git a/eei.go b/eei.go index 15d280a..17346dc 100644 --- a/eei.go +++ b/eei.go @@ -11,9 +11,7 @@ type EEI interface { Write16(addr uint32, value uint16) error Write32(addr, value uint32) error - Syscall() - - Trap() (bool, error) + Syscall() error MemFence(opcode uint32) error } diff --git a/virtualEei.go b/virtualEei.go index 65e87bb..0a7c2b2 100644 --- a/virtualEei.go +++ b/virtualEei.go @@ -108,14 +108,10 @@ func (ve *VirtualEEI) WriteAt(p []byte, off int64) (n int, err error) { return len(p), nil } -func (ve *VirtualEEI) Syscall() { +func (ve *VirtualEEI) Syscall() error { panic("syscall") } -func (ve *VirtualEEI) Trap() (bool, error) { - panic("trap") -} - func (ve *VirtualEEI) MemFence(opcode uint32) error { // In the virtual EEI, a memory fence is a no-op. // It matters for synchronizing multiple cores or for peripherals.