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