Add check for System Call instruction.

main
Jean-François Nguyen 2 years ago
parent ae76adefbf
commit 0038f3fff5

@ -1,5 +1,6 @@
from .addsub import *
from .branch import *
from .syscall import *
from .loadstore import *
from .cr import *
from .compare import *

@ -0,0 +1,9 @@
from power_fv.insn import const
from power_fv.insn.spec.syscall import SystemCallSpec
from power_fv.check.insn import InsnCheck


__all__ = ["SC"]


class SC(InsnCheck, spec_cls=SystemCallSpec, insn_cls=const.SC): pass

@ -21,6 +21,11 @@ class BCCTRL (WordInsn): _fields = (f.PO(19), f.BO(), f.BI(), f.BH(), f.XO_XL(5
class BCTAR (WordInsn): _fields = (f.PO(19), f.BO(), f.BI(), f.BH(), f.XO_XL(560), f.LK(0))
class BCTARL (WordInsn): _fields = (f.PO(19), f.BO(), f.BI(), f.BH(), f.XO_XL(560), f.LK(1))

# System Call

class SC (WordInsn): _fields = (f.PO(17), f.LEV(), f.SC_30(1))
class SCV (WordInsn): _fields = (f.PO(17), f.LEV(), f.SC_30(0), f.SC_31(1))

# Condition Register

class CRAND (WordInsn): _fields = (f.PO(19), f.BT(), f.BA(), f.BB(), f.XO_XL(257))

@ -18,6 +18,7 @@ class D (InsnField): _shape = signed(16); _offset = 16; _name = "D"
class d0 (InsnField): _shape = signed(10); _offset = 16; _name = "d0"
class d1 (InsnField): _shape = signed( 5); _offset = 11; _name = "d1"
class d2 (InsnField): _shape = signed( 1); _offset = 31; _name = "d2"
class LEV (InsnField): _shape = unsigned( 7); _offset = 20; _name = "LEV"
class L_D10 (InsnField): _shape = unsigned( 1); _offset = 10; _name = "L"
class L_X10 (InsnField): _shape = unsigned( 1); _offset = 10; _name = "L"
class L_X15 (InsnField): _shape = unsigned( 1); _offset = 15; _name = "L"
@ -32,6 +33,8 @@ class RB (InsnField): _shape = unsigned( 5); _offset = 16; _name = "RB"
class Rc (InsnField): _shape = unsigned( 1); _offset = 31; _name = "Rc"
class RS (InsnField): _shape = unsigned( 5); _offset = 6; _name = "RS"
class RT (InsnField): _shape = unsigned( 5); _offset = 6; _name = "RT"
class SC_30 (InsnField): _shape = unsigned( 1); _offset = 30; _name = "_30"
class SC_31 (InsnField): _shape = unsigned( 1); _offset = 31; _name = "_31"
class SI (InsnField): _shape = signed(16); _offset = 16; _name = "SI"
class SH (InsnField): _shape = unsigned( 5); _offset = 16; _name = "SH"
class UI (InsnField): _shape = unsigned(16); _offset = 16; _name = "UI"

@ -0,0 +1,56 @@
from amaranth import *

from power_fv import pfv
from power_fv.insn.const import *

from . import InsnSpec
from .utils import iea


__all__ = ["SystemCallSpec"]


class SystemCallSpec(InsnSpec, Elaboratable):
def __init__(self, insn):
self.pfv = pfv.Interface()
self.insn = insn

def elaborate(self, platform):
m = Module()

m.d.comb += [
self.pfv.stb .eq(1),
self.pfv.insn.eq(Cat(Const(0, 32), self.insn.as_value())),
self.pfv.msr.r_mask.sf.eq(1),
]

if isinstance(self.insn, SC):
def _msr_to_srr1(start, stop):
stmts = [
self.pfv.msr .r_mask[63-stop:64-start].eq(Repl(1, stop-start+1)),
self.pfv.srr1.w_mask[63-stop:64-start].eq(Repl(1, stop-start+1)),
self.pfv.srr1.w_data[63-stop:64-start].eq(self.pfv.msr.r_data[63-stop:64-start]),
]
return stmts

m.d.comb += [
self.pfv.srr0.w_mask.eq(Repl(1, 64)),
self.pfv.srr0.w_data.eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)),

self.pfv.srr1.w_mask[63-36:64-33].eq(Repl(1, 4)),
self.pfv.srr1.w_data[63-36:64-33].eq(0),
self.pfv.srr1.w_mask[63-47:64-42].eq(Repl(1, 6)),
self.pfv.srr1.w_data[63-47:64-42].eq(0),

_msr_to_srr1( 0, 32),
_msr_to_srr1(37, 41),
_msr_to_srr1(48, 63),

self.pfv.intr.eq(1),
self.pfv.nia .eq(0xc00),
]

else:
assert False

return m
Loading…
Cancel
Save