"""
from functools import wraps
+from copy import copy
from soc.decoder.orderedset import OrderedSet
from soc.decoder.selectable_int import (FieldSelectableInt, SelectableInt,
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.consts import PI, MSR
+ insns, MicrOp)
+from soc.decoder.helpers import exts
+from soc.consts import PIb, MSRb # big-endian (PowerISA versions)
from collections import namedtuple
import math
initial_insns=None, respect_pc=False,
disassembly=None,
initial_pc=0,
- bigendian=True):
+ bigendian=False):
self.bigendian = bigendian
self.halted = False
assert self.respect_pc == False, "instructions required to honor pc"
print ("ISACaller insns", respect_pc, initial_insns, disassembly)
+ print ("ISACaller initial_msr", initial_msr)
# "fake program counter" mode (for unit testing)
self.fake_pc = 0
self.decoder = decoder2.dec
self.dec2 = decoder2
- def TRAP(self, trap_addr=0x700, trap_bit=PI.TRAP):
- print ("TRAP:", hex(trap_addr))
+ def TRAP(self, trap_addr=0x700, trap_bit=PIb.TRAP):
+ print ("TRAP:", hex(trap_addr), hex(self.namespace['MSR'].value))
# store CIA(+4?) in SRR0, set NIA to 0x700
# store MSR in SRR1, set MSR to um errr something, have to check spec
- self.spr['SRR0'] = self.pc.CIA
- self.spr['SRR1'] = self.namespace['MSR']
+ self.spr['SRR0'].value = self.pc.CIA.value
+ self.spr['SRR1'].value = self.namespace['MSR'].value
self.trap_nia = SelectableInt(trap_addr, 64)
- self.namespace['MSR'][63-trap_bit] = 1
+ self.spr['SRR1'][trap_bit] = 1 # change *copy* of MSR in SRR1
+
+ # set exception bits. TODO: this should, based on the address
+ # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
+ # bits appropriately. however it turns out that *for now* in all
+ # cases (all trap_addrs) the exact same thing is needed.
+ self.msr[MSRb.SF] = 1
+ self.msr[MSRb.EE] = 0
+ self.msr[MSRb.PR] = 0
+ self.msr[MSRb.IR] = 0
+ self.msr[MSRb.DR] = 0
+ self.msr[MSRb.RI] = 0
+ self.msr[MSRb.LE] = 1
def memassign(self, ea, sz, val):
self.mem.memassign(ea, sz, val)
yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff)
yield self.dec2.dec.bigendian.eq(self.bigendian)
+ yield self.dec2.msr.eq(self.msr.value)
+ yield self.dec2.cia.eq(pc)
def execute_one(self):
"""execute one instruction
asmcode = yield self.dec2.dec.op.asmcode
print ("get assembly name asmcode", asmcode)
asmop = insns.get(asmcode, None)
+ int_op = yield self.dec2.dec.op.internal_op
# sigh reconstruct the assembly instruction name
ov_en = yield self.dec2.e.do.oe.oe
ov_ok = yield self.dec2.e.do.oe.ok
- if ov_en & ov_ok:
- asmop += "."
+ rc_en = yield self.dec2.e.do.rc.data
+ rc_ok = yield self.dec2.e.do.rc.ok
+ # grrrr have to special-case MUL op (see DecodeOE)
+ print ("ov en rc en", ov_ok, ov_en, rc_ok, rc_en, int_op)
+ if int_op in [MicrOp.OP_MUL_H64.value, MicrOp.OP_MUL_H32.value]:
+ print ("mul op")
+ if rc_en & rc_ok:
+ asmop += "."
+ else:
+ if ov_en & ov_ok:
+ asmop += "."
lk = yield self.dec2.e.do.lk
if lk:
asmop += "l"
- int_op = yield self.dec2.dec.op.internal_op
print ("int_op", int_op)
- if int_op in [InternalOp.OP_B.value, InternalOp.OP_BC.value]:
+ if int_op in [MicrOp.OP_B.value, MicrOp.OP_BC.value]:
AA = yield self.dec2.dec.fields.FormI.AA[0:-1]
print ("AA", AA)
if AA:
asmop += "a"
- if int_op == InternalOp.OP_MFCR.value:
- dec_insn = yield self.dec2.e.do.insn
- if dec_insn & (1<<20) != 0: # sigh
+ spr_msb = yield from self.get_spr_msb()
+ if int_op == MicrOp.OP_MFCR.value:
+ if spr_msb:
asmop = 'mfocrf'
else:
asmop = 'mfcr'
# XXX TODO: for whatever weird reason this doesn't work
# https://bugs.libre-soc.org/show_bug.cgi?id=390
- if int_op == InternalOp.OP_MTCRF.value:
- dec_insn = yield self.dec2.e.do.insn
- if dec_insn & (1<<20) != 0: # sigh
+ if int_op == MicrOp.OP_MTCRF.value:
+ if spr_msb:
asmop = 'mtocrf'
else:
asmop = 'mtcrf'
return asmop
+ def get_spr_msb(self):
+ dec_insn = yield self.dec2.e.do.insn
+ return dec_insn & (1<<20) != 0 # sigh - XFF.spr[-1]?
+
def call(self, name):
name = name.strip() # remove spaces if not already done so
if self.halted:
asmop = yield from self.get_assembly_name()
print ("call", name, asmop)
+ # check privileged
+ int_op = yield self.dec2.dec.op.internal_op
+ spr_msb = yield from self.get_spr_msb()
+
+ instr_is_privileged = False
+ if int_op in [MicrOp.OP_ATTN.value,
+ MicrOp.OP_MFMSR.value,
+ MicrOp.OP_MTMSR.value,
+ MicrOp.OP_MTMSRD.value,
+ # TODO: OP_TLBIE
+ MicrOp.OP_RFID.value]:
+ instr_is_privileged = True
+ if int_op in [MicrOp.OP_MFSPR.value,
+ MicrOp.OP_MTSPR.value] and spr_msb:
+ instr_is_privileged = True
+
+ print ("is priv", instr_is_privileged, hex(self.msr.value),
+ self.msr[MSRb.PR])
+ # check MSR priv bit and whether op is privileged: if so, throw trap
+ if instr_is_privileged and self.msr[MSRb.PR] == 1:
+ self.TRAP(0x700, PIb.PRIV)
+ self.namespace['NIA'] = self.trap_nia
+ self.pc.update(self.namespace)
+ return
+
# check halted condition
if name == 'attn':
self.halted = True
illegal = name != asmop
if illegal:
- print ("name %s != %s - calling ILLEGAL trap" % (name, asmop))
- self.TRAP(0x700, PI.ILLEG)
+ self.TRAP(0x700, PIb.ILLEG)
self.namespace['NIA'] = self.trap_nia
self.pc.update(self.namespace)
+ print ("name %s != %s - calling ILLEGAL trap, PC: %x" % \
+ (name, asmop, self.pc.CIA.value))
return
info = self.instrs[name]
ov_en = yield self.dec2.e.do.oe.oe
ov_ok = yield self.dec2.e.do.oe.ok
- print ("internal overflow", overflow)
+ print ("internal overflow", overflow, ov_en, ov_ok)
if ov_en & ov_ok:
yield from self.handle_overflow(inputs, results, overflow)