hwstub/jz4760b: add lua code to probe for ei/di and ext instructions

Add lua code to check whether ei/di and ext instructions are supported. This
is unclear since xburst is somewhere between mips32r1 and mips32r2. Details
results are below, but in summary: they don't work (ei has no effect, di/ext
cause illegal instruction exceptions)

> ./hwstub_shell -q -b -e 'require("jz/misc"); JZ.misc.enable_sram()' \
  -f lua/xburst.lua -e "XBURST.test_ext_inst(0xb32d0000)"
[...]
Selecting soc jz4760b. Redirecting HW to hwstub.soc.jz4760b
  data: d7168acf
error: lua/xburst.lua:209: call failed
trapped exception in call

> ./hwstub_shell -q -b -e 'require("jz/misc"); JZ.misc.enable_sram()' \
  -f lua/xburst.lua -e "XBURST.test_ei_di_inst(0xb32d0000)"
[...]
Selecting soc jz4760b. Redirecting HW to hwstub.soc.jz4760b
Testing ei
  Test SR
    Enable interrupts with CP0
    SR: 0x1
    Disable interrupts with CP0
    SR: 0x0
  Test ei/di
    Enable interrupts with ei
    SR: 0x0
    Disable interrupts with di
error: lua/xburst.lua:244: call failed
trapped exception in call

Change-Id: I2e162b5dd5e70488bcd8b58f3ca401a3ecab3c4b
diff --git a/utils/hwstub/tools/lua/xburst.lua b/utils/hwstub/tools/lua/xburst.lua
index ddaf7fb..62e94fa 100644
--- a/utils/hwstub/tools/lua/xburst.lua
+++ b/utils/hwstub/tools/lua/xburst.lua
@@ -181,6 +181,73 @@
     print("  Exception result: " .. XBURST.do_ebase_exc_test(mem_addr))
 end
 
+function XBURST.test_ext_inst(mem_addr)
+    data_addr = mem_addr + 0x80
+    -----------
+    -- test ext
+    -----------
+    for pos = 0, 31 do
+        for size = 1, 32 - pos do
+            -- lui     v0,<low part of data_addr>
+            -- addiu   v0,v0,<high part>
+            -- lw      v1,0(v0)
+            DEV.write32(mem_addr + 0, 0x3c020000 + bit32.rshift(data_addr, 16))
+            DEV.write32(mem_addr + 4, 0x8c430000 + bit32.band(data_addr, 0xffff))
+            DEV.write32(mem_addr + 8, 0x8c430000)
+            -- ext     v1, v1, pos, size
+            DEV.write32(mem_addr + 12, 0x7c630000 + bit32.rshift(size - 1, 11) + bit32.rshift(pos, 6))
+            -- sw      v1,0(v0)
+            DEV.write32(mem_addr + 16, 0xac430000)
+            -- jr   ra
+            -- nop
+            DEV.write32(mem_addr + 20, 0x03e00008)
+            DEV.write32(mem_addr + 24, 0)
+            -- write some random data
+            data = math.random(0xffffffff)
+            print(string.format("  data: %x", data))
+            DEV.write32(data_addr, data)
+            DEV.call(mem_addr)
+            ext_data = DEV.read32(data_addr)
+            print(string.format("  result: %x vs %x", ext_data, bit32.extract(data, pos, size)))
+            break
+        end
+        break
+    end
+end
+
+function XBURST.test_ei_di_inst(mem_addr)
+    -- save SR and disable interrupts
+    old_sr = XBURST.read_cp0(12, 0)
+    XBURST.write_cp0(12, 0, bit32.replace(old_sr, 0, 0)) -- clear EI
+    print("Testing ei")
+    print("  Test SR")
+    print("    Enable interrupts with CP0")
+    XBURST.write_cp0(12, 0, bit32.replace(old_sr, 1, 0)) -- set EI
+    print(string.format("    SR: 0x%x", XBURST.read_cp0(12, 0)))
+    print("    Disable interrupts with CP0")
+    XBURST.write_cp0(12, 0, bit32.replace(old_sr, 0, 0)) -- clear EI
+    print(string.format("    SR: 0x%x", XBURST.read_cp0(12, 0)))
+
+    print("  Test ei/di")
+    print("    Enable interrupts with ei")
+    -- ei
+    -- jr   ra
+    -- nop
+    DEV.write32(mem_addr + 4, 0x41606020)
+    DEV.write32(mem_addr + 4, 0x03e00008)
+    DEV.write32(mem_addr + 8, 0)
+    DEV.call(mem_addr)
+    print(string.format("    SR: 0x%x", XBURST.read_cp0(12, 0)))
+    print("    Disable interrupts with di")
+    -- di
+    DEV.write32(mem_addr + 4, 0x41606000)
+    DEV.call(mem_addr)
+    print(string.format("    SR: 0x%x", XBURST.read_cp0(12, 0)))
+
+    -- restore SR
+    XBURST.write_cp0(old_sr)
+end
+
 function XBURST.init()
     -- enable CP1 in SR
     sr_old = XBURST.read_cp0(12, 0)