+ # ... and svp64 rm
+ for i in [dec_a.insn_in, dec_b.insn_in,
+ dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in]:
+ comb += i.eq(self.sv_rm)
+
+ # ...and subdecoders' input fields
+ comb += dec_a.sel_in.eq(op.in1_sel)
+ comb += dec_b.sel_in.eq(op.in2_sel)
+ comb += dec_c.sel_in.eq(op.in3_sel)
+ comb += dec_o.sel_in.eq(op.out_sel)
+ comb += dec_o2.sel_in.eq(op.out_sel)
+ if hasattr(do, "lk"):
+ comb += dec_o2.lk.eq(do.lk)
+
+ # registers a, b, c and out and out2 (LD/ST EA)
+ for to_reg, fromreg in (
+ (e.read_reg1, dec_a.reg_out),
+ (e.read_reg2, dec_b.reg_out),
+ (e.read_reg3, dec_c.reg_out),
+ (e.write_reg, dec_o.reg_out),
+ (e.write_ea, dec_o2.reg_out)):
+ comb += to_reg.data.eq(fromreg.data)
+ comb += to_reg.ok.eq(fromreg.ok)
+
+ # SPRs out
+ comb += e.read_spr1.eq(dec_a.spr_out)
+ comb += e.write_spr.eq(dec_o.spr_out)
+
+ # Fast regs out
+ comb += e.read_fast1.eq(dec_a.fast_out)
+ comb += e.read_fast2.eq(dec_b.fast_out)
+ comb += e.write_fast1.eq(dec_o.fast_out)
+ comb += e.write_fast2.eq(dec_o2.fast_out)
+
+ # condition registers (CR)
+ comb += e.read_cr1.eq(self.dec_cr_in.cr_bitfield)
+ comb += e.read_cr2.eq(self.dec_cr_in.cr_bitfield_b)
+ comb += e.read_cr3.eq(self.dec_cr_in.cr_bitfield_o)
+ comb += e.write_cr.eq(self.dec_cr_out.cr_bitfield)
+
+ # sigh this is exactly the sort of thing for which the
+ # decoder is designed to not need. MTSPR, MFSPR and others need
+ # access to the XER bits. however setting e.oe is not appropriate
+ with m.If(op.internal_op == MicrOp.OP_MFSPR):
+ comb += e.xer_in.eq(0b111) # SO, CA, OV
+ with m.If(op.internal_op == MicrOp.OP_CMP):
+ comb += e.xer_in.eq(1<<XERRegs.SO) # SO
+ with m.If(op.internal_op == MicrOp.OP_MTSPR):
+ comb += e.xer_out.eq(1)
+
+ # set the trapaddr to 0x700 for a td/tw/tdi/twi operation
+ with m.If(op.internal_op == MicrOp.OP_TRAP):
+ # *DO NOT* call self.trap here. that would reset absolutely
+ # everything including destroying read of RA and RB.
+ comb += self.do_copy("trapaddr", 0x70) # strip first nibble
+
+ ####################
+ # ok so the instruction's been decoded, blah blah, however
+ # now we need to determine if it's actually going to go ahead...
+ # *or* if in fact it's a privileged operation, whether there's
+ # an external interrupt, etc. etc. this is a simple priority
+ # if-elif-elif sequence. decrement takes highest priority,
+ # EINT next highest, privileged operation third.
+
+ # check if instruction is privileged
+ is_priv_insn = instr_is_priv(m, op.internal_op, e.do.insn)
+
+ # different IRQ conditions
+ ext_irq_ok = Signal()
+ dec_irq_ok = Signal()
+ priv_ok = Signal()
+ illeg_ok = Signal()
+ exc = self.exc
+
+ comb += ext_irq_ok.eq(ext_irq & msr[MSR.EE]) # v3.0B p944 (MSR.EE)
+ comb += dec_irq_ok.eq(dec_spr[63] & msr[MSR.EE]) # 6.5.11 p1076
+ comb += priv_ok.eq(is_priv_insn & msr[MSR.PR])
+ comb += illeg_ok.eq(op.internal_op == MicrOp.OP_ILLEGAL)
+
+ # LD/ST exceptions. TestIssuer copies the exception info at us
+ # after a failed LD/ST.
+ with m.If(exc.happened):
+ with m.If(exc.alignment):
+ self.trap(m, TT.PRIV, 0x600)
+ with m.Elif(exc.instr_fault):
+ with m.If(exc.segment_fault):
+ self.trap(m, TT.PRIV, 0x480)
+ with m.Else():
+ # pass exception info to trap to create SRR1
+ self.trap(m, TT.MEMEXC, 0x400, exc)
+ with m.Else():
+ with m.If(exc.segment_fault):
+ self.trap(m, TT.PRIV, 0x380)
+ with m.Else():
+ self.trap(m, TT.PRIV, 0x300)
+
+ # decrement counter (v3.0B p1099): TODO 32-bit version (MSR.LPCR)
+ with m.Elif(dec_irq_ok):
+ self.trap(m, TT.DEC, 0x900) # v3.0B 6.5 p1065
+
+ # external interrupt? only if MSR.EE set
+ with m.Elif(ext_irq_ok):
+ self.trap(m, TT.EINT, 0x500)
+
+ # privileged instruction trap
+ with m.Elif(priv_ok):
+ self.trap(m, TT.PRIV, 0x700)
+
+ # illegal instruction must redirect to trap. this is done by
+ # *overwriting* the decoded instruction and starting again.
+ # (note: the same goes for interrupts and for privileged operations,
+ # just with different trapaddr and traptype)
+ with m.Elif(illeg_ok):
+ # illegal instruction trap
+ self.trap(m, TT.ILLEG, 0x700)
+
+ # no exception, just copy things to the output
+ with m.Else():
+ comb += e_out.eq(e)
+
+ ####################
+ # follow-up after trap/irq to set up SRR0/1
+
+ # trap: (note e.insn_type so this includes OP_ILLEGAL) set up fast regs
+ # Note: OP_SC could actually be modified to just be a trap
+ with m.If((do_out.insn_type == MicrOp.OP_TRAP) |
+ (do_out.insn_type == MicrOp.OP_SC)):
+ # TRAP write fast1 = SRR0
+ comb += e_out.write_fast1.data.eq(FastRegs.SRR0) # constant: SRR0
+ comb += e_out.write_fast1.ok.eq(1)
+ # TRAP write fast2 = SRR1
+ comb += e_out.write_fast2.data.eq(FastRegs.SRR1) # constant: SRR1
+ comb += e_out.write_fast2.ok.eq(1)
+
+ # RFID: needs to read SRR0/1
+ with m.If(do_out.insn_type == MicrOp.OP_RFID):
+ # TRAP read fast1 = SRR0
+ comb += e_out.read_fast1.data.eq(FastRegs.SRR0) # constant: SRR0
+ comb += e_out.read_fast1.ok.eq(1)
+ # TRAP read fast2 = SRR1
+ comb += e_out.read_fast2.data.eq(FastRegs.SRR1) # constant: SRR1
+ comb += e_out.read_fast2.ok.eq(1)
+
+ # annoying simulator bug
+ if hasattr(e_out, "asmcode") and hasattr(self.dec.op, "asmcode"):
+ comb += e_out.asmcode.eq(self.dec.op.asmcode)