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
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.
13 * https://bugs.libre-soc.org/show_bug.cgi?id=424
17 from nmigen
.back
.pysim
import Settle
18 from functools
import wraps
19 from copy
import copy
, deepcopy
20 from openpower
.decoder
.orderedset
import OrderedSet
21 from openpower
.decoder
.selectable_int
import (
27 from openpower
.decoder
.power_enums
import (spr_dict
, spr_byname
, XER_bits
,
29 In1Sel
, In2Sel
, In3Sel
,
30 OutSel
, CRInSel
, CROutSel
, LDSTMode
,
31 SVP64RMMode
, SVP64PredMode
,
32 SVP64PredInt
, SVP64PredCR
,
35 from openpower
.decoder
.power_enums
import SVPtype
37 from openpower
.decoder
.helpers
import (exts
, gtu
, ltu
, undefined
,
38 ISACallerHelper
, ISAFPHelpers
)
39 from openpower
.consts
import PIb
, MSRb
# big-endian (PowerISA versions)
40 from openpower
.consts
import (SVP64MODE
,
43 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
45 from openpower
.decoder
.isa
.radixmmu
import RADIX
46 from openpower
.decoder
.isa
.mem
import Mem
, swap_order
, MemException
47 from openpower
.decoder
.isa
.svshape
import SVSHAPE
48 from openpower
.decoder
.isa
.svstate
import SVP64State
51 from openpower
.util
import log
53 from collections
import namedtuple
57 instruction_info
= namedtuple('instruction_info',
58 'func read_regs uninit_regs write_regs ' +
59 'special_regs op_fields form asmregs')
70 # TODO (lkcl): adjust other registers that should be in a particular order
71 # probably CA, CA32, and CR
97 "overflow": 7, # should definitely be last
100 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
103 def create_args(reglist
, extra
=None):
104 retval
= list(OrderedSet(reglist
))
105 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
106 if extra
is not None:
107 return [extra
] + retval
112 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
115 self
.isacaller
= isacaller
116 self
.svstate
= svstate
117 for i
in range(len(regfile
)):
118 self
[i
] = SelectableInt(regfile
[i
], 64)
120 def __call__(self
, ridx
):
121 if isinstance(ridx
, SelectableInt
):
125 def set_form(self
, form
):
128 def __setitem__(self
, rnum
, value
):
129 # rnum = rnum.value # only SelectableInt allowed
130 log("GPR setitem", rnum
, value
)
131 if isinstance(rnum
, SelectableInt
):
133 dict.__setitem
__(self
, rnum
, value
)
135 def getz(self
, rnum
):
136 # rnum = rnum.value # only SelectableInt allowed
137 log("GPR getzero?", rnum
)
139 return SelectableInt(0, 64)
142 def _get_regnum(self
, attr
):
143 getform
= self
.sd
.sigforms
[self
.form
]
144 rnum
= getattr(getform
, attr
)
147 def ___getitem__(self
, attr
):
148 """ XXX currently not used
150 rnum
= self
._get
_regnum
(attr
)
151 log("GPR getitem", attr
, rnum
)
152 return self
.regfile
[rnum
]
154 def dump(self
, printout
=True):
156 for i
in range(len(self
)):
157 res
.append(self
[i
].value
)
159 for i
in range(0, len(res
), 8):
162 s
.append("%08x" % res
[i
+j
])
164 print("reg", "%2d" % i
, s
)
169 def __init__(self
, dec2
, initial_sprs
={}):
172 for key
, v
in initial_sprs
.items():
173 if isinstance(key
, SelectableInt
):
175 key
= special_sprs
.get(key
, key
)
176 if isinstance(key
, int):
179 info
= spr_byname
[key
]
180 if not isinstance(v
, SelectableInt
):
181 v
= SelectableInt(v
, info
.length
)
184 def __getitem__(self
, key
):
186 log("dict", self
.items())
187 # if key in special_sprs get the special spr, otherwise return key
188 if isinstance(key
, SelectableInt
):
190 if isinstance(key
, int):
191 key
= spr_dict
[key
].SPR
192 key
= special_sprs
.get(key
, key
)
193 if key
== 'HSRR0': # HACK!
195 if key
== 'HSRR1': # HACK!
198 res
= dict.__getitem
__(self
, key
)
200 if isinstance(key
, int):
203 info
= spr_byname
[key
]
204 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
205 res
= dict.__getitem
__(self
, key
)
206 log("spr returning", key
, res
)
209 def __setitem__(self
, key
, value
):
210 if isinstance(key
, SelectableInt
):
212 if isinstance(key
, int):
213 key
= spr_dict
[key
].SPR
215 key
= special_sprs
.get(key
, key
)
216 if key
== 'HSRR0': # HACK!
217 self
.__setitem
__('SRR0', value
)
218 if key
== 'HSRR1': # HACK!
219 self
.__setitem
__('SRR1', value
)
220 log("setting spr", key
, value
)
221 dict.__setitem
__(self
, key
, value
)
223 def __call__(self
, ridx
):
226 def dump(self
, printout
=True):
228 keys
= list(self
.keys())
231 sprname
= spr_dict
.get(k
, None)
235 sprname
= sprname
.SPR
236 res
.append((sprname
, self
[k
].value
))
238 for sprname
, value
in res
:
239 print(" ", sprname
, hex(value
))
244 def __init__(self
, pc_init
=0):
245 self
.CIA
= SelectableInt(pc_init
, 64)
246 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
248 def update_nia(self
, is_svp64
):
249 increment
= 8 if is_svp64
else 4
250 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
252 def update(self
, namespace
, is_svp64
):
253 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
255 self
.CIA
= namespace
['NIA'].narrow(64)
256 self
.update_nia(is_svp64
)
257 namespace
['CIA'] = self
.CIA
258 namespace
['NIA'] = self
.NIA
262 class SVP64RMFields(SelectableIntMapping
):
263 def __init__(self
, value
=0):
264 self
.spr
= SelectableInt(value
=value
, bits
=24)
265 return super().__init
__(si
=self
.spr
, fields
={
267 # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
270 "elwidth": range(4, 6),
271 "ewsrc": range(6, 8),
272 "subvl": range(8, 10),
273 "extra": range(10, 19),
274 "mode": range(19, 24),
275 # these cover the same extra field, split into parts as EXTRA2
276 "extra2": dict(enumerate([
282 "smask": range(16, 19),
283 # and here as well, but EXTRA3
284 "extra3": dict(enumerate([
292 SVP64RM_MMODE_SIZE
= len(SVP64RMFields().mmode
.br
)
293 SVP64RM_MASK_SIZE
= len(SVP64RMFields().mask
.br
)
294 SVP64RM_ELWIDTH_SIZE
= len(SVP64RMFields().elwidth
.br
)
295 SVP64RM_EWSRC_SIZE
= len(SVP64RMFields().ewsrc
.br
)
296 SVP64RM_SUBVL_SIZE
= len(SVP64RMFields().subvl
.br
)
297 SVP64RM_EXTRA2_SPEC_SIZE
= len(SVP64RMFields().extra2
[0].br
)
298 SVP64RM_EXTRA3_SPEC_SIZE
= len(SVP64RMFields().extra3
[0].br
)
299 SVP64RM_SMASK_SIZE
= len(SVP64RMFields().smask
.br
)
300 SVP64RM_MODE_SIZE
= len(SVP64RMFields().mode
.br
)
303 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
304 class SVP64PrefixFields(SelectableIntMapping
):
306 self
.insn
= SelectableInt(0, 32)
307 return super().__init
__(si
=self
.insn
, fields
={
309 # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
310 "major": range(0, 6),
312 # SVP64 24-bit RM (ReMap)
313 "rm": ((6, 8) + tuple(range(10, 32))),
317 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields().major
.br
)
318 SV64P_PID_SIZE
= len(SVP64PrefixFields().pid
.br
)
319 SV64P_RM_SIZE
= len(SVP64PrefixFields().rm
.br
)
323 # See PowerISA Version 3.0 B Book 1
324 # Section 2.3.1 Condition Register pages 30 - 31
326 LT
= FL
= 0 # negative, less than, floating-point less than
327 GT
= FG
= 1 # positive, greater than, floating-point greater than
328 EQ
= FE
= 2 # equal, floating-point equal
329 SO
= FU
= 3 # summary overflow, floating-point unordered
331 def __init__(self
, init
=0):
332 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
333 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
334 self
.cr
= SelectableInt(init
, 64) # underlying reg
335 # field-selectable versions of Condition Register TODO check bitranges?
338 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
339 _cr
= FieldSelectableInt(self
.cr
, bits
)
342 # decode SVP64 predicate integer to reg number and invert
345 def get_predint(gpr
, mask
):
348 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
349 if mask
== SVP64PredInt
.ALWAYS
.value
:
350 return 0xffff_ffff_ffff_ffff # 64 bits of 1
351 if mask
== SVP64PredInt
.R3_UNARY
.value
:
352 return 1 << (gpr(3).value
& 0b111111)
353 if mask
== SVP64PredInt
.R3
.value
:
355 if mask
== SVP64PredInt
.R3_N
.value
:
357 if mask
== SVP64PredInt
.R10
.value
:
359 if mask
== SVP64PredInt
.R10_N
.value
:
360 return ~
gpr(10).value
361 if mask
== SVP64PredInt
.R30
.value
:
363 if mask
== SVP64PredInt
.R30_N
.value
:
364 return ~
gpr(30).value
366 # decode SVP64 predicate CR to reg number and invert status
369 def _get_predcr(mask
):
370 if mask
== SVP64PredCR
.LT
.value
:
372 if mask
== SVP64PredCR
.GE
.value
:
374 if mask
== SVP64PredCR
.GT
.value
:
376 if mask
== SVP64PredCR
.LE
.value
:
378 if mask
== SVP64PredCR
.EQ
.value
:
380 if mask
== SVP64PredCR
.NE
.value
:
382 if mask
== SVP64PredCR
.SO
.value
:
384 if mask
== SVP64PredCR
.NS
.value
:
387 # read individual CR fields (0..VL-1), extract the required bit
388 # and construct the mask
391 def get_predcr(crl
, mask
, vl
):
392 idx
, noninv
= _get_predcr(mask
)
395 cr
= crl
[i
+SVP64CROffs
.CRPred
]
396 if cr
[idx
].value
== noninv
:
401 # TODO, really should just be using PowerDecoder2
402 def get_pdecode_idx_in(dec2
, name
):
404 in1_sel
= yield op
.in1_sel
405 in2_sel
= yield op
.in2_sel
406 in3_sel
= yield op
.in3_sel
407 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
408 in1
= yield dec2
.e
.read_reg1
.data
409 in2
= yield dec2
.e
.read_reg2
.data
410 in3
= yield dec2
.e
.read_reg3
.data
411 in1_isvec
= yield dec2
.in1_isvec
412 in2_isvec
= yield dec2
.in2_isvec
413 in3_isvec
= yield dec2
.in3_isvec
414 log("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
416 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
418 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
420 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
422 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
424 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
426 # identify which regnames map to in1/2/3
428 if (in1_sel
== In1Sel
.RA
.value
or
429 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
430 return in1
, in1_isvec
431 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
432 return in1
, in1_isvec
434 if in2_sel
== In2Sel
.RB
.value
:
435 return in2
, in2_isvec
436 if in3_sel
== In3Sel
.RB
.value
:
437 return in3
, in3_isvec
438 # XXX TODO, RC doesn't exist yet!
440 assert False, "RC does not exist yet"
442 if in1_sel
== In1Sel
.RS
.value
:
443 return in1
, in1_isvec
444 if in2_sel
== In2Sel
.RS
.value
:
445 return in2
, in2_isvec
446 if in3_sel
== In3Sel
.RS
.value
:
447 return in3
, in3_isvec
449 if in1_sel
== In1Sel
.FRA
.value
:
450 return in1
, in1_isvec
452 if in2_sel
== In2Sel
.FRB
.value
:
453 return in2
, in2_isvec
455 if in3_sel
== In3Sel
.FRC
.value
:
456 return in3
, in3_isvec
458 if in1_sel
== In1Sel
.FRS
.value
:
459 return in1
, in1_isvec
460 if in3_sel
== In3Sel
.FRS
.value
:
461 return in3
, in3_isvec
465 # TODO, really should just be using PowerDecoder2
466 def get_pdecode_cr_in(dec2
, name
):
468 in_sel
= yield op
.cr_in
469 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
470 sv_cr_in
= yield op
.sv_cr_in
471 spec
= yield dec2
.crin_svdec
.spec
472 sv_override
= yield dec2
.dec_cr_in
.sv_override
473 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
474 in1
= yield dec2
.e
.read_cr1
.data
475 cr_isvec
= yield dec2
.cr_in_isvec
476 log("get_pdecode_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
477 log(" sv_cr_in", sv_cr_in
)
478 log(" cr_bf", in_bitfield
)
480 log(" override", sv_override
)
481 # identify which regnames map to in / o2
483 if in_sel
== CRInSel
.BI
.value
:
485 log("get_pdecode_cr_in not found", name
)
489 # TODO, really should just be using PowerDecoder2
490 def get_pdecode_cr_out(dec2
, name
):
492 out_sel
= yield op
.cr_out
493 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
494 sv_cr_out
= yield op
.sv_cr_out
495 spec
= yield dec2
.crout_svdec
.spec
496 sv_override
= yield dec2
.dec_cr_out
.sv_override
497 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
498 out
= yield dec2
.e
.write_cr
.data
499 o_isvec
= yield dec2
.o_isvec
500 log("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
501 log(" sv_cr_out", sv_cr_out
)
502 log(" cr_bf", out_bitfield
)
504 log(" override", sv_override
)
505 # identify which regnames map to out / o2
507 if out_sel
== CROutSel
.CR0
.value
:
509 log("get_pdecode_cr_out not found", name
)
513 # TODO, really should just be using PowerDecoder2
514 def get_pdecode_idx_out(dec2
, name
):
516 out_sel
= yield op
.out_sel
517 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
518 out
= yield dec2
.e
.write_reg
.data
519 o_isvec
= yield dec2
.o_isvec
520 # identify which regnames map to out / o2
522 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
523 if out_sel
== OutSel
.RA
.value
:
526 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
527 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
529 if out_sel
== OutSel
.RT
.value
:
531 elif name
== 'RT_OR_ZERO':
532 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
533 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
535 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
538 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
539 if out_sel
== OutSel
.FRA
.value
:
542 log("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
543 OutSel
.FRT
.value
, out
, o_isvec
)
544 if out_sel
== OutSel
.FRT
.value
:
546 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
550 # TODO, really should just be using PowerDecoder2
551 def get_pdecode_idx_out2(dec2
, name
):
552 # check first if register is activated for write
554 out_sel
= yield op
.out_sel
555 out
= yield dec2
.e
.write_ea
.data
556 o_isvec
= yield dec2
.o2_isvec
557 out_ok
= yield dec2
.e
.write_ea
.ok
558 log("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
563 if hasattr(op
, "upd"):
564 # update mode LD/ST uses read-reg A also as an output
566 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
567 out_sel
, OutSel
.RA
.value
,
569 if upd
== LDSTMode
.update
.value
:
572 int_op
= yield dec2
.dec
.op
.internal_op
573 fft_en
= yield dec2
.use_svp64_fft
574 # if int_op == MicrOp.OP_FP_MADD.value and fft_en:
576 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
582 class ISACaller(ISACallerHelper
, ISAFPHelpers
):
583 # decoder2 - an instance of power_decoder2
584 # regfile - a list of initial values for the registers
585 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
586 # respect_pc - tracks the program counter. requires initial_insns
587 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
588 initial_mem
=None, initial_msr
=0,
599 self
.bigendian
= bigendian
601 self
.is_svp64_mode
= False
602 self
.respect_pc
= respect_pc
603 if initial_sprs
is None:
605 if initial_mem
is None:
607 if fpregfile
is None:
609 if initial_insns
is None:
611 assert self
.respect_pc
== False, "instructions required to honor pc"
613 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
614 log("ISACaller initial_msr", initial_msr
)
616 # "fake program counter" mode (for unit testing)
620 if isinstance(initial_mem
, tuple):
621 self
.fake_pc
= initial_mem
[0]
622 disasm_start
= self
.fake_pc
624 disasm_start
= initial_pc
626 # disassembly: we need this for now (not given from the decoder)
627 self
.disassembly
= {}
629 for i
, code
in enumerate(disassembly
):
630 self
.disassembly
[i
*4 + disasm_start
] = code
632 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
633 self
.svp64rm
= SVP64RM()
634 if initial_svstate
is None:
636 if isinstance(initial_svstate
, int):
637 initial_svstate
= SVP64State(initial_svstate
)
638 # SVSTATE, MSR and PC
639 self
.svstate
= initial_svstate
640 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
642 # GPR FPR SPR registers
643 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
644 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
645 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
646 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
648 # set up 4 dummy SVSHAPEs if they aren't already set up
650 sname
= 'SVSHAPE%d' % i
651 if sname
not in self
.spr
:
652 self
.spr
[sname
] = SVSHAPE(0)
654 # make sure it's an SVSHAPE
655 val
= self
.spr
[sname
].value
656 self
.spr
[sname
] = SVSHAPE(val
)
657 self
.last_op_svshape
= False
660 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
661 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
662 # MMU mode, redirect underlying Mem through RADIX
664 self
.mem
= RADIX(self
.mem
, self
)
666 self
.imem
= RADIX(self
.imem
, self
)
669 # FPR (same as GPR except for FP nums)
670 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
671 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
672 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
673 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
675 # 2.3.2 LR (actually SPR #8) -- Done
676 # 2.3.3 CTR (actually SPR #9) -- Done
677 # 2.3.4 TAR (actually SPR #815)
678 # 3.2.2 p45 XER (actually SPR #1) -- Done
679 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
681 # create CR then allow portions of it to be "selectable" (below)
682 self
.cr_fields
= CRFields(initial_cr
)
683 self
.cr
= self
.cr_fields
.cr
685 # "undefined", just set to variable-bit-width int (use exts "max")
686 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
689 self
.namespace
.update(self
.spr
)
690 self
.namespace
.update({'GPR': self
.gpr
,
694 'memassign': self
.memassign
,
697 'SVSTATE': self
.svstate
,
698 'SVSHAPE0': self
.spr
['SVSHAPE0'],
699 'SVSHAPE1': self
.spr
['SVSHAPE1'],
700 'SVSHAPE2': self
.spr
['SVSHAPE2'],
701 'SVSHAPE3': self
.spr
['SVSHAPE3'],
704 'undefined': undefined
,
705 'mode_is_64bit': True,
706 'SO': XER_bits
['SO'],
707 'XLEN': 64 # elwidth overrides, later
710 # update pc to requested start point
711 self
.set_pc(initial_pc
)
713 # field-selectable versions of Condition Register
714 self
.crl
= self
.cr_fields
.crl
716 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
718 self
.decoder
= decoder2
.dec
721 super().__init
__(XLEN
=self
.namespace
["XLEN"])
725 return self
.namespace
["XLEN"]
727 def call_trap(self
, trap_addr
, trap_bit
):
728 """calls TRAP and sets up NIA to the new execution location.
729 next instruction will begin at trap_addr.
731 self
.TRAP(trap_addr
, trap_bit
)
732 self
.namespace
['NIA'] = self
.trap_nia
733 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
735 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
736 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
738 TRAP function is callable from inside the pseudocode itself,
739 hence the default arguments. when calling from inside ISACaller
740 it is best to use call_trap()
742 log("TRAP:", hex(trap_addr
), hex(self
.namespace
['MSR'].value
))
743 # store CIA(+4?) in SRR0, set NIA to 0x700
744 # store MSR in SRR1, set MSR to um errr something, have to check spec
745 # store SVSTATE (if enabled) in SVSRR0
746 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
747 self
.spr
['SRR1'].value
= self
.namespace
['MSR'].value
748 if self
.is_svp64_mode
:
749 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
750 self
.trap_nia
= SelectableInt(trap_addr
, 64)
751 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
753 # set exception bits. TODO: this should, based on the address
754 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
755 # bits appropriately. however it turns out that *for now* in all
756 # cases (all trap_addrs) the exact same thing is needed.
757 self
.msr
[MSRb
.IR
] = 0
758 self
.msr
[MSRb
.DR
] = 0
759 self
.msr
[MSRb
.FE0
] = 0
760 self
.msr
[MSRb
.FE1
] = 0
761 self
.msr
[MSRb
.EE
] = 0
762 self
.msr
[MSRb
.RI
] = 0
763 self
.msr
[MSRb
.SF
] = 1
764 self
.msr
[MSRb
.TM
] = 0
765 self
.msr
[MSRb
.VEC
] = 0
766 self
.msr
[MSRb
.VSX
] = 0
767 self
.msr
[MSRb
.PR
] = 0
768 self
.msr
[MSRb
.FP
] = 0
769 self
.msr
[MSRb
.PMM
] = 0
770 self
.msr
[MSRb
.TEs
] = 0
771 self
.msr
[MSRb
.TEe
] = 0
772 self
.msr
[MSRb
.UND
] = 0
773 self
.msr
[MSRb
.LE
] = 1
775 def memassign(self
, ea
, sz
, val
):
776 self
.mem
.memassign(ea
, sz
, val
)
778 def prep_namespace(self
, insn_name
, formname
, op_fields
):
779 # TODO: get field names from form in decoder*1* (not decoder2)
780 # decoder2 is hand-created, and decoder1.sigform is auto-generated
782 # then "yield" fields only from op_fields rather than hard-coded
784 fields
= self
.decoder
.sigforms
[formname
]
785 log("prep_namespace", formname
, op_fields
)
786 for name
in op_fields
:
787 # CR immediates. deal with separately. needs modifying
789 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
790 # BI is a 5-bit, must reconstruct the value
791 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
792 sig
= getattr(fields
, name
)
794 # low 2 LSBs (CR field selector) remain same, CR num extended
795 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
796 val
= (val
& 0b11) |
(regnum
<< 2)
799 sig
= getattr(fields
, name
.upper())
801 sig
= getattr(fields
, name
)
803 # these are all opcode fields involved in index-selection of CR,
804 # and need to do "standard" arithmetic. CR[BA+32] for example
805 # would, if using SelectableInt, only be 5-bit.
806 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
807 self
.namespace
[name
] = val
809 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
811 self
.namespace
['XER'] = self
.spr
['XER']
812 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
813 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
815 # add some SVSTATE convenience variables
817 srcstep
= self
.svstate
.srcstep
818 self
.namespace
['VL'] = vl
819 self
.namespace
['srcstep'] = srcstep
821 # sv.bc* need some extra fields
822 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
823 # blegh grab bits manually
824 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
825 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
826 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
827 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
828 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
829 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
830 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
831 sz
= yield self
.dec2
.rm_dec
.pred_sz
832 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
833 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
834 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
835 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
836 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
837 self
.namespace
['sz'] = SelectableInt(sz
, 1)
838 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
840 def handle_carry_(self
, inputs
, outputs
, already_done
):
841 inv_a
= yield self
.dec2
.e
.do
.invert_in
843 inputs
[0] = ~inputs
[0]
845 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
847 imm
= yield self
.dec2
.e
.do
.imm_data
.data
848 inputs
.append(SelectableInt(imm
, 64))
849 assert len(outputs
) >= 1
850 log("outputs", repr(outputs
))
851 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
857 log("gt input", x
, output
)
858 gt
= (gtu(x
, output
))
861 cy
= 1 if any(gts
) else 0
863 if not (1 & already_done
):
864 self
.spr
['XER'][XER_bits
['CA']] = cy
866 log("inputs", already_done
, inputs
)
868 # ARGH... different for OP_ADD... *sigh*...
869 op
= yield self
.dec2
.e
.do
.insn_type
870 if op
== MicrOp
.OP_ADD
.value
:
871 res32
= (output
.value
& (1 << 32)) != 0
872 a32
= (inputs
[0].value
& (1 << 32)) != 0
874 b32
= (inputs
[1].value
& (1 << 32)) != 0
877 cy32
= res32 ^ a32 ^ b32
878 log("CA32 ADD", cy32
)
882 log("input", x
, output
)
883 log(" x[32:64]", x
, x
[32:64])
884 log(" o[32:64]", output
, output
[32:64])
885 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
887 cy32
= 1 if any(gts
) else 0
888 log("CA32", cy32
, gts
)
889 if not (2 & already_done
):
890 self
.spr
['XER'][XER_bits
['CA32']] = cy32
892 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
893 if hasattr(self
.dec2
.e
.do
, "invert_in"):
894 inv_a
= yield self
.dec2
.e
.do
.invert_in
896 inputs
[0] = ~inputs
[0]
898 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
900 imm
= yield self
.dec2
.e
.do
.imm_data
.data
901 inputs
.append(SelectableInt(imm
, 64))
902 assert len(outputs
) >= 1
903 log("handle_overflow", inputs
, outputs
, div_overflow
)
904 if len(inputs
) < 2 and div_overflow
is None:
907 # div overflow is different: it's returned by the pseudo-code
908 # because it's more complex than can be done by analysing the output
909 if div_overflow
is not None:
910 ov
, ov32
= div_overflow
, div_overflow
911 # arithmetic overflow can be done by analysing the input and output
912 elif len(inputs
) >= 2:
916 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
917 output_sgn
= exts(output
.value
, output
.bits
) < 0
918 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
919 output_sgn
!= input_sgn
[0] else 0
922 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
923 output32_sgn
= exts(output
.value
, 32) < 0
924 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
925 output32_sgn
!= input32_sgn
[0] else 0
927 self
.spr
['XER'][XER_bits
['OV']] = ov
928 self
.spr
['XER'][XER_bits
['OV32']] = ov32
929 so
= self
.spr
['XER'][XER_bits
['SO']]
931 self
.spr
['XER'][XER_bits
['SO']] = so
933 def handle_comparison(self
, outputs
, cr_idx
=0):
935 assert isinstance(out
, SelectableInt
), \
936 "out zero not a SelectableInt %s" % repr(outputs
)
937 log("handle_comparison", out
.bits
, hex(out
.value
))
938 # TODO - XXX *processor* in 32-bit mode
939 # https://bugs.libre-soc.org/show_bug.cgi?id=424
941 # o32 = exts(out.value, 32)
942 # print ("handle_comparison exts 32 bit", hex(o32))
943 out
= exts(out
.value
, out
.bits
)
944 log("handle_comparison exts", hex(out
))
945 zero
= SelectableInt(out
== 0, 1)
946 positive
= SelectableInt(out
> 0, 1)
947 negative
= SelectableInt(out
< 0, 1)
948 SO
= self
.spr
['XER'][XER_bits
['SO']]
949 log("handle_comparison SO", SO
)
950 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
951 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
952 self
.crl
[cr_idx
].eq(cr_field
)
954 def set_pc(self
, pc_val
):
955 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
956 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
958 def get_next_insn(self
):
962 pc
= self
.pc
.CIA
.value
965 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
967 raise KeyError("no instruction at 0x%x" % pc
)
971 """set up one instruction
973 pc
, insn
= self
.get_next_insn()
974 yield from self
.setup_next_insn(pc
, insn
)
976 def setup_next_insn(self
, pc
, ins
):
977 """set up next instruction
980 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
981 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
983 yield self
.dec2
.sv_rm
.eq(0)
984 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
985 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
986 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
987 yield self
.dec2
.state
.pc
.eq(pc
)
988 if self
.svstate
is not None:
989 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
991 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
993 opcode
= yield self
.dec2
.dec
.opcode_in
994 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
995 pfx
.insn
.value
= opcode
996 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
997 log("prefix test: opcode:", major
, bin(major
),
998 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
999 self
.is_svp64_mode
= ((major
== 0b000001) and
1000 pfx
.insn
[7].value
== 0b1 and
1001 pfx
.insn
[9].value
== 0b1)
1002 self
.pc
.update_nia(self
.is_svp64_mode
)
1004 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1005 self
.namespace
['NIA'] = self
.pc
.NIA
1006 self
.namespace
['SVSTATE'] = self
.svstate
1007 if not self
.is_svp64_mode
:
1010 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1011 log("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
1012 log(" svstate.vl", self
.svstate
.vl
)
1013 log(" svstate.mvl", self
.svstate
.maxvl
)
1014 sv_rm
= pfx
.rm
.asint(msb0
=True)
1015 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1016 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1017 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1018 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
1021 def execute_one(self
):
1022 """execute one instruction
1024 # get the disassembly code for this instruction
1025 if self
.is_svp64_mode
:
1026 if not self
.disassembly
:
1027 code
= yield from self
.get_assembly_name()
1029 code
= self
.disassembly
[self
._pc
+4]
1030 log(" svp64 sim-execute", hex(self
._pc
), code
)
1032 if not self
.disassembly
:
1033 code
= yield from self
.get_assembly_name()
1035 code
= self
.disassembly
[self
._pc
]
1036 log("sim-execute", hex(self
._pc
), code
)
1037 opname
= code
.split(' ')[0]
1039 yield from self
.call(opname
) # execute the instruction
1040 except MemException
as e
: # check for memory errors
1041 if e
.args
[0] == 'unaligned': # alignment error
1042 # run a Trap but set DAR first
1043 print("memory unaligned exception, DAR", e
.dar
)
1044 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1045 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1047 elif e
.args
[0] == 'invalid': # invalid
1048 # run a Trap but set DAR first
1049 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1050 if e
.mode
== 'EXECUTE':
1051 # XXX TODO: must set a few bits in SRR1,
1052 # see microwatt loadstore1.vhdl
1053 # if m_in.segerr = '0' then
1054 # v.srr1(47 - 33) := m_in.invalid;
1055 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1056 # v.srr1(47 - 44) := m_in.badtree;
1057 # v.srr1(47 - 45) := m_in.rc_error;
1058 # v.intr_vec := 16#400#;
1060 # v.intr_vec := 16#480#;
1061 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1063 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1065 # not supported yet:
1066 raise e
# ... re-raise
1068 # don't use this except in special circumstances
1069 if not self
.respect_pc
:
1072 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1073 hex(self
.pc
.NIA
.value
))
1075 def get_assembly_name(self
):
1076 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1077 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1078 dec_insn
= yield self
.dec2
.e
.do
.insn
1079 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1080 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1081 int_op
= yield self
.dec2
.dec
.op
.internal_op
1082 log("get assembly name asmcode", asmcode
, int_op
,
1083 hex(dec_insn
), bin(insn_1_11
))
1084 asmop
= insns
.get(asmcode
, None)
1086 # sigh reconstruct the assembly instruction name
1087 if hasattr(self
.dec2
.e
.do
, "oe"):
1088 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1089 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1093 if hasattr(self
.dec2
.e
.do
, "rc"):
1094 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1095 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1099 # grrrr have to special-case MUL op (see DecodeOE)
1100 log("ov %d en %d rc %d en %d op %d" %
1101 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1102 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1107 if not asmop
.endswith("."): # don't add "." to "andis."
1110 if hasattr(self
.dec2
.e
.do
, "lk"):
1111 lk
= yield self
.dec2
.e
.do
.lk
1114 log("int_op", int_op
)
1115 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1116 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1120 spr_msb
= yield from self
.get_spr_msb()
1121 if int_op
== MicrOp
.OP_MFCR
.value
:
1126 # XXX TODO: for whatever weird reason this doesn't work
1127 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1128 if int_op
== MicrOp
.OP_MTCRF
.value
:
1135 def get_remap_indices(self
):
1136 """WARNING, this function stores remap_idxs and remap_loopends
1137 in the class for later use. this to avoid problems with yield
1139 # go through all iterators in lock-step, advance to next remap_idx
1140 srcstep
, dststep
= self
.get_src_dststeps()
1141 # get four SVSHAPEs. here we are hard-coding
1142 SVSHAPE0
= self
.spr
['SVSHAPE0']
1143 SVSHAPE1
= self
.spr
['SVSHAPE1']
1144 SVSHAPE2
= self
.spr
['SVSHAPE2']
1145 SVSHAPE3
= self
.spr
['SVSHAPE3']
1146 # set up the iterators
1147 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1148 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1149 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1150 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1153 self
.remap_loopends
= [0] * 4
1154 self
.remap_idxs
= [0, 1, 2, 3]
1156 for i
, (shape
, remap
) in enumerate(remaps
):
1157 # zero is "disabled"
1158 if shape
.value
== 0x0:
1159 self
.remap_idxs
[i
] = 0
1160 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1161 step
= dststep
if (i
in [3, 4]) else srcstep
1162 # this is terrible. O(N^2) looking for the match. but hey.
1163 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1166 self
.remap_idxs
[i
] = remap_idx
1167 self
.remap_loopends
[i
] = loopends
1168 dbg
.append((i
, step
, remap_idx
, loopends
))
1169 for (i
, step
, remap_idx
, loopends
) in dbg
:
1170 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1173 def get_spr_msb(self
):
1174 dec_insn
= yield self
.dec2
.e
.do
.insn
1175 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1177 def call(self
, name
):
1178 """call(opcode) - the primary execution point for instructions
1180 self
.last_st_addr
= None # reset the last known store address
1181 self
.last_ld_addr
= None # etc.
1183 ins_name
= name
.strip() # remove spaces if not already done so
1185 log("halted - not executing", ins_name
)
1188 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1189 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1190 asmop
= yield from self
.get_assembly_name()
1191 log("call", ins_name
, asmop
)
1194 int_op
= yield self
.dec2
.dec
.op
.internal_op
1195 spr_msb
= yield from self
.get_spr_msb()
1197 instr_is_privileged
= False
1198 if int_op
in [MicrOp
.OP_ATTN
.value
,
1199 MicrOp
.OP_MFMSR
.value
,
1200 MicrOp
.OP_MTMSR
.value
,
1201 MicrOp
.OP_MTMSRD
.value
,
1203 MicrOp
.OP_RFID
.value
]:
1204 instr_is_privileged
= True
1205 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1206 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1207 instr_is_privileged
= True
1209 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1211 # check MSR priv bit and whether op is privileged: if so, throw trap
1212 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1213 self
.call_trap(0x700, PIb
.PRIV
)
1216 # check halted condition
1217 if ins_name
== 'attn':
1221 # check illegal instruction
1223 if ins_name
not in ['mtcrf', 'mtocrf']:
1224 illegal
= ins_name
!= asmop
1226 # sigh deal with setvl not being supported by binutils (.long)
1227 if asmop
.startswith('setvl'):
1231 # and svstep not being supported by binutils (.long)
1232 if asmop
.startswith('svstep'):
1236 # and svremap not being supported by binutils (.long)
1237 if asmop
.startswith('svremap'):
1239 ins_name
= 'svremap'
1241 # and svshape not being supported by binutils (.long)
1242 if asmop
.startswith('svshape'):
1244 ins_name
= 'svshape'
1247 if asmop
== 'fsins':
1250 if asmop
== 'fcoss':
1254 # sigh also deal with ffmadds not being supported by binutils (.long)
1255 if asmop
== 'ffmadds':
1257 ins_name
= 'ffmadds'
1259 # and fdmadds not being supported by binutils (.long)
1260 if asmop
== 'fdmadds':
1262 ins_name
= 'fdmadds'
1264 # and ffadds not being supported by binutils (.long)
1265 if asmop
== 'ffadds':
1269 if asmop
== 'ternlogi' \
1270 or re
.fullmatch(r
'grevw?i?\.?', asmop
or ''):
1274 # branch-conditional redirects to sv.bc
1275 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1276 ins_name
= 'sv.%s' % ins_name
1278 log(" post-processed name", ins_name
, asmop
)
1280 # illegal instructions call TRAP at 0x700
1282 print("illegal", ins_name
, asmop
)
1283 self
.call_trap(0x700, PIb
.ILLEG
)
1284 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1285 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1288 # this is for setvl "Vertical" mode: if set true,
1289 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1290 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1291 self
.allow_next_step_inc
= False
1292 self
.svstate_next_mode
= 0
1294 # nop has to be supported, we could let the actual op calculate
1295 # but PowerDecoder has a pattern for nop
1296 if ins_name
is 'nop':
1297 self
.update_pc_next()
1300 # look up instruction in ISA.instrs, prepare namespace
1301 info
= self
.instrs
[ins_name
]
1302 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1304 # preserve order of register names
1305 input_names
= create_args(list(info
.read_regs
) +
1306 list(info
.uninit_regs
))
1307 log("input names", input_names
)
1309 # get SVP64 entry for the current instruction
1310 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1311 if sv_rm
is not None:
1312 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1314 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1315 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1317 # see if srcstep/dststep need skipping over masked-out predicate bits
1318 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1319 ins_name
in ['svremap', 'svstate']):
1320 yield from self
.svstate_pre_inc()
1321 if self
.is_svp64_mode
:
1322 pre
= yield from self
.update_new_svstate_steps()
1324 self
.svp64_reset_loop()
1326 self
.update_pc_next()
1328 srcstep
, dststep
= self
.get_src_dststeps()
1329 pred_dst_zero
= self
.pred_dst_zero
1330 pred_src_zero
= self
.pred_src_zero
1331 vl
= self
.svstate
.vl
1333 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1334 if self
.is_svp64_mode
and vl
== 0:
1335 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1336 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1337 self
.namespace
['NIA'])
1340 # for when SVREMAP is active, using pre-arranged schedule.
1341 # note: modifying PowerDecoder2 needs to "settle"
1342 remap_en
= self
.svstate
.SVme
1343 persist
= self
.svstate
.RMpst
1344 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1345 if self
.is_svp64_mode
:
1346 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1348 if persist
or self
.last_op_svshape
:
1349 remaps
= self
.get_remap_indices()
1350 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1351 # just some convenient debug info
1353 sname
= 'SVSHAPE%d' % i
1354 shape
= self
.spr
[sname
]
1355 log(sname
, bin(shape
.value
))
1356 log(" lims", shape
.lims
)
1357 log(" mode", shape
.mode
)
1358 log(" skip", shape
.skip
)
1360 # set up the list of steps to remap
1361 mi0
= self
.svstate
.mi0
1362 mi1
= self
.svstate
.mi1
1363 mi2
= self
.svstate
.mi2
1364 mo0
= self
.svstate
.mo0
1365 mo1
= self
.svstate
.mo1
1366 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1367 (self
.dec2
.in2_step
, mi1
), # RB
1368 (self
.dec2
.in3_step
, mi2
), # RC
1369 (self
.dec2
.o_step
, mo0
), # RT
1370 (self
.dec2
.o2_step
, mo1
), # EA
1372 remap_idxs
= self
.remap_idxs
1374 # now cross-index the required SHAPE for each of 3-in 2-out regs
1375 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1376 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1377 (shape
, remap
) = remaps
[shape_idx
]
1378 remap_idx
= remap_idxs
[shape_idx
]
1379 # zero is "disabled"
1380 if shape
.value
== 0x0:
1382 # now set the actual requested step to the current index
1383 yield dstep
.eq(remap_idx
)
1385 # debug printout info
1386 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
,
1389 log("shape remap", x
)
1390 # after that, settle down (combinatorial) to let Vector reg numbers
1391 # work themselves out
1393 if self
.is_svp64_mode
:
1394 remap_active
= yield self
.dec2
.remap_active
1396 remap_active
= False
1397 log("remap active", bin(remap_active
))
1399 # main input registers (RT, RA ...)
1401 for name
in input_names
:
1402 # using PowerDecoder2, first, find the decoder index.
1403 # (mapping name RA RB RC RS to in1, in2, in3)
1404 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1406 # doing this is not part of svp64, it's because output
1407 # registers, to be modified, need to be in the namespace.
1408 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1410 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1413 # in case getting the register number is needed, _RA, _RB
1414 regname
= "_" + name
1415 self
.namespace
[regname
] = regnum
1416 if not self
.is_svp64_mode
or not pred_src_zero
:
1417 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1419 reg_val
= SelectableInt(self
.fpr(regnum
))
1420 elif name
is not None:
1421 reg_val
= SelectableInt(self
.gpr(regnum
))
1423 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1425 inputs
.append(reg_val
)
1426 # arrrrgh, awful hack, to get _RT into namespace
1427 if ins_name
in ['setvl', 'svstep']:
1429 RT
= yield self
.dec2
.dec
.RT
1430 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1432 self
.namespace
["RT"] = SelectableInt(0, 5)
1433 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1434 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1436 # in SVP64 mode for LD/ST work out immediate
1437 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1438 # use info.form to detect
1439 replace_d
= False # update / replace constant in pseudocode
1440 if self
.is_svp64_mode
:
1441 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1442 # shift mode reads SVD (or SVDS - TODO)
1443 # *BUT*... because this is "overloading" of LD operations,
1444 # it gets *STORED* into D (or DS, TODO)
1445 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1446 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1447 imm
= exts(imm
, 11) # sign-extend to integer
1448 log("shift SVD", imm
)
1451 if info
.form
== 'DS':
1452 # DS-Form, multiply by 4 then knock 2 bits off after
1453 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1455 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1456 imm
= exts(imm
, 16) # sign-extend to integer
1457 # get the right step. LD is from srcstep, ST is dststep
1458 op
= yield self
.dec2
.e
.do
.insn_type
1460 if op
== MicrOp
.OP_LOAD
.value
:
1462 offsmul
= yield self
.dec2
.in1_step
1463 log("D-field REMAP src", imm
, offsmul
)
1466 log("D-field src", imm
, offsmul
)
1467 elif op
== MicrOp
.OP_STORE
.value
:
1468 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1470 log("D-field dst", imm
, offsmul
)
1471 # bit-reverse mode, rev already done through get_src_dst_steps()
1472 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1473 # manually look up RC, sigh
1474 RC
= yield self
.dec2
.dec
.RC
[0:5]
1476 log("LD-SHIFT:", "VL", vl
,
1477 "RC", RC
.value
, "imm", imm
,
1478 "offs", bin(offsmul
),
1480 imm
= SelectableInt((imm
* offsmul
) << RC
.value
, 32)
1481 # Unit-Strided LD/ST adds offset*width to immediate
1482 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1483 ldst_len
= yield self
.dec2
.e
.do
.data_len
1484 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1486 # Element-strided multiplies the immediate by element step
1487 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1488 imm
= SelectableInt(imm
* offsmul
, 32)
1491 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1492 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1493 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1494 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1495 # new replacement D... errr.. DS
1497 if info
.form
== 'DS':
1498 # TODO: assert 2 LSBs are zero?
1499 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1500 imm
.value
= imm
.value
>> 2
1501 self
.namespace
['DS'] = imm
1503 self
.namespace
['D'] = imm
1505 # "special" registers
1506 for special
in info
.special_regs
:
1507 if special
in special_sprs
:
1508 inputs
.append(self
.spr
[special
])
1510 inputs
.append(self
.namespace
[special
])
1512 # clear trap (trap) NIA
1513 self
.trap_nia
= None
1515 # check if this was an sv.bc* and create an indicator that
1516 # this is the last check to be made as a loop. combined with
1517 # the ALL/ANY mode we can early-exit
1518 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1519 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1520 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1521 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1523 # execute actual instruction here (finally)
1524 log("inputs", inputs
)
1525 results
= info
.func(self
, *inputs
)
1526 log("results", results
)
1528 # "inject" decorator takes namespace from function locals: we need to
1529 # overwrite NIA being overwritten (sigh)
1530 if self
.trap_nia
is not None:
1531 self
.namespace
['NIA'] = self
.trap_nia
1533 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1535 # check if op was a LD/ST so that debugging can check the
1537 if int_op
in [MicrOp
.OP_STORE
.value
,
1539 self
.last_st_addr
= self
.mem
.last_st_addr
1540 if int_op
in [MicrOp
.OP_LOAD
.value
,
1542 self
.last_ld_addr
= self
.mem
.last_ld_addr
1543 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1544 self
.last_st_addr
, self
.last_ld_addr
)
1546 # detect if CA/CA32 already in outputs (sra*, basically)
1549 output_names
= create_args(info
.write_regs
)
1550 for name
in output_names
:
1556 log("carry already done?", bin(already_done
))
1557 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1558 carry_en
= yield self
.dec2
.e
.do
.output_carry
1562 yield from self
.handle_carry_(inputs
, results
, already_done
)
1564 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1565 # detect if overflow was in return result
1568 for name
, output
in zip(output_names
, results
):
1569 if name
== 'overflow':
1572 if hasattr(self
.dec2
.e
.do
, "oe"):
1573 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1574 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1578 log("internal overflow", overflow
, ov_en
, ov_ok
)
1580 yield from self
.handle_overflow(inputs
, results
, overflow
)
1582 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1584 if not self
.is_svp64_mode
or not pred_dst_zero
:
1585 if hasattr(self
.dec2
.e
.do
, "rc"):
1586 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1587 if rc_en
and ins_name
not in ['svstep']:
1588 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1589 self
.handle_comparison(results
, regnum
)
1591 # any modified return results?
1593 for name
, output
in zip(output_names
, results
):
1594 if name
== 'overflow': # ignore, done already (above)
1596 if isinstance(output
, int):
1597 output
= SelectableInt(output
, 256)
1598 if name
in ['CA', 'CA32']:
1600 log("writing %s to XER" % name
, output
)
1601 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1603 log("NOT writing %s to XER" % name
, output
)
1604 elif name
in info
.special_regs
:
1605 log('writing special %s' % name
, output
, special_sprs
)
1606 if name
in special_sprs
:
1607 self
.spr
[name
] = output
1609 self
.namespace
[name
].eq(output
)
1611 log('msr written', hex(self
.msr
.value
))
1613 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1616 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1619 # temporary hack for not having 2nd output
1620 regnum
= yield getattr(self
.decoder
, name
)
1622 if self
.is_svp64_mode
and pred_dst_zero
:
1623 log('zeroing reg %d %s' % (regnum
, str(output
)),
1625 output
= SelectableInt(0, 256)
1631 log('writing %s %s %s' % (ftype
, regnum
, str(output
)),
1633 if output
.bits
> 64:
1634 output
= SelectableInt(output
.value
, 64)
1636 self
.fpr
[regnum
] = output
1638 self
.gpr
[regnum
] = output
1640 # check if it is the SVSTATE.src/dest step that needs incrementing
1641 # this is our Sub-Program-Counter loop from 0 to VL-1
1645 if self
.allow_next_step_inc
:
1646 log("SVSTATE_NEXT: inc requested, mode",
1647 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1648 yield from self
.svstate_pre_inc()
1649 pre
= yield from self
.update_new_svstate_steps()
1651 # reset at end of loop including exit Vertical Mode
1652 log("SVSTATE_NEXT: end of loop, reset")
1653 self
.svp64_reset_loop()
1654 self
.svstate
.vfirst
= 0
1657 results
= [SelectableInt(0, 64)]
1658 self
.handle_comparison(results
) # CR0
1660 if self
.allow_next_step_inc
== 2:
1661 log("SVSTATE_NEXT: read")
1662 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1664 log("SVSTATE_NEXT: post-inc")
1665 # use actual src/dst-step here to check end, do NOT
1666 # use bit-reversed version
1667 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1668 remaps
= self
.get_remap_indices()
1669 remap_idxs
= self
.remap_idxs
1670 vl
= self
.svstate
.vl
1671 end_src
= srcstep
== vl
-1
1672 end_dst
= dststep
== vl
-1
1673 if self
.allow_next_step_inc
!= 2:
1675 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1677 self
.svstate
.dststep
+= SelectableInt(1, 7)
1678 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1679 # set CR0 (if Rc=1) based on end
1681 srcstep
= self
.svstate
.srcstep
1682 dststep
= self
.svstate
.srcstep
1683 endtest
= 1 if (end_src
or end_dst
) else 0
1684 #results = [SelectableInt(endtest, 64)]
1685 # self.handle_comparison(results) # CR0
1687 # see if svstep was requested, if so, which SVSTATE
1689 if self
.svstate_next_mode
> 0:
1690 shape_idx
= self
.svstate_next_mode
.value
-1
1691 endings
= self
.remap_loopends
[shape_idx
]
1692 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
1693 print("svstep Rc=1, CR0", cr_field
)
1694 self
.crl
[0].eq(cr_field
) # CR0
1695 if end_src
or end_dst
:
1696 # reset at end of loop including exit Vertical Mode
1697 log("SVSTATE_NEXT: after increments, reset")
1698 self
.svp64_reset_loop()
1699 self
.svstate
.vfirst
= 0
1701 elif self
.is_svp64_mode
:
1702 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1704 # XXX only in non-SVP64 mode!
1705 # record state of whether the current operation was an svshape,
1706 # to be able to know if it should apply in the next instruction.
1707 # also (if going to use this instruction) should disable ability
1708 # to interrupt in between. sigh.
1709 self
.last_op_svshape
= asmop
== 'svremap'
1712 self
.update_pc_next()
1714 def SVSTATE_NEXT(self
, mode
, submode
):
1715 """explicitly moves srcstep/dststep on to next element, for
1716 "Vertical-First" mode. this function is called from
1717 setvl pseudo-code, as a pseudo-op "svstep"
1719 WARNING: this function uses information that was created EARLIER
1720 due to it being in the middle of a yield, but this function is
1721 *NOT* called from yield (it's called from compiled pseudocode).
1723 self
.allow_next_step_inc
= submode
.value
+ 1
1724 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1725 self
.svstate_next_mode
= mode
1726 if self
.svstate_next_mode
> 0:
1727 shape_idx
= self
.svstate_next_mode
.value
-1
1728 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1729 return SelectableInt(0, 7)
1731 def svstate_pre_inc(self
):
1732 """check if srcstep/dststep need to skip over masked-out predicate bits
1734 # get SVSTATE VL (oh and print out some debug stuff)
1735 vl
= self
.svstate
.vl
1736 srcstep
= self
.svstate
.srcstep
1737 dststep
= self
.svstate
.dststep
1738 sv_a_nz
= yield self
.dec2
.sv_a_nz
1739 fft_mode
= yield self
.dec2
.use_svp64_fft
1740 in1
= yield self
.dec2
.e
.read_reg1
.data
1741 log("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft, svp64",
1742 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
,
1745 # get predicate mask (all 64 bits)
1746 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1748 pmode
= yield self
.dec2
.rm_dec
.predmode
1749 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1750 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1751 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1752 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1753 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1754 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1755 if pmode
== SVP64PredMode
.INT
.value
:
1756 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1757 if sv_ptype
== SVPtype
.P2
.value
:
1758 srcmask
= get_predint(self
.gpr
, srcpred
)
1759 elif pmode
== SVP64PredMode
.CR
.value
:
1760 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1761 if sv_ptype
== SVPtype
.P2
.value
:
1762 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1763 log(" pmode", pmode
)
1764 log(" reverse", reverse_gear
)
1765 log(" ptype", sv_ptype
)
1766 log(" srcpred", bin(srcpred
))
1767 log(" dstpred", bin(dstpred
))
1768 log(" srcmask", bin(srcmask
))
1769 log(" dstmask", bin(dstmask
))
1770 log(" pred_sz", bin(pred_src_zero
))
1771 log(" pred_dz", bin(pred_dst_zero
))
1773 # okaaay, so here we simply advance srcstep (TODO dststep)
1774 # until the predicate mask has a "1" bit... or we run out of VL
1775 # let srcstep==VL be the indicator to move to next instruction
1776 if not pred_src_zero
:
1777 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1778 log(" skip", bin(1 << srcstep
))
1781 if not pred_dst_zero
:
1782 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1783 log(" skip", bin(1 << dststep
))
1786 # now work out if the relevant mask bits require zeroing
1788 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1790 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1792 # store new srcstep / dststep
1793 self
.new_srcstep
, self
.new_dststep
= srcstep
, dststep
1794 self
.pred_dst_zero
, self
.pred_src_zero
= pred_dst_zero
, pred_src_zero
1795 log(" new srcstep", srcstep
)
1796 log(" new dststep", dststep
)
1798 def get_src_dststeps(self
):
1799 """gets srcstep and dststep
1801 return self
.new_srcstep
, self
.new_dststep
1803 def update_new_svstate_steps(self
):
1804 # note, do not get the bit-reversed srcstep here!
1805 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1807 # update SVSTATE with new srcstep
1808 self
.svstate
.srcstep
= srcstep
1809 self
.svstate
.dststep
= dststep
1810 self
.namespace
['SVSTATE'] = self
.svstate
1811 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1812 yield Settle() # let decoder update
1813 srcstep
= self
.svstate
.srcstep
1814 dststep
= self
.svstate
.dststep
1815 vl
= self
.svstate
.vl
1816 log(" srcstep", srcstep
)
1817 log(" dststep", dststep
)
1820 # check if end reached (we let srcstep overrun, above)
1821 # nothing needs doing (TODO zeroing): just do next instruction
1822 return srcstep
== vl
or dststep
== vl
1824 def svstate_post_inc(self
, insn_name
, vf
=0):
1825 # check if SV "Vertical First" mode is enabled
1826 vfirst
= self
.svstate
.vfirst
1827 log(" SV Vertical First", vf
, vfirst
)
1828 if not vf
and vfirst
== 1:
1832 # check if it is the SVSTATE.src/dest step that needs incrementing
1833 # this is our Sub-Program-Counter loop from 0 to VL-1
1834 # XXX twin predication TODO
1835 vl
= self
.svstate
.vl
1836 mvl
= self
.svstate
.maxvl
1837 srcstep
= self
.svstate
.srcstep
1838 dststep
= self
.svstate
.dststep
1839 rm_mode
= yield self
.dec2
.rm_dec
.mode
1840 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1841 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1842 out_vec
= not (yield self
.dec2
.no_out_vec
)
1843 in_vec
= not (yield self
.dec2
.no_in_vec
)
1844 log(" svstate.vl", vl
)
1845 log(" svstate.mvl", mvl
)
1846 log(" svstate.srcstep", srcstep
)
1847 log(" svstate.dststep", dststep
)
1848 log(" mode", rm_mode
)
1849 log(" reverse", reverse_gear
)
1850 log(" out_vec", out_vec
)
1851 log(" in_vec", in_vec
)
1852 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1853 # check if srcstep needs incrementing by one, stop PC advancing
1854 # svp64 loop can end early if the dest is scalar for single-pred
1855 # but for 2-pred both src/dest have to be checked.
1856 # XXX this might not be true! it may just be LD/ST
1857 if sv_ptype
== SVPtype
.P2
.value
:
1858 svp64_is_vector
= (out_vec
or in_vec
)
1860 svp64_is_vector
= out_vec
1861 # check if this was an sv.bc* and if so did it succeed
1862 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1863 end_loop
= self
.namespace
['end_loop']
1864 log("branch %s end_loop" % insn_name
, end_loop
)
1866 self
.svp64_reset_loop()
1867 self
.update_pc_next()
1869 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1870 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1871 self
.svstate
.dststep
+= SelectableInt(1, 7)
1872 self
.namespace
['SVSTATE'] = self
.svstate
1873 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
1874 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
1875 # this way we keep repeating the same instruction (with new steps)
1876 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1877 self
.namespace
['NIA'] = self
.pc
.NIA
1878 log("end of sub-pc call", self
.namespace
['CIA'],
1879 self
.namespace
['NIA'])
1880 return False # DO NOT allow PC update whilst Sub-PC loop running
1882 # reset loop to zero and update NIA
1883 self
.svp64_reset_loop()
1888 def update_pc_next(self
):
1889 # UPDATE program counter
1890 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1891 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1892 log("end of call", self
.namespace
['CIA'],
1893 self
.namespace
['NIA'],
1894 self
.namespace
['SVSTATE'])
1896 def svp64_reset_loop(self
):
1897 self
.svstate
.srcstep
= 0
1898 self
.svstate
.dststep
= 0
1899 log(" svstate.srcstep loop end (PC to update)")
1900 self
.namespace
['SVSTATE'] = self
.svstate
1902 def update_nia(self
):
1903 self
.pc
.update_nia(self
.is_svp64_mode
)
1904 self
.namespace
['NIA'] = self
.pc
.NIA
1908 """Decorator factory.
1910 this decorator will "inject" variables into the function's namespace,
1911 from the *dictionary* in self.namespace. it therefore becomes possible
1912 to make it look like a whole stack of variables which would otherwise
1913 need "self." inserted in front of them (*and* for those variables to be
1914 added to the instance) "appear" in the function.
1916 "self.namespace['SI']" for example becomes accessible as just "SI" but
1917 *only* inside the function, when decorated.
1919 def variable_injector(func
):
1921 def decorator(*args
, **kwargs
):
1923 func_globals
= func
.__globals
__ # Python 2.6+
1924 except AttributeError:
1925 func_globals
= func
.func_globals
# Earlier versions.
1927 context
= args
[0].namespace
# variables to be injected
1928 saved_values
= func_globals
.copy() # Shallow copy of dict.
1929 log("globals before", context
.keys())
1930 func_globals
.update(context
)
1931 result
= func(*args
, **kwargs
)
1932 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1933 log("args[0]", args
[0].namespace
['CIA'],
1934 args
[0].namespace
['NIA'],
1935 args
[0].namespace
['SVSTATE'])
1936 if 'end_loop' in func_globals
:
1937 log("args[0] end_loop", func_globals
['end_loop'])
1938 args
[0].namespace
= func_globals
1939 #exec (func.__code__, func_globals)
1942 # func_globals = saved_values # Undo changes.
1948 return variable_injector