X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fopenpower%2Fdecoder%2Fisa%2Fcaller.py;h=5d8498857e7ee95b1f621f25cbc8f05d14694236;hb=f5c40a5fb2220a7256bc2eff9c80b56602e6c2a5;hp=7e656d83527453dea99594e432a64c63a364f2c8;hpb=b6cc66b62909e282a1bfeb377cdc6aba857e11b1;p=openpower-isa.git diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 7e656d83..5d849885 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -33,13 +33,20 @@ from openpower.decoder.power_enums import (FPTRANS_INSNS, CRInSel, CROutSel, SVP64LDSTmode, SVP64PredCR, SVP64PredInt, SVP64PredMode, SVP64RMMode, SVPType, XER_bits, - insns, spr_byname, spr_dict) + insns, spr_byname, spr_dict, + BFP_FLAG_NAMES) from openpower.decoder.power_insn import SVP64Instruction from openpower.decoder.power_svp64 import SVP64RM, decode_extra from openpower.decoder.selectable_int import (FieldSelectableInt, - SelectableInt, selectconcat) + SelectableInt, selectconcat, + EFFECTIVELY_UNLIMITED) +from openpower.fpscr import FPSCRState +from openpower.xer import XERState from openpower.util import LogKind, log +LDST_UPDATE_INSNS = ['ldu', 'lwzu', 'lbzu', 'lhzu', 'lhau', 'lfsu', 'lfdu', + ] + instruction_info = namedtuple('instruction_info', 'func read_regs uninit_regs write_regs ' + 'special_regs op_fields form asmregs') @@ -74,6 +81,7 @@ REG_SORT_ORDER = { "CTR": 0, "TAR": 0, "MSR": 0, + "FPSCR": 0, "SVSTATE": 0, "SVSHAPE0": 0, "SVSHAPE1": 0, @@ -264,7 +272,7 @@ class SPR(dict): info = spr_dict[key] else: info = spr_byname[key] - dict.__setitem__(self, key, SelectableInt(0, info.length)) + self[key] = SelectableInt(0, info.length) res = dict.__getitem__(self, key) log("spr returning", key, res) return res @@ -280,6 +288,8 @@ class SPR(dict): self.__setitem__('SRR0', value) if key == 'HSRR1': # HACK! self.__setitem__('SRR1', value) + if key == 1: + value = XERState(value) log("setting spr", key, value) dict.__setitem__(self, key, value) @@ -431,6 +441,8 @@ def get_idx_map(dec2, name): elif name == 'FRA': if in1_sel == In1Sel.FRA.value: return 1 + if in3_sel == In3Sel.FRA.value: + return 3 elif name == 'FRB': if in2_sel == In2Sel.FRB.value: return 2 @@ -442,6 +454,12 @@ def get_idx_map(dec2, name): return 1 if in3_sel == In3Sel.FRS.value: return 3 + elif name == 'FRT': + if in1_sel == In1Sel.FRT.value: + return 1 + elif name == 'RT': + if in1_sel == In1Sel.RT.value: + return 1 return None @@ -543,6 +561,15 @@ def get_cr_out(dec2, name): if name == 'CR1': # these are not actually calculated correctly if out_sel == CROutSel.CR1.value: return out, o_isvec + # check RC1 set? if so return implicit vector, this is a REAL bad hack + RC1 = yield dec2.rm_dec.RC1 + if RC1: + log("get_cr_out RC1 mode") + if name == 'CR0': + return 0, True # XXX TODO: offset CR0 from SVSTATE SPR + if name == 'CR1': + return 1, True # XXX TODO: offset CR1 from SVSTATE SPR + # nope - not found. log("get_cr_out not found", name) return None, False @@ -568,6 +595,9 @@ def get_out_map(dec2, name): elif name == 'FRA': if out_sel == OutSel.FRA.value: return True + elif name == 'FRS': + if out_sel == OutSel.FRS.value: + return True elif name == 'FRT': if out_sel == OutSel.FRT.value: return True @@ -1113,7 +1143,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): initial_pc=0, bigendian=False, mmu=False, - icachemmu=False): + icachemmu=False, + initial_fpscr=0): self.bigendian = bigendian self.halted = False @@ -1186,6 +1217,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): # FPR (same as GPR except for FP nums) # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR) # note that mffs, mcrfs, mtfsf "manage" this FPSCR + self.fpscr = FPSCRState(initial_fpscr) + # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO) # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs # -- Done @@ -1201,7 +1234,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): self.cr_backup = 0 # sigh, dreadful hack: for fail-first (VLi) # "undefined", just set to variable-bit-width int (use exts "max") - # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256! + # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED) self.namespace = {} self.namespace.update(self.spr) @@ -1219,12 +1252,16 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): 'SVSHAPE3': self.spr['SVSHAPE3'], 'CR': self.cr, 'MSR': self.msr, + 'FPSCR': self.fpscr, 'undefined': undefined, 'mode_is_64bit': True, 'SO': XER_bits['SO'], 'XLEN': 64 # elwidth overrides }) + for name in BFP_FLAG_NAMES: + setattr(self, name, 0) + # update pc to requested start point self.set_pc(initial_pc) @@ -1236,12 +1273,16 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): self.decoder = decoder2.dec self.dec2 = decoder2 - super().__init__(XLEN=self.namespace["XLEN"]) + super().__init__(XLEN=self.namespace["XLEN"], FPSCR=self.fpscr) @property def XLEN(self): return self.namespace["XLEN"] + @property + def FPSCR(self): + return self.fpscr + def call_trap(self, trap_addr, trap_bit): """calls TRAP and sets up NIA to the new execution location. next instruction will begin at trap_addr. @@ -1667,6 +1708,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): def execute_one(self): """execute one instruction """ + self.insnlog = [] # log the instruction # get the disassembly code for this instruction if not self.disassembly: code = yield from self.get_assembly_name() @@ -1676,6 +1718,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): offs, dbg = 4, "svp64 " code = self.disassembly[self._pc+offs] log(" %s sim-execute" % dbg, hex(self._pc), code) + self.insnlog.append(code) opname = code.split(' ')[0] try: yield from self.call(opname) # execute the instruction @@ -1707,6 +1750,10 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): # not supported yet: raise e # ... re-raise + # append the log file + with open("/tmp/insnlog.txt", "a+") as f: + f.write(" ".join(self.insnlog)+"\n") + log("gprs after code", code) self.gpr.dump() crs = [] @@ -1887,15 +1934,21 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): # list of instructions not being supported by binutils (.long) dotstrp = asmop[:-1] if asmop[-1] == '.' else asmop if dotstrp in [*FPTRANS_INSNS, + *LDST_UPDATE_INSNS, 'ffmadds', 'fdmadds', 'ffadds', - 'mins', 'maxs', 'minu', 'maxu', + 'minmax', 'setvl', 'svindex', 'svremap', 'svstep', 'svshape', 'svshape2', 'grev', 'ternlogi', 'bmask', 'cprop', 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd', 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du", "dsld", "dsrd", "maddedus", - "shadd", "shadduw", + "shadd", "shaddw", "shadduw", + "fcvttg", "fcvttgo", "fcvttgs", "fcvttgso", + "fmvtg", "fmvtgs", + "fcvtfg", "fcvtfgs", + "fmvfg", "fmvfgs", + "maddsubrs", "maddrs" ]: illegal = False ins_name = dotstrp @@ -2195,11 +2248,13 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): self.crl[regnum].eq(cr0) def do_outregs_nia(self, asmop, ins_name, info, outs, - carry_en, rc_en, ffirst_hit, ew_dst): + ca_en, rc_en, ffirst_hit, ew_dst): ffirst_hit, vli = ffirst_hit - # write out any regs for this instruction - for name, output in outs.items(): - yield from self.check_write(info, name, output, carry_en, ew_dst) + # write out any regs for this instruction, but only if fail-first is ok + # XXX TODO: allow CR-vector to be written out even if ffirst fails + if not ffirst_hit or vli: + for name, output in outs.items(): + yield from self.check_write(info, name, output, ca_en, ew_dst) # restore the CR value on non-VLI failfirst (from sv.cmp and others # which write directly to CR in the pseudocode (gah, what a mess) # if ffirst_hit and not vli: @@ -2295,8 +2350,10 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): if name in fregs: reg_val = SelectableInt(self.fpr(base, is_vec, offs, ew_src)) log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value)) + self.insnlog.append("rFPR:%d.%d/%d" % (base, offs, ew_src)) elif name is not None: reg_val = SelectableInt(self.gpr(base, is_vec, offs, ew_src)) + self.insnlog.append("rGPR:%d.%d/%d" % (base, offs, ew_src)) log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value)) else: log('zero input reg %s %s' % (name, str(regnum)), is_vec) @@ -2371,7 +2428,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): if name == 'CR0': # ignore, done already (above) return if isinstance(output, int): - output = SelectableInt(output, 256) + output = SelectableInt(output, EFFECTIVELY_UNLIMITED) # write carry flafs if name in ['CA', 'CA32']: if carry_en: @@ -2408,17 +2465,20 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): # check zeroing due to predicate bit being zero if self.is_svp64_mode and self.pred_dst_zero: log('zeroing reg %s %s' % (str(regnum), str(output)), is_vec) - output = SelectableInt(0, 256) + output = SelectableInt(0, EFFECTIVELY_UNLIMITED) log("write reg %s%s 0x%x ew %d" % (reg_prefix, str(regnum), output.value, ew_dst), kind=LogKind.InstrInOuts) # zero-extend tov64 bit begore storing (should use EXT oh well) if output.bits > 64: output = SelectableInt(output.value, 64) + rnum, base, offset = regnum if name in fregs: self.fpr.write(regnum, output, is_vec, ew_dst) + self.insnlog.append("wFPR:%d.%d/%d" % (rnum, offset, ew_dst)) else: self.gpr.write(regnum, output, is_vec, ew_dst) + self.insnlog.append("wGPR:%d.%d/%d" % (rnum, offset, ew_dst)) def check_step_increment(self, rc_en, asmop, ins_name): # check if it is the SVSTATE.src/dest step that needs incrementing