cater for illegal instruction (generates a trap)
[soc.git] / src / soc / fu / trap / main_stage.py
1 """Trap Pipeline
2
3 Deals with td/tw/tdi/twi as well as mfmsr/mtmsr, sc and rfid. addpcis TODO.
4 Also used generally for interrupts (as a micro-coding mechanism) by
5 actually modifying the decoded instruction in PowerDecode2.
6
7 * https://bugs.libre-soc.org/show_bug.cgi?id=325
8 * https://bugs.libre-soc.org/show_bug.cgi?id=344
9 * https://libre-soc.org/openpower/isa/fixedtrap/
10 """
11
12 from nmigen import (Module, Signal, Cat, Mux, Const, signed)
13 from nmutil.pipemodbase import PipeModBase
14 from nmutil.extend import exts
15 from soc.fu.trap.pipe_data import TrapInputData, TrapOutputData
16 from soc.fu.branch.main_stage import br_ext
17 from soc.decoder.power_enums import InternalOp
18
19 from soc.decoder.power_fields import DecodeFields
20 from soc.decoder.power_fieldsn import SignalBitRange
21
22 from soc.decoder.power_decoder2 import (TT_FP, TT_PRIV, TT_TRAP, TT_ADDR,
23 TT_ILLEG)
24 from soc.consts import MSR, PI
25
26
27 def msr_copy(msr_o, msr_i, zero_me=True):
28 """msr_copy
29 ISA says this:
30 Defined MSR bits are classified as either full func tion or partial
31 function. Full function MSR bits are saved in SRR1 or HSRR1 when
32 an interrupt other than a System Call Vectored interrupt occurs and
33 restored by rfscv, rfid, or hrfid, while partial function MSR bits
34 are not saved or restored. Full function MSR bits lie in the range
35 0:32, 37:41, and 48:63, and partial function MSR bits lie in the
36 range 33:36 and 42:47. (Note this is IBM bit numbering).
37 """
38 l = []
39 if zero_me:
40 l.append(msr_o.eq(0))
41 for stt, end in [(0,16), (22, 27), (31, 64)]:
42 l.append(msr_o[stt:end].eq(msr_i[stt:end]))
43 return l
44
45
46 def msr_check_pr(m, msr):
47 """msr_check_pr: checks "problem state"
48 """
49 comb = m.d.comb
50 with m.If(msr[MSR.PR]):
51 comb += msr[MSR.EE].eq(1) # set external interrupt bit
52 comb += msr[MSR.IR].eq(1) # set instruction relocation bit
53 comb += msr[MSR.DR].eq(1) # set data relocation bit
54
55
56 class TrapMainStage(PipeModBase):
57 def __init__(self, pspec):
58 super().__init__(pspec, "main")
59 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
60 self.fields.create_specs()
61
62 def trap(self, m, trap_addr, return_addr):
63 """trap. sets new PC, stores MSR and old PC in SRR1 and SRR0
64 """
65 comb = m.d.comb
66 msr_i = self.i.msr
67 nia_o, srr0_o, srr1_o = self.o.nia, self.o.srr0, self.o.srr1
68
69 # trap address
70 comb += nia_o.data.eq(trap_addr)
71 comb += nia_o.ok.eq(1)
72
73 # addr to begin from on return
74 comb += srr0_o.data.eq(return_addr)
75 comb += srr0_o.ok.eq(1)
76
77 # take a copy of the current MSR in SRR1
78 comb += msr_copy(srr1_o.data, msr_i) # old MSR
79 comb += srr1_o.ok.eq(1)
80
81 def ispec(self):
82 return TrapInputData(self.pspec)
83
84 def ospec(self):
85 return TrapOutputData(self.pspec)
86
87 def elaborate(self, platform):
88 m = Module()
89 comb = m.d.comb
90 op = self.i.ctx.op
91
92 # convenience variables
93 a_i, b_i, cia_i, msr_i = self.i.a, self.i.b, self.i.cia, self.i.msr
94 srr0_i, srr1_i = self.i.srr0, self.i.srr1
95 o, msr_o, nia_o = self.o.o, self.o.msr, self.o.nia
96 srr0_o, srr1_o = self.o.srr0, self.o.srr1
97 traptype, trapaddr = op.traptype, op.trapaddr
98
99 # take copy of D-Form TO field
100 i_fields = self.fields.FormD
101 to = Signal(i_fields.TO[0:-1].shape())
102 comb += to.eq(i_fields.TO[0:-1])
103
104 # signed/unsigned temporaries for RA and RB
105 a_s = Signal(signed(64), reset_less=True)
106 b_s = Signal(signed(64), reset_less=True)
107
108 a = Signal(64, reset_less=True)
109 b = Signal(64, reset_less=True)
110
111 # set up A and B comparison (truncate/sign-extend if 32 bit)
112 with m.If(op.is_32bit):
113 comb += a_s.eq(exts(a_i, 32, 64))
114 comb += b_s.eq(exts(b_i, 32, 64))
115 comb += a.eq(a_i[0:32])
116 comb += b.eq(b_i[0:32])
117 with m.Else():
118 comb += a_s.eq(a_i)
119 comb += b_s.eq(b_i)
120 comb += a.eq(a_i)
121 comb += b.eq(b_i)
122
123 # establish comparison bits
124 lt_s = Signal(reset_less=True)
125 gt_s = Signal(reset_less=True)
126 lt_u = Signal(reset_less=True)
127 gt_u = Signal(reset_less=True)
128 equal = Signal(reset_less=True)
129
130 comb += lt_s.eq(a_s < b_s)
131 comb += gt_s.eq(a_s > b_s)
132 comb += lt_u.eq(a < b)
133 comb += gt_u.eq(a > b)
134 comb += equal.eq(a == b)
135
136 # They're in reverse bit order because POWER.
137 # Check V3.0B Book 1, Appendix C.6 for chart
138 trap_bits = Signal(5, reset_less=True)
139 comb += trap_bits.eq(Cat(gt_u, lt_u, equal, gt_s, lt_s))
140
141 # establish if the trap should go ahead (any tests requested in TO)
142 # or if traptype is set already
143 should_trap = Signal(reset_less=True)
144 comb += should_trap.eq((trap_bits & to).any() | traptype.any())
145
146 # TODO: some #defines for the bits n stuff.
147 with m.Switch(op.insn_type):
148 #### trap ####
149 with m.Case(InternalOp.OP_TRAP):
150 # trap instructions (tw, twi, td, tdi)
151 with m.If(should_trap):
152 # generate trap-type program interrupt
153 self.trap(m, trapaddr<<4, cia_i)
154 with m.If(traptype == 0):
155 # say trap occurred (see 3.0B Book III 7.5.9)
156 comb += srr1_o.data[PI.TRAP].eq(1)
157 with m.If(traptype & TT_PRIV):
158 comb += srr1_o.data[PI.PRIV].eq(1)
159 with m.If(traptype & TT_FP):
160 comb += srr1_o.data[PI.FP].eq(1)
161 with m.If(traptype & TT_ADDR):
162 comb += srr1_o.data[PI.ADR].eq(1)
163 with m.If(traptype & TT_ILLEG):
164 comb += srr1_o.data[PI.ILLEG].eq(1)
165
166 # move to MSR
167 with m.Case(InternalOp.OP_MTMSRD):
168 L = self.fields.FormX.L[0:-1] # X-Form field L
169 with m.If(L):
170 # just update EE and RI
171 comb += msr_o.data[MSR.EE].eq(a_i[MSR.EE])
172 comb += msr_o.data[MSR.RI].eq(a_i[MSR.RI])
173 with m.Else():
174 # Architecture says to leave out bits 3 (HV), 51 (ME)
175 # and 63 (LE) (IBM bit numbering)
176 for stt, end in [(1,12), (13, 60), (61, 64)]:
177 comb += msr_o.data[stt:end].eq(a_i[stt:end])
178 msr_check_pr(m, msr_o.data)
179 comb += msr_o.ok.eq(1)
180
181 # move from MSR
182 with m.Case(InternalOp.OP_MFMSR):
183 # TODO: some of the bits need zeroing? apparently not
184 comb += o.data.eq(msr_i)
185 comb += o.ok.eq(1)
186
187 with m.Case(InternalOp.OP_RFID):
188 # XXX f_out.virt_mode <= b_in(MSR.IR) or b_in(MSR.PR);
189 # XXX f_out.priv_mode <= not b_in(MSR.PR);
190
191 # return addr was in srr0
192 comb += nia_o.data.eq(br_ext(srr0_i[2:]))
193 comb += nia_o.ok.eq(1)
194 # MSR was in srr1
195 comb += msr_copy(msr_o.data, srr1_i, zero_me=False) # don't zero
196 msr_check_pr(m, msr_o.data)
197 comb += msr_o.ok.eq(1)
198
199 # OP_SC
200 with m.Case(InternalOp.OP_SC):
201 # TODO: scv must generate illegal instruction. this is
202 # the decoder's job, not ours, here.
203
204 # jump to the trap address, return at cia+4
205 self.trap(m, 0xc00, cia_i+4)
206
207 # TODO (later)
208 #with m.Case(InternalOp.OP_ADDPCIS):
209 # pass
210
211 comb += self.o.ctx.eq(self.i.ctx)
212
213 return m