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