Files
Odin/core/rexcode/mips/tests/smoke.odin
2026-06-14 16:30:18 +01:00

261 lines
11 KiB
Odin

package rexcode_mips_tests
// Spot-check that ENCODING_TABLE entries are present and have the
// known canonical bit patterns. Validates one entry from each major
// section of the table.
//
// Run with: odin run mips/tests
import "core:fmt"
import "core:os"
import mips "../"
@(private="file") passes := 0
@(private="file") failures := 0
check :: proc(name: string, m: mips.Mnemonic, want_bits, want_mask: u32) {
encs := mips.ENCODING_TABLE[m]
if len(encs) == 0 {
fmt.printfln(" [FAIL] %s: no encoding in table", name)
failures += 1
return
}
e := encs[0]
if e.bits != want_bits || e.mask != want_mask {
fmt.printfln(" [FAIL] %s: got bits=%08x mask=%08x; want bits=%08x mask=%08x",
name, e.bits, e.mask, want_bits, want_mask)
failures += 1
return
}
fmt.printfln(" [ok] %-10s %08x / %08x (feature=%v)", name, e.bits, e.mask, e.feature)
passes += 1
}
main :: proc() {
fmt.println("=== MIPS encoding-table spot checks ===")
// MIPS I core
check("ADD", .ADD, 0x00000020, 0xFC0007FF)
check("ADDI", .ADDI, 0x20000000, 0xFC000000)
check("LW", .LW, 0x8C000000, 0xFC000000)
check("SW", .SW, 0xAC000000, 0xFC000000)
check("BEQ", .BEQ, 0x10000000, 0xFC000000)
check("BLTZ", .BLTZ, 0x04000000, 0xFC1F0000)
check("J", .J, 0x08000000, 0xFC000000)
check("JR", .JR, 0x00000008, 0xFC1FFFFF)
check("MULT", .MULT, 0x00000018, 0xFC00FFFF)
check("MFHI", .MFHI, 0x00000010, 0xFFFF07FF)
check("SLL", .SLL, 0x00000000, 0xFFE0003F)
check("NOP", .NOP, 0x00000000, 0xFFFFFFFF)
check("LUI", .LUI, 0x3C000000, 0xFFE00000)
check("SYSCALL", .SYSCALL, 0x0000000C, 0xFC00003F)
// MIPS II
check("LL", .LL, 0xC0000000, 0xFC000000)
check("BEQL", .BEQL, 0x50000000, 0xFC000000)
// MIPS III
check("DADD", .DADD, 0x0000002C, 0xFC0007FF)
check("LD", .LD, 0xDC000000, 0xFC000000)
// MIPS IV
check("MOVN", .MOVN, 0x0000000B, 0xFC0007FF)
// MIPS32 R1/R2
check("MUL", .MUL, 0x70000002, 0xFC0007FF)
check("CLZ", .CLZ, 0x70000020, 0xFC1F07FF)
check("EXT", .EXT, 0x7C000000, 0xFC00003F)
check("SEB", .SEB, 0x7C000420, 0xFFE007FF)
check("ROTR", .ROTR, 0x00200002, 0xFFE0003F)
check("ERET", .ERET, 0x42000018, 0xFFFFFFFF)
// FPU base
check("ADD.S", .ADD_S, 0x46000000, 0xFFE0003F)
check("MUL.D", .MUL_D, 0x46200002, 0xFFE0003F)
check("ABS.S", .ABS_S, 0x46000005, 0xFFFF003F)
check("SQRT.D", .SQRT_D, 0x46200004, 0xFFFF003F)
check("CVT.D.S", .CVT_D_S, 0x46000021, 0xFFFF003F)
check("MFC1", .MFC1, 0x44000000, 0xFFE007FF)
check("LWC1", .LWC1, 0xC4000000, 0xFC000000)
check("BC1F", .BC1F, 0x45000000, 0xFFE30000)
check("BC1T", .BC1T, 0x45010000, 0xFFE30000)
// FP compares
check("C.F.S", .C_F_S, 0x46000030, 0xFFE000FF)
check("C.EQ.S", .C_EQ_S, 0x46000032, 0xFFE000FF)
check("C.LT.D", .C_LT_D, 0x4620003C, 0xFFE000FF)
check("C.NGT.S", .C_NGT_S, 0x4600003F, 0xFFE000FF)
check("C.EQ.PS", .C_EQ_PS, 0x46C00032, 0xFFE000FF)
// COP0
check("MFC0", .MFC0, 0x40000000, 0xFFE007F8)
check("TLBP", .TLBP, 0x42000008, 0xFFFFFFFF)
check("CACHE", .CACHE, 0xBC000000, 0xFC000000)
// PS1 GTE
check("RTPS", .RTPS, 0x4A000001, 0xFE00003F)
check("NCLIP", .NCLIP, 0x4A000006, 0xFE00003F)
check("RTPT", .RTPT, 0x4A000030, 0xFE00003F)
check("AVSZ3", .AVSZ3, 0x4A00002D, 0xFE00003F)
check("MFC2", .MFC2, 0x48000000, 0xFFE007FF)
// PS2 MMI
check("LQ", .LQ, 0x78000000, 0xFC000000)
check("SQ", .SQ, 0x7C000000, 0xFC000000)
check("MFHI1", .MFHI1, 0x70000010, 0xFFFF07FF)
check("PADDB", .PADDB, 0x70000208, 0xFC0007FF)
check("PADDW", .PADDW, 0x70000008, 0xFC0007FF)
check("PMULTW", .PMULTW, 0x70000309, 0xFC0007FF)
check("PMFHI", .PMFHI, 0x70000209, 0xFFFF07FF)
check("PINTOH", .PINTOH, 0x700002A9, 0xFC0007FF)
check("MFSA", .MFSA, 0x00000028, 0xFFFF07FF)
// MIPS32 R6
check("BC", .BC, 0xC8000000, 0xFC000000)
check("BALC", .BALC, 0xE8000000, 0xFC000000)
check("JIC", .JIC, 0xD8000000, 0xFFE00000)
check("BEQZC", .BEQZC, 0xD8000000, 0xFC000000)
check("AUI", .AUI, 0x3C000000, 0xFC000000)
check("MUH", .MUH, 0x000000D8, 0xFC0007FF)
check("MODU", .MODU, 0x000000DB, 0xFC0007FF)
check("LSA", .LSA, 0x00000005, 0xFC00071F)
check("SELEQZ", .SELEQZ, 0x00000035, 0xFC0007FF)
check("BITSWAP", .BITSWAP, 0x7C000020, 0xFFE007FF)
check("BC1EQZ", .BC1EQZ, 0x45200000, 0xFFE00000)
check("CRC32B", .CRC32B, 0x7C00000F, 0xFC00F8FF)
check("CRC32CD", .CRC32CD, 0x7C00034F, 0xFC00F8FF)
// MIPS DSP ASE
check("ADDU.QB", .ADDU_QB, 0x7C000010, 0xFC0007FF)
check("ADDQ.PH", .ADDQ_PH, 0x7C000290, 0xFC0007FF)
check("DPAQ.S.W.PH",.DPAQ_S_W_PH,0x7C000130, 0xFC0007FF)
check("EXTR.W", .EXTR_W, 0x7C000038, 0xFC00073F)
check("RDDSP", .RDDSP, 0x7C0004B8, 0xFC1F07FF)
check("BITREV", .BITREV, 0x7C0006D2, 0xFFE007FF)
check("LWX", .LWX, 0x7C00000A, 0xFC0007FF)
check("INSV", .INSV, 0x7C00000C, 0xFC00FFFF)
check("BPOSGE32", .BPOSGE32, 0x041C0000, 0xFFFF0000)
// ---- MSA (MIPS SIMD Architecture) -----------------------------------
check("ADDV.B", .ADDV_B, 0x7800000E, 0xFFE0003F)
check("ADDV.W", .ADDV_W, 0x7840000E, 0xFFE0003F)
check("SUBV.D", .SUBV_D, 0x78E0000E, 0xFFE0003F)
check("MULV.W", .MULV_W, 0x78400012, 0xFFE0003F)
check("AND.V", .AND_V, 0x7800001E, 0xFFE0003F)
check("XOR.V", .XOR_V, 0x7860001E, 0xFFE0003F)
check("CEQ.B", .CEQ_B, 0x7800000F, 0xFFE0003F)
check("MIN_S.W", .MIN_S_W, 0x7A40000E, 0xFFE0003F)
check("MAX_U.D", .MAX_U_D, 0x79E0000E, 0xFFE0003F)
check("LD.W", .LD_W, 0x78000022, 0xFC00003F)
check("ST.D", .ST_D, 0x78000027, 0xFC00003F)
// ---- VFPU (PSP Allegrex) control / no-operand ops -------------------
check("VNOP", .VNOP, 0xFFFF0000, 0xFFFFFFFF)
check("VSYNC", .VSYNC, 0xFFFF0320, 0xFFFFFFFF)
check("VFLUSH", .VFLUSH, 0xFFFF040D, 0xFFFFFFFF)
// ---- VFPU arithmetic ------------------------------------------------
check("VADD.S", .VADD_S, 0x60000000, 0xFF808080)
check("VADD.P", .VADD_P, 0x60000080, 0xFF808080)
check("VADD.T", .VADD_T, 0x60008000, 0xFF808080)
check("VADD.Q", .VADD_Q, 0x60008080, 0xFF808080)
check("VSUB.S", .VSUB_S, 0x60800000, 0xFF808080)
check("VMUL.S", .VMUL_S, 0x64000000, 0xFF808080)
check("VMUL.Q", .VMUL_Q, 0x64008080, 0xFF808080)
check("VDIV.S", .VDIV_S, 0x63800000, 0xFF808080)
check("VABS.S", .VABS_S, 0xD0010000, 0xFFFF8080)
check("VNEG.Q", .VNEG_Q, 0xD0028080, 0xFFFF8080)
check("VMOV.S", .VMOV_S, 0xD0000000, 0xFFFF8080)
check("VSQRT.S", .VSQRT_S, 0xD0160000, 0xFFFF8080)
check("VRCP.P", .VRCP_P, 0xD0100080, 0xFFFF8080)
check("VRSQ.T", .VRSQ_T, 0xD0118000, 0xFFFF8080)
check("VMIN.Q", .VMIN_Q, 0x6D008080, 0xFF808080)
check("VMAX.S", .VMAX_S, 0x6D800000, 0xFF808080)
check("VSCL.Q", .VSCL_Q, 0x65008080, 0xFF808080)
check("VDOT.Q", .VDOT_Q, 0x64808080, 0xFF808080)
// ---- VFPU memory + prefix + GPR-bridge ------------------------------
check("LV.S", .LV_S, 0xC8000000, 0xFC000000)
check("LV.Q", .LV_Q, 0xD8000000, 0xFC000000)
check("SV.S", .SV_S, 0xE8000000, 0xFC000000)
check("SV.Q", .SV_Q, 0xF8000000, 0xFC000000)
check("VCST.S", .VCST_S, 0xD0600000, 0xFFE08080)
check("VPFXS", .VPFXS, 0xDC000000, 0xFFF00000)
check("VPFXT", .VPFXT, 0xDD000000, 0xFFF00000)
check("VPFXD", .VPFXD, 0xDE000000, 0xFFF00000)
check("MFV", .MFV, 0x48600000, 0xFFE00080)
check("MTV", .MTV, 0x48E00000, 0xFFE00080)
// ---- VFPU transcendentals -------------------------------------------
check("VSIN.S", .VSIN_S, 0xD0120000, 0xFFFF8080)
check("VCOS.S", .VCOS_S, 0xD0130000, 0xFFFF8080)
check("VEXP2.S", .VEXP2_S, 0xD0140000, 0xFFFF8080)
check("VLOG2.S", .VLOG2_S, 0xD0150000, 0xFFFF8080)
check("VASIN.S", .VASIN_S, 0xD0170000, 0xFFFF8080)
check("VNRCP.S", .VNRCP_S, 0xD0180000, 0xFFFF8080)
check("VNSIN.S", .VNSIN_S, 0xD01A0000, 0xFFFF8080)
check("VREXP2.S", .VREXP2_S, 0xD01C0000, 0xFFFF8080)
check("VSGN.S", .VSGN_S, 0xD04A0000, 0xFFFF8080)
// ---- VFPU conversions -----------------------------------------------
check("VF2IN.S", .VF2IN_S, 0xD2000000, 0xFFE08080)
check("VF2IZ.Q", .VF2IZ_Q, 0xD2208080, 0xFFE08080)
check("VF2IU.T", .VF2IU_T, 0xD2408000, 0xFFE08080)
check("VF2ID.P", .VF2ID_P, 0xD2600080, 0xFFE08080)
check("VI2F.S", .VI2F_S, 0xD2800000, 0xFFE08080)
check("VF2H.P", .VF2H_P, 0xD0320080, 0xFFFF8080)
check("VH2F.S", .VH2F_S, 0xD0330000, 0xFFFF8080)
// ---- VFPU reductions ------------------------------------------------
check("VFAD.Q", .VFAD_Q, 0xD0468080, 0xFFFF8080)
check("VAVG.Q", .VAVG_Q, 0xD0478080, 0xFFFF8080)
check("VHDP.Q", .VHDP_Q, 0x66008080, 0xFF808080)
// ---- VFPU compare ---------------------------------------------------
check("VCMP.S", .VCMP_S, 0x6C000000, 0xFF8080F0)
check("VCMP.Q", .VCMP_Q, 0x6C008080, 0xFF8080F0)
// ---- VFPU matrix ----------------------------------------------------
check("VMMUL.P", .VMMUL_P, 0xF0000080, 0xFF808080)
check("VMMUL.T", .VMMUL_T, 0xF0008000, 0xFF808080)
check("VMMUL.Q", .VMMUL_Q, 0xF0008080, 0xFF808080)
check("VTFM2.P", .VTFM2_P, 0xF0800080, 0xFF808080)
check("VTFM4.Q", .VTFM4_Q, 0xF0808080, 0xFF808080)
check("VHTFM2.P", .VHTFM2_P, 0xF0800000, 0xFF808080)
check("VMSCL.Q", .VMSCL_Q, 0xF2008080, 0xFF808080)
check("VMMOV.Q", .VMMOV_Q, 0xF3808080, 0xFFFF8080)
check("VMIDT.Q", .VMIDT_Q, 0xF3838080, 0xFFFFFF80)
check("VMZERO.Q", .VMZERO_Q, 0xF3868080, 0xFFFFFF80)
check("VMONE.Q", .VMONE_Q, 0xF3878080, 0xFFFFFF80)
// ---- VFPU cross / quaternion ----------------------------------------
check("VCRS.T", .VCRS_T, 0x66808000, 0xFF808080)
check("VQMUL.Q", .VQMUL_Q, 0xF2808080, 0xFF808080)
// ---- VFPU control + branches ----------------------------------------
check("MFVC", .MFVC, 0x48400000, 0xFFE00000)
check("MTVC", .MTVC, 0x48C00000, 0xFFE00000)
check("BVF", .BVF, 0x49000000, 0xFFE30000)
check("BVT", .BVT, 0x49010000, 0xFFE30000)
check("BVFL", .BVFL, 0x49020000, 0xFFE30000)
check("BVTL", .BVTL, 0x49030000, 0xFFE30000)
// ---- VFPU unaligned quad memory -------------------------------------
check("LVL.Q", .LVL_Q, 0xD4000002, 0xFC000002)
check("LVR.Q", .LVR_Q, 0xD4000000, 0xFC000002)
check("SVL.Q", .SVL_Q, 0xF4000002, 0xFC000002)
check("SVR.Q", .SVR_Q, 0xF4000000, 0xFC000002)
// ---- VFPU integer/float immediate load ------------------------------
check("VIIM.S", .VIIM_S, 0xDF000000, 0xFF800000)
check("VFIM.S", .VFIM_S, 0xDF800000, 0xFF800000)
fmt.println()
fmt.printfln("==> table: %d passed, %d failed", passes, failures)
if failures > 0 { os.exit(1) }
run_encoder_tests()
run_decoder_tests()
run_printer_tests()
}