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