X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fdecoder%2Fisa%2Fcaller.py;h=299b74c0e136a65a0f1a68955e6ccda786e2cf99;hb=7bcc2eb604806b9b69993974cb0b5519136a7d01;hp=a5712320aeb52d1005eae62b4b063e58c24cc07d;hpb=76a6f7d5099f4999bdf3bc061a0e9a1f1208212e;p=soc.git diff --git a/src/soc/decoder/isa/caller.py b/src/soc/decoder/isa/caller.py index a5712320..299b74c0 100644 --- a/src/soc/decoder/isa/caller.py +++ b/src/soc/decoder/isa/caller.py @@ -2,7 +2,7 @@ from functools import wraps from soc.decoder.orderedset import OrderedSet from soc.decoder.selectable_int import (FieldSelectableInt, SelectableInt, selectconcat) -from soc.decoder.power_enums import spr_dict +from soc.decoder.power_enums import spr_dict, XER_bits from soc.decoder.helpers import exts from collections import namedtuple import math @@ -15,7 +15,7 @@ special_sprs = { 'LR': 8, 'CTR': 9, 'TAR': 815, - 'XER': 0, + 'XER': 1, 'VRSAVE': 256} @@ -137,9 +137,10 @@ class PC: class SPR(dict): - def __init__(self, dec2): + def __init__(self, dec2, initial_sprs={}): self.sd = dec2 dict.__init__(self) + self.update(initial_sprs) def __getitem__(self, key): # if key in special_sprs get the special spr, otherwise return key @@ -150,7 +151,8 @@ class SPR(dict): return dict.__getitem__(self, key) else: info = spr_dict[key] - return SelectableInt(0, info.length) + dict.__setitem__(self, key, SelectableInt(0, info.length)) + return dict.__getitem__(self, key) def __setitem__(self, key, value): if isinstance(key, SelectableInt): @@ -166,25 +168,26 @@ class SPR(dict): class ISACaller: # decoder2 - an instance of power_decoder2 # regfile - a list of initial values for the registers - def __init__(self, decoder2, regfile): + def __init__(self, decoder2, regfile, initial_sprs={}, initial_cr=0): self.gpr = GPR(decoder2, regfile) self.mem = Mem() self.pc = PC() - self.spr = SPR(decoder2) + self.spr = SPR(decoder2, initial_sprs) # TODO, needed here: # 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 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO) # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs - # 2.3.2 LR (actually SPR #8) - # 2.3.3 CTR (actually SPR #9) + # -- Done + # 2.3.2 LR (actually SPR #8) -- Done + # 2.3.3 CTR (actually SPR #9) -- Done # 2.3.4 TAR (actually SPR #815) - # 3.2.2 p45 XER (actually SPR #0) + # 3.2.2 p45 XER (actually SPR #1) -- Done # 3.2.3 p46 p232 VRSAVE (actually SPR #256) # create CR then allow portions of it to be "selectable" (below) - self._cr = SelectableInt(0, 64) # underlying reg + self._cr = SelectableInt(initial_cr, 64) # underlying reg self.cr = FieldSelectableInt(self._cr, list(range(32,64))) # "undefined", just set to variable-bit-width int (use exts "max") @@ -199,6 +202,7 @@ class ISACaller: 'CR': self.cr, 'undefined': self.undefined, 'mode_is_64bit': True, + 'SO': XER_bits['SO'] } # field-selectable versions of Condition Register TODO check bitranges? @@ -228,19 +232,60 @@ class ISACaller: else: sig = getattr(fields, name) val = yield sig - self.namespace[name] = SelectableInt(val, sig.width) + if name in ['BF', 'BFA']: + self.namespace[name] = val + else: + self.namespace[name] = SelectableInt(val, sig.width) + + self.namespace['XER'] = self.spr['XER'] + self.namespace['CA'] = self.spr['XER'][XER_bits['CA']].value - def handle_carry(self, inputs, outputs): - inv_a = yield self.dec2.invert_a + def handle_carry_(self, inputs, outputs): + inv_a = yield self.dec2.e.invert_a if inv_a: inputs[0] = ~inputs[0] + + imm_ok = yield self.dec2.e.imm_data.ok + if imm_ok: + imm = yield self.dec2.e.imm_data.data + inputs.append(SelectableInt(imm, 64)) assert len(outputs) >= 1 output = outputs[0] - gts = [(x > output) == SelectableInt(1, 1) for x in inputs] + gts = [(x > output) for x in inputs] print(gts) - if all(gts): - return True - return False + cy = 1 if any(gts) else 0 + self.spr['XER'][XER_bits['CA']] = cy + + + # 32 bit carry + gts = [(x[32:64] > output[32:64]) == SelectableInt(1, 1) + for x in inputs] + cy32 = 1 if any(gts) else 0 + self.spr['XER'][XER_bits['CA32']] = cy32 + + def handle_overflow(self, inputs, outputs): + inv_a = yield self.dec2.e.invert_a + if inv_a: + inputs[0] = ~inputs[0] + + imm_ok = yield self.dec2.e.imm_data.ok + if imm_ok: + imm = yield self.dec2.e.imm_data.data + inputs.append(SelectableInt(imm, 64)) + assert len(outputs) >= 1 + if len(inputs) >= 2: + output = outputs[0] + input_sgn = [exts(x.value, x.bits) < 0 for x in inputs] + output_sgn = exts(output.value, output.bits) < 0 + ov = 1 if input_sgn[0] == input_sgn[1] and \ + output_sgn != input_sgn[0] else 0 + + self.spr['XER'][XER_bits['OV']] = ov + so = self.spr['XER'][XER_bits['SO']] + so = so | ov + self.spr['XER'][XER_bits['SO']] = so + + def handle_comparison(self, outputs): out = outputs[0] @@ -248,9 +293,13 @@ class ISACaller: zero = SelectableInt(out == 0, 1) positive = SelectableInt(out > 0, 1) negative = SelectableInt(out < 0, 1) - SO = SelectableInt(0, 1) + SO = self.spr['XER'][XER_bits['SO']] cr_field = selectconcat(negative, positive, zero, SO) self.crl[0].eq(cr_field) + + def set_pc(self, pc_val): + self.namespace['NIA'] = SelectableInt(pc_val, 64) + self.pc.update(self.namespace) def call(self, name): @@ -283,16 +332,22 @@ class ISACaller: results = info.func(self, *inputs) print(results) - carry_en = yield self.dec2.e.rc.data + carry_en = yield self.dec2.e.output_carry if carry_en: - cy = self.handle_carry(inputs, results) - + yield from self.handle_carry_(inputs, results) + ov_en = yield self.dec2.e.oe + if ov_en: + yield from self.handle_overflow(inputs, results) + rc_en = yield self.dec2.e.rc.data + if rc_en: self.handle_comparison(results) # any modified return results? if info.write_regs: output_names = create_args(info.write_regs) for name, output in zip(output_names, results): + if isinstance(output, int): + output = SelectableInt(output, 256) if name in info.special_regs: print('writing special %s' % name, output) if name in special_sprs: @@ -301,7 +356,7 @@ class ISACaller: self.namespace[name].eq(output) else: regnum = yield getattr(self.decoder, name) - print('writing reg %d' % regnum) + print('writing reg %d %s' % (regnum, str(output))) if output.bits > 64: output = SelectableInt(output.value, 64) self.gpr[regnum] = output