cpu: implement FENCE/FENCE.TSO/PAUSE as stub

This commit is contained in:
mappu 2022-12-28 14:42:55 +13:00
parent 2864b16817
commit b5809d4689
3 changed files with 26 additions and 1 deletions

19
cpu.go
View File

@ -464,7 +464,24 @@ func (c *CPUState) Step() error {
case 0b0001111: case 0b0001111:
// FENCE/FENCE.TSO/PAUSE // FENCE/FENCE.TSO/PAUSE
panic("todo") funct3 := (opcode >> 12) & 0b111
if funct3 != 0b000 {
return ErrInvalidOpcode{}
}
if opcode == 0b00000001000000000000000000001111 {
// Zihintpause PAUSE extension
// PAUSE is encoded as a FENCE instruction with pred=W, succ=0, fm=0, rd=x0, and rs1=x0.
// PAUSE is encoded as a hint within the FENCE opcode because some implementations are ex-
// pected to deliberately stall the PAUSE instruction until outstanding memory transactions have
// completed. Because the successor set is null, however, PAUSE does not mandate any particular
// memory ordering - hence, it truly is a HINT.
}
err := c.w.MemFence(opcode)
if err != nil {
return err
}
case 0b1110011: case 0b1110011:
// ECALL/EBREAK // ECALL/EBREAK

2
eei.go
View File

@ -14,4 +14,6 @@ type EEI interface {
Syscall() Syscall()
Trap() (bool, error) Trap() (bool, error)
MemFence(opcode uint32) error
} }

View File

@ -116,4 +116,10 @@ func (ve *VirtualEEI) Trap() (bool, error) {
panic("trap") 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.
return nil
}
var _ EEI = &VirtualEEI{} // interface assertion var _ EEI = &VirtualEEI{} // interface assertion