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