convert assigned values to SVSHAPE when writing to SVSHAPE[0-3] SPRs
[openpower-isa.git] / src / openpower / decoder / isa / caller.py
1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020 Michael Nolan
4 # Funded by NLnet http://nlnet.nl
5 """core of the python-based POWER9 simulator
6
7 this is part of a cycle-accurate POWER9 simulator. its primary purpose is
8 not speed, it is for both learning and educational purposes, as well as
9 a method of verifying the HDL.
10
11 related bugs:
12
13 * https://bugs.libre-soc.org/show_bug.cgi?id=424
14 """
15
16 from collections import namedtuple
17 from copy import deepcopy
18 from functools import wraps
19 import os
20 import sys
21
22 from nmigen.sim import Settle
23 import openpower.syscalls
24 from openpower.consts import (MSRb, PIb, # big-endian (PowerISA versions)
25 SVP64CROffs, SVP64MODEb)
26 from openpower.decoder.helpers import (ISACallerHelper, ISAFPHelpers, exts,
27 gtu, undefined, copy_assign_rhs)
28 from openpower.decoder.isa.mem import Mem, MemMMap, MemException
29 from openpower.decoder.isa.radixmmu import RADIX
30 from openpower.decoder.isa.svshape import SVSHAPE
31 from openpower.decoder.isa.svstate import SVP64State
32 from openpower.decoder.orderedset import OrderedSet
33 from openpower.decoder.power_enums import (FPTRANS_INSNS, CRInSel, CROutSel,
34 In1Sel, In2Sel, In3Sel, LDSTMode,
35 MicrOp, OutSel, SVMode,
36 SVP64LDSTmode, SVP64PredCR,
37 SVP64PredInt, SVP64PredMode,
38 SVP64RMMode, SVPType, XER_bits,
39 insns, spr_byname, spr_dict,
40 BFP_FLAG_NAMES)
41 from openpower.insndb.core import SVP64Instruction
42 from openpower.decoder.power_svp64 import SVP64RM, decode_extra
43 from openpower.decoder.selectable_int import (FieldSelectableInt,
44 SelectableInt, selectconcat,
45 EFFECTIVELY_UNLIMITED)
46 from openpower.consts import DEFAULT_MSR
47 from openpower.fpscr import FPSCRState
48 from openpower.xer import XERState
49 from openpower.util import LogType, log
50
51 LDST_UPDATE_INSNS = ['ldu', 'lwzu', 'lbzu', 'lhzu', 'lhau', 'lfsu', 'lfdu',
52 'stwu', 'stbu', 'sthu', 'stfsu', 'stfdu', 'stdu',
53 ]
54
55
56 instruction_info = namedtuple('instruction_info',
57 'func read_regs uninit_regs write_regs ' +
58 'special_regs op_fields form asmregs')
59
60 special_sprs = {
61 'LR': 8,
62 'CTR': 9,
63 'TAR': 815,
64 'XER': 1,
65 'VRSAVE': 256}
66
67
68 # rrright. this is here basically because the compiler pywriter returns
69 # results in a specific priority order. to make sure regs match up they
70 # need partial sorting. sigh.
71 REG_SORT_ORDER = {
72 # TODO (lkcl): adjust other registers that should be in a particular order
73 # probably CA, CA32, and CR
74 "FRT": 0,
75 "FRA": 0,
76 "FRB": 0,
77 "FRC": 0,
78 "FRS": 0,
79 "RT": 0,
80 "RA": 0,
81 "RB": 0,
82 "RC": 0,
83 "RS": 0,
84 "BI": 0,
85 "CR": 0,
86 "LR": 0,
87 "CTR": 0,
88 "TAR": 0,
89 "MSR": 0,
90 "SVSTATE": 0,
91 "SVSHAPE0": 0,
92 "SVSHAPE1": 0,
93 "SVSHAPE2": 0,
94 "SVSHAPE3": 0,
95
96 "CA": 0,
97 "CA32": 0,
98
99 "FPSCR": 1,
100
101 "overflow": 7, # should definitely be last
102 "CR0": 8, # likewise
103 }
104
105 fregs = ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
106
107
108 def get_masked_reg(regs, base, offs, ew_bits):
109 # rrrright. start by breaking down into row/col, based on elwidth
110 gpr_offs = offs // (64 // ew_bits)
111 gpr_col = offs % (64 // ew_bits)
112 # compute the mask based on ew_bits
113 mask = (1 << ew_bits) - 1
114 # now select the 64-bit register, but get its value (easier)
115 val = regs[base + gpr_offs]
116 # shift down so element we want is at LSB
117 val >>= gpr_col * ew_bits
118 # mask so we only return the LSB element
119 return val & mask
120
121
122 def set_masked_reg(regs, base, offs, ew_bits, value):
123 # rrrright. start by breaking down into row/col, based on elwidth
124 gpr_offs = offs // (64//ew_bits)
125 gpr_col = offs % (64//ew_bits)
126 # compute the mask based on ew_bits
127 mask = (1 << ew_bits)-1
128 # now select the 64-bit register, but get its value (easier)
129 val = regs[base+gpr_offs]
130 # now mask out the bit we don't want
131 val = val & ~(mask << (gpr_col*ew_bits))
132 # then wipe the bit we don't want from the value
133 value = value & mask
134 # OR the new value in, shifted up
135 val |= value << (gpr_col*ew_bits)
136 regs[base+gpr_offs] = val
137
138
139 def create_args(reglist, extra=None):
140 retval = list(OrderedSet(reglist))
141 retval.sort(key=lambda reg: REG_SORT_ORDER.get(reg, 0))
142 if extra is not None:
143 return [extra] + retval
144 return retval
145
146
147 def create_full_args(*, read_regs, special_regs, uninit_regs, write_regs,
148 extra=None):
149 return create_args([
150 *read_regs, *uninit_regs, *write_regs, *special_regs], extra=extra)
151
152
153 class GPR(dict):
154 def __init__(self, decoder, isacaller, svstate, regfile):
155 dict.__init__(self)
156 self.sd = decoder
157 self.isacaller = isacaller
158 self.svstate = svstate
159 for i in range(len(regfile)):
160 self[i] = SelectableInt(regfile[i], 64)
161
162 def __call__(self, ridx, is_vec=False, offs=0, elwidth=64):
163 if isinstance(ridx, SelectableInt):
164 ridx = ridx.value
165 if elwidth == 64:
166 return self[ridx+offs]
167 # rrrright. start by breaking down into row/col, based on elwidth
168 gpr_offs = offs // (64//elwidth)
169 gpr_col = offs % (64//elwidth)
170 # now select the 64-bit register, but get its value (easier)
171 val = self[ridx+gpr_offs].value
172 # now shift down and mask out
173 val = val >> (gpr_col*elwidth) & ((1 << elwidth)-1)
174 # finally, return a SelectableInt at the required elwidth
175 log("GPR call", ridx, "isvec", is_vec, "offs", offs,
176 "elwid", elwidth, "offs/col", gpr_offs, gpr_col, "val", hex(val))
177 return SelectableInt(val, elwidth)
178
179 def set_form(self, form):
180 self.form = form
181
182 def write(self, rnum, value, is_vec=False, elwidth=64):
183 # get internal value
184 if isinstance(rnum, SelectableInt):
185 rnum = rnum.value
186 if isinstance(value, SelectableInt):
187 value = value.value
188 # compatibility...
189 if isinstance(rnum, tuple):
190 rnum, base, offs = rnum
191 else:
192 base, offs = rnum, 0
193 # rrrright. start by breaking down into row/col, based on elwidth
194 gpr_offs = offs // (64//elwidth)
195 gpr_col = offs % (64//elwidth)
196 # compute the mask based on elwidth
197 mask = (1 << elwidth)-1
198 # now select the 64-bit register, but get its value (easier)
199 val = self[base+gpr_offs].value
200 # now mask out the bit we don't want
201 val = val & ~(mask << (gpr_col*elwidth))
202 # then wipe the bit we don't want from the value
203 value = value & mask
204 # OR the new value in, shifted up
205 val |= value << (gpr_col*elwidth)
206 # finally put the damn value into the regfile
207 log("GPR write", base, "isvec", is_vec, "offs", offs,
208 "elwid", elwidth, "offs/col", gpr_offs, gpr_col, "val", hex(val),
209 "@", base+gpr_offs)
210 dict.__setitem__(self, base+gpr_offs, SelectableInt(val, 64))
211
212 def __setitem__(self, rnum, value):
213 # rnum = rnum.value # only SelectableInt allowed
214 log("GPR setitem", rnum, value)
215 if isinstance(rnum, SelectableInt):
216 rnum = rnum.value
217 dict.__setitem__(self, rnum, value)
218
219 def getz(self, rnum):
220 # rnum = rnum.value # only SelectableInt allowed
221 log("GPR getzero?", rnum)
222 if rnum == 0:
223 return SelectableInt(0, 64)
224 return self[rnum]
225
226 def _get_regnum(self, attr):
227 getform = self.sd.sigforms[self.form]
228 rnum = getattr(getform, attr)
229 return rnum
230
231 def ___getitem__(self, attr):
232 """ XXX currently not used
233 """
234 rnum = self._get_regnum(attr)
235 log("GPR getitem", attr, rnum)
236 return self.regfile[rnum]
237
238 def dump(self, printout=True):
239 res = []
240 for i in range(len(self)):
241 res.append(self[i].value)
242 if printout:
243 for i in range(0, len(res), 8):
244 s = []
245 for j in range(8):
246 s.append("%08x" % res[i+j])
247 s = ' '.join(s)
248 print("reg", "%2d" % i, s)
249 return res
250
251
252 class SPR(dict):
253 def __init__(self, dec2, initial_sprs={}, gpr=None):
254 self.sd = dec2
255 self.gpr = gpr # for SVSHAPE[0-3]
256 dict.__init__(self)
257 for key, v in initial_sprs.items():
258 if isinstance(key, SelectableInt):
259 key = key.value
260 key = special_sprs.get(key, key)
261 if isinstance(key, int):
262 info = spr_dict[key]
263 else:
264 info = spr_byname[key]
265 if not isinstance(v, SelectableInt):
266 v = SelectableInt(v, info.length)
267 self[key] = v
268
269 def __getitem__(self, key):
270 #log("get spr", key)
271 #log("dict", self.items())
272 # if key in special_sprs get the special spr, otherwise return key
273 if isinstance(key, SelectableInt):
274 key = key.value
275 if isinstance(key, int):
276 key = spr_dict[key].SPR
277 key = special_sprs.get(key, key)
278 if key == 'HSRR0': # HACK!
279 key = 'SRR0'
280 if key == 'HSRR1': # HACK!
281 key = 'SRR1'
282 if key in self:
283 res = dict.__getitem__(self, key)
284 else:
285 if isinstance(key, int):
286 info = spr_dict[key]
287 else:
288 info = spr_byname[key]
289 self[key] = SelectableInt(0, info.length)
290 res = dict.__getitem__(self, key)
291 #log("spr returning", key, res)
292 return res
293
294 def __setitem__(self, key, value):
295 if isinstance(key, SelectableInt):
296 key = key.value
297 if isinstance(key, int):
298 key = spr_dict[key].SPR
299 log("spr key", key)
300 key = special_sprs.get(key, key)
301 if key == 'HSRR0': # HACK!
302 self.__setitem__('SRR0', value)
303 if key == 'HSRR1': # HACK!
304 self.__setitem__('SRR1', value)
305 if key == 1:
306 value = XERState(value)
307 if key in ('SVSHAPE0', 'SVSHAPE1', 'SVSHAPE2', 'SVSHAPE3'):
308 value = SVSHAPE(value, self.gpr)
309 log("setting spr", key, value)
310 dict.__setitem__(self, key, value)
311
312 def __call__(self, ridx):
313 return self[ridx]
314
315 def dump(self, printout=True):
316 res = []
317 keys = list(self.keys())
318 # keys.sort()
319 for k in keys:
320 sprname = spr_dict.get(k, None)
321 if sprname is None:
322 sprname = k
323 else:
324 sprname = sprname.SPR
325 res.append((sprname, self[k].value))
326 if printout:
327 for sprname, value in res:
328 print(" ", sprname, hex(value))
329 return res
330
331
332 class PC:
333 def __init__(self, pc_init=0):
334 self.CIA = SelectableInt(pc_init, 64)
335 self.NIA = self.CIA + SelectableInt(4, 64) # only true for v3.0B!
336
337 def update_nia(self, is_svp64):
338 increment = 8 if is_svp64 else 4
339 self.NIA = self.CIA + SelectableInt(increment, 64)
340
341 def update(self, namespace, is_svp64):
342 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
343 """
344 self.CIA = namespace['NIA'].narrow(64)
345 self.update_nia(is_svp64)
346 namespace['CIA'] = self.CIA
347 namespace['NIA'] = self.NIA
348
349
350 # CR register fields
351 # See PowerISA Version 3.0 B Book 1
352 # Section 2.3.1 Condition Register pages 30 - 31
353 class CRFields:
354 LT = FL = 0 # negative, less than, floating-point less than
355 GT = FG = 1 # positive, greater than, floating-point greater than
356 EQ = FE = 2 # equal, floating-point equal
357 SO = FU = 3 # summary overflow, floating-point unordered
358
359 def __init__(self, init=0):
360 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
361 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
362 self.cr = SelectableInt(init, 64) # underlying reg
363 # field-selectable versions of Condition Register TODO check bitranges?
364 self.crl = []
365 for i in range(8):
366 bits = tuple(range(i*4+32, (i+1)*4+32))
367 _cr = FieldSelectableInt(self.cr, bits)
368 self.crl.append(_cr)
369
370
371 # decode SVP64 predicate integer to reg number and invert
372 def get_predint(gpr, mask):
373 r3 = gpr(3)
374 r10 = gpr(10)
375 r30 = gpr(30)
376 log("get_predint", mask, SVP64PredInt.ALWAYS.value)
377 if mask == SVP64PredInt.ALWAYS.value:
378 return 0xffff_ffff_ffff_ffff # 64 bits of 1
379 if mask == SVP64PredInt.R3_UNARY.value:
380 return 1 << (r3.value & 0b111111)
381 if mask == SVP64PredInt.R3.value:
382 return r3.value
383 if mask == SVP64PredInt.R3_N.value:
384 return ~r3.value
385 if mask == SVP64PredInt.R10.value:
386 return r10.value
387 if mask == SVP64PredInt.R10_N.value:
388 return ~r10.value
389 if mask == SVP64PredInt.R30.value:
390 return r30.value
391 if mask == SVP64PredInt.R30_N.value:
392 return ~r30.value
393
394
395 # decode SVP64 predicate CR to reg number and invert status
396 def _get_predcr(mask):
397 if mask == SVP64PredCR.LT.value:
398 return 0, 1
399 if mask == SVP64PredCR.GE.value:
400 return 0, 0
401 if mask == SVP64PredCR.GT.value:
402 return 1, 1
403 if mask == SVP64PredCR.LE.value:
404 return 1, 0
405 if mask == SVP64PredCR.EQ.value:
406 return 2, 1
407 if mask == SVP64PredCR.NE.value:
408 return 2, 0
409 if mask == SVP64PredCR.SO.value:
410 return 3, 1
411 if mask == SVP64PredCR.NS.value:
412 return 3, 0
413
414
415 # read individual CR fields (0..VL-1), extract the required bit
416 # and construct the mask
417 def get_predcr(crl, mask, vl):
418 idx, noninv = _get_predcr(mask)
419 mask = 0
420 for i in range(vl):
421 cr = crl[i+SVP64CROffs.CRPred]
422 if cr[idx].value == noninv:
423 mask |= (1 << i)
424 return mask
425
426
427 # TODO, really should just be using PowerDecoder2
428 def get_idx_map(dec2, name):
429 op = dec2.dec.op
430 in1_sel = yield op.in1_sel
431 in2_sel = yield op.in2_sel
432 in3_sel = yield op.in3_sel
433 in1 = yield dec2.e.read_reg1.data
434 # identify which regnames map to in1/2/3
435 if name == 'RA' or name == 'RA_OR_ZERO':
436 if (in1_sel == In1Sel.RA.value or
437 (in1_sel == In1Sel.RA_OR_ZERO.value and in1 != 0)):
438 return 1
439 if in1_sel == In1Sel.RA_OR_ZERO.value:
440 return 1
441 elif name == 'RB':
442 if in2_sel == In2Sel.RB.value:
443 return 2
444 if in3_sel == In3Sel.RB.value:
445 return 3
446 # XXX TODO, RC doesn't exist yet!
447 elif name == 'RC':
448 if in3_sel == In3Sel.RC.value:
449 return 3
450 elif name in ['EA', 'RS']:
451 if in1_sel == In1Sel.RS.value:
452 return 1
453 if in2_sel == In2Sel.RS.value:
454 return 2
455 if in3_sel == In3Sel.RS.value:
456 return 3
457 elif name == 'FRA':
458 if in1_sel == In1Sel.FRA.value:
459 return 1
460 if in3_sel == In3Sel.FRA.value:
461 return 3
462 elif name == 'FRB':
463 if in2_sel == In2Sel.FRB.value:
464 return 2
465 elif name == 'FRC':
466 if in3_sel == In3Sel.FRC.value:
467 return 3
468 elif name == 'FRS':
469 if in1_sel == In1Sel.FRS.value:
470 return 1
471 if in3_sel == In3Sel.FRS.value:
472 return 3
473 elif name == 'FRT':
474 if in1_sel == In1Sel.FRT.value:
475 return 1
476 elif name == 'RT':
477 if in1_sel == In1Sel.RT.value:
478 return 1
479 return None
480
481
482 # TODO, really should just be using PowerDecoder2
483 def get_idx_in(dec2, name, ewmode=False):
484 idx = yield from get_idx_map(dec2, name)
485 if idx is None:
486 return None, False
487 op = dec2.dec.op
488 in1_sel = yield op.in1_sel
489 in2_sel = yield op.in2_sel
490 in3_sel = yield op.in3_sel
491 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
492 in1 = yield dec2.e.read_reg1.data
493 in2 = yield dec2.e.read_reg2.data
494 in3 = yield dec2.e.read_reg3.data
495 if ewmode:
496 in1_base = yield dec2.e.read_reg1.base
497 in2_base = yield dec2.e.read_reg2.base
498 in3_base = yield dec2.e.read_reg3.base
499 in1_offs = yield dec2.e.read_reg1.offs
500 in2_offs = yield dec2.e.read_reg2.offs
501 in3_offs = yield dec2.e.read_reg3.offs
502 in1 = (in1, in1_base, in1_offs)
503 in2 = (in2, in2_base, in2_offs)
504 in3 = (in3, in3_base, in3_offs)
505
506 in1_isvec = yield dec2.in1_isvec
507 in2_isvec = yield dec2.in2_isvec
508 in3_isvec = yield dec2.in3_isvec
509 log("get_idx_in in1", name, in1_sel, In1Sel.RA.value,
510 in1, in1_isvec)
511 log("get_idx_in in2", name, in2_sel, In2Sel.RB.value,
512 in2, in2_isvec)
513 log("get_idx_in in3", name, in3_sel, In3Sel.RS.value,
514 in3, in3_isvec)
515 log("get_idx_in FRS in3", name, in3_sel, In3Sel.FRS.value,
516 in3, in3_isvec)
517 log("get_idx_in FRB in2", name, in2_sel, In2Sel.FRB.value,
518 in2, in2_isvec)
519 log("get_idx_in FRC in3", name, in3_sel, In3Sel.FRC.value,
520 in3, in3_isvec)
521 if idx == 1:
522 return in1, in1_isvec
523 if idx == 2:
524 return in2, in2_isvec
525 if idx == 3:
526 return in3, in3_isvec
527 return None, False
528
529
530 # TODO, really should just be using PowerDecoder2
531 def get_cr_in(dec2, name):
532 op = dec2.dec.op
533 in_sel = yield op.cr_in
534 in_bitfield = yield dec2.dec_cr_in.cr_bitfield.data
535 sv_cr_in = yield op.sv_cr_in
536 spec = yield dec2.crin_svdec.spec
537 sv_override = yield dec2.dec_cr_in.sv_override
538 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
539 in1 = yield dec2.e.read_cr1.data
540 cr_isvec = yield dec2.cr_in_isvec
541 log("get_cr_in", in_sel, CROutSel.CR0.value, in1, cr_isvec)
542 log(" sv_cr_in", sv_cr_in)
543 log(" cr_bf", in_bitfield)
544 log(" spec", spec)
545 log(" override", sv_override)
546 # identify which regnames map to in / o2
547 if name == 'BI':
548 if in_sel == CRInSel.BI.value:
549 return in1, cr_isvec
550 log("get_cr_in not found", name)
551 return None, False
552
553
554 # TODO, really should just be using PowerDecoder2
555 def get_cr_out(dec2, name):
556 op = dec2.dec.op
557 out_sel = yield op.cr_out
558 out_bitfield = yield dec2.dec_cr_out.cr_bitfield.data
559 sv_cr_out = yield op.sv_cr_out
560 spec = yield dec2.crout_svdec.spec
561 sv_override = yield dec2.dec_cr_out.sv_override
562 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
563 out = yield dec2.e.write_cr.data
564 o_isvec = yield dec2.cr_out_isvec
565 log("get_cr_out", out_sel, CROutSel.CR0.value, out, o_isvec)
566 log(" sv_cr_out", sv_cr_out)
567 log(" cr_bf", out_bitfield)
568 log(" spec", spec)
569 log(" override", sv_override)
570 # identify which regnames map to out / o2
571 if name == 'BF':
572 if out_sel == CROutSel.BF.value:
573 return out, o_isvec
574 if name == 'CR0':
575 if out_sel == CROutSel.CR0.value:
576 return out, o_isvec
577 if name == 'CR1': # these are not actually calculated correctly
578 if out_sel == CROutSel.CR1.value:
579 return out, o_isvec
580 # check RC1 set? if so return implicit vector, this is a REAL bad hack
581 RC1 = yield dec2.rm_dec.RC1
582 if RC1:
583 log("get_cr_out RC1 mode")
584 if name == 'CR0':
585 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
586 if name == 'CR1':
587 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
588 # nope - not found.
589 log("get_cr_out not found", name)
590 return None, False
591
592
593 # TODO, really should just be using PowerDecoder2
594 def get_out_map(dec2, name):
595 op = dec2.dec.op
596 out_sel = yield op.out_sel
597 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
598 out = yield dec2.e.write_reg.data
599 # identify which regnames map to out / o2
600 if name == 'RA':
601 if out_sel == OutSel.RA.value:
602 return True
603 elif name == 'RT':
604 if out_sel == OutSel.RT.value:
605 return True
606 if out_sel == OutSel.RT_OR_ZERO.value and out != 0:
607 return True
608 elif name == 'RT_OR_ZERO':
609 if out_sel == OutSel.RT_OR_ZERO.value:
610 return True
611 elif name == 'FRA':
612 if out_sel == OutSel.FRA.value:
613 return True
614 elif name == 'FRS':
615 if out_sel == OutSel.FRS.value:
616 return True
617 elif name == 'FRT':
618 if out_sel == OutSel.FRT.value:
619 return True
620 return False
621
622
623 # TODO, really should just be using PowerDecoder2
624 def get_idx_out(dec2, name, ewmode=False):
625 op = dec2.dec.op
626 out_sel = yield op.out_sel
627 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
628 out = yield dec2.e.write_reg.data
629 o_isvec = yield dec2.o_isvec
630 if ewmode:
631 offs = yield dec2.e.write_reg.offs
632 base = yield dec2.e.write_reg.base
633 out = (out, base, offs)
634 # identify which regnames map to out / o2
635 ismap = yield from get_out_map(dec2, name)
636 if ismap:
637 log("get_idx_out", name, out_sel, out, o_isvec)
638 return out, o_isvec
639 log("get_idx_out not found", name, out_sel, out, o_isvec)
640 return None, False
641
642
643 # TODO, really should just be using PowerDecoder2
644 def get_out2_map(dec2, name):
645 # check first if register is activated for write
646 op = dec2.dec.op
647 out_sel = yield op.out_sel
648 out = yield dec2.e.write_ea.data
649 out_ok = yield dec2.e.write_ea.ok
650 if not out_ok:
651 return False
652
653 if name in ['EA', 'RA']:
654 if hasattr(op, "upd"):
655 # update mode LD/ST uses read-reg A also as an output
656 upd = yield op.upd
657 log("get_idx_out2", upd, LDSTMode.update.value,
658 out_sel, OutSel.RA.value,
659 out)
660 if upd == LDSTMode.update.value:
661 return True
662 if name == 'RS':
663 fft_en = yield dec2.implicit_rs
664 if fft_en:
665 log("get_idx_out2", out_sel, OutSel.RS.value,
666 out)
667 return True
668 if name == 'FRS':
669 fft_en = yield dec2.implicit_rs
670 if fft_en:
671 log("get_idx_out2", out_sel, OutSel.FRS.value,
672 out)
673 return True
674 return False
675
676
677 # TODO, really should just be using PowerDecoder2
678 def get_idx_out2(dec2, name, ewmode=False):
679 # check first if register is activated for write
680 op = dec2.dec.op
681 out_sel = yield op.out_sel
682 out = yield dec2.e.write_ea.data
683 if ewmode:
684 offs = yield dec2.e.write_ea.offs
685 base = yield dec2.e.write_ea.base
686 out = (out, base, offs)
687 o_isvec = yield dec2.o2_isvec
688 ismap = yield from get_out2_map(dec2, name)
689 if ismap:
690 log("get_idx_out2", name, out_sel, out, o_isvec)
691 return out, o_isvec
692 return None, False
693
694
695 class StepLoop:
696 """deals with svstate looping.
697 """
698
699 def __init__(self, svstate):
700 self.svstate = svstate
701 self.new_iterators()
702
703 def new_iterators(self):
704 self.src_it = self.src_iterator()
705 self.dst_it = self.dst_iterator()
706 self.loopend = False
707 self.new_srcstep = 0
708 self.new_dststep = 0
709 self.new_ssubstep = 0
710 self.new_dsubstep = 0
711 self.pred_dst_zero = 0
712 self.pred_src_zero = 0
713
714 def src_iterator(self):
715 """source-stepping iterator
716 """
717 pack = self.svstate.pack
718
719 # source step
720 if pack:
721 # pack advances subvl in *outer* loop
722 while True: # outer subvl loop
723 while True: # inner vl loop
724 vl = self.svstate.vl
725 subvl = self.subvl
726 srcmask = self.srcmask
727 srcstep = self.svstate.srcstep
728 pred_src_zero = ((1 << srcstep) & srcmask) != 0
729 if self.pred_sz or pred_src_zero:
730 self.pred_src_zero = not pred_src_zero
731 log(" advance src", srcstep, vl,
732 self.svstate.ssubstep, subvl)
733 # yield actual substep/srcstep
734 yield (self.svstate.ssubstep, srcstep)
735 # the way yield works these could have been modified.
736 vl = self.svstate.vl
737 subvl = self.subvl
738 srcstep = self.svstate.srcstep
739 log(" advance src check", srcstep, vl,
740 self.svstate.ssubstep, subvl, srcstep == vl-1,
741 self.svstate.ssubstep == subvl)
742 if srcstep == vl-1: # end-point
743 self.svstate.srcstep = SelectableInt(0, 7) # reset
744 if self.svstate.ssubstep == subvl: # end-point
745 log(" advance pack stop")
746 return
747 break # exit inner loop
748 self.svstate.srcstep += SelectableInt(1, 7) # advance ss
749 subvl = self.subvl
750 if self.svstate.ssubstep == subvl: # end-point
751 self.svstate.ssubstep = SelectableInt(0, 2) # reset
752 log(" advance pack stop")
753 return
754 self.svstate.ssubstep += SelectableInt(1, 2)
755
756 else:
757 # these cannot be done as for-loops because SVSTATE may change
758 # (srcstep/substep may be modified, interrupted, subvl/vl change)
759 # but they *can* be done as while-loops as long as every SVSTATE
760 # "thing" is re-read every single time a yield gives indices
761 while True: # outer vl loop
762 while True: # inner subvl loop
763 vl = self.svstate.vl
764 subvl = self.subvl
765 srcmask = self.srcmask
766 srcstep = self.svstate.srcstep
767 pred_src_zero = ((1 << srcstep) & srcmask) != 0
768 if self.pred_sz or pred_src_zero:
769 self.pred_src_zero = not pred_src_zero
770 log(" advance src", srcstep, vl,
771 self.svstate.ssubstep, subvl)
772 # yield actual substep/srcstep
773 yield (self.svstate.ssubstep, srcstep)
774 if self.svstate.ssubstep == subvl: # end-point
775 self.svstate.ssubstep = SelectableInt(0, 2) # reset
776 break # exit inner loop
777 self.svstate.ssubstep += SelectableInt(1, 2)
778 vl = self.svstate.vl
779 if srcstep == vl-1: # end-point
780 self.svstate.srcstep = SelectableInt(0, 7) # reset
781 self.loopend = True
782 return
783 self.svstate.srcstep += SelectableInt(1, 7) # advance srcstep
784
785 def dst_iterator(self):
786 """dest-stepping iterator
787 """
788 unpack = self.svstate.unpack
789
790 # dest step
791 if unpack:
792 # pack advances subvl in *outer* loop
793 while True: # outer subvl loop
794 while True: # inner vl loop
795 vl = self.svstate.vl
796 subvl = self.subvl
797 dstmask = self.dstmask
798 dststep = self.svstate.dststep
799 pred_dst_zero = ((1 << dststep) & dstmask) != 0
800 if self.pred_dz or pred_dst_zero:
801 self.pred_dst_zero = not pred_dst_zero
802 log(" advance dst", dststep, vl,
803 self.svstate.dsubstep, subvl)
804 # yield actual substep/dststep
805 yield (self.svstate.dsubstep, dststep)
806 # the way yield works these could have been modified.
807 vl = self.svstate.vl
808 dststep = self.svstate.dststep
809 log(" advance dst check", dststep, vl,
810 self.svstate.ssubstep, subvl)
811 if dststep == vl-1: # end-point
812 self.svstate.dststep = SelectableInt(0, 7) # reset
813 if self.svstate.dsubstep == subvl: # end-point
814 log(" advance unpack stop")
815 return
816 break
817 self.svstate.dststep += SelectableInt(1, 7) # advance ds
818 subvl = self.subvl
819 if self.svstate.dsubstep == subvl: # end-point
820 self.svstate.dsubstep = SelectableInt(0, 2) # reset
821 log(" advance unpack stop")
822 return
823 self.svstate.dsubstep += SelectableInt(1, 2)
824 else:
825 # these cannot be done as for-loops because SVSTATE may change
826 # (dststep/substep may be modified, interrupted, subvl/vl change)
827 # but they *can* be done as while-loops as long as every SVSTATE
828 # "thing" is re-read every single time a yield gives indices
829 while True: # outer vl loop
830 while True: # inner subvl loop
831 subvl = self.subvl
832 dstmask = self.dstmask
833 dststep = self.svstate.dststep
834 pred_dst_zero = ((1 << dststep) & dstmask) != 0
835 if self.pred_dz or pred_dst_zero:
836 self.pred_dst_zero = not pred_dst_zero
837 log(" advance dst", dststep, self.svstate.vl,
838 self.svstate.dsubstep, subvl)
839 # yield actual substep/dststep
840 yield (self.svstate.dsubstep, dststep)
841 if self.svstate.dsubstep == subvl: # end-point
842 self.svstate.dsubstep = SelectableInt(0, 2) # reset
843 break
844 self.svstate.dsubstep += SelectableInt(1, 2)
845 subvl = self.subvl
846 vl = self.svstate.vl
847 if dststep == vl-1: # end-point
848 self.svstate.dststep = SelectableInt(0, 7) # reset
849 return
850 self.svstate.dststep += SelectableInt(1, 7) # advance dststep
851
852 def src_iterate(self):
853 """source-stepping iterator
854 """
855 subvl = self.subvl
856 vl = self.svstate.vl
857 pack = self.svstate.pack
858 unpack = self.svstate.unpack
859 ssubstep = self.svstate.ssubstep
860 end_ssub = ssubstep == subvl
861 end_src = self.svstate.srcstep == vl-1
862 log(" pack/unpack/subvl", pack, unpack, subvl,
863 "end", end_src,
864 "sub", end_ssub)
865 # first source step
866 srcstep = self.svstate.srcstep
867 srcmask = self.srcmask
868 if pack:
869 # pack advances subvl in *outer* loop
870 while True:
871 assert srcstep <= vl-1
872 end_src = srcstep == vl-1
873 if end_src:
874 if end_ssub:
875 self.loopend = True
876 else:
877 self.svstate.ssubstep += SelectableInt(1, 2)
878 srcstep = 0 # reset
879 break
880 else:
881 srcstep += 1 # advance srcstep
882 if not self.srcstep_skip:
883 break
884 if ((1 << srcstep) & srcmask) != 0:
885 break
886 else:
887 log(" sskip", bin(srcmask), bin(1 << srcstep))
888 else:
889 # advance subvl in *inner* loop
890 if end_ssub:
891 while True:
892 assert srcstep <= vl-1
893 end_src = srcstep == vl-1
894 if end_src: # end-point
895 self.loopend = True
896 srcstep = 0
897 break
898 else:
899 srcstep += 1
900 if not self.srcstep_skip:
901 break
902 if ((1 << srcstep) & srcmask) != 0:
903 break
904 else:
905 log(" sskip", bin(srcmask), bin(1 << srcstep))
906 self.svstate.ssubstep = SelectableInt(0, 2) # reset
907 else:
908 # advance ssubstep
909 self.svstate.ssubstep += SelectableInt(1, 2)
910
911 self.svstate.srcstep = SelectableInt(srcstep, 7)
912 log(" advance src", self.svstate.srcstep, self.svstate.ssubstep,
913 self.loopend)
914
915 def dst_iterate(self):
916 """dest step iterator
917 """
918 vl = self.svstate.vl
919 subvl = self.subvl
920 pack = self.svstate.pack
921 unpack = self.svstate.unpack
922 dsubstep = self.svstate.dsubstep
923 end_dsub = dsubstep == subvl
924 dststep = self.svstate.dststep
925 end_dst = dststep == vl-1
926 dstmask = self.dstmask
927 log(" pack/unpack/subvl", pack, unpack, subvl,
928 "end", end_dst,
929 "sub", end_dsub)
930 # now dest step
931 if unpack:
932 # unpack advances subvl in *outer* loop
933 while True:
934 assert dststep <= vl-1
935 end_dst = dststep == vl-1
936 if end_dst:
937 if end_dsub:
938 self.loopend = True
939 else:
940 self.svstate.dsubstep += SelectableInt(1, 2)
941 dststep = 0 # reset
942 break
943 else:
944 dststep += 1 # advance dststep
945 if not self.dststep_skip:
946 break
947 if ((1 << dststep) & dstmask) != 0:
948 break
949 else:
950 log(" dskip", bin(dstmask), bin(1 << dststep))
951 else:
952 # advance subvl in *inner* loop
953 if end_dsub:
954 while True:
955 assert dststep <= vl-1
956 end_dst = dststep == vl-1
957 if end_dst: # end-point
958 self.loopend = True
959 dststep = 0
960 break
961 else:
962 dststep += 1
963 if not self.dststep_skip:
964 break
965 if ((1 << dststep) & dstmask) != 0:
966 break
967 else:
968 log(" dskip", bin(dstmask), bin(1 << dststep))
969 self.svstate.dsubstep = SelectableInt(0, 2) # reset
970 else:
971 # advance ssubstep
972 self.svstate.dsubstep += SelectableInt(1, 2)
973
974 self.svstate.dststep = SelectableInt(dststep, 7)
975 log(" advance dst", self.svstate.dststep, self.svstate.dsubstep,
976 self.loopend)
977
978 def at_loopend(self):
979 """tells if this is the last possible element. uses the cached values
980 for src/dst-step and sub-steps
981 """
982 subvl = self.subvl
983 vl = self.svstate.vl
984 srcstep, dststep = self.new_srcstep, self.new_dststep
985 ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
986 end_ssub = ssubstep == subvl
987 end_dsub = dsubstep == subvl
988 if srcstep == vl-1 and end_ssub:
989 return True
990 if dststep == vl-1 and end_dsub:
991 return True
992 return False
993
994 def advance_svstate_steps(self):
995 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
996 TODO when Pack/Unpack is set, substep becomes the *outer* loop
997 """
998 self.subvl = yield self.dec2.rm_dec.rm_in.subvl
999 if self.loopend: # huhn??
1000 return
1001 self.src_iterate()
1002 self.dst_iterate()
1003
1004 def read_src_mask(self):
1005 """read/update pred_sz and src mask
1006 """
1007 # get SVSTATE VL (oh and print out some debug stuff)
1008 vl = self.svstate.vl
1009 srcstep = self.svstate.srcstep
1010 ssubstep = self.svstate.ssubstep
1011
1012 # get predicate mask (all 64 bits)
1013 srcmask = 0xffff_ffff_ffff_ffff
1014
1015 pmode = yield self.dec2.rm_dec.predmode
1016 sv_ptype = yield self.dec2.dec.op.SV_Ptype
1017 srcpred = yield self.dec2.rm_dec.srcpred
1018 dstpred = yield self.dec2.rm_dec.dstpred
1019 pred_sz = yield self.dec2.rm_dec.pred_sz
1020 if pmode == SVP64PredMode.INT.value:
1021 srcmask = dstmask = get_predint(self.gpr, dstpred)
1022 if sv_ptype == SVPType.P2.value:
1023 srcmask = get_predint(self.gpr, srcpred)
1024 elif pmode == SVP64PredMode.CR.value:
1025 srcmask = dstmask = get_predcr(self.crl, dstpred, vl)
1026 if sv_ptype == SVPType.P2.value:
1027 srcmask = get_predcr(self.crl, srcpred, vl)
1028 # work out if the ssubsteps are completed
1029 ssubstart = ssubstep == 0
1030 log(" pmode", pmode)
1031 log(" ptype", sv_ptype)
1032 log(" srcpred", bin(srcpred))
1033 log(" srcmask", bin(srcmask))
1034 log(" pred_sz", bin(pred_sz))
1035 log(" ssubstart", ssubstart)
1036
1037 # store all that above
1038 self.srcstep_skip = False
1039 self.srcmask = srcmask
1040 self.pred_sz = pred_sz
1041 self.new_ssubstep = ssubstep
1042 log(" new ssubstep", ssubstep)
1043 # until the predicate mask has a "1" bit... or we run out of VL
1044 # let srcstep==VL be the indicator to move to next instruction
1045 if not pred_sz:
1046 self.srcstep_skip = True
1047
1048 def read_dst_mask(self):
1049 """same as read_src_mask - check and record everything needed
1050 """
1051 # get SVSTATE VL (oh and print out some debug stuff)
1052 # yield Delay(1e-10) # make changes visible
1053 vl = self.svstate.vl
1054 dststep = self.svstate.dststep
1055 dsubstep = self.svstate.dsubstep
1056
1057 # get predicate mask (all 64 bits)
1058 dstmask = 0xffff_ffff_ffff_ffff
1059
1060 pmode = yield self.dec2.rm_dec.predmode
1061 reverse_gear = yield self.dec2.rm_dec.reverse_gear
1062 sv_ptype = yield self.dec2.dec.op.SV_Ptype
1063 dstpred = yield self.dec2.rm_dec.dstpred
1064 pred_dz = yield self.dec2.rm_dec.pred_dz
1065 if pmode == SVP64PredMode.INT.value:
1066 dstmask = get_predint(self.gpr, dstpred)
1067 elif pmode == SVP64PredMode.CR.value:
1068 dstmask = get_predcr(self.crl, dstpred, vl)
1069 # work out if the ssubsteps are completed
1070 dsubstart = dsubstep == 0
1071 log(" pmode", pmode)
1072 log(" ptype", sv_ptype)
1073 log(" dstpred", bin(dstpred))
1074 log(" dstmask", bin(dstmask))
1075 log(" pred_dz", bin(pred_dz))
1076 log(" dsubstart", dsubstart)
1077
1078 self.dststep_skip = False
1079 self.dstmask = dstmask
1080 self.pred_dz = pred_dz
1081 self.new_dsubstep = dsubstep
1082 log(" new dsubstep", dsubstep)
1083 if not pred_dz:
1084 self.dststep_skip = True
1085
1086 def svstate_pre_inc(self):
1087 """check if srcstep/dststep need to skip over masked-out predicate bits
1088 note that this is not supposed to do anything to substep,
1089 it is purely for skipping masked-out bits
1090 """
1091
1092 self.subvl = yield self.dec2.rm_dec.rm_in.subvl
1093 yield from self.read_src_mask()
1094 yield from self.read_dst_mask()
1095
1096 self.skip_src()
1097 self.skip_dst()
1098
1099 def skip_src(self):
1100
1101 srcstep = self.svstate.srcstep
1102 srcmask = self.srcmask
1103 pred_src_zero = self.pred_sz
1104 vl = self.svstate.vl
1105 # srcstep-skipping opportunity identified
1106 if self.srcstep_skip:
1107 # cannot do this with sv.bc - XXX TODO
1108 if srcmask == 0:
1109 self.loopend = True
1110 while (((1 << srcstep) & srcmask) == 0) and (srcstep != vl):
1111 log(" sskip", bin(1 << srcstep))
1112 srcstep += 1
1113
1114 # now work out if the relevant mask bits require zeroing
1115 if pred_src_zero:
1116 pred_src_zero = ((1 << srcstep) & srcmask) == 0
1117
1118 # store new srcstep / dststep
1119 self.new_srcstep = srcstep
1120 self.pred_src_zero = pred_src_zero
1121 log(" new srcstep", srcstep)
1122
1123 def skip_dst(self):
1124 # dststep-skipping opportunity identified
1125 dststep = self.svstate.dststep
1126 dstmask = self.dstmask
1127 pred_dst_zero = self.pred_dz
1128 vl = self.svstate.vl
1129 if self.dststep_skip:
1130 # cannot do this with sv.bc - XXX TODO
1131 if dstmask == 0:
1132 self.loopend = True
1133 while (((1 << dststep) & dstmask) == 0) and (dststep != vl):
1134 log(" dskip", bin(1 << dststep))
1135 dststep += 1
1136
1137 # now work out if the relevant mask bits require zeroing
1138 if pred_dst_zero:
1139 pred_dst_zero = ((1 << dststep) & dstmask) == 0
1140
1141 # store new srcstep / dststep
1142 self.new_dststep = dststep
1143 self.pred_dst_zero = pred_dst_zero
1144 log(" new dststep", dststep)
1145
1146
1147 class SyscallEmulator(openpower.syscalls.Dispatcher):
1148 def __init__(self, isacaller):
1149 self.__isacaller = isacaller
1150
1151 host = os.uname().machine
1152 bits = (64 if (sys.maxsize > (2**32)) else 32)
1153 host = openpower.syscalls.architecture(arch=host, bits=bits)
1154
1155 return super().__init__(guest="ppc64", host=host)
1156
1157 def __call__(self, identifier, *arguments):
1158 (identifier, *arguments) = map(int, (identifier, *arguments))
1159 return super().__call__(identifier, *arguments)
1160
1161
1162 class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
1163 # decoder2 - an instance of power_decoder2
1164 # regfile - a list of initial values for the registers
1165 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1166 # respect_pc - tracks the program counter. requires initial_insns
1167 def __init__(self, decoder2, regfile, initial_sprs=None, initial_cr=0,
1168 initial_mem=None, initial_msr=0,
1169 initial_svstate=0,
1170 initial_insns=None,
1171 fpregfile=None,
1172 respect_pc=False,
1173 disassembly=None,
1174 initial_pc=0,
1175 bigendian=False,
1176 mmu=False,
1177 icachemmu=False,
1178 initial_fpscr=0,
1179 insnlog=None,
1180 use_mmap_mem=False,
1181 use_syscall_emu=False):
1182 if use_syscall_emu:
1183 self.syscall = SyscallEmulator(isacaller=self)
1184 if not use_mmap_mem:
1185 log("forcing use_mmap_mem due to use_syscall_emu active")
1186 use_mmap_mem = True
1187 else:
1188 self.syscall = None
1189
1190 # trace log file for model output. if None do nothing
1191 self.insnlog = insnlog
1192 self.insnlog_is_file = hasattr(insnlog, "write")
1193 if not self.insnlog_is_file and self.insnlog:
1194 self.insnlog = open(self.insnlog, "w")
1195
1196 self.bigendian = bigendian
1197 self.halted = False
1198 self.is_svp64_mode = False
1199 self.respect_pc = respect_pc
1200 if initial_sprs is None:
1201 initial_sprs = {}
1202 if initial_mem is None:
1203 initial_mem = {}
1204 if fpregfile is None:
1205 fpregfile = [0] * 32
1206 if initial_insns is None:
1207 initial_insns = {}
1208 assert self.respect_pc == False, "instructions required to honor pc"
1209 if initial_msr is None:
1210 initial_msr = DEFAULT_MSR
1211
1212 log("ISACaller insns", respect_pc, initial_insns, disassembly)
1213 log("ISACaller initial_msr", initial_msr)
1214
1215 # "fake program counter" mode (for unit testing)
1216 self.fake_pc = 0
1217 disasm_start = 0
1218 if not respect_pc:
1219 if isinstance(initial_mem, tuple):
1220 self.fake_pc = initial_mem[0]
1221 disasm_start = self.fake_pc
1222 else:
1223 disasm_start = initial_pc
1224
1225 # disassembly: we need this for now (not given from the decoder)
1226 self.disassembly = {}
1227 if disassembly:
1228 for i, code in enumerate(disassembly):
1229 self.disassembly[i*4 + disasm_start] = code
1230
1231 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1232 self.svp64rm = SVP64RM()
1233 if initial_svstate is None:
1234 initial_svstate = 0
1235 if isinstance(initial_svstate, int):
1236 initial_svstate = SVP64State(initial_svstate)
1237 # SVSTATE, MSR and PC
1238 StepLoop.__init__(self, initial_svstate)
1239 self.msr = SelectableInt(initial_msr, 64) # underlying reg
1240 self.pc = PC()
1241 # GPR FPR SPR registers
1242 initial_sprs = deepcopy(initial_sprs) # so as not to get modified
1243 self.gpr = GPR(decoder2, self, self.svstate, regfile)
1244 self.fpr = GPR(decoder2, self, self.svstate, fpregfile)
1245 # initialise SPRs before MMU
1246 self.spr = SPR(decoder2, initial_sprs, gpr=self.gpr)
1247
1248 # set up 4 dummy SVSHAPEs if they aren't already set up
1249 for i in range(4):
1250 sname = 'SVSHAPE%d' % i
1251 val = self.spr.get(sname, 0)
1252 # make sure it's an SVSHAPE -- conversion done by SPR.__setitem__
1253 self.spr[sname] = val
1254 self.last_op_svshape = False
1255
1256 # "raw" memory
1257 if use_mmap_mem:
1258 self.mem = MemMMap(row_bytes=8,
1259 initial_mem=initial_mem,
1260 misaligned_ok=True)
1261 self.imem = self.mem
1262 self.mem.initialize(row_bytes=4, initial_mem=initial_insns)
1263 self.mem.log_fancy(kind=LogType.InstrInOuts)
1264 else:
1265 self.mem = Mem(row_bytes=8, initial_mem=initial_mem,
1266 misaligned_ok=True)
1267 self.mem.log_fancy(kind=LogType.InstrInOuts)
1268 self.imem = Mem(row_bytes=4, initial_mem=initial_insns)
1269 # MMU mode, redirect underlying Mem through RADIX
1270 if mmu:
1271 self.mem = RADIX(self.mem, self)
1272 if icachemmu:
1273 self.imem = RADIX(self.imem, self)
1274
1275 # TODO, needed here:
1276 # FPR (same as GPR except for FP nums)
1277 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1278 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1279 self.fpscr = FPSCRState(initial_fpscr)
1280
1281 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1282 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1283 # -- Done
1284 # 2.3.2 LR (actually SPR #8) -- Done
1285 # 2.3.3 CTR (actually SPR #9) -- Done
1286 # 2.3.4 TAR (actually SPR #815)
1287 # 3.2.2 p45 XER (actually SPR #1) -- Done
1288 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1289
1290 # create CR then allow portions of it to be "selectable" (below)
1291 self.cr_fields = CRFields(initial_cr)
1292 self.cr = self.cr_fields.cr
1293 self.cr_backup = 0 # sigh, dreadful hack: for fail-first (VLi)
1294
1295 # "undefined", just set to variable-bit-width int (use exts "max")
1296 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1297
1298 self.namespace = {}
1299 self.namespace.update(self.spr)
1300 self.namespace.update({'GPR': self.gpr,
1301 'FPR': self.fpr,
1302 'MEM': self.mem,
1303 'SPR': self.spr,
1304 'memassign': self.memassign,
1305 'NIA': self.pc.NIA,
1306 'CIA': self.pc.CIA,
1307 'SVSTATE': self.svstate,
1308 'SVSHAPE0': self.spr['SVSHAPE0'],
1309 'SVSHAPE1': self.spr['SVSHAPE1'],
1310 'SVSHAPE2': self.spr['SVSHAPE2'],
1311 'SVSHAPE3': self.spr['SVSHAPE3'],
1312 'CR': self.cr,
1313 'MSR': self.msr,
1314 'FPSCR': self.fpscr,
1315 'undefined': undefined,
1316 'mode_is_64bit': True,
1317 'SO': XER_bits['SO'],
1318 'XLEN': 64 # elwidth overrides
1319 })
1320
1321 for name in BFP_FLAG_NAMES:
1322 setattr(self, name, 0)
1323
1324 # update pc to requested start point
1325 self.set_pc(initial_pc)
1326
1327 # field-selectable versions of Condition Register
1328 self.crl = self.cr_fields.crl
1329 for i in range(8):
1330 self.namespace["CR%d" % i] = self.crl[i]
1331
1332 self.decoder = decoder2.dec
1333 self.dec2 = decoder2
1334
1335 super().__init__(XLEN=self.namespace["XLEN"], FPSCR=self.fpscr)
1336
1337 def trace(self, out):
1338 if self.insnlog is None:
1339 return
1340 self.insnlog.write(out)
1341
1342 @property
1343 def XLEN(self):
1344 return self.namespace["XLEN"]
1345
1346 @property
1347 def FPSCR(self):
1348 return self.fpscr
1349
1350 def call_trap(self, trap_addr, trap_bit):
1351 """calls TRAP and sets up NIA to the new execution location.
1352 next instruction will begin at trap_addr.
1353 """
1354 self.TRAP(trap_addr, trap_bit)
1355 self.namespace['NIA'] = self.trap_nia
1356 self.pc.update(self.namespace, self.is_svp64_mode)
1357
1358 def TRAP(self, trap_addr=0x700, trap_bit=PIb.TRAP):
1359 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1360
1361 TRAP function is callable from inside the pseudocode itself,
1362 hence the default arguments. when calling from inside ISACaller
1363 it is best to use call_trap()
1364
1365 trap_addr: int | SelectableInt
1366 the address to go to (before any modifications from `KAIVB`)
1367 trap_bit: int | None
1368 the bit in `SRR1` to set, `None` means don't set any bits.
1369 """
1370 if isinstance(trap_addr, SelectableInt):
1371 trap_addr = trap_addr.value
1372 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1373 kaivb = self.spr['KAIVB'].value
1374 msr = self.namespace['MSR'].value
1375 log("TRAP:", hex(trap_addr), hex(msr), "kaivb", hex(kaivb))
1376 # store CIA(+4?) in SRR0, set NIA to 0x700
1377 # store MSR in SRR1, set MSR to um errr something, have to check spec
1378 # store SVSTATE (if enabled) in SVSRR0
1379 self.spr['SRR0'].value = self.pc.CIA.value
1380 self.spr['SRR1'].value = msr
1381 if self.is_svp64_mode:
1382 self.spr['SVSRR0'] = self.namespace['SVSTATE'].value
1383 self.trap_nia = SelectableInt(trap_addr | (kaivb & ~0x1fff), 64)
1384 if trap_bit is not None:
1385 self.spr['SRR1'][trap_bit] = 1 # change *copy* of MSR in SRR1
1386
1387 # set exception bits. TODO: this should, based on the address
1388 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1389 # bits appropriately. however it turns out that *for now* in all
1390 # cases (all trap_addrs) the exact same thing is needed.
1391 self.msr[MSRb.IR] = 0
1392 self.msr[MSRb.DR] = 0
1393 self.msr[MSRb.FE0] = 0
1394 self.msr[MSRb.FE1] = 0
1395 self.msr[MSRb.EE] = 0
1396 self.msr[MSRb.RI] = 0
1397 self.msr[MSRb.SF] = 1
1398 self.msr[MSRb.TM] = 0
1399 self.msr[MSRb.VEC] = 0
1400 self.msr[MSRb.VSX] = 0
1401 self.msr[MSRb.PR] = 0
1402 self.msr[MSRb.FP] = 0
1403 self.msr[MSRb.PMM] = 0
1404 self.msr[MSRb.TEs] = 0
1405 self.msr[MSRb.TEe] = 0
1406 self.msr[MSRb.UND] = 0
1407 self.msr[MSRb.LE] = 1
1408
1409 def memassign(self, ea, sz, val):
1410 self.mem.memassign(ea, sz, val)
1411
1412 def prep_namespace(self, insn_name, formname, op_fields, xlen):
1413 # TODO: get field names from form in decoder*1* (not decoder2)
1414 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1415 # from spec
1416 # then "yield" fields only from op_fields rather than hard-coded
1417 # list, here.
1418 fields = self.decoder.sigforms[formname]
1419 log("prep_namespace", formname, op_fields, insn_name)
1420 for name in op_fields:
1421 # CR immediates. deal with separately. needs modifying
1422 # pseudocode
1423 if self.is_svp64_mode and name in ['BI']: # TODO, more CRs
1424 # BI is a 5-bit, must reconstruct the value
1425 regnum, is_vec = yield from get_cr_in(self.dec2, name)
1426 sig = getattr(fields, name)
1427 val = yield sig
1428 # low 2 LSBs (CR field selector) remain same, CR num extended
1429 assert regnum <= 7, "sigh, TODO, 128 CR fields"
1430 val = (val & 0b11) | (regnum << 2)
1431 elif self.is_svp64_mode and name in ['BF']: # TODO, more CRs
1432 regnum, is_vec = yield from get_cr_out(self.dec2, "BF")
1433 log('hack %s' % name, regnum, is_vec)
1434 val = regnum
1435 else:
1436 sig = getattr(fields, name)
1437 val = yield sig
1438 # these are all opcode fields involved in index-selection of CR,
1439 # and need to do "standard" arithmetic. CR[BA+32] for example
1440 # would, if using SelectableInt, only be 5-bit.
1441 if name in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1442 self.namespace[name] = val
1443 else:
1444 self.namespace[name] = SelectableInt(val, sig.width)
1445
1446 self.namespace['XER'] = self.spr['XER']
1447 self.namespace['CA'] = self.spr['XER'][XER_bits['CA']].value
1448 self.namespace['CA32'] = self.spr['XER'][XER_bits['CA32']].value
1449 self.namespace['OV'] = self.spr['XER'][XER_bits['OV']].value
1450 self.namespace['OV32'] = self.spr['XER'][XER_bits['OV32']].value
1451 self.namespace['XLEN'] = xlen
1452
1453 # add some SVSTATE convenience variables
1454 vl = self.svstate.vl
1455 srcstep = self.svstate.srcstep
1456 self.namespace['VL'] = vl
1457 self.namespace['srcstep'] = srcstep
1458
1459 # take a copy of the CR field value: if non-VLi fail-first fails
1460 # this is because the pseudocode writes *directly* to CR. sigh
1461 self.cr_backup = self.cr.value
1462
1463 # sv.bc* need some extra fields
1464 if not self.is_svp64_mode or not insn_name.startswith("sv.bc"):
1465 return
1466
1467 # blegh grab bits manually
1468 mode = yield self.dec2.rm_dec.rm_in.mode
1469 # convert to SelectableInt before test
1470 mode = SelectableInt(mode, 5)
1471 bc_vlset = mode[SVP64MODEb.BC_VLSET] != 0
1472 bc_vli = mode[SVP64MODEb.BC_VLI] != 0
1473 bc_snz = mode[SVP64MODEb.BC_SNZ] != 0
1474 bc_vsb = yield self.dec2.rm_dec.bc_vsb
1475 bc_ctrtest = yield self.dec2.rm_dec.bc_ctrtest
1476 bc_lru = yield self.dec2.rm_dec.bc_lru
1477 bc_gate = yield self.dec2.rm_dec.bc_gate
1478 sz = yield self.dec2.rm_dec.pred_sz
1479 self.namespace['mode'] = SelectableInt(mode, 5)
1480 self.namespace['ALL'] = SelectableInt(bc_gate, 1)
1481 self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
1482 self.namespace['LRu'] = SelectableInt(bc_lru, 1)
1483 self.namespace['CTRtest'] = SelectableInt(bc_ctrtest, 1)
1484 self.namespace['VLSET'] = SelectableInt(bc_vlset, 1)
1485 self.namespace['VLI'] = SelectableInt(bc_vli, 1)
1486 self.namespace['sz'] = SelectableInt(sz, 1)
1487 self.namespace['SNZ'] = SelectableInt(bc_snz, 1)
1488
1489 def get_kludged_op_add_ca_ov(self, inputs, inp_ca_ov):
1490 """ this was not at all necessary to do. this function massively
1491 duplicates - in a laborious and complex fashion - the contents of
1492 the CSV files that were extracted two years ago from microwatt's
1493 source code. A-inversion is the "inv A" column, output inversion
1494 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1495 "cry in" column
1496
1497 all of that information is available in
1498 self.instrs[ins_name].op_fields
1499 where info is usually assigned to self.instrs[ins_name]
1500
1501 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1502
1503 the immediate constants are *also* decoded correctly and placed
1504 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1505 """
1506 def ca(a, b, ca_in, width):
1507 mask = (1 << width) - 1
1508 y = (a & mask) + (b & mask) + ca_in
1509 return y >> width
1510
1511 asmcode = yield self.dec2.dec.op.asmcode
1512 insn = insns.get(asmcode)
1513 SI = yield self.dec2.dec.SI
1514 SI &= 0xFFFF
1515 CA, OV = inp_ca_ov
1516 inputs = [i.value for i in inputs]
1517 if SI & 0x8000:
1518 SI -= 0x10000
1519 if insn in ("add", "addo", "addc", "addco"):
1520 a = inputs[0]
1521 b = inputs[1]
1522 ca_in = 0
1523 elif insn == "addic" or insn == "addic.":
1524 a = inputs[0]
1525 b = SI
1526 ca_in = 0
1527 elif insn in ("subf", "subfo", "subfc", "subfco"):
1528 a = ~inputs[0]
1529 b = inputs[1]
1530 ca_in = 1
1531 elif insn == "subfic":
1532 a = ~inputs[0]
1533 b = SI
1534 ca_in = 1
1535 elif insn == "adde" or insn == "addeo":
1536 a = inputs[0]
1537 b = inputs[1]
1538 ca_in = CA
1539 elif insn == "subfe" or insn == "subfeo":
1540 a = ~inputs[0]
1541 b = inputs[1]
1542 ca_in = CA
1543 elif insn == "addme" or insn == "addmeo":
1544 a = inputs[0]
1545 b = ~0
1546 ca_in = CA
1547 elif insn == "addze" or insn == "addzeo":
1548 a = inputs[0]
1549 b = 0
1550 ca_in = CA
1551 elif insn == "subfme" or insn == "subfmeo":
1552 a = ~inputs[0]
1553 b = ~0
1554 ca_in = CA
1555 elif insn == "subfze" or insn == "subfzeo":
1556 a = ~inputs[0]
1557 b = 0
1558 ca_in = CA
1559 elif insn == "addex":
1560 # CA[32] aren't actually written, just generate so we have
1561 # something to return
1562 ca64 = ov64 = ca(inputs[0], inputs[1], OV, 64)
1563 ca32 = ov32 = ca(inputs[0], inputs[1], OV, 32)
1564 return ca64, ca32, ov64, ov32
1565 elif insn == "neg" or insn == "nego":
1566 a = ~inputs[0]
1567 b = 0
1568 ca_in = 1
1569 else:
1570 raise NotImplementedError(
1571 "op_add kludge unimplemented instruction: ", asmcode, insn)
1572
1573 ca64 = ca(a, b, ca_in, 64)
1574 ca32 = ca(a, b, ca_in, 32)
1575 ov64 = ca64 != ca(a, b, ca_in, 63)
1576 ov32 = ca32 != ca(a, b, ca_in, 31)
1577 return ca64, ca32, ov64, ov32
1578
1579 def handle_carry_(self, inputs, output, ca, ca32, inp_ca_ov):
1580 if ca is not None and ca32 is not None:
1581 return
1582 op = yield self.dec2.e.do.insn_type
1583 if op == MicrOp.OP_ADD.value and ca is None and ca32 is None:
1584 retval = yield from self.get_kludged_op_add_ca_ov(
1585 inputs, inp_ca_ov)
1586 ca, ca32, ov, ov32 = retval
1587 asmcode = yield self.dec2.dec.op.asmcode
1588 if insns.get(asmcode) == 'addex':
1589 # TODO: if 32-bit mode, set ov to ov32
1590 self.spr['XER'][XER_bits['OV']] = ov
1591 self.spr['XER'][XER_bits['OV32']] = ov32
1592 log(f"write OV/OV32 OV={ov} OV32={ov32}",
1593 kind=LogType.InstrInOuts)
1594 else:
1595 # TODO: if 32-bit mode, set ca to ca32
1596 self.spr['XER'][XER_bits['CA']] = ca
1597 self.spr['XER'][XER_bits['CA32']] = ca32
1598 log(f"write CA/CA32 CA={ca} CA32={ca32}",
1599 kind=LogType.InstrInOuts)
1600 return
1601 inv_a = yield self.dec2.e.do.invert_in
1602 if inv_a:
1603 inputs[0] = ~inputs[0]
1604
1605 imm_ok = yield self.dec2.e.do.imm_data.ok
1606 if imm_ok:
1607 imm = yield self.dec2.e.do.imm_data.data
1608 inputs.append(SelectableInt(imm, 64))
1609 gts = []
1610 for x in inputs:
1611 log("gt input", x, output)
1612 gt = (gtu(x, output))
1613 gts.append(gt)
1614 log(gts)
1615 cy = 1 if any(gts) else 0
1616 log("CA", cy, gts)
1617 if ca is None: # already written
1618 self.spr['XER'][XER_bits['CA']] = cy
1619
1620 # 32 bit carry
1621 # ARGH... different for OP_ADD... *sigh*...
1622 op = yield self.dec2.e.do.insn_type
1623 if op == MicrOp.OP_ADD.value:
1624 res32 = (output.value & (1 << 32)) != 0
1625 a32 = (inputs[0].value & (1 << 32)) != 0
1626 if len(inputs) >= 2:
1627 b32 = (inputs[1].value & (1 << 32)) != 0
1628 else:
1629 b32 = False
1630 cy32 = res32 ^ a32 ^ b32
1631 log("CA32 ADD", cy32)
1632 else:
1633 gts = []
1634 for x in inputs:
1635 log("input", x, output)
1636 log(" x[32:64]", x, x[32:64])
1637 log(" o[32:64]", output, output[32:64])
1638 gt = (gtu(x[32:64], output[32:64])) == SelectableInt(1, 1)
1639 gts.append(gt)
1640 cy32 = 1 if any(gts) else 0
1641 log("CA32", cy32, gts)
1642 if ca32 is None: # already written
1643 self.spr['XER'][XER_bits['CA32']] = cy32
1644
1645 def handle_overflow(self, inputs, output, div_overflow, inp_ca_ov):
1646 op = yield self.dec2.e.do.insn_type
1647 if op == MicrOp.OP_ADD.value:
1648 retval = yield from self.get_kludged_op_add_ca_ov(
1649 inputs, inp_ca_ov)
1650 ca, ca32, ov, ov32 = retval
1651 # TODO: if 32-bit mode, set ov to ov32
1652 self.spr['XER'][XER_bits['OV']] = ov
1653 self.spr['XER'][XER_bits['OV32']] = ov32
1654 self.spr['XER'][XER_bits['SO']] |= ov
1655 return
1656 if hasattr(self.dec2.e.do, "invert_in"):
1657 inv_a = yield self.dec2.e.do.invert_in
1658 if inv_a:
1659 inputs[0] = ~inputs[0]
1660
1661 imm_ok = yield self.dec2.e.do.imm_data.ok
1662 if imm_ok:
1663 imm = yield self.dec2.e.do.imm_data.data
1664 inputs.append(SelectableInt(imm, 64))
1665 log("handle_overflow", inputs, output, div_overflow)
1666 if len(inputs) < 2 and div_overflow is None:
1667 return
1668
1669 # div overflow is different: it's returned by the pseudo-code
1670 # because it's more complex than can be done by analysing the output
1671 if div_overflow is not None:
1672 ov, ov32 = div_overflow, div_overflow
1673 # arithmetic overflow can be done by analysing the input and output
1674 elif len(inputs) >= 2:
1675 # OV (64-bit)
1676 input_sgn = [exts(x.value, x.bits) < 0 for x in inputs]
1677 output_sgn = exts(output.value, output.bits) < 0
1678 ov = 1 if input_sgn[0] == input_sgn[1] and \
1679 output_sgn != input_sgn[0] else 0
1680
1681 # OV (32-bit)
1682 input32_sgn = [exts(x.value, 32) < 0 for x in inputs]
1683 output32_sgn = exts(output.value, 32) < 0
1684 ov32 = 1 if input32_sgn[0] == input32_sgn[1] and \
1685 output32_sgn != input32_sgn[0] else 0
1686
1687 # now update XER OV/OV32/SO
1688 so = self.spr['XER'][XER_bits['SO']]
1689 new_so = so | ov # sticky overflow ORs in old with new
1690 self.spr['XER'][XER_bits['OV']] = ov
1691 self.spr['XER'][XER_bits['OV32']] = ov32
1692 self.spr['XER'][XER_bits['SO']] = new_so
1693 log(" set overflow", ov, ov32, so, new_so)
1694
1695 def handle_comparison(self, out, cr_idx=0, overflow=None, no_so=False):
1696 assert isinstance(out, SelectableInt), \
1697 "out zero not a SelectableInt %s" % repr(outputs)
1698 log("handle_comparison", out.bits, hex(out.value))
1699 # TODO - XXX *processor* in 32-bit mode
1700 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1701 # if is_32bit:
1702 # o32 = exts(out.value, 32)
1703 # print ("handle_comparison exts 32 bit", hex(o32))
1704 out = exts(out.value, out.bits)
1705 log("handle_comparison exts", hex(out))
1706 # create the three main CR flags, EQ GT LT
1707 zero = SelectableInt(out == 0, 1)
1708 positive = SelectableInt(out > 0, 1)
1709 negative = SelectableInt(out < 0, 1)
1710 # get (or not) XER.SO. for setvl this is important *not* to read SO
1711 if no_so:
1712 SO = SelectableInt(1, 0)
1713 else:
1714 SO = self.spr['XER'][XER_bits['SO']]
1715 log("handle_comparison SO", SO.value,
1716 "overflow", overflow,
1717 "zero", zero.value,
1718 "+ve", positive.value,
1719 "-ve", negative.value)
1720 # alternative overflow checking (setvl mainly at the moment)
1721 if overflow is not None and overflow == 1:
1722 SO = SelectableInt(1, 1)
1723 # create the four CR field values and set the required CR field
1724 cr_field = selectconcat(negative, positive, zero, SO)
1725 log("handle_comparison cr_field", self.cr, cr_idx, cr_field)
1726 self.crl[cr_idx].eq(cr_field)
1727
1728 def set_pc(self, pc_val):
1729 self.namespace['NIA'] = SelectableInt(pc_val, 64)
1730 self.pc.update(self.namespace, self.is_svp64_mode)
1731
1732 def get_next_insn(self):
1733 """check instruction
1734 """
1735 if self.respect_pc:
1736 pc = self.pc.CIA.value
1737 else:
1738 pc = self.fake_pc
1739 ins = self.imem.ld(pc, 4, False, True, instr_fetch=True)
1740 if ins is None:
1741 raise KeyError("no instruction at 0x%x" % pc)
1742 return pc, ins
1743
1744 def setup_one(self):
1745 """set up one instruction
1746 """
1747 pc, insn = self.get_next_insn()
1748 yield from self.setup_next_insn(pc, insn)
1749
1750 # cache since it's really slow to construct
1751 __PREFIX_CACHE = SVP64Instruction.Prefix(SelectableInt(value=0, bits=32))
1752
1753 def __decode_prefix(self, opcode):
1754 pfx = self.__PREFIX_CACHE
1755 pfx.storage.eq(opcode)
1756 return pfx
1757
1758 def setup_next_insn(self, pc, ins):
1759 """set up next instruction
1760 """
1761 self._pc = pc
1762 log("setup: 0x%x 0x%x %s" % (pc, ins & 0xffffffff, bin(ins)))
1763 log("CIA NIA", self.respect_pc, self.pc.CIA.value, self.pc.NIA.value)
1764
1765 yield self.dec2.sv_rm.eq(0)
1766 yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff)
1767 yield self.dec2.dec.bigendian.eq(self.bigendian)
1768 yield self.dec2.state.msr.eq(self.msr.value)
1769 yield self.dec2.state.pc.eq(pc)
1770 if self.svstate is not None:
1771 yield self.dec2.state.svstate.eq(self.svstate.value)
1772
1773 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1774 yield Settle()
1775 opcode = yield self.dec2.dec.opcode_in
1776 opcode = SelectableInt(value=opcode, bits=32)
1777 pfx = self.__decode_prefix(opcode)
1778 log("prefix test: opcode:", pfx.PO, bin(pfx.PO), pfx.id)
1779 self.is_svp64_mode = bool((pfx.PO == 0b000001) and (pfx.id == 0b11))
1780 self.pc.update_nia(self.is_svp64_mode)
1781 # set SVP64 decode
1782 yield self.dec2.is_svp64_mode.eq(self.is_svp64_mode)
1783 self.namespace['NIA'] = self.pc.NIA
1784 self.namespace['SVSTATE'] = self.svstate
1785 if not self.is_svp64_mode:
1786 return
1787
1788 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1789 log("svp64.rm", bin(pfx.rm))
1790 log(" svstate.vl", self.svstate.vl)
1791 log(" svstate.mvl", self.svstate.maxvl)
1792 ins = self.imem.ld(pc+4, 4, False, True, instr_fetch=True)
1793 log(" svsetup: 0x%x 0x%x %s" % (pc+4, ins & 0xffffffff, bin(ins)))
1794 yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff) # v3.0B suffix
1795 yield self.dec2.sv_rm.eq(int(pfx.rm)) # svp64 prefix
1796 yield Settle()
1797
1798 def execute_one(self):
1799 """execute one instruction
1800 """
1801 # get the disassembly code for this instruction
1802 if not self.disassembly:
1803 code = yield from self.get_assembly_name()
1804 else:
1805 offs, dbg = 0, ""
1806 if self.is_svp64_mode:
1807 offs, dbg = 4, "svp64 "
1808 code = self.disassembly[self._pc+offs]
1809 log(" %s sim-execute" % dbg, hex(self._pc), code)
1810 opname = code.split(' ')[0]
1811 try:
1812 yield from self.call(opname) # execute the instruction
1813 except MemException as e: # check for memory errors
1814 if e.args[0] == 'unaligned': # alignment error
1815 # run a Trap but set DAR first
1816 print("memory unaligned exception, DAR", e.dar, repr(e))
1817 self.spr['DAR'] = SelectableInt(e.dar, 64)
1818 self.call_trap(0x600, PIb.PRIV) # 0x600, privileged
1819 return
1820 elif e.args[0] == 'invalid': # invalid
1821 # run a Trap but set DAR first
1822 log("RADIX MMU memory invalid error, mode %s" % e.mode)
1823 if e.mode == 'EXECUTE':
1824 # XXX TODO: must set a few bits in SRR1,
1825 # see microwatt loadstore1.vhdl
1826 # if m_in.segerr = '0' then
1827 # v.srr1(47 - 33) := m_in.invalid;
1828 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1829 # v.srr1(47 - 44) := m_in.badtree;
1830 # v.srr1(47 - 45) := m_in.rc_error;
1831 # v.intr_vec := 16#400#;
1832 # else
1833 # v.intr_vec := 16#480#;
1834 self.call_trap(0x400, PIb.PRIV) # 0x400, privileged
1835 else:
1836 self.call_trap(0x300, PIb.PRIV) # 0x300, privileged
1837 return
1838 # not supported yet:
1839 raise e # ... re-raise
1840
1841 # append to the trace log file
1842 self.trace(" # %s\n" % code)
1843
1844 log("gprs after code", code)
1845 self.gpr.dump()
1846 crs = []
1847 for i in range(len(self.crl)):
1848 crs.append(bin(self.crl[i].asint()))
1849 log("crs", " ".join(crs))
1850 log("vl,maxvl", self.svstate.vl, self.svstate.maxvl)
1851
1852 # don't use this except in special circumstances
1853 if not self.respect_pc:
1854 self.fake_pc += 4
1855
1856 log("execute one, CIA NIA", hex(self.pc.CIA.value),
1857 hex(self.pc.NIA.value))
1858
1859 def get_assembly_name(self):
1860 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1861 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1862 dec_insn = yield self.dec2.e.do.insn
1863 insn_1_11 = yield self.dec2.e.do.insn[1:11]
1864 asmcode = yield self.dec2.dec.op.asmcode
1865 int_op = yield self.dec2.dec.op.internal_op
1866 log("get assembly name asmcode", asmcode, int_op,
1867 hex(dec_insn), bin(insn_1_11))
1868 asmop = insns.get(asmcode, None)
1869
1870 # sigh reconstruct the assembly instruction name
1871 if hasattr(self.dec2.e.do, "oe"):
1872 ov_en = yield self.dec2.e.do.oe.oe
1873 ov_ok = yield self.dec2.e.do.oe.ok
1874 else:
1875 ov_en = False
1876 ov_ok = False
1877 if hasattr(self.dec2.e.do, "rc"):
1878 rc_en = yield self.dec2.e.do.rc.rc
1879 rc_ok = yield self.dec2.e.do.rc.ok
1880 else:
1881 rc_en = False
1882 rc_ok = False
1883 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1884 RC1 = yield self.dec2.rm_dec.RC1
1885 if RC1:
1886 rc_en = False
1887 rc_ok = False
1888 # grrrr have to special-case MUL op (see DecodeOE)
1889 log("ov %d en %d rc %d en %d op %d" %
1890 (ov_ok, ov_en, rc_ok, rc_en, int_op))
1891 if int_op in [MicrOp.OP_MUL_H64.value, MicrOp.OP_MUL_H32.value]:
1892 log("mul op")
1893 if rc_en & rc_ok:
1894 asmop += "."
1895 else:
1896 if not asmop.endswith("."): # don't add "." to "andis."
1897 if rc_en & rc_ok:
1898 asmop += "."
1899 if hasattr(self.dec2.e.do, "lk"):
1900 lk = yield self.dec2.e.do.lk
1901 if lk:
1902 asmop += "l"
1903 log("int_op", int_op)
1904 if int_op in [MicrOp.OP_B.value, MicrOp.OP_BC.value]:
1905 AA = yield self.dec2.dec.fields.FormI.AA[0:-1]
1906 log("AA", AA)
1907 if AA:
1908 asmop += "a"
1909 spr_msb = yield from self.get_spr_msb()
1910 if int_op == MicrOp.OP_MFCR.value:
1911 if spr_msb:
1912 asmop = 'mfocrf'
1913 else:
1914 asmop = 'mfcr'
1915 # XXX TODO: for whatever weird reason this doesn't work
1916 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1917 if int_op == MicrOp.OP_MTCRF.value:
1918 if spr_msb:
1919 asmop = 'mtocrf'
1920 else:
1921 asmop = 'mtcrf'
1922 return asmop
1923
1924 def reset_remaps(self):
1925 self.remap_loopends = [0] * 4
1926 self.remap_idxs = [0, 1, 2, 3]
1927
1928 def get_remap_indices(self):
1929 """WARNING, this function stores remap_idxs and remap_loopends
1930 in the class for later use. this to avoid problems with yield
1931 """
1932 # go through all iterators in lock-step, advance to next remap_idx
1933 srcstep, dststep, ssubstep, dsubstep = self.get_src_dststeps()
1934 # get four SVSHAPEs. here we are hard-coding
1935 self.reset_remaps()
1936 SVSHAPE0 = self.spr['SVSHAPE0']
1937 SVSHAPE1 = self.spr['SVSHAPE1']
1938 SVSHAPE2 = self.spr['SVSHAPE2']
1939 SVSHAPE3 = self.spr['SVSHAPE3']
1940 # set up the iterators
1941 remaps = [(SVSHAPE0, SVSHAPE0.get_iterator()),
1942 (SVSHAPE1, SVSHAPE1.get_iterator()),
1943 (SVSHAPE2, SVSHAPE2.get_iterator()),
1944 (SVSHAPE3, SVSHAPE3.get_iterator()),
1945 ]
1946
1947 dbg = []
1948 for i, (shape, remap) in enumerate(remaps):
1949 # zero is "disabled"
1950 if shape.value == 0x0:
1951 self.remap_idxs[i] = 0
1952 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1953 step = dststep if (i in [3, 4]) else srcstep
1954 # this is terrible. O(N^2) looking for the match. but hey.
1955 for idx, (remap_idx, loopends) in enumerate(remap):
1956 if idx == step:
1957 break
1958 self.remap_idxs[i] = remap_idx
1959 self.remap_loopends[i] = loopends
1960 dbg.append((i, step, remap_idx, loopends))
1961 for (i, step, remap_idx, loopends) in dbg:
1962 log("SVSHAPE %d idx, end" % i, step, remap_idx, bin(loopends))
1963 return remaps
1964
1965 def get_spr_msb(self):
1966 dec_insn = yield self.dec2.e.do.insn
1967 return dec_insn & (1 << 20) != 0 # sigh - XFF.spr[-1]?
1968
1969 def call(self, name, syscall_emu_active=False):
1970 """call(opcode) - the primary execution point for instructions
1971 """
1972 self.last_st_addr = None # reset the last known store address
1973 self.last_ld_addr = None # etc.
1974
1975 ins_name = name.strip() # remove spaces if not already done so
1976 if self.halted:
1977 log("halted - not executing", ins_name)
1978 return
1979
1980 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1981 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1982 asmop = yield from self.get_assembly_name()
1983 log("call", ins_name, asmop,
1984 kind=LogType.InstrInOuts)
1985
1986 # sv.setvl is *not* a loop-function. sigh
1987 log("is_svp64_mode", self.is_svp64_mode, asmop)
1988
1989 # check privileged
1990 int_op = yield self.dec2.dec.op.internal_op
1991 spr_msb = yield from self.get_spr_msb()
1992
1993 instr_is_privileged = False
1994 if int_op in [MicrOp.OP_ATTN.value,
1995 MicrOp.OP_MFMSR.value,
1996 MicrOp.OP_MTMSR.value,
1997 MicrOp.OP_MTMSRD.value,
1998 # TODO: OP_TLBIE
1999 MicrOp.OP_RFID.value]:
2000 instr_is_privileged = True
2001 if int_op in [MicrOp.OP_MFSPR.value,
2002 MicrOp.OP_MTSPR.value] and spr_msb:
2003 instr_is_privileged = True
2004
2005 log("is priv", instr_is_privileged, hex(self.msr.value),
2006 self.msr[MSRb.PR])
2007 # check MSR priv bit and whether op is privileged: if so, throw trap
2008 if instr_is_privileged and self.msr[MSRb.PR] == 1:
2009 self.call_trap(0x700, PIb.PRIV)
2010 return
2011
2012 # check halted condition
2013 if ins_name == 'attn':
2014 self.halted = True
2015 return
2016
2017 # User mode system call emulation consists of several steps:
2018 # 1. Detect whether instruction is sc or scv.
2019 # 2. Call the HDL implementation which invokes trap.
2020 # 3. Reroute the guest system call to host system call.
2021 # 4. Force return from the interrupt as if we had guest OS.
2022 # "executing" rfid requires putting 0x4c000024 temporarily
2023 # into the program at the PC. TODO investigate and remove
2024 if ((asmop in ("sc", "scv")) and
2025 (self.syscall is not None) and
2026 not syscall_emu_active):
2027 # Memoize PC and trigger an interrupt
2028 if self.respect_pc:
2029 pc = self.pc.CIA.value
2030 else:
2031 pc = self.fake_pc
2032 yield from self.call(asmop, syscall_emu_active=True)
2033
2034 # Reroute the syscall to host OS
2035 identifier = self.gpr(0)
2036 arguments = map(self.gpr, range(3, 9))
2037 result = self.syscall(identifier, *arguments)
2038 self.gpr.write(3, result, False, self.namespace["XLEN"])
2039
2040 # Return from interrupt
2041 backup = self.imem.ld(pc, 4, False, True, instr_fetch=True)
2042 self.imem.st(pc, 0x4c000024, width=4, swap=True)
2043 yield from self.call("rfid", syscall_emu_active=True)
2044 self.imem.st(pc, backup, width=4, swap=True)
2045 elif ((name in ("rfid", "hrfid")) and syscall_emu_active):
2046 asmop = "rfid"
2047
2048 # check illegal instruction
2049 illegal = False
2050 if ins_name not in ['mtcrf', 'mtocrf']:
2051 illegal = ins_name != asmop
2052
2053 # list of instructions not being supported by binutils (.long)
2054 dotstrp = asmop[:-1] if asmop[-1] == '.' else asmop
2055 if dotstrp in [*FPTRANS_INSNS,
2056 *LDST_UPDATE_INSNS,
2057 'ffmadds', 'fdmadds', 'ffadds',
2058 'minmax',
2059 "brh", "brw", "brd",
2060 'setvl', 'svindex', 'svremap', 'svstep',
2061 'svshape', 'svshape2',
2062 'ternlogi', 'bmask', 'cprop',
2063 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2064 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2065 "dsld", "dsrd", "maddedus",
2066 "sadd", "saddw", "sadduw",
2067 "cffpr", "cffpro",
2068 "mffpr", "mffprs",
2069 "ctfpr", "ctfprs",
2070 "mtfpr", "mtfprs",
2071 "maddsubrs", "maddrs", "msubrs",
2072 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2073 "setbc", "setbcr", "setnbc", "setnbcr",
2074 ]:
2075 illegal = False
2076 ins_name = dotstrp
2077
2078 # branch-conditional redirects to sv.bc
2079 if asmop.startswith('bc') and self.is_svp64_mode:
2080 ins_name = 'sv.%s' % ins_name
2081
2082 # ld-immediate-with-pi mode redirects to ld-with-postinc
2083 ldst_imm_postinc = False
2084 if 'u' in ins_name and self.is_svp64_mode:
2085 ldst_pi = yield self.dec2.rm_dec.ldst_postinc
2086 if ldst_pi:
2087 ins_name = ins_name.replace("u", "up")
2088 ldst_imm_postinc = True
2089 log(" enable ld/st postinc", ins_name)
2090
2091 log(" post-processed name", dotstrp, ins_name, asmop)
2092
2093 # illegal instructions call TRAP at 0x700
2094 if illegal:
2095 print("illegal", ins_name, asmop)
2096 self.call_trap(0x700, PIb.ILLEG)
2097 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2098 (ins_name, asmop, self.pc.CIA.value))
2099 return
2100
2101 # this is for setvl "Vertical" mode: if set true,
2102 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2103 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2104 self.allow_next_step_inc = False
2105 self.svstate_next_mode = 0
2106
2107 # nop has to be supported, we could let the actual op calculate
2108 # but PowerDecoder has a pattern for nop
2109 if ins_name == 'nop':
2110 self.update_pc_next()
2111 return
2112
2113 # get elwidths, defaults to 64
2114 xlen = 64
2115 ew_src = 64
2116 ew_dst = 64
2117 if self.is_svp64_mode:
2118 ew_src = yield self.dec2.rm_dec.ew_src
2119 ew_dst = yield self.dec2.rm_dec.ew_dst
2120 ew_src = 8 << (3-int(ew_src)) # convert to bitlength
2121 ew_dst = 8 << (3-int(ew_dst)) # convert to bitlength
2122 xlen = max(ew_src, ew_dst)
2123 log("elwdith", ew_src, ew_dst)
2124 log("XLEN:", self.is_svp64_mode, xlen)
2125
2126 # look up instruction in ISA.instrs, prepare namespace
2127 if ins_name == 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2128 info = self.instrs[ins_name+"."]
2129 elif asmop[-1] == '.' and asmop in self.instrs:
2130 info = self.instrs[asmop]
2131 else:
2132 info = self.instrs[ins_name]
2133 yield from self.prep_namespace(ins_name, info.form, info.op_fields,
2134 xlen)
2135
2136 # dict retains order
2137 inputs = dict.fromkeys(create_full_args(
2138 read_regs=info.read_regs, special_regs=info.special_regs,
2139 uninit_regs=info.uninit_regs, write_regs=info.write_regs))
2140
2141 # preserve order of register names
2142 write_without_special_regs = OrderedSet(info.write_regs)
2143 write_without_special_regs -= OrderedSet(info.special_regs)
2144 input_names = create_args([
2145 *info.read_regs, *info.uninit_regs, *write_without_special_regs])
2146 log("input names", input_names)
2147
2148 # get SVP64 entry for the current instruction
2149 sv_rm = self.svp64rm.instrs.get(ins_name)
2150 if sv_rm is not None:
2151 dest_cr, src_cr, src_byname, dest_byname = decode_extra(sv_rm)
2152 else:
2153 dest_cr, src_cr, src_byname, dest_byname = False, False, {}, {}
2154 log("sv rm", sv_rm, dest_cr, src_cr, src_byname, dest_byname)
2155
2156 # see if srcstep/dststep need skipping over masked-out predicate bits
2157 # svstep also needs advancement because it calls SVSTATE_NEXT.
2158 # bit the remaps get computed just after pre_inc moves them on
2159 # with remap_set_steps substituting for PowerDecider2 not doing it,
2160 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2161 # svstep is necessary for now.
2162 self.reset_remaps()
2163 if (self.is_svp64_mode or ins_name in ['svstep']):
2164 yield from self.svstate_pre_inc()
2165 if self.is_svp64_mode:
2166 pre = yield from self.update_new_svstate_steps()
2167 if pre:
2168 self.svp64_reset_loop()
2169 self.update_nia()
2170 self.update_pc_next()
2171 return
2172 srcstep, dststep, ssubstep, dsubstep = self.get_src_dststeps()
2173 pred_dst_zero = self.pred_dst_zero
2174 pred_src_zero = self.pred_src_zero
2175 vl = self.svstate.vl
2176 subvl = yield self.dec2.rm_dec.rm_in.subvl
2177
2178 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2179 if self.is_svp64_mode and vl == 0:
2180 self.pc.update(self.namespace, self.is_svp64_mode)
2181 log("SVP64: VL=0, end of call", self.namespace['CIA'],
2182 self.namespace['NIA'], kind=LogType.InstrInOuts)
2183 return
2184
2185 # for when SVREMAP is active, using pre-arranged schedule.
2186 # note: modifying PowerDecoder2 needs to "settle"
2187 remap_en = self.svstate.SVme
2188 persist = self.svstate.RMpst
2189 active = (persist or self.last_op_svshape) and remap_en != 0
2190 if self.is_svp64_mode:
2191 yield self.dec2.remap_active.eq(remap_en if active else 0)
2192 yield Settle()
2193 if persist or self.last_op_svshape:
2194 remaps = self.get_remap_indices()
2195 if self.is_svp64_mode and (persist or self.last_op_svshape):
2196 yield from self.remap_set_steps(remaps)
2197 # after that, settle down (combinatorial) to let Vector reg numbers
2198 # work themselves out
2199 yield Settle()
2200 if self.is_svp64_mode:
2201 remap_active = yield self.dec2.remap_active
2202 else:
2203 remap_active = False
2204 log("remap active", bin(remap_active))
2205
2206 # main input registers (RT, RA ...)
2207 for name in input_names:
2208 if name == "overflow":
2209 inputs[name] = SelectableInt(0, 1)
2210 elif name == "FPSCR":
2211 inputs[name] = self.FPSCR
2212 elif name in ("CA", "CA32", "OV", "OV32"):
2213 inputs[name] = self.spr['XER'][XER_bits[name]]
2214 elif name in "CR0":
2215 inputs[name] = self.crl[0]
2216 elif name in spr_byname:
2217 inputs[name] = self.spr[name]
2218 else:
2219 regval = (yield from self.get_input(name, ew_src))
2220 log("regval name", name, regval)
2221 inputs[name] = regval
2222
2223 # arrrrgh, awful hack, to get _RT into namespace
2224 if ins_name in ['setvl', 'svstep']:
2225 regname = "_RT"
2226 RT = yield self.dec2.dec.RT
2227 self.namespace[regname] = SelectableInt(RT, 5)
2228 if RT == 0:
2229 self.namespace["RT"] = SelectableInt(0, 5)
2230 regnum, is_vec = yield from get_idx_out(self.dec2, "RT")
2231 log('hack input reg %s %s' % (name, str(regnum)), is_vec)
2232
2233 # in SVP64 mode for LD/ST work out immediate
2234 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2235 # use info.form to detect
2236 if self.is_svp64_mode and not ldst_imm_postinc:
2237 yield from self.check_replace_d(info, remap_active)
2238
2239 # "special" registers
2240 for special in info.special_regs:
2241 if special in special_sprs:
2242 inputs[special] = self.spr[special]
2243 else:
2244 inputs[special] = self.namespace[special]
2245
2246 # clear trap (trap) NIA
2247 self.trap_nia = None
2248
2249 # check if this was an sv.bc* and create an indicator that
2250 # this is the last check to be made as a loop. combined with
2251 # the ALL/ANY mode we can early-exit. note that BI (to test)
2252 # is an input so there is no termination if BI is scalar
2253 # (because early-termination is for *output* scalars)
2254 if self.is_svp64_mode and ins_name.startswith("sv.bc"):
2255 end_loop = srcstep == vl-1 or dststep == vl-1
2256 self.namespace['end_loop'] = SelectableInt(end_loop, 1)
2257
2258 inp_ca_ov = (self.spr['XER'][XER_bits['CA']].value,
2259 self.spr['XER'][XER_bits['OV']].value)
2260
2261 for k, v in inputs.items():
2262 if v is None:
2263 v = SelectableInt(0, self.XLEN)
2264 # prevent pseudo-code from modifying input registers
2265 v = copy_assign_rhs(v)
2266 if isinstance(v, SelectableInt):
2267 v.ok = False
2268 inputs[k] = v
2269
2270 # execute actual instruction here (finally)
2271 log("inputs", inputs)
2272 inputs = list(inputs.values())
2273 results = info.func(self, *inputs)
2274 output_names = create_args(info.write_regs)
2275 outs = {}
2276 # record .ok before anything after the pseudo-code can modify it
2277 outs_ok = {}
2278 for out, n in zip(results or [], output_names):
2279 outs[n] = out
2280 outs_ok[n] = True
2281 if isinstance(out, SelectableInt):
2282 outs_ok[n] = out.ok
2283 log("results", outs)
2284 log("results ok", outs_ok)
2285
2286 # "inject" decorator takes namespace from function locals: we need to
2287 # overwrite NIA being overwritten (sigh)
2288 if self.trap_nia is not None:
2289 self.namespace['NIA'] = self.trap_nia
2290
2291 log("after func", self.namespace['CIA'], self.namespace['NIA'])
2292
2293 # check if op was a LD/ST so that debugging can check the
2294 # address
2295 if int_op in [MicrOp.OP_STORE.value,
2296 ]:
2297 self.last_st_addr = self.mem.last_st_addr
2298 if int_op in [MicrOp.OP_LOAD.value,
2299 ]:
2300 self.last_ld_addr = self.mem.last_ld_addr
2301 log("op", int_op, MicrOp.OP_STORE.value, MicrOp.OP_LOAD.value,
2302 self.last_st_addr, self.last_ld_addr)
2303
2304 # detect if CA/CA32 already in outputs (sra*, basically)
2305 ca = outs.get("CA")
2306 ca32 = outs.get("CA32")
2307
2308 log("carry already done?", ca, ca32, output_names)
2309 # soc test_pipe_caller tests don't have output_carry
2310 has_output_carry = hasattr(self.dec2.e.do, "output_carry")
2311 carry_en = has_output_carry and (yield self.dec2.e.do.output_carry)
2312 if carry_en:
2313 yield from self.handle_carry_(
2314 inputs, results[0], ca, ca32, inp_ca_ov=inp_ca_ov)
2315
2316 # get output named "overflow" and "CR0"
2317 overflow = outs.get('overflow')
2318 cr0 = outs.get('CR0')
2319 cr1 = outs.get('CR1')
2320
2321 # soc test_pipe_caller tests don't have oe
2322 has_oe = hasattr(self.dec2.e.do, "oe")
2323 # yeah just no. not in parallel processing
2324 if has_oe and not self.is_svp64_mode:
2325 # detect if overflow was in return result
2326 ov_en = yield self.dec2.e.do.oe.oe
2327 ov_ok = yield self.dec2.e.do.oe.ok
2328 log("internal overflow", ins_name, overflow, "en?", ov_en, ov_ok)
2329 if ov_en & ov_ok:
2330 yield from self.handle_overflow(
2331 inputs, results[0], overflow, inp_ca_ov=inp_ca_ov)
2332
2333 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2334 rc_en = False
2335 if not self.is_svp64_mode or not pred_dst_zero:
2336 if hasattr(self.dec2.e.do, "rc"):
2337 rc_en = yield self.dec2.e.do.rc.rc
2338 # don't do Rc=1 for svstep it is handled explicitly.
2339 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2340 # to write directly to CR0 instead of in ISACaller. hooyahh.
2341 if rc_en and ins_name not in ['svstep']:
2342 if outs_ok.get('FPSCR', False):
2343 FPSCR = outs['FPSCR']
2344 else:
2345 FPSCR = self.FPSCR
2346 yield from self.do_rc_ov(
2347 ins_name, results[0], overflow, cr0, cr1, FPSCR)
2348
2349 # check failfirst
2350 ffirst_hit = False, False
2351 if self.is_svp64_mode:
2352 sv_mode = yield self.dec2.rm_dec.sv_mode
2353 is_cr = sv_mode == SVMode.CROP.value
2354 chk = rc_en or is_cr
2355 if outs_ok.get('CR', False):
2356 # early write so check_ffirst can see value
2357 self.namespace['CR'].eq(outs['CR'])
2358 ffirst_hit = (yield from self.check_ffirst(info, chk, srcstep))
2359
2360 # any modified return results?
2361 yield from self.do_outregs(
2362 info, outs, carry_en, ffirst_hit, ew_dst, outs_ok)
2363
2364 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2365 # and raise the exception *after* if VLi=1 but if VLi=0 then
2366 # truncate and make the exception "disappear".
2367 if self.FPSCR.FEX and (self.msr[MSRb.FE0] or self.msr[MSRb.FE1]):
2368 self.call_trap(0x700, PIb.FP)
2369 return
2370
2371 yield from self.do_nia(asmop, ins_name, rc_en, ffirst_hit)
2372
2373 def check_ffirst(self, info, rc_en, srcstep):
2374 """fail-first mode: checks a bit of Rc Vector, truncates VL
2375 """
2376 rm_mode = yield self.dec2.rm_dec.mode
2377 ff_inv = yield self.dec2.rm_dec.inv
2378 cr_bit = yield self.dec2.rm_dec.cr_sel
2379 RC1 = yield self.dec2.rm_dec.RC1
2380 vli_ = yield self.dec2.rm_dec.vli # VL inclusive if truncated
2381 log(" ff rm_mode", rc_en, rm_mode, SVP64RMMode.FFIRST.value)
2382 log(" inv", ff_inv)
2383 log(" RC1", RC1)
2384 log(" vli", vli_)
2385 log(" cr_bit", cr_bit)
2386 log(" rc_en", rc_en)
2387 if not rc_en or rm_mode != SVP64RMMode.FFIRST.value:
2388 return False, False
2389 # get the CR vevtor, do BO-test
2390 crf = "CR0"
2391 log("asmregs", info.asmregs[0], info.write_regs)
2392 if 'CR' in info.write_regs and 'BF' in info.asmregs[0]:
2393 crf = 'BF'
2394 regnum, is_vec = yield from get_cr_out(self.dec2, crf)
2395 crtest = self.crl[regnum]
2396 ffirst_hit = crtest[cr_bit] != ff_inv
2397 log("cr test", crf, regnum, int(crtest), crtest, cr_bit, ff_inv)
2398 log("cr test?", ffirst_hit)
2399 if not ffirst_hit:
2400 return False, False
2401 # Fail-first activated, truncate VL
2402 vli = SelectableInt(int(vli_), 7)
2403 self.svstate.vl = srcstep + vli
2404 yield self.dec2.state.svstate.eq(self.svstate.value)
2405 yield Settle() # let decoder update
2406 return True, vli_
2407
2408 def do_rc_ov(self, ins_name, result, overflow, cr0, cr1, FPSCR):
2409 cr_out = yield self.dec2.op.cr_out
2410 if cr_out == CROutSel.CR1.value:
2411 rc_reg = "CR1"
2412 else:
2413 rc_reg = "CR0"
2414 regnum, is_vec = yield from get_cr_out(self.dec2, rc_reg)
2415 # hang on... for `setvl` actually you want to test SVSTATE.VL
2416 is_setvl = ins_name in ('svstep', 'setvl')
2417 if is_setvl:
2418 result = SelectableInt(result.vl, 64)
2419 # else:
2420 # overflow = None # do not override overflow except in setvl
2421
2422 if rc_reg == "CR1":
2423 if cr1 is None:
2424 cr1 = int(FPSCR.FX) << 3
2425 cr1 |= int(FPSCR.FEX) << 2
2426 cr1 |= int(FPSCR.VX) << 1
2427 cr1 |= int(FPSCR.OX)
2428 log("default fp cr1", cr1)
2429 else:
2430 log("explicit cr1", cr1)
2431 self.crl[regnum].eq(cr1)
2432 elif cr0 is None:
2433 # if there was not an explicit CR0 in the pseudocode,
2434 # do implicit Rc=1
2435 self.handle_comparison(result, regnum, overflow, no_so=is_setvl)
2436 else:
2437 # otherwise we just blat CR0 into the required regnum
2438 log("explicit rc0", cr0)
2439 self.crl[regnum].eq(cr0)
2440
2441 def do_outregs(self, info, outs, ca_en, ffirst_hit, ew_dst, outs_ok):
2442 ffirst_hit, vli = ffirst_hit
2443 # write out any regs for this instruction, but only if fail-first is ok
2444 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2445 if not ffirst_hit or vli:
2446 for name, output in outs.items():
2447 if not outs_ok[name]:
2448 log("skipping writing output with .ok=False", name, output)
2449 continue
2450 yield from self.check_write(info, name, output, ca_en, ew_dst)
2451 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2452 # which write directly to CR in the pseudocode (gah, what a mess)
2453 # if ffirst_hit and not vli:
2454 # self.cr.value = self.cr_backup
2455
2456 def do_nia(self, asmop, ins_name, rc_en, ffirst_hit):
2457 ffirst_hit, vli = ffirst_hit
2458 if ffirst_hit:
2459 self.svp64_reset_loop()
2460 nia_update = True
2461 else:
2462 # check advancement of src/dst/sub-steps and if PC needs updating
2463 nia_update = (yield from self.check_step_increment(
2464 rc_en, asmop, ins_name))
2465 if nia_update:
2466 self.update_pc_next()
2467
2468 def check_replace_d(self, info, remap_active):
2469 replace_d = False # update / replace constant in pseudocode
2470 ldstmode = yield self.dec2.rm_dec.ldstmode
2471 vl = self.svstate.vl
2472 subvl = yield self.dec2.rm_dec.rm_in.subvl
2473 srcstep, dststep = self.new_srcstep, self.new_dststep
2474 ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
2475 if info.form == 'DS':
2476 # DS-Form, multiply by 4 then knock 2 bits off after
2477 imm = yield self.dec2.dec.fields.FormDS.DS[0:14] * 4
2478 else:
2479 imm = yield self.dec2.dec.fields.FormD.D[0:16]
2480 imm = exts(imm, 16) # sign-extend to integer
2481 # get the right step. LD is from srcstep, ST is dststep
2482 op = yield self.dec2.e.do.insn_type
2483 offsmul = 0
2484 if op == MicrOp.OP_LOAD.value:
2485 if remap_active:
2486 offsmul = yield self.dec2.in1_step
2487 log("D-field REMAP src", imm, offsmul, ldstmode)
2488 else:
2489 offsmul = (srcstep * (subvl+1)) + ssubstep
2490 log("D-field src", imm, offsmul, ldstmode)
2491 elif op == MicrOp.OP_STORE.value:
2492 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2493 offsmul = (dststep * (subvl+1)) + dsubstep
2494 log("D-field dst", imm, offsmul, ldstmode)
2495 # Unit-Strided LD/ST adds offset*width to immediate
2496 if ldstmode == SVP64LDSTmode.UNITSTRIDE.value:
2497 ldst_len = yield self.dec2.e.do.data_len
2498 imm = SelectableInt(imm + offsmul * ldst_len, 32)
2499 replace_d = True
2500 # Element-strided multiplies the immediate by element step
2501 elif ldstmode == SVP64LDSTmode.ELSTRIDE.value:
2502 imm = SelectableInt(imm * offsmul, 32)
2503 replace_d = True
2504 if replace_d:
2505 ldst_ra_vec = yield self.dec2.rm_dec.ldst_ra_vec
2506 ldst_imz_in = yield self.dec2.rm_dec.ldst_imz_in
2507 log("LDSTmode", SVP64LDSTmode(ldstmode),
2508 offsmul, imm, ldst_ra_vec, ldst_imz_in)
2509 # new replacement D... errr.. DS
2510 if replace_d:
2511 if info.form == 'DS':
2512 # TODO: assert 2 LSBs are zero?
2513 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm.value))
2514 imm.value = imm.value >> 2
2515 self.namespace['DS'] = imm
2516 else:
2517 self.namespace['D'] = imm
2518
2519 def get_input(self, name, ew_src):
2520 # using PowerDecoder2, first, find the decoder index.
2521 # (mapping name RA RB RC RS to in1, in2, in3)
2522 regnum, is_vec = yield from get_idx_in(self.dec2, name, True)
2523 if regnum is None:
2524 # doing this is not part of svp64, it's because output
2525 # registers, to be modified, need to be in the namespace.
2526 regnum, is_vec = yield from get_idx_out(self.dec2, name, True)
2527 if regnum is None:
2528 regnum, is_vec = yield from get_idx_out2(self.dec2, name, True)
2529
2530 if isinstance(regnum, tuple):
2531 (regnum, base, offs) = regnum
2532 else:
2533 base, offs = regnum, 0 # temporary HACK
2534
2535 # in case getting the register number is needed, _RA, _RB
2536 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2537 regname = "_" + name
2538 if not self.is_svp64_mode or ew_src == 64:
2539 self.namespace[regname] = regnum
2540 elif regname in self.namespace:
2541 del self.namespace[regname]
2542
2543 if not self.is_svp64_mode or not self.pred_src_zero:
2544 log('reading reg %s %s' % (name, str(regnum)), is_vec)
2545 if name in fregs:
2546 reg_val = SelectableInt(self.fpr(base, is_vec, offs, ew_src))
2547 log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value),
2548 kind=LogType.InstrInOuts)
2549 self.trace("r:FPR:%d:%d:%d " % (base, offs, ew_src))
2550 elif name is not None:
2551 reg_val = SelectableInt(self.gpr(base, is_vec, offs, ew_src))
2552 self.trace("r:GPR:%d:%d:%d " % (base, offs, ew_src))
2553 log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value),
2554 kind=LogType.InstrInOuts)
2555 else:
2556 log('zero input reg %s %s' % (name, str(regnum)), is_vec)
2557 reg_val = SelectableInt(0, ew_src)
2558 return reg_val
2559
2560 def remap_set_steps(self, remaps):
2561 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2562 they work in concert with PowerDecoder2 at the moment,
2563 there is no HDL implementation of REMAP. therefore this
2564 function, because ISACaller still uses PowerDecoder2,
2565 will *explicitly* write the dec2.XX_step values. this has
2566 to get sorted out.
2567 """
2568 # just some convenient debug info
2569 for i in range(4):
2570 sname = 'SVSHAPE%d' % i
2571 shape = self.spr[sname]
2572 log(sname, bin(shape.value))
2573 log(" lims", shape.lims)
2574 log(" mode", shape.mode)
2575 log(" skip", shape.skip)
2576
2577 # set up the list of steps to remap
2578 mi0 = self.svstate.mi0
2579 mi1 = self.svstate.mi1
2580 mi2 = self.svstate.mi2
2581 mo0 = self.svstate.mo0
2582 mo1 = self.svstate.mo1
2583 steps = [[self.dec2.in1_step, mi0], # RA
2584 [self.dec2.in2_step, mi1], # RB
2585 [self.dec2.in3_step, mi2], # RC
2586 [self.dec2.o_step, mo0], # RT
2587 [self.dec2.o2_step, mo1], # EA
2588 ]
2589 if False: # TODO
2590 rnames = ['RA', 'RB', 'RC', 'RT', 'RS']
2591 for i, reg in enumerate(rnames):
2592 idx = yield from get_idx_map(self.dec2, reg)
2593 if idx is None:
2594 idx = yield from get_idx_map(self.dec2, "F"+reg)
2595 if idx == 1: # RA
2596 steps[i][0] = self.dec2.in1_step
2597 elif idx == 2: # RB
2598 steps[i][0] = self.dec2.in2_step
2599 elif idx == 3: # RC
2600 steps[i][0] = self.dec2.in3_step
2601 log("remap step", i, reg, idx, steps[i][1])
2602 remap_idxs = self.remap_idxs
2603 rremaps = []
2604 # now cross-index the required SHAPE for each of 3-in 2-out regs
2605 rnames = ['RA', 'RB', 'RC', 'RT', 'EA']
2606 for i, (dstep, shape_idx) in enumerate(steps):
2607 (shape, remap) = remaps[shape_idx]
2608 remap_idx = remap_idxs[shape_idx]
2609 # zero is "disabled"
2610 if shape.value == 0x0:
2611 continue
2612 # now set the actual requested step to the current index
2613 if dstep is not None:
2614 yield dstep.eq(remap_idx)
2615
2616 # debug printout info
2617 rremaps.append((shape.mode, hex(shape.value), dstep,
2618 i, rnames[i], shape_idx, remap_idx))
2619 for x in rremaps:
2620 log("shape remap", x)
2621
2622 def check_write(self, info, name, output, carry_en, ew_dst):
2623 if name == 'overflow': # ignore, done already (above)
2624 return
2625 if name == 'CR0': # ignore, done already (above)
2626 return
2627 if isinstance(output, int):
2628 output = SelectableInt(output, EFFECTIVELY_UNLIMITED)
2629 # write FPSCR
2630 if name in ['FPSCR', ]:
2631 log("write FPSCR 0x%x" % (output.value))
2632 self.FPSCR.eq(output)
2633 return
2634 # write carry flags
2635 if name in ['CA', 'CA32']:
2636 if carry_en:
2637 log("writing %s to XER" % name, output)
2638 log("write XER %s 0x%x" % (name, output.value))
2639 self.spr['XER'][XER_bits[name]] = output.value
2640 else:
2641 log("NOT writing %s to XER" % name, output)
2642 return
2643 # write special SPRs
2644 if name in info.special_regs:
2645 log('writing special %s' % name, output, special_sprs)
2646 log("write reg %s 0x%x" % (name, output.value),
2647 kind=LogType.InstrInOuts)
2648 if name in special_sprs:
2649 self.spr[name] = output
2650 else:
2651 self.namespace[name].eq(output)
2652 if name == 'MSR':
2653 log('msr written', hex(self.msr.value))
2654 return
2655 # find out1/out2 PR/FPR
2656 regnum, is_vec = yield from get_idx_out(self.dec2, name, True)
2657 if regnum is None:
2658 regnum, is_vec = yield from get_idx_out2(self.dec2, name, True)
2659 if regnum is None:
2660 # temporary hack for not having 2nd output
2661 regnum = yield getattr(self.decoder, name)
2662 is_vec = False
2663 # convenient debug prefix
2664 if name in fregs:
2665 reg_prefix = 'f'
2666 else:
2667 reg_prefix = 'r'
2668 # check zeroing due to predicate bit being zero
2669 if self.is_svp64_mode and self.pred_dst_zero:
2670 log('zeroing reg %s %s' % (str(regnum), str(output)), is_vec)
2671 output = SelectableInt(0, EFFECTIVELY_UNLIMITED)
2672 log("write reg %s%s 0x%x ew %d" % (reg_prefix, str(regnum),
2673 output.value, ew_dst),
2674 kind=LogType.InstrInOuts)
2675 # zero-extend tov64 bit begore storing (should use EXT oh well)
2676 if output.bits > 64:
2677 output = SelectableInt(output.value, 64)
2678 rnum, base, offset = regnum
2679 if name in fregs:
2680 self.fpr.write(regnum, output, is_vec, ew_dst)
2681 self.trace("w:FPR:%d:%d:%d " % (rnum, offset, ew_dst))
2682 else:
2683 self.gpr.write(regnum, output, is_vec, ew_dst)
2684 self.trace("w:GPR:%d:%d:%d " % (rnum, offset, ew_dst))
2685
2686 def check_step_increment(self, rc_en, asmop, ins_name):
2687 # check if it is the SVSTATE.src/dest step that needs incrementing
2688 # this is our Sub-Program-Counter loop from 0 to VL-1
2689 if not self.allow_next_step_inc:
2690 if self.is_svp64_mode:
2691 return (yield from self.svstate_post_inc(ins_name))
2692
2693 # XXX only in non-SVP64 mode!
2694 # record state of whether the current operation was an svshape,
2695 # OR svindex!
2696 # to be able to know if it should apply in the next instruction.
2697 # also (if going to use this instruction) should disable ability
2698 # to interrupt in between. sigh.
2699 self.last_op_svshape = asmop in ['svremap', 'svindex',
2700 'svshape2']
2701 return True
2702
2703 pre = False
2704 post = False
2705 nia_update = True
2706 log("SVSTATE_NEXT: inc requested, mode",
2707 self.svstate_next_mode, self.allow_next_step_inc)
2708 yield from self.svstate_pre_inc()
2709 pre = yield from self.update_new_svstate_steps()
2710 if pre:
2711 # reset at end of loop including exit Vertical Mode
2712 log("SVSTATE_NEXT: end of loop, reset")
2713 self.svp64_reset_loop()
2714 self.svstate.vfirst = 0
2715 self.update_nia()
2716 if not rc_en:
2717 return True
2718 self.handle_comparison(SelectableInt(0, 64)) # CR0
2719 return True
2720 if self.allow_next_step_inc == 2:
2721 log("SVSTATE_NEXT: read")
2722 nia_update = (yield from self.svstate_post_inc(ins_name))
2723 else:
2724 log("SVSTATE_NEXT: post-inc")
2725 # use actual (cached) src/dst-step here to check end
2726 remaps = self.get_remap_indices()
2727 remap_idxs = self.remap_idxs
2728 vl = self.svstate.vl
2729 subvl = yield self.dec2.rm_dec.rm_in.subvl
2730 if self.allow_next_step_inc != 2:
2731 yield from self.advance_svstate_steps()
2732 #self.namespace['SVSTATE'] = self.svstate.spr
2733 # set CR0 (if Rc=1) based on end
2734 endtest = 1 if self.at_loopend() else 0
2735 if rc_en:
2736 #results = [SelectableInt(endtest, 64)]
2737 # self.handle_comparison(results) # CR0
2738
2739 # see if svstep was requested, if so, which SVSTATE
2740 endings = 0b111
2741 if self.svstate_next_mode > 0:
2742 shape_idx = self.svstate_next_mode.value-1
2743 endings = self.remap_loopends[shape_idx]
2744 cr_field = SelectableInt((~endings) << 1 | endtest, 4)
2745 log("svstep Rc=1, CR0", cr_field, endtest)
2746 self.crl[0].eq(cr_field) # CR0
2747 if endtest:
2748 # reset at end of loop including exit Vertical Mode
2749 log("SVSTATE_NEXT: after increments, reset")
2750 self.svp64_reset_loop()
2751 self.svstate.vfirst = 0
2752 return nia_update
2753
2754 def SVSTATE_NEXT(self, mode, submode):
2755 """explicitly moves srcstep/dststep on to next element, for
2756 "Vertical-First" mode. this function is called from
2757 setvl pseudo-code, as a pseudo-op "svstep"
2758
2759 WARNING: this function uses information that was created EARLIER
2760 due to it being in the middle of a yield, but this function is
2761 *NOT* called from yield (it's called from compiled pseudocode).
2762 """
2763 self.allow_next_step_inc = submode.value + 1
2764 log("SVSTATE_NEXT mode", mode, submode, self.allow_next_step_inc)
2765 self.svstate_next_mode = mode
2766 if self.svstate_next_mode > 0 and self.svstate_next_mode < 5:
2767 shape_idx = self.svstate_next_mode.value-1
2768 return SelectableInt(self.remap_idxs[shape_idx], 7)
2769 if self.svstate_next_mode == 5:
2770 self.svstate_next_mode = 0
2771 return SelectableInt(self.svstate.srcstep, 7)
2772 if self.svstate_next_mode == 6:
2773 self.svstate_next_mode = 0
2774 return SelectableInt(self.svstate.dststep, 7)
2775 if self.svstate_next_mode == 7:
2776 self.svstate_next_mode = 0
2777 return SelectableInt(self.svstate.ssubstep, 7)
2778 if self.svstate_next_mode == 8:
2779 self.svstate_next_mode = 0
2780 return SelectableInt(self.svstate.dsubstep, 7)
2781 return SelectableInt(0, 7)
2782
2783 def get_src_dststeps(self):
2784 """gets srcstep, dststep, and ssubstep, dsubstep
2785 """
2786 return (self.new_srcstep, self.new_dststep,
2787 self.new_ssubstep, self.new_dsubstep)
2788
2789 def update_svstate_namespace(self, overwrite_svstate=True):
2790 if overwrite_svstate:
2791 # note, do not get the bit-reversed srcstep here!
2792 srcstep, dststep = self.new_srcstep, self.new_dststep
2793 ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
2794
2795 # update SVSTATE with new srcstep
2796 self.svstate.srcstep = srcstep
2797 self.svstate.dststep = dststep
2798 self.svstate.ssubstep = ssubstep
2799 self.svstate.dsubstep = dsubstep
2800 self.namespace['SVSTATE'] = self.svstate
2801 yield self.dec2.state.svstate.eq(self.svstate.value)
2802 yield Settle() # let decoder update
2803
2804 def update_new_svstate_steps(self, overwrite_svstate=True):
2805 yield from self.update_svstate_namespace(overwrite_svstate)
2806 srcstep = self.svstate.srcstep
2807 dststep = self.svstate.dststep
2808 ssubstep = self.svstate.ssubstep
2809 dsubstep = self.svstate.dsubstep
2810 pack = self.svstate.pack
2811 unpack = self.svstate.unpack
2812 vl = self.svstate.vl
2813 sv_mode = yield self.dec2.rm_dec.sv_mode
2814 subvl = yield self.dec2.rm_dec.rm_in.subvl
2815 rm_mode = yield self.dec2.rm_dec.mode
2816 ff_inv = yield self.dec2.rm_dec.inv
2817 cr_bit = yield self.dec2.rm_dec.cr_sel
2818 log(" srcstep", srcstep)
2819 log(" dststep", dststep)
2820 log(" pack", pack)
2821 log(" unpack", unpack)
2822 log(" ssubstep", ssubstep)
2823 log(" dsubstep", dsubstep)
2824 log(" vl", vl)
2825 log(" subvl", subvl)
2826 log(" rm_mode", rm_mode)
2827 log(" sv_mode", sv_mode)
2828 log(" inv", ff_inv)
2829 log(" cr_bit", cr_bit)
2830
2831 # check if end reached (we let srcstep overrun, above)
2832 # nothing needs doing (TODO zeroing): just do next instruction
2833 if self.loopend:
2834 return True
2835 return ((ssubstep == subvl and srcstep == vl) or
2836 (dsubstep == subvl and dststep == vl))
2837
2838 def svstate_post_inc(self, insn_name, vf=0):
2839 # check if SV "Vertical First" mode is enabled
2840 vfirst = self.svstate.vfirst
2841 log(" SV Vertical First", vf, vfirst)
2842 if not vf and vfirst == 1:
2843 if insn_name.startswith("sv.bc"):
2844 self.update_pc_next()
2845 return False
2846 self.update_nia()
2847 return True
2848
2849 # check if it is the SVSTATE.src/dest step that needs incrementing
2850 # this is our Sub-Program-Counter loop from 0 to VL-1
2851 # XXX twin predication TODO
2852 vl = self.svstate.vl
2853 subvl = yield self.dec2.rm_dec.rm_in.subvl
2854 mvl = self.svstate.maxvl
2855 srcstep = self.svstate.srcstep
2856 dststep = self.svstate.dststep
2857 ssubstep = self.svstate.ssubstep
2858 dsubstep = self.svstate.dsubstep
2859 pack = self.svstate.pack
2860 unpack = self.svstate.unpack
2861 rm_mode = yield self.dec2.rm_dec.mode
2862 reverse_gear = yield self.dec2.rm_dec.reverse_gear
2863 sv_ptype = yield self.dec2.dec.op.SV_Ptype
2864 out_vec = not (yield self.dec2.no_out_vec)
2865 in_vec = not (yield self.dec2.no_in_vec)
2866 log(" svstate.vl", vl)
2867 log(" svstate.mvl", mvl)
2868 log(" rm.subvl", subvl)
2869 log(" svstate.srcstep", srcstep)
2870 log(" svstate.dststep", dststep)
2871 log(" svstate.ssubstep", ssubstep)
2872 log(" svstate.dsubstep", dsubstep)
2873 log(" svstate.pack", pack)
2874 log(" svstate.unpack", unpack)
2875 log(" mode", rm_mode)
2876 log(" reverse", reverse_gear)
2877 log(" out_vec", out_vec)
2878 log(" in_vec", in_vec)
2879 log(" sv_ptype", sv_ptype, sv_ptype == SVPType.P2.value)
2880 # check if this was an sv.bc* and if so did it succeed
2881 if self.is_svp64_mode and insn_name.startswith("sv.bc"):
2882 end_loop = self.namespace['end_loop']
2883 log("branch %s end_loop" % insn_name, end_loop)
2884 if end_loop.value:
2885 self.svp64_reset_loop()
2886 self.update_pc_next()
2887 return False
2888 # check if srcstep needs incrementing by one, stop PC advancing
2889 # but for 2-pred both src/dest have to be checked.
2890 # XXX this might not be true! it may just be LD/ST
2891 if sv_ptype == SVPType.P2.value:
2892 svp64_is_vector = (out_vec or in_vec)
2893 else:
2894 svp64_is_vector = out_vec
2895 # loops end at the first "hit" (source or dest)
2896 yield from self.advance_svstate_steps()
2897 loopend = self.loopend
2898 log("loopend", svp64_is_vector, loopend)
2899 if not svp64_is_vector or loopend:
2900 # reset loop to zero and update NIA
2901 self.svp64_reset_loop()
2902 self.update_nia()
2903
2904 return True
2905
2906 # still looping, advance and update NIA
2907 self.namespace['SVSTATE'] = self.svstate
2908
2909 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2910 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2911 # this way we keep repeating the same instruction (with new steps)
2912 self.pc.NIA.eq(self.pc.CIA)
2913 self.namespace['NIA'] = self.pc.NIA
2914 log("end of sub-pc call", self.namespace['CIA'], self.namespace['NIA'])
2915 return False # DO NOT allow PC update whilst Sub-PC loop running
2916
2917 def update_pc_next(self):
2918 # UPDATE program counter
2919 self.pc.update(self.namespace, self.is_svp64_mode)
2920 #self.svstate.spr = self.namespace['SVSTATE']
2921 log("end of call", self.namespace['CIA'],
2922 self.namespace['NIA'],
2923 self.namespace['SVSTATE'])
2924
2925 def svp64_reset_loop(self):
2926 self.svstate.srcstep = 0
2927 self.svstate.dststep = 0
2928 self.svstate.ssubstep = 0
2929 self.svstate.dsubstep = 0
2930 self.loopend = False
2931 log(" svstate.srcstep loop end (PC to update)")
2932 self.namespace['SVSTATE'] = self.svstate
2933
2934 def update_nia(self):
2935 self.pc.update_nia(self.is_svp64_mode)
2936 self.namespace['NIA'] = self.pc.NIA
2937
2938
2939 def inject():
2940 """Decorator factory.
2941
2942 this decorator will "inject" variables into the function's namespace,
2943 from the *dictionary* in self.namespace. it therefore becomes possible
2944 to make it look like a whole stack of variables which would otherwise
2945 need "self." inserted in front of them (*and* for those variables to be
2946 added to the instance) "appear" in the function.
2947
2948 "self.namespace['SI']" for example becomes accessible as just "SI" but
2949 *only* inside the function, when decorated.
2950 """
2951 def variable_injector(func):
2952 @wraps(func)
2953 def decorator(*args, **kwargs):
2954 try:
2955 func_globals = func.__globals__ # Python 2.6+
2956 except AttributeError:
2957 func_globals = func.func_globals # Earlier versions.
2958
2959 context = args[0].namespace # variables to be injected
2960 saved_values = func_globals.copy() # Shallow copy of dict.
2961 log("globals before", context.keys())
2962 func_globals.update(context)
2963 result = func(*args, **kwargs)
2964 log("globals after", func_globals['CIA'], func_globals['NIA'])
2965 log("args[0]", args[0].namespace['CIA'],
2966 args[0].namespace['NIA'],
2967 args[0].namespace['SVSTATE'])
2968 if 'end_loop' in func_globals:
2969 log("args[0] end_loop", func_globals['end_loop'])
2970 args[0].namespace = func_globals
2971 #exec (func.__code__, func_globals)
2972
2973 # finally:
2974 # func_globals = saved_values # Undo changes.
2975
2976 return result
2977
2978 return decorator
2979
2980 return variable_injector