+ 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
+ self.namespace['CA32'] = self.spr['XER'][XER_bits['CA32']].value
+
+ def handle_carry_(self, inputs, outputs, already_done):
+ inv_a = yield self.dec2.e.do.invert_a
+ if inv_a:
+ inputs[0] = ~inputs[0]
+
+ imm_ok = yield self.dec2.e.do.imm_data.ok
+ if imm_ok:
+ imm = yield self.dec2.e.do.imm_data.data
+ inputs.append(SelectableInt(imm, 64))
+ assert len(outputs) >= 1
+ print ("outputs", repr(outputs))
+ if isinstance(outputs, list) or isinstance(outputs, tuple):
+ output = outputs[0]
+ else:
+ output = outputs
+ gts = []
+ for x in inputs:
+ print ("gt input", x, output)
+ gt = (x > output)
+ gts.append(gt)
+ print(gts)
+ cy = 1 if any(gts) else 0
+ if not (1 & already_done):
+ self.spr['XER'][XER_bits['CA']] = cy
+
+ print ("inputs", inputs)
+ # 32 bit carry
+ gts = []
+ for x in inputs:
+ print ("input", x, output)
+ gt = (x[32:64] > output[32:64]) == SelectableInt(1, 1)
+ gts.append(gt)
+ cy32 = 1 if any(gts) else 0
+ if not (2 & already_done):
+ self.spr['XER'][XER_bits['CA32']] = cy32
+
+ def handle_overflow(self, inputs, outputs, div_overflow):
+ inv_a = yield self.dec2.e.do.invert_a
+ if inv_a:
+ inputs[0] = ~inputs[0]
+
+ imm_ok = yield self.dec2.e.do.imm_data.ok
+ if imm_ok:
+ imm = yield self.dec2.e.do.imm_data.data
+ inputs.append(SelectableInt(imm, 64))
+ assert len(outputs) >= 1
+ 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)
+ 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
+
+ # OV (32-bit)
+ input32_sgn = [exts(x.value, 32) < 0 for x in inputs]
+ output32_sgn = exts(output.value, 32) < 0
+ 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
+
+ def handle_comparison(self, outputs):
+ out = outputs[0]
+ out = exts(out.value, out.bits)
+ zero = SelectableInt(out == 0, 1)
+ positive = SelectableInt(out > 0, 1)
+ negative = SelectableInt(out < 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 setup_one(self):
+ """set up one instruction
+ """
+ if self.respect_pc:
+ pc = self.pc.CIA.value
+ else:
+ pc = self.fake_pc
+ self._pc = pc
+ ins = self.imem.ld(pc, 4, False, True)
+ if ins is None:
+ raise KeyError("no instruction at 0x%x" % pc)
+ print("setup: 0x%x 0x%x %s" % (pc, ins & 0xffffffff, bin(ins)))
+ 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?
+
+ def execute_one(self):
+ """execute one instruction
+ """
+ # get the disassembly code for this instruction
+ code = self.disassembly[self._pc]
+ print("sim-execute", hex(self._pc), code)
+ opname = code.split(' ')[0]
+ yield from self.call(opname)
+
+ if not self.respect_pc:
+ self.fake_pc += 4
+ print ("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value)
+
+ def get_assembly_name(self):
+ # 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
+ asmop = insns.get(asmcode, None)
+
+ # 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 += "."
+ 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]:
+ 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
+ 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
+ asmop = 'mtocrf'
+ else:
+ asmop = 'mtcrf'
+ return asmop