X-Git-Url: https://git.libre-soc.org/?p=soc.git;a=blobdiff_plain;f=src%2Fsoc%2Fdecoder%2Fisa%2Fcaller.py;h=488df5ceeaa88289edbb157ccf6ab622060e4266;hp=b3b2c17132db8afbc299e8ee50f23e18635f884f;hb=0c3689e8f95c8b2d08100055c9b9c3711d366f1c;hpb=6891172f1bffde3f2b322a9151c21964b8f6f35d diff --git a/src/soc/decoder/isa/caller.py b/src/soc/decoder/isa/caller.py index b3b2c171..488df5ce 100644 --- a/src/soc/decoder/isa/caller.py +++ b/src/soc/decoder/isa/caller.py @@ -9,7 +9,8 @@ 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, XER_bits, insns, InternalOp +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 collections import namedtuple import math @@ -186,7 +187,14 @@ class SPR(dict): def __init__(self, dec2, initial_sprs={}): self.sd = dec2 dict.__init__(self) - self.update(initial_sprs) + for key, v in initial_sprs.items(): + if isinstance(key, SelectableInt): + key = key.value + key = special_sprs.get(key, key) + info = spr_byname[key] + if not isinstance(v, SelectableInt): + v = SelectableInt(v, info.length) + self[key] = v def __getitem__(self, key): # if key in special_sprs get the special spr, otherwise return key @@ -271,7 +279,9 @@ class ISACaller: # "undefined", just set to variable-bit-width int (use exts "max") self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256! - self.namespace = {'GPR': self.gpr, + self.namespace = {} + self.namespace.update(self.spr) + self.namespace.update({'GPR': self.gpr, 'MEM': self.mem, 'SPR': self.spr, 'memassign': self.memassign, @@ -282,7 +292,8 @@ class ISACaller: 'undefined': self.undefined, 'mode_is_64bit': True, 'SO': XER_bits['SO'] - } + }) + # field-selectable versions of Condition Register TODO check bitranges? self.crl = [] @@ -365,7 +376,7 @@ class ISACaller: if not (2 & already_done): self.spr['XER'][XER_bits['CA32']] = cy32 - def handle_overflow(self, inputs, outputs): + def handle_overflow(self, inputs, outputs, div_overflow): inv_a = yield self.dec2.e.invert_a if inv_a: inputs[0] = ~inputs[0] @@ -375,8 +386,16 @@ class ISACaller: imm = yield self.dec2.e.imm_data.data inputs.append(SelectableInt(imm, 64)) assert len(outputs) >= 1 - print ("handle_overflow", inputs, outputs) - if len(inputs) >= 2: + print ("handle_overflow", inputs, outputs, div_overflow) + if len(inputs) < 2 and div_overflow != 1: + 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 + # arithmetic overflow can be done by analysing the input and output + elif len(inputs) >= 2: output = outputs[0] # OV (64-bit) @@ -391,11 +410,11 @@ class ISACaller: ov32 = 1 if input32_sgn[0] == input32_sgn[1] and \ output32_sgn != input32_sgn[0] else 0 - self.spr['XER'][XER_bits['OV']] = ov - self.spr['XER'][XER_bits['OV32']] = ov32 - so = self.spr['XER'][XER_bits['SO']] - so = so | ov - self.spr['XER'][XER_bits['SO']] = so + self.spr['XER'][XER_bits['OV']] = ov + self.spr['XER'][XER_bits['OV32']] = ov32 + 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] @@ -527,10 +546,20 @@ class ISACaller: carry_en = yield self.dec2.e.output_carry if carry_en: yield from self.handle_carry_(inputs, results, already_done) + + # detect if overflow was in return result + overflow = None + if info.write_regs: + for name, output in zip(output_names, results): + if name == 'overflow': + overflow = output + ov_en = yield self.dec2.e.oe.oe ov_ok = yield self.dec2.e.oe.ok + print ("internal overflow", overflow) if ov_en & ov_ok: - yield from self.handle_overflow(inputs, results) + yield from self.handle_overflow(inputs, results, overflow) + rc_en = yield self.dec2.e.rc.data if rc_en: self.handle_comparison(results) @@ -538,6 +567,8 @@ class ISACaller: # any modified return results? if info.write_regs: for name, output in zip(output_names, results): + if name == 'overflow': # ignore, done already (above) + continue if isinstance(output, int): output = SelectableInt(output, 256) if name in ['CA', 'CA32']: