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