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