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