add an illegal instruction trap test
[soc.git] / src / soc / decoder / isa / caller.py
index d25fa6282c069c227c1373607275e14b44ae7314..fbbbb75fdb390bf4cd3877dd70900f93e6ebde35 100644 (file)
@@ -260,6 +260,7 @@ class ISACaller:
 
         # "fake program counter" mode (for unit testing)
         self.fake_pc = 0
+        disasm_start = 0
         if not respect_pc:
             if isinstance(initial_mem, tuple):
                 self.fake_pc = initial_mem[0]
@@ -330,14 +331,14 @@ class ISACaller:
         self.decoder = decoder2.dec
         self.dec2 = decoder2
 
-    def TRAP(self, trap_addr=0x700):
+    def TRAP(self, trap_addr=0x700, trap_bit=PI.TRAP):
         print ("TRAP:", hex(trap_addr))
         # 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.trap_nia = SelectableInt(trap_addr, 64)
-        self.namespace['MSR'][63-PI.TRAP] = 1 # bit 45, "this is a trap"
+        self.namespace['MSR'][63-trap_bit] = 1
 
     def memassign(self, ea, sz, val):
         self.mem.memassign(ea, sz, val)
@@ -365,13 +366,13 @@ class ISACaller:
         self.namespace['CA32'] = self.spr['XER'][XER_bits['CA32']].value
 
     def handle_carry_(self, inputs, outputs, already_done):
-        inv_a = yield self.dec2.e.invert_a
+        inv_a = yield self.dec2.e.do.invert_a
         if inv_a:
             inputs[0] = ~inputs[0]
 
-        imm_ok = yield self.dec2.e.imm_data.ok
+        imm_ok = yield self.dec2.e.do.imm_data.ok
         if imm_ok:
-            imm = yield self.dec2.e.imm_data.data
+            imm = yield self.dec2.e.do.imm_data.data
             inputs.append(SelectableInt(imm, 64))
         assert len(outputs) >= 1
         print ("outputs", repr(outputs))
@@ -401,13 +402,13 @@ class ISACaller:
             self.spr['XER'][XER_bits['CA32']] = cy32
 
     def handle_overflow(self, inputs, outputs, div_overflow):
-        inv_a = yield self.dec2.e.invert_a
+        inv_a = yield self.dec2.e.do.invert_a
         if inv_a:
             inputs[0] = ~inputs[0]
 
-        imm_ok = yield self.dec2.e.imm_data.ok
+        imm_ok = yield self.dec2.e.do.imm_data.ok
         if imm_ok:
-            imm = yield self.dec2.e.imm_data.data
+            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)
@@ -491,11 +492,11 @@ class ISACaller:
         asmop = insns.get(asmcode, None)
 
         # sigh reconstruct the assembly instruction name
-        ov_en = yield self.dec2.e.oe.oe
-        ov_ok = yield self.dec2.e.oe.ok
+        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.lk
+        lk = yield self.dec2.e.do.lk
         if lk:
             asmop += "l"
         int_op = yield self.dec2.dec.op.internal_op
@@ -506,7 +507,7 @@ class ISACaller:
             if AA:
                 asmop += "a"
         if int_op == InternalOp.OP_MFCR.value:
-            dec_insn = yield self.dec2.e.insn
+            dec_insn = yield self.dec2.e.do.insn
             if dec_insn & (1<<20) != 0: # sigh
                 asmop = 'mfocrf'
             else:
@@ -514,7 +515,7 @@ class ISACaller:
         # 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.insn
+            dec_insn = yield self.dec2.e.do.insn
             if dec_insn & (1<<20) != 0: # sigh
                 asmop = 'mtocrf'
             else:
@@ -526,14 +527,22 @@ class ISACaller:
         # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
         asmop = yield from self.get_assembly_name()
         print  ("call", name, asmop)
+        illegal = False
         if name not in ['mtcrf', 'mtocrf']:
-            assert name == asmop, "name %s != %s" % (name, asmop)
+            illegal = name != asmop
+
+        if illegal:
+            self.TRAP(0x700, PI.ILLEG)
+            self.namespace['NIA'] = self.trap_nia
+            self.pc.update(self.namespace)
+            return
 
         info = self.instrs[name]
         yield from self.prep_namespace(info.form, info.op_fields)
 
         # preserve order of register names
-        input_names = create_args(list(info.read_regs) + list(info.uninit_regs))
+        input_names = create_args(list(info.read_regs) +
+                                  list(info.uninit_regs))
         print(input_names)
 
         # main registers (RT, RA ...)
@@ -577,7 +586,7 @@ class ISACaller:
                     already_done |= 2
 
         print ("carry already done?", bin(already_done))
-        carry_en = yield self.dec2.e.output_carry
+        carry_en = yield self.dec2.e.do.output_carry
         if carry_en:
             yield from self.handle_carry_(inputs, results, already_done)
 
@@ -588,13 +597,13 @@ class ISACaller:
                 if name == 'overflow':
                     overflow = output
 
-        ov_en = yield self.dec2.e.oe.oe
-        ov_ok = yield self.dec2.e.oe.ok
+        ov_en = yield self.dec2.e.do.oe.oe
+        ov_ok = yield self.dec2.e.do.oe.ok
         print ("internal overflow", overflow)
         if ov_en & ov_ok:
             yield from self.handle_overflow(inputs, results, overflow)
 
-        rc_en = yield self.dec2.e.rc.data
+        rc_en = yield self.dec2.e.do.rc.data
         if rc_en:
             self.handle_comparison(results)