You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
7.2 KiB
Python
202 lines
7.2 KiB
Python
from amaranth import *
|
|
from amaranth.asserts import Assume
|
|
from amaranth.lib.coding import Encoder
|
|
|
|
from power_fv import pfv
|
|
from power_fv.insn.const import *
|
|
from power_fv.build.sby import SymbiYosysPlatform
|
|
|
|
from . import InsnSpec
|
|
from .utils import iea
|
|
|
|
|
|
__all__ = ["CRLogicalSpec", "CRMoveSpec"]
|
|
|
|
|
|
class CRLogicalSpec(InsnSpec, Elaboratable):
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
|
|
m.d.comb += [
|
|
self.insn .eq(self.pfv.insn[32:]),
|
|
self.pfv.stb .eq(self.insn.is_valid() & ~self.pfv.insn[:32].any()),
|
|
self.pfv.intr.eq(0),
|
|
self.pfv.nia .eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)),
|
|
self.pfv.msr.r_mask.sf.eq(1),
|
|
]
|
|
|
|
if isinstance(self.insn, (
|
|
CRAND, CROR , CRNAND, CRXOR,
|
|
CRNOR, CRANDC, CREQV , CRORC,
|
|
)):
|
|
src_a = Signal()
|
|
src_b = Signal()
|
|
result = Signal()
|
|
|
|
m.d.comb += [
|
|
self.pfv.cr.r_mask.bit_select(31-self.insn.BA, width=1).eq(1),
|
|
self.pfv.cr.r_mask.bit_select(31-self.insn.BB, width=1).eq(1),
|
|
|
|
src_a.eq(self.pfv.cr.r_data.bit_select(31-self.insn.BA, width=1)),
|
|
src_b.eq(self.pfv.cr.r_data.bit_select(31-self.insn.BB, width=1)),
|
|
]
|
|
|
|
if isinstance(self.insn, CRAND):
|
|
m.d.comb += result.eq(src_a & src_b)
|
|
if isinstance(self.insn, CROR):
|
|
m.d.comb += result.eq(src_a | src_b)
|
|
if isinstance(self.insn, CRNAND):
|
|
m.d.comb += result.eq(~(src_a & src_b))
|
|
if isinstance(self.insn, CRXOR):
|
|
m.d.comb += result.eq(src_a ^ src_b)
|
|
if isinstance(self.insn, CRNOR):
|
|
m.d.comb += result.eq(~(src_a | src_b))
|
|
if isinstance(self.insn, CRANDC):
|
|
m.d.comb += result.eq(src_a & ~src_b)
|
|
if isinstance(self.insn, CREQV):
|
|
m.d.comb += result.eq(src_a == src_b)
|
|
if isinstance(self.insn, CRORC):
|
|
m.d.comb += result.eq(src_a | ~src_b)
|
|
|
|
m.d.comb += [
|
|
self.pfv.cr.w_mask.bit_select(31-self.insn.BT, width=1).eq(1),
|
|
self.pfv.cr.w_data.bit_select(31-self.insn.BT, width=1).eq(result),
|
|
]
|
|
|
|
else:
|
|
assert False
|
|
|
|
return m
|
|
|
|
|
|
class CRMoveSpec(InsnSpec, Elaboratable):
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
|
|
m.d.comb += [
|
|
self.insn .eq(self.pfv.insn[32:]),
|
|
self.pfv.stb .eq(self.insn.is_valid() & ~self.pfv.insn[:32].any()),
|
|
self.pfv.intr.eq(0),
|
|
self.pfv.nia .eq(iea(self.pfv.cia + 4, self.pfv.msr.r_data.sf)),
|
|
self.pfv.msr.r_mask.sf.eq(1),
|
|
]
|
|
|
|
if isinstance(self.insn, MCRF):
|
|
crf = Signal(4)
|
|
m.d.comb += [
|
|
self.pfv.cr.r_mask.word_select(7-self.insn.BFA, width=4).eq(0xf),
|
|
crf.eq(self.pfv.cr.r_data.word_select(7-self.insn.BFA, width=4)),
|
|
|
|
self.pfv.cr.w_mask.word_select(7-self.insn.BF, width=4).eq(0xf),
|
|
self.pfv.cr.w_data.word_select(7-self.insn.BF, width=4).eq(crf),
|
|
]
|
|
|
|
elif isinstance(self.insn, MCRXRX):
|
|
crf = Record([("ca32", 1), ("ca", 1), ("ov32", 1), ("ov", 1)])
|
|
|
|
m.d.comb += [
|
|
self.pfv.xer.r_mask.ov .eq(1),
|
|
self.pfv.xer.r_mask.ov32.eq(1),
|
|
self.pfv.xer.r_mask.ca .eq(1),
|
|
self.pfv.xer.r_mask.ca32.eq(1),
|
|
|
|
crf.ov .eq(self.pfv.xer.r_data.ov),
|
|
crf.ov32.eq(self.pfv.xer.r_data.ov32),
|
|
crf.ca .eq(self.pfv.xer.r_data.ca),
|
|
crf.ca32.eq(self.pfv.xer.r_data.ca32),
|
|
|
|
self.pfv.cr.w_mask.word_select(7-self.insn.BF, width=4).eq(0xf),
|
|
self.pfv.cr.w_data.word_select(7-self.insn.BF, width=4).eq(crf),
|
|
]
|
|
|
|
elif isinstance(self.insn, MTOCRF):
|
|
crf = Signal(4)
|
|
|
|
m.submodules.fxm_enc = fxm_enc = Encoder(width=8)
|
|
m.d.comb += [
|
|
fxm_enc.i.eq(self.insn.FXM),
|
|
|
|
self.pfv.rs.index.eq(self.insn.RS),
|
|
self.pfv.rs.r_stb.eq(1),
|
|
crf.eq(self.pfv.rs.r_data.word_select(fxm_enc.o, width=4)),
|
|
|
|
self.pfv.cr.w_mask.word_select(fxm_enc.o, width=4).eq(0xf),
|
|
self.pfv.cr.w_data.word_select(fxm_enc.o, width=4).eq(crf),
|
|
]
|
|
|
|
# Unless exactly one FXM bit is set to 1, CR contents are undefined.
|
|
if isinstance(platform, SymbiYosysPlatform):
|
|
m.d.comb += Assume(~fxm_enc.n)
|
|
|
|
elif isinstance(self.insn, MTCRF):
|
|
m.d.comb += [
|
|
self.pfv.rs.index.eq(self.insn.RS),
|
|
self.pfv.rs.r_stb.eq(1),
|
|
|
|
self.pfv.cr.w_mask.eq(Cat(Repl(b, 4) for b in self.insn.FXM)),
|
|
self.pfv.cr.w_data.eq(self.pfv.rs.r_data[:32]),
|
|
]
|
|
|
|
elif isinstance(self.insn, MFOCRF):
|
|
crf = Signal(4)
|
|
|
|
m.submodules.fxm_enc = fxm_enc = Encoder(width=8)
|
|
m.d.comb += [
|
|
fxm_enc.i.eq(self.insn.FXM),
|
|
|
|
self.pfv.cr.r_mask.word_select(fxm_enc.o, width=4).eq(Mux(fxm_enc.n, 0x0, 0xf)),
|
|
crf.eq(self.pfv.cr.r_data.word_select(fxm_enc.o, width=4)),
|
|
|
|
self.pfv.rt.index.eq(self.insn.RT),
|
|
self.pfv.rt.w_stb.eq(1),
|
|
self.pfv.rt.w_data.word_select(fxm_enc.o, width=4).eq(crf),
|
|
]
|
|
|
|
# Unless exactly one FXM bit is set to 1, RT contents are undefined.
|
|
if isinstance(platform, SymbiYosysPlatform):
|
|
m.d.comb += Assume(~fxm_enc.n)
|
|
|
|
elif isinstance(self.insn, MFCR):
|
|
m.d.comb += [
|
|
self.pfv.cr.r_mask.eq(Repl(1, 32)),
|
|
self.pfv.rt.index .eq(self.insn.RT),
|
|
self.pfv.rt.w_stb .eq(1),
|
|
self.pfv.rt.w_data.eq(self.pfv.cr.r_data),
|
|
]
|
|
|
|
elif isinstance(self.insn, SETB):
|
|
crf = Signal(4)
|
|
m.d.comb += [
|
|
self.pfv.cr.r_mask.word_select(7-self.insn.BFA, width=4).eq(0xf),
|
|
crf.eq(self.pfv.cr.r_data.word_select(7-self.insn.BFA, width=4)),
|
|
|
|
self.pfv.rt.index.eq(self.insn.RT),
|
|
self.pfv.rt.w_stb.eq(1),
|
|
self.pfv.rt.w_data.eq(Mux(crf[3-0], Repl(1, 64), crf[3-1])),
|
|
]
|
|
|
|
elif isinstance(self.insn, (SETBC, SETBCR, SETNBC, SETNBCR)):
|
|
crb = Signal()
|
|
|
|
m.d.comb += [
|
|
self.pfv.cr.r_mask.bit_select(31-self.insn.BI, width=1).eq(1),
|
|
crb.eq(self.pfv.cr.r_data.bit_select(31-self.insn.BI, width=1)),
|
|
|
|
self.pfv.rt.index.eq(self.insn.RT),
|
|
self.pfv.rt.w_stb.eq(1),
|
|
]
|
|
|
|
if isinstance(self.insn, SETBC):
|
|
m.d.comb += self.pfv.rt.w_data.eq(crb)
|
|
if isinstance(self.insn, SETBCR):
|
|
m.d.comb += self.pfv.rt.w_data.eq(~crb)
|
|
if isinstance(self.insn, SETNBC):
|
|
m.d.comb += self.pfv.rt.w_data.eq(Mux(crb, -1, 0))
|
|
if isinstance(self.insn, SETNBCR):
|
|
m.d.comb += self.pfv.rt.w_data.eq(Mux(crb, 0, -1))
|
|
|
|
else:
|
|
assert False
|
|
|
|
return m
|