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