this is part of a cycle-accurate POWER9 simulator. its primary purpose is
not speed, it is for both learning and educational purposes, as well as
a method of verifying the HDL.
+
+related bugs:
+
+* https://bugs.libre-soc.org/show_bug.cgi?id=424
"""
from functools import wraps
selectconcat)
from soc.decoder.power_enums import (spr_dict, spr_byname, XER_bits,
insns, InternalOp)
-from soc.decoder.helpers import exts, trunc_div, trunc_rem
+from soc.decoder.helpers import exts
from soc.consts import PI, MSR
from collections import namedtuple
initial_mem=None, initial_msr=0,
initial_insns=None, respect_pc=False,
disassembly=None,
- initial_pc=0):
+ initial_pc=0,
+ bigendian=True):
+ self.bigendian = bigendian
+ self.halted = False
self.respect_pc = respect_pc
if initial_sprs is None:
initial_sprs = {}
inputs.append(SelectableInt(imm, 64))
assert len(outputs) >= 1
print ("handle_overflow", inputs, outputs, div_overflow)
- if len(inputs) < 2 and div_overflow != 1:
+ if len(inputs) < 2 and div_overflow is None:
return
# div overflow is different: it's returned by the pseudo-code
# because it's more complex than can be done by analysing the output
- if div_overflow == 1:
- ov, ov32 = 1, 1
+ if div_overflow is not None:
+ ov, ov32 = div_overflow, div_overflow
# arithmetic overflow can be done by analysing the input and output
elif len(inputs) >= 2:
output = outputs[0]
def handle_comparison(self, outputs):
out = outputs[0]
+ print ("handle_comparison", out.bits, hex(out.value))
+ # TODO - XXX *processor* in 32-bit mode
+ # https://bugs.libre-soc.org/show_bug.cgi?id=424
+ #if is_32bit:
+ # o32 = exts(out.value, 32)
+ # print ("handle_comparison exts 32 bit", hex(o32))
out = exts(out.value, out.bits)
+ print ("handle_comparison exts", hex(out))
zero = SelectableInt(out == 0, 1)
positive = SelectableInt(out > 0, 1)
negative = SelectableInt(out < 0, 1)
SO = self.spr['XER'][XER_bits['SO']]
+ print ("handle_comparison SO", SO)
cr_field = selectconcat(negative, positive, zero, SO)
self.crl[0].eq(cr_field)
print ("CIA NIA", self.respect_pc, self.pc.CIA.value, self.pc.NIA.value)
yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff)
- yield self.dec2.dec.bigendian.eq(0) # little / big?
+ yield self.dec2.dec.bigendian.eq(self.bigendian)
def execute_one(self):
"""execute one instruction
# TODO, asmregs is from the spec, e.g. add RT,RA,RB
# see http://bugs.libre-riscv.org/show_bug.cgi?id=282
asmcode = yield self.dec2.dec.op.asmcode
+ print ("get assembly name asmcode", asmcode)
asmop = insns.get(asmcode, None)
# sigh reconstruct the assembly instruction name
return asmop
def call(self, name):
+ name = name.strip() # remove spaces if not already done so
+ if self.halted:
+ print ("halted - not executing", name)
+ return
+
# TODO, asmregs is from the spec, e.g. add RT,RA,RB
# see http://bugs.libre-riscv.org/show_bug.cgi?id=282
asmop = yield from self.get_assembly_name()
print ("call", name, asmop)
+
+ # check halted condition
+ if name == 'attn':
+ self.halted = True
+ return
+
+ # check illegal instruction
illegal = False
if name not in ['mtcrf', 'mtocrf']:
illegal = name != asmop
if illegal:
+ print ("name %s != %s - calling ILLEGAL trap" % (name, asmop))
self.TRAP(0x700, PI.ILLEG)
self.namespace['NIA'] = self.trap_nia
self.pc.update(self.namespace)