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