rexcode/mips: FPU FMA, MSA COPY/INSERT, DSP 2-register, DI/EI/RDHWR

New FR (FP reg at 25:21) encoding for the COP1X 4-register fused
multiply-adds MADD/MSUB/NMADD/NMSUB.S/.D. New GPR_AT_6 / GPR_AT_11
encodings (GPR in a vector-register slot, with correct GPR decode) for
MSA COPY_S/U (lane->GPR) and INSERT (GPR->lane). DSP two-register
PRECEQU/PRECEU (.PH.QBLA/QBRA) and REPLV (.PH/.QB). Control ops DI/EI and
RDHWR. 25 forms; spot-checked byte-exact vs llvm-mc and decode-clean; 281
tests green.
This commit is contained in:
Brendan Punsky
2026-06-18 03:31:40 -04:00
committed by Flāvius
parent 930b988ebf
commit c2de507bb0
15 changed files with 1252 additions and 990 deletions

View File

@@ -200,6 +200,12 @@ extract_operand_inline :: #force_inline proc "contextless" (
return reg_operand(decode_reg(word, 11, ot), ot)
case .FD:
return reg_operand(decode_reg(word, 6, ot), ot)
case .FR:
return reg_operand(decode_reg(word, 21, ot), ot)
case .GPR_AT_6:
return reg_operand(decode_reg(word, 6, ot), ot)
case .GPR_AT_11:
return reg_operand(decode_reg(word, 11, ot), ot)
// Immediates ------------------------------------------------------------
case .IMM_16:

View File

@@ -394,6 +394,12 @@ pack_operand_inline :: #force_inline proc(
return (u32(op.immediate) & 0x3F) << 16
case .MSA_I8:
return (u32(op.immediate) & 0xFF) << 16
case .FR:
return (u32(reg_hw(op.reg)) & 0x1F) << 21
case .GPR_AT_6:
return (u32(reg_hw(op.reg)) & 0x1F) << 6
case .GPR_AT_11:
return (u32(reg_hw(op.reg)) & 0x1F) << 11
// MSA memory operand: base GPR at 15:11, signed-10 disp at 25:16
// (caller has already scaled the displacement by element size).

View File

@@ -237,6 +237,9 @@ Operand_Encoding :: enum u8 {
MSA_BIT_SHIFT, // BIT-format shift amount (.B m=0x70|sh, .H 0x60|sh, .W 0x40|sh, .D sh)
MSA_ELM_IDX, // ELM-format element index (.B n, .H 0x20|n, .W 0x30|n, .D 0x38|n)
MSA_I8, // 8-bit immediate at bits 23:16 (I8 forms: ANDI.B/SHF/...)
FR, // FP register at bits 25:21 (COP1X 4-register FMA: fr)
GPR_AT_6, // GPR at bits 10:6 (MSA COPY destination)
GPR_AT_11, // GPR at bits 15:11 (MSA INSERT source)
// MSA memory operand: base GPR at bits 15:11 + signed 10-bit disp at 25:16,
// scaled by element size (1/2/4/8 for B/H/W/D).

View File

@@ -330,6 +330,12 @@ inst_seb_r_r :: #force_inline proc "contextless" (dst: GPR, src: G
emit_seb_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_seb_r_r(dst, src)) }
inst_seh_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .SEH, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_seh_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_seh_r_r(dst, src)) }
inst_rdhwr_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .RDHWR, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_rdhwr_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_rdhwr_r_r(dst, src)) }
inst_di_r :: #force_inline proc "contextless" (dst: GPR) -> Instruction { return Instruction{mnemonic = .DI, operand_count = 1, length = 4, ops = {op_gpr(dst), {}, {}, {}}} }
emit_di_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR) { append(instructions, inst_di_r(dst)) }
inst_ei_r :: #force_inline proc "contextless" (dst: GPR) -> Instruction { return Instruction{mnemonic = .EI, operand_count = 1, length = 4, ops = {op_gpr(dst), {}, {}, {}}} }
emit_ei_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR) { append(instructions, inst_ei_r(dst)) }
inst_eret_none :: #force_inline proc "contextless" () -> Instruction { return Instruction{mnemonic = .ERET, operand_count = 0, length = 4, ops = {{}, {}, {}, {}}} }
emit_eret_none :: #force_inline proc(instructions: ^[dynamic]Instruction) { append(instructions, inst_eret_none()) }
inst_deret_none :: #force_inline proc "contextless" () -> Instruction { return Instruction{mnemonic = .DERET, operand_count = 0, length = 4, ops = {{}, {}, {}, {}}} }
@@ -504,6 +510,22 @@ inst_rsqrt_s_f_f :: #force_inline proc "contextless" (dst: FPR, src: F
emit_rsqrt_s_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR) { append(instructions, inst_rsqrt_s_f_f(dst, src)) }
inst_rsqrt_d_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR) -> Instruction { return Instruction{mnemonic = .RSQRT_D, operand_count = 2, length = 4, ops = {op_fpr(dst), op_fpr(src), {}, {}}} }
emit_rsqrt_d_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR) { append(instructions, inst_rsqrt_d_f_f(dst, src)) }
inst_madd_s_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .MADD_S, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_madd_s_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_madd_s_f_f_f_f(dst, src, src2, src3)) }
inst_madd_d_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .MADD_D, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_madd_d_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_madd_d_f_f_f_f(dst, src, src2, src3)) }
inst_msub_s_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .MSUB_S, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_msub_s_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_msub_s_f_f_f_f(dst, src, src2, src3)) }
inst_msub_d_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .MSUB_D, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_msub_d_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_msub_d_f_f_f_f(dst, src, src2, src3)) }
inst_nmadd_s_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .NMADD_S, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_nmadd_s_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_nmadd_s_f_f_f_f(dst, src, src2, src3)) }
inst_nmadd_d_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .NMADD_D, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_nmadd_d_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_nmadd_d_f_f_f_f(dst, src, src2, src3)) }
inst_nmsub_s_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .NMSUB_S, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_nmsub_s_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_nmsub_s_f_f_f_f(dst, src, src2, src3)) }
inst_nmsub_d_f_f_f_f :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: FPR, src3: FPR) -> Instruction { return Instruction{mnemonic = .NMSUB_D, operand_count = 4, length = 4, ops = {op_fpr(dst), op_fpr(src), op_fpr(src2), op_fpr(src3)}} }
emit_nmsub_d_f_f_f_f :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: FPR, src3: FPR) { append(instructions, inst_nmsub_d_f_f_f_f(dst, src, src2, src3)) }
inst_movn_s_f_f_r :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: GPR) -> Instruction { return Instruction{mnemonic = .MOVN_S, operand_count = 3, length = 4, ops = {op_fpr(dst), op_fpr(src), op_gpr(src2), {}}} }
emit_movn_s_f_f_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: FPR, src: FPR, src2: GPR) { append(instructions, inst_movn_s_f_f_r(dst, src, src2)) }
inst_movn_d_f_f_r :: #force_inline proc "contextless" (dst: FPR, src: FPR, src2: GPR) -> Instruction { return Instruction{mnemonic = .MOVN_D, operand_count = 3, length = 4, ops = {op_fpr(dst), op_fpr(src), op_gpr(src2), {}}} }
@@ -1066,10 +1088,18 @@ inst_precequ_ph_qbl_r_r :: #force_inline proc "contextless" (dst: GPR, src: G
emit_precequ_ph_qbl_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_precequ_ph_qbl_r_r(dst, src)) }
inst_precequ_ph_qbr_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEQU_PH_QBR, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_precequ_ph_qbr_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_precequ_ph_qbr_r_r(dst, src)) }
inst_precequ_ph_qbla_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEQU_PH_QBLA, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_precequ_ph_qbla_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_precequ_ph_qbla_r_r(dst, src)) }
inst_precequ_ph_qbra_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEQU_PH_QBRA, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_precequ_ph_qbra_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_precequ_ph_qbra_r_r(dst, src)) }
inst_preceu_ph_qbl_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEU_PH_QBL, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_preceu_ph_qbl_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_preceu_ph_qbl_r_r(dst, src)) }
inst_preceu_ph_qbr_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEU_PH_QBR, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_preceu_ph_qbr_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_preceu_ph_qbr_r_r(dst, src)) }
inst_preceu_ph_qbla_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEU_PH_QBLA, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_preceu_ph_qbla_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_preceu_ph_qbla_r_r(dst, src)) }
inst_preceu_ph_qbra_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .PRECEU_PH_QBRA, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_preceu_ph_qbra_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_preceu_ph_qbra_r_r(dst, src)) }
inst_precrq_rs_ph_w_r_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR, src2: GPR) -> Instruction { return Instruction{mnemonic = .PRECRQ_RS_PH_W, operand_count = 3, length = 4, ops = {op_gpr(dst), op_gpr(src), op_gpr(src2), {}}} }
emit_precrq_rs_ph_w_r_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR, src2: GPR) { append(instructions, inst_precrq_rs_ph_w_r_r_r(dst, src, src2)) }
inst_cmpu_eq_qb_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .CMPU_EQ_QB, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
@@ -1146,6 +1176,10 @@ inst_absq_s_ph_r_r :: #force_inline proc "contextless" (dst: GPR, src: G
emit_absq_s_ph_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_absq_s_ph_r_r(dst, src)) }
inst_absq_s_w_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .ABSQ_S_W, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_absq_s_w_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_absq_s_w_r_r(dst, src)) }
inst_replv_ph_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .REPLV_PH, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_replv_ph_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_replv_ph_r_r(dst, src)) }
inst_replv_qb_r_r :: #force_inline proc "contextless" (dst: GPR, src: GPR) -> Instruction { return Instruction{mnemonic = .REPLV_QB, operand_count = 2, length = 4, ops = {op_gpr(dst), op_gpr(src), {}, {}}} }
emit_replv_qb_r_r :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: GPR) { append(instructions, inst_replv_qb_r_r(dst, src)) }
inst_addv_b_w_w_w :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .ADDV_B, operand_count = 3, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_addv_b_w_w_w :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_addv_b_w_w_w(dst, src, src2)) }
inst_addv_h_w_w_w :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .ADDV_H, operand_count = 3, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
@@ -1512,6 +1546,22 @@ inst_ldi_w_w_i5 :: #force_inline proc "contextless" (dst: Register, i
emit_ldi_w_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, imm: i64) { append(instructions, inst_ldi_w_w_i5(dst, imm)) }
inst_ldi_d_w_i5 :: #force_inline proc "contextless" (dst: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .LDI_D, operand_count = 2, length = 4, ops = {op_reg(dst), op_imm(imm, 1), {}, {}}} }
emit_ldi_d_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, imm: i64) { append(instructions, inst_ldi_d_w_i5(dst, imm)) }
inst_copy_s_b_r_w_i5 :: #force_inline proc "contextless" (dst: GPR, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .COPY_S_B, operand_count = 3, length = 4, ops = {op_gpr(dst), op_reg(src), op_imm(imm, 1), {}}} }
emit_copy_s_b_r_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: Register, imm: i64) { append(instructions, inst_copy_s_b_r_w_i5(dst, src, imm)) }
inst_copy_s_h_r_w_i5 :: #force_inline proc "contextless" (dst: GPR, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .COPY_S_H, operand_count = 3, length = 4, ops = {op_gpr(dst), op_reg(src), op_imm(imm, 1), {}}} }
emit_copy_s_h_r_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: Register, imm: i64) { append(instructions, inst_copy_s_h_r_w_i5(dst, src, imm)) }
inst_copy_s_w_r_w_i5 :: #force_inline proc "contextless" (dst: GPR, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .COPY_S_W, operand_count = 3, length = 4, ops = {op_gpr(dst), op_reg(src), op_imm(imm, 1), {}}} }
emit_copy_s_w_r_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: Register, imm: i64) { append(instructions, inst_copy_s_w_r_w_i5(dst, src, imm)) }
inst_copy_u_b_r_w_i5 :: #force_inline proc "contextless" (dst: GPR, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .COPY_U_B, operand_count = 3, length = 4, ops = {op_gpr(dst), op_reg(src), op_imm(imm, 1), {}}} }
emit_copy_u_b_r_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: Register, imm: i64) { append(instructions, inst_copy_u_b_r_w_i5(dst, src, imm)) }
inst_copy_u_h_r_w_i5 :: #force_inline proc "contextless" (dst: GPR, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .COPY_U_H, operand_count = 3, length = 4, ops = {op_gpr(dst), op_reg(src), op_imm(imm, 1), {}}} }
emit_copy_u_h_r_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: GPR, src: Register, imm: i64) { append(instructions, inst_copy_u_h_r_w_i5(dst, src, imm)) }
inst_insert_b_w_r_i5 :: #force_inline proc "contextless" (dst: Register, src: GPR, imm: i64) -> Instruction { return Instruction{mnemonic = .INSERT_B, operand_count = 3, length = 4, ops = {op_reg(dst), op_gpr(src), op_imm(imm, 1), {}}} }
emit_insert_b_w_r_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: GPR, imm: i64) { append(instructions, inst_insert_b_w_r_i5(dst, src, imm)) }
inst_insert_h_w_r_i5 :: #force_inline proc "contextless" (dst: Register, src: GPR, imm: i64) -> Instruction { return Instruction{mnemonic = .INSERT_H, operand_count = 3, length = 4, ops = {op_reg(dst), op_gpr(src), op_imm(imm, 1), {}}} }
emit_insert_h_w_r_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: GPR, imm: i64) { append(instructions, inst_insert_h_w_r_i5(dst, src, imm)) }
inst_insert_w_w_r_i5 :: #force_inline proc "contextless" (dst: Register, src: GPR, imm: i64) -> Instruction { return Instruction{mnemonic = .INSERT_W, operand_count = 3, length = 4, ops = {op_reg(dst), op_gpr(src), op_imm(imm, 1), {}}} }
emit_insert_w_w_r_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: GPR, imm: i64) { append(instructions, inst_insert_w_w_r_i5(dst, src, imm)) }
inst_insve_b_w_w_i5 :: #force_inline proc "contextless" (dst: Register, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .INSVE_B, operand_count = 3, length = 4, ops = {op_reg(dst), op_reg(src), op_imm(imm, 1), {}}} }
emit_insve_b_w_w_i5 :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, imm: i64) { append(instructions, inst_insve_b_w_w_i5(dst, src, imm)) }
inst_insve_h_w_w_i5 :: #force_inline proc "contextless" (dst: Register, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .INSVE_H, operand_count = 3, length = 4, ops = {op_reg(dst), op_reg(src), op_imm(imm, 1), {}}} }
@@ -2197,6 +2247,12 @@ inst_seb :: inst_seb_r_r
emit_seb :: emit_seb_r_r
inst_seh :: inst_seh_r_r
emit_seh :: emit_seh_r_r
inst_rdhwr :: inst_rdhwr_r_r
emit_rdhwr :: emit_rdhwr_r_r
inst_di :: inst_di_r
emit_di :: emit_di_r
inst_ei :: inst_ei_r
emit_ei :: emit_ei_r
inst_eret :: inst_eret_none
emit_eret :: emit_eret_none
inst_deret :: inst_deret_none
@@ -2371,6 +2427,22 @@ inst_rsqrt_s :: inst_rsqrt_s_f_f
emit_rsqrt_s :: emit_rsqrt_s_f_f
inst_rsqrt_d :: inst_rsqrt_d_f_f
emit_rsqrt_d :: emit_rsqrt_d_f_f
inst_madd_s :: inst_madd_s_f_f_f_f
emit_madd_s :: emit_madd_s_f_f_f_f
inst_madd_d :: inst_madd_d_f_f_f_f
emit_madd_d :: emit_madd_d_f_f_f_f
inst_msub_s :: inst_msub_s_f_f_f_f
emit_msub_s :: emit_msub_s_f_f_f_f
inst_msub_d :: inst_msub_d_f_f_f_f
emit_msub_d :: emit_msub_d_f_f_f_f
inst_nmadd_s :: inst_nmadd_s_f_f_f_f
emit_nmadd_s :: emit_nmadd_s_f_f_f_f
inst_nmadd_d :: inst_nmadd_d_f_f_f_f
emit_nmadd_d :: emit_nmadd_d_f_f_f_f
inst_nmsub_s :: inst_nmsub_s_f_f_f_f
emit_nmsub_s :: emit_nmsub_s_f_f_f_f
inst_nmsub_d :: inst_nmsub_d_f_f_f_f
emit_nmsub_d :: emit_nmsub_d_f_f_f_f
inst_movn_s :: inst_movn_s_f_f_r
emit_movn_s :: emit_movn_s_f_f_r
inst_movn_d :: inst_movn_d_f_f_r
@@ -2933,10 +3005,18 @@ inst_precequ_ph_qbl :: inst_precequ_ph_qbl_r_r
emit_precequ_ph_qbl :: emit_precequ_ph_qbl_r_r
inst_precequ_ph_qbr :: inst_precequ_ph_qbr_r_r
emit_precequ_ph_qbr :: emit_precequ_ph_qbr_r_r
inst_precequ_ph_qbla :: inst_precequ_ph_qbla_r_r
emit_precequ_ph_qbla :: emit_precequ_ph_qbla_r_r
inst_precequ_ph_qbra :: inst_precequ_ph_qbra_r_r
emit_precequ_ph_qbra :: emit_precequ_ph_qbra_r_r
inst_preceu_ph_qbl :: inst_preceu_ph_qbl_r_r
emit_preceu_ph_qbl :: emit_preceu_ph_qbl_r_r
inst_preceu_ph_qbr :: inst_preceu_ph_qbr_r_r
emit_preceu_ph_qbr :: emit_preceu_ph_qbr_r_r
inst_preceu_ph_qbla :: inst_preceu_ph_qbla_r_r
emit_preceu_ph_qbla :: emit_preceu_ph_qbla_r_r
inst_preceu_ph_qbra :: inst_preceu_ph_qbra_r_r
emit_preceu_ph_qbra :: emit_preceu_ph_qbra_r_r
inst_precrq_rs_ph_w :: inst_precrq_rs_ph_w_r_r_r
emit_precrq_rs_ph_w :: emit_precrq_rs_ph_w_r_r_r
inst_cmpu_eq_qb :: inst_cmpu_eq_qb_r_r
@@ -3013,6 +3093,10 @@ inst_absq_s_ph :: inst_absq_s_ph_r_r
emit_absq_s_ph :: emit_absq_s_ph_r_r
inst_absq_s_w :: inst_absq_s_w_r_r
emit_absq_s_w :: emit_absq_s_w_r_r
inst_replv_ph :: inst_replv_ph_r_r
emit_replv_ph :: emit_replv_ph_r_r
inst_replv_qb :: inst_replv_qb_r_r
emit_replv_qb :: emit_replv_qb_r_r
inst_addv_b :: inst_addv_b_w_w_w
emit_addv_b :: emit_addv_b_w_w_w
inst_addv_h :: inst_addv_h_w_w_w
@@ -3379,6 +3463,22 @@ inst_ldi_w :: inst_ldi_w_w_i5
emit_ldi_w :: emit_ldi_w_w_i5
inst_ldi_d :: inst_ldi_d_w_i5
emit_ldi_d :: emit_ldi_d_w_i5
inst_copy_s_b :: inst_copy_s_b_r_w_i5
emit_copy_s_b :: emit_copy_s_b_r_w_i5
inst_copy_s_h :: inst_copy_s_h_r_w_i5
emit_copy_s_h :: emit_copy_s_h_r_w_i5
inst_copy_s_w :: inst_copy_s_w_r_w_i5
emit_copy_s_w :: emit_copy_s_w_r_w_i5
inst_copy_u_b :: inst_copy_u_b_r_w_i5
emit_copy_u_b :: emit_copy_u_b_r_w_i5
inst_copy_u_h :: inst_copy_u_h_r_w_i5
emit_copy_u_h :: emit_copy_u_h_r_w_i5
inst_insert_b :: inst_insert_b_w_r_i5
emit_insert_b :: emit_insert_b_w_r_i5
inst_insert_h :: inst_insert_h_w_r_i5
emit_insert_h :: emit_insert_h_w_r_i5
inst_insert_w :: inst_insert_w_w_r_i5
emit_insert_w :: emit_insert_w_w_r_i5
inst_insve_b :: inst_insve_b_w_w_i5
emit_insve_b :: emit_insve_b_w_w_i5
inst_insve_h :: inst_insve_h_w_w_i5

View File

@@ -1600,5 +1600,30 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
.FCVT_D_W = { {.FCVT_D_W, {.FPR_D,.FPR_W,.NONE,.NONE}, {.FD,.FS,.NONE,.NONE}, 0x46800021, 0xFFFF003F, .FPU, {}} },
.FCVT_S_D = { {.FCVT_S_D, {.FPR_S,.FPR_D,.NONE,.NONE}, {.FD,.FS,.NONE,.NONE}, 0x46200020, 0xFFFF003F, .FPU, {}} },
.FCVT_S_W = { {.FCVT_S_W, {.FPR_S,.FPR_W,.NONE,.NONE}, {.FD,.FS,.NONE,.NONE}, 0x46800020, 0xFFFF003F, .FPU, {}} },
.PRECEQU_PH_QBLA = { {.PRECEQU_PH_QBLA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000192, 0xFFE007FF, .DSP_R2, {}} },
.PRECEQU_PH_QBRA = { {.PRECEQU_PH_QBRA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0001D2, 0xFFE007FF, .DSP_R2, {}} },
.PRECEU_PH_QBLA = { {.PRECEU_PH_QBLA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000792, 0xFFE007FF, .DSP_R2, {}} },
.PRECEU_PH_QBRA = { {.PRECEU_PH_QBRA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0007D2, 0xFFE007FF, .DSP_R2, {}} },
.REPLV_PH = { {.REPLV_PH, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0002D2, 0xFFE007FF, .DSP_R2, {}} },
.REPLV_QB = { {.REPLV_QB, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0000D2, 0xFFE007FF, .DSP_R2, {}} },
.MADD_S = { {.MADD_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000020, 0xFC00003F, .FPU, {}} },
.MADD_D = { {.MADD_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000021, 0xFC00003F, .FPU, {}} },
.MSUB_S = { {.MSUB_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000028, 0xFC00003F, .FPU, {}} },
.MSUB_D = { {.MSUB_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000029, 0xFC00003F, .FPU, {}} },
.NMADD_S = { {.NMADD_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000030, 0xFC00003F, .FPU, {}} },
.NMADD_D = { {.NMADD_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000031, 0xFC00003F, .FPU, {}} },
.NMSUB_S = { {.NMSUB_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000038, 0xFC00003F, .FPU, {}} },
.NMSUB_D = { {.NMSUB_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000039, 0xFC00003F, .FPU, {}} },
.COPY_S_B = { {.COPY_S_B, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78800019, 0xFFF0003F, .MSA, {}} },
.COPY_S_H = { {.COPY_S_H, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78A00019, 0xFFF8003F, .MSA, {}} },
.COPY_S_W = { {.COPY_S_W, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78B00019, 0xFFFC003F, .MSA, {}} },
.COPY_U_B = { {.COPY_U_B, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78C00019, 0xFFF0003F, .MSA, {}} },
.COPY_U_H = { {.COPY_U_H, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78E00019, 0xFFF8003F, .MSA, {}} },
.INSERT_B = { {.INSERT_B, {.MSA_VEC,.GPR,.IMM5,.NONE}, {.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}, 0x79000019, 0xFFF0003F, .MSA, {}} },
.INSERT_H = { {.INSERT_H, {.MSA_VEC,.GPR,.IMM5,.NONE}, {.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}, 0x79200019, 0xFFF8003F, .MSA, {}} },
.INSERT_W = { {.INSERT_W, {.MSA_VEC,.GPR,.IMM5,.NONE}, {.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}, 0x79300019, 0xFFFC003F, .MSA, {}} },
.DI = { {.DI, {.GPR,.NONE,.NONE,.NONE}, {.RT,.NONE,.NONE,.NONE}, 0x41606000, 0xFFE0FFFF, .MIPS32_R2, {}} },
.EI = { {.EI, {.GPR,.NONE,.NONE,.NONE}, {.RT,.NONE,.NONE,.NONE}, 0x41606020, 0xFFE0FFFF, .MIPS32_R2, {}} },
.RDHWR = { {.RDHWR, {.GPR,.GPR,.NONE,.NONE}, {.RT,.RD,.NONE,.NONE}, 0x7C00003B, 0xFFE007FF, .MIPS32_R2, {}} },
// SPECGEN:END
}

View File

@@ -8,7 +8,7 @@ package rexcode_mips_generated
import lib "../.."
@(rodata)
DECODE_ENTRIES := [931]lib.Decode_Entry{
DECODE_ENTRIES := [956]lib.Decode_Entry{
{ .NOP, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00000000, 0xFFFFFFFF, .MIPS_I, {} },
{ .SSNOP, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00000040, 0xFFFFFFFF, .MIPS32_R1, {} },
{ .EHB, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x000000C0, 0xFFFFFFFF, .MIPS32_R2, {} },
@@ -134,6 +134,8 @@ DECODE_ENTRIES := [931]lib.Decode_Entry{
{ .TLBR, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x42000001, 0xFFFFFFFF, .COP0, {} },
{ .TLBWI, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x42000002, 0xFFFFFFFF, .COP0, {} },
{ .TLBWR, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x42000006, 0xFFFFFFFF, .COP0, {} },
{ .DI, {.GPR,.NONE,.NONE,.NONE}, {.RT,.NONE,.NONE,.NONE}, 0x41606000, 0xFFE0FFFF, .MIPS32_R2, {} },
{ .EI, {.GPR,.NONE,.NONE,.NONE}, {.RT,.NONE,.NONE,.NONE}, 0x41606020, 0xFFE0FFFF, .MIPS32_R2, {} },
{ .MFC0, {.GPR,.CP0_REG,.SEL,.NONE}, {.RT,.RD,.SEL,.NONE}, 0x40000000, 0xFFE007F8, .COP0, {} },
{ .MTC0, {.GPR,.CP0_REG,.SEL,.NONE}, {.RT,.RD,.SEL,.NONE}, 0x40800000, 0xFFE007F8, .COP0, {} },
{ .DMFC0, {.GPR,.CP0_REG,.SEL,.NONE}, {.RT,.RD,.SEL,.NONE}, 0x40200000, 0xFFE007F8, .COP0, {only_64=true} },
@@ -307,6 +309,14 @@ DECODE_ENTRIES := [931]lib.Decode_Entry{
{ .SWXC1, {.FPR_S,.GPR,.GPR,.NONE}, {.FS,.RS,.RT,.NONE}, 0x4C000008, 0xFC0007FF, .MIPS_IV, {} },
{ .LDXC1, {.FPR_D,.GPR,.GPR,.NONE}, {.FD,.RS,.RT,.NONE}, 0x4C000001, 0xFC0007FF, .MIPS_IV, {} },
{ .SDXC1, {.FPR_D,.GPR,.GPR,.NONE}, {.FS,.RS,.RT,.NONE}, 0x4C000009, 0xFC0007FF, .MIPS_IV, {} },
{ .MADD_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000020, 0xFC00003F, .FPU, {} },
{ .MADD_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000021, 0xFC00003F, .FPU, {} },
{ .MSUB_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000028, 0xFC00003F, .FPU, {} },
{ .MSUB_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000029, 0xFC00003F, .FPU, {} },
{ .NMADD_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000030, 0xFC00003F, .FPU, {} },
{ .NMADD_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000031, 0xFC00003F, .FPU, {} },
{ .NMSUB_S, {.FPR_S,.FPR_S,.FPR_S,.FPR_S}, {.FD,.FR,.FS,.FT}, 0x4C000038, 0xFC00003F, .FPU, {} },
{ .NMSUB_D, {.FPR_D,.FPR_D,.FPR_D,.FPR_D}, {.FD,.FR,.FS,.FT}, 0x4C000039, 0xFC00003F, .FPU, {} },
{ .BEQL, {.GPR,.GPR,.REL16,.NONE}, {.RS,.RT,.BRANCH_16,.NONE}, 0x50000000, 0xFC000000, .MIPS_II, {delay_slot=true, likely=true} },
{ .BNEL, {.GPR,.GPR,.REL16,.NONE}, {.RS,.RT,.BRANCH_16,.NONE}, 0x54000000, 0xFC000000, .MIPS_II, {delay_slot=true, likely=true} },
{ .BLEZL, {.GPR,.REL16,.NONE,.NONE}, {.RS,.BRANCH_16,.NONE,.NONE}, 0x58000000, 0xFC1F0000, .MIPS_II, {delay_slot=true, likely=true} },
@@ -494,18 +504,26 @@ DECODE_ENTRIES := [931]lib.Decode_Entry{
{ .INSVE_D, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x79780019, 0xFFFE003F, .MSA, {} },
{ .SLDI_D, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78380019, 0xFFFE003F, .MSA, {} },
{ .SPLATI_D, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78780019, 0xFFFE003F, .MSA, {} },
{ .COPY_S_W, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78B00019, 0xFFFC003F, .MSA, {} },
{ .INSERT_W, {.MSA_VEC,.GPR,.IMM5,.NONE}, {.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}, 0x79300019, 0xFFFC003F, .MSA, {} },
{ .INSVE_W, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x79700019, 0xFFFC003F, .MSA, {} },
{ .SLDI_W, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78300019, 0xFFFC003F, .MSA, {} },
{ .SPLATI_W, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78700019, 0xFFFC003F, .MSA, {} },
{ .SLLI_B, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_BIT_SHIFT,.NONE}, 0x78700009, 0xFFF8003F, .MSA, {} },
{ .SRLI_B, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_BIT_SHIFT,.NONE}, 0x79700009, 0xFFF8003F, .MSA, {} },
{ .SRAI_B, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_BIT_SHIFT,.NONE}, 0x78F00009, 0xFFF8003F, .MSA, {} },
{ .COPY_S_H, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78A00019, 0xFFF8003F, .MSA, {} },
{ .COPY_U_H, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78E00019, 0xFFF8003F, .MSA, {} },
{ .INSERT_H, {.MSA_VEC,.GPR,.IMM5,.NONE}, {.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}, 0x79200019, 0xFFF8003F, .MSA, {} },
{ .INSVE_H, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x79600019, 0xFFF8003F, .MSA, {} },
{ .SLDI_H, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78200019, 0xFFF8003F, .MSA, {} },
{ .SPLATI_H, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78600019, 0xFFF8003F, .MSA, {} },
{ .SLLI_H, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_BIT_SHIFT,.NONE}, 0x78600009, 0xFFF0003F, .MSA, {} },
{ .SRLI_H, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_BIT_SHIFT,.NONE}, 0x79600009, 0xFFF0003F, .MSA, {} },
{ .SRAI_H, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_BIT_SHIFT,.NONE}, 0x78E00009, 0xFFF0003F, .MSA, {} },
{ .COPY_S_B, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78800019, 0xFFF0003F, .MSA, {} },
{ .COPY_U_B, {.GPR,.MSA_VEC,.IMM5,.NONE}, {.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}, 0x78C00019, 0xFFF0003F, .MSA, {} },
{ .INSERT_B, {.MSA_VEC,.GPR,.IMM5,.NONE}, {.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}, 0x79000019, 0xFFF0003F, .MSA, {} },
{ .INSVE_B, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x79400019, 0xFFF0003F, .MSA, {} },
{ .SLDI_B, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78000019, 0xFFF0003F, .MSA, {} },
{ .SPLATI_B, {.MSA_VEC,.MSA_VEC,.IMM5,.NONE}, {.WD,.WS,.MSA_ELM_IDX,.NONE}, 0x78400019, 0xFFF0003F, .MSA, {} },
@@ -745,11 +763,17 @@ DECODE_ENTRIES := [931]lib.Decode_Entry{
{ .PRECEQ_W_PHR, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000352, 0xFFE007FF, .DSP_R1, {} },
{ .PRECEQU_PH_QBL, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000112, 0xFFE007FF, .DSP_R1, {} },
{ .PRECEQU_PH_QBR, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000152, 0xFFE007FF, .DSP_R1, {} },
{ .PRECEQU_PH_QBLA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000192, 0xFFE007FF, .DSP_R2, {} },
{ .PRECEQU_PH_QBRA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0001D2, 0xFFE007FF, .DSP_R2, {} },
{ .PRECEU_PH_QBL, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000712, 0xFFE007FF, .DSP_R1, {} },
{ .PRECEU_PH_QBR, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000752, 0xFFE007FF, .DSP_R1, {} },
{ .PRECEU_PH_QBLA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000792, 0xFFE007FF, .DSP_R2, {} },
{ .PRECEU_PH_QBRA, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0007D2, 0xFFE007FF, .DSP_R2, {} },
{ .BITREV, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0006D2, 0xFFE007FF, .DSP_R2, {} },
{ .ABSQ_S_PH, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000252, 0xFFE007FF, .DSP_R1, {} },
{ .ABSQ_S_W, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C000452, 0xFFE007FF, .DSP_R1, {} },
{ .REPLV_PH, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0002D2, 0xFFE007FF, .DSP_R2, {} },
{ .REPLV_QB, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RT,.NONE,.NONE}, 0x7C0000D2, 0xFFE007FF, .DSP_R2, {} },
{ .SHLL_QB, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RT,.IMM_5,.NONE}, 0x7C000013, 0xFFE0073F, .DSP_R1, {} },
{ .SHLL_PH, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RT,.IMM_5,.NONE}, 0x7C000213, 0xFFE0073F, .DSP_R1, {} },
{ .SHLL_S_PH, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RT,.IMM_5,.NONE}, 0x7C000313, 0xFFE0073F, .DSP_R1, {} },
@@ -795,6 +819,7 @@ DECODE_ENTRIES := [931]lib.Decode_Entry{
{ .EXTR_RS_W, {.GPR,.IMM5,.IMM5,.NONE}, {.RT,.RS,.RD,.NONE}, 0x7C0001B8, 0xFC00073F, .DSP_R1, {} },
{ .EXTR_S_H, {.GPR,.IMM5,.IMM5,.NONE}, {.RT,.RS,.RD,.NONE}, 0x7C0003B8, 0xFC00073F, .DSP_R1, {} },
{ .EXTP, {.GPR,.IMM5,.IMM5,.NONE}, {.RT,.RS,.RD,.NONE}, 0x7C0000B8, 0xFC00073F, .DSP_R1, {} },
{ .RDHWR, {.GPR,.GPR,.NONE,.NONE}, {.RT,.RD,.NONE,.NONE}, 0x7C00003B, 0xFFE007FF, .MIPS32_R2, {} },
{ .LB, {.GPR,.MEM,.NONE,.NONE}, {.RT,.OFFSET_BASE,.NONE,.NONE}, 0x80000000, 0xFC000000, .MIPS_I, {} },
{ .LH, {.GPR,.MEM,.NONE,.NONE}, {.RT,.OFFSET_BASE,.NONE,.NONE}, 0x84000000, 0xFC000000, .MIPS_I, {} },
{ .LWL, {.GPR,.MEM,.NONE,.NONE}, {.RT,.OFFSET_BASE,.NONE,.NONE}, 0x88000000, 0xFC000000, .MIPS_I, {} },
@@ -960,54 +985,54 @@ DECODE_INDEX_PRIMARY := [64]lib.Decode_Index{
0x0D = { 115, 1},
0x0E = { 116, 1},
0x0F = { 117, 2},
0x10 = { 119, 13},
0x11 = { 132, 125},
0x12 = { 257, 36},
0x13 = { 293, 5},
0x14 = { 298, 1},
0x15 = { 299, 1},
0x16 = { 300, 1},
0x17 = { 301, 1},
0x18 = { 302, 13},
0x19 = { 315, 15},
0x1A = { 330, 1},
0x1B = { 331, 13},
0x1C = { 344, 109},
0x1D = { 453, 1},
0x1E = { 454, 220},
0x1F = { 674, 112},
0x20 = { 786, 1},
0x21 = { 787, 1},
0x22 = { 788, 1},
0x23 = { 789, 1},
0x24 = { 790, 1},
0x25 = { 791, 1},
0x26 = { 792, 1},
0x27 = { 793, 1},
0x28 = { 794, 1},
0x29 = { 795, 1},
0x2A = { 796, 1},
0x2B = { 797, 1},
0x2C = { 798, 1},
0x2D = { 799, 1},
0x2E = { 800, 1},
0x2F = { 801, 1},
0x30 = { 802, 1},
0x31 = { 803, 1},
0x32 = { 804, 3},
0x33 = { 807, 1},
0x34 = { 808, 63},
0x35 = { 871, 3},
0x36 = { 874, 5},
0x37 = { 879, 6},
0x38 = { 885, 1},
0x39 = { 886, 1},
0x3A = { 887, 3},
0x3B = { 890, 2},
0x3C = { 892, 27},
0x3D = { 919, 3},
0x3E = { 922, 5},
0x3F = { 927, 4},
0x10 = { 119, 15},
0x11 = { 134, 125},
0x12 = { 259, 36},
0x13 = { 295, 13},
0x14 = { 308, 1},
0x15 = { 309, 1},
0x16 = { 310, 1},
0x17 = { 311, 1},
0x18 = { 312, 13},
0x19 = { 325, 15},
0x1A = { 340, 1},
0x1B = { 341, 13},
0x1C = { 354, 109},
0x1D = { 463, 1},
0x1E = { 464, 228},
0x1F = { 692, 119},
0x20 = { 811, 1},
0x21 = { 812, 1},
0x22 = { 813, 1},
0x23 = { 814, 1},
0x24 = { 815, 1},
0x25 = { 816, 1},
0x26 = { 817, 1},
0x27 = { 818, 1},
0x28 = { 819, 1},
0x29 = { 820, 1},
0x2A = { 821, 1},
0x2B = { 822, 1},
0x2C = { 823, 1},
0x2D = { 824, 1},
0x2E = { 825, 1},
0x2F = { 826, 1},
0x30 = { 827, 1},
0x31 = { 828, 1},
0x32 = { 829, 3},
0x33 = { 832, 1},
0x34 = { 833, 63},
0x35 = { 896, 3},
0x36 = { 899, 5},
0x37 = { 904, 6},
0x38 = { 910, 1},
0x39 = { 911, 1},
0x3A = { 912, 3},
0x3B = { 915, 2},
0x3C = { 917, 27},
0x3D = { 944, 3},
0x3E = { 947, 5},
0x3F = { 952, 4},
}
@(rodata)
@@ -1101,77 +1126,78 @@ DECODE_INDEX_REGIMM := [32]lib.Decode_Index{
@(rodata)
DECODE_INDEX_COP1 := [32]lib.Decode_Index{
0x00 = { 132, 1},
0x01 = { 133, 1},
0x02 = { 134, 1},
0x03 = { 135, 1},
0x04 = { 136, 1},
0x05 = { 137, 1},
0x06 = { 138, 1},
0x07 = { 139, 1},
0x08 = { 140, 4},
0x09 = { 144, 1},
0x0D = { 145, 1},
0x10 = { 146, 41},
0x11 = { 187, 42},
0x14 = { 229, 4},
0x15 = { 233, 2},
0x16 = { 235, 22},
0x00 = { 134, 1},
0x01 = { 135, 1},
0x02 = { 136, 1},
0x03 = { 137, 1},
0x04 = { 138, 1},
0x05 = { 139, 1},
0x06 = { 140, 1},
0x07 = { 141, 1},
0x08 = { 142, 4},
0x09 = { 146, 1},
0x0D = { 147, 1},
0x10 = { 148, 41},
0x11 = { 189, 42},
0x14 = { 231, 4},
0x15 = { 235, 2},
0x16 = { 237, 22},
}
@(rodata)
DECODE_INDEX_SPECIAL2 := [64]lib.Decode_Index{
0x00 = { 344, 1},
0x01 = { 345, 1},
0x02 = { 346, 1},
0x04 = { 347, 2},
0x05 = { 349, 1},
0x08 = { 350, 25},
0x09 = { 375, 26},
0x10 = { 401, 1},
0x11 = { 402, 1},
0x12 = { 403, 1},
0x13 = { 404, 1},
0x18 = { 405, 1},
0x19 = { 406, 1},
0x1A = { 407, 1},
0x1B = { 408, 1},
0x20 = { 409, 2},
0x21 = { 411, 2},
0x24 = { 413, 1},
0x25 = { 414, 1},
0x28 = { 415, 17},
0x29 = { 432, 8},
0x30 = { 440, 5},
0x31 = { 445, 1},
0x34 = { 446, 1},
0x36 = { 447, 1},
0x37 = { 448, 1},
0x3C = { 449, 1},
0x3E = { 450, 1},
0x3F = { 451, 2},
0x00 = { 354, 1},
0x01 = { 355, 1},
0x02 = { 356, 1},
0x04 = { 357, 2},
0x05 = { 359, 1},
0x08 = { 360, 25},
0x09 = { 385, 26},
0x10 = { 411, 1},
0x11 = { 412, 1},
0x12 = { 413, 1},
0x13 = { 414, 1},
0x18 = { 415, 1},
0x19 = { 416, 1},
0x1A = { 417, 1},
0x1B = { 418, 1},
0x20 = { 419, 2},
0x21 = { 421, 2},
0x24 = { 423, 1},
0x25 = { 424, 1},
0x28 = { 425, 17},
0x29 = { 442, 8},
0x30 = { 450, 5},
0x31 = { 455, 1},
0x34 = { 456, 1},
0x36 = { 457, 1},
0x37 = { 458, 1},
0x3C = { 459, 1},
0x3E = { 460, 1},
0x3F = { 461, 2},
}
@(rodata)
DECODE_INDEX_SPECIAL3 := [64]lib.Decode_Index{
0x00 = { 674, 2},
0x01 = { 676, 1},
0x02 = { 677, 1},
0x03 = { 678, 1},
0x04 = { 679, 1},
0x05 = { 680, 1},
0x06 = { 681, 1},
0x07 = { 682, 1},
0x0A = { 683, 3},
0x0C = { 686, 1},
0x0F = { 687, 8},
0x10 = { 695, 22},
0x11 = { 717, 15},
0x12 = { 732, 9},
0x13 = { 741, 18},
0x20 = { 759, 5},
0x24 = { 764, 4},
0x30 = { 768, 9},
0x38 = { 777, 9},
0x00 = { 692, 2},
0x01 = { 694, 1},
0x02 = { 695, 1},
0x03 = { 696, 1},
0x04 = { 697, 1},
0x05 = { 698, 1},
0x06 = { 699, 1},
0x07 = { 700, 1},
0x0A = { 701, 3},
0x0C = { 704, 1},
0x0F = { 705, 8},
0x10 = { 713, 22},
0x11 = { 735, 15},
0x12 = { 750, 15},
0x13 = { 765, 18},
0x20 = { 783, 5},
0x24 = { 788, 4},
0x30 = { 792, 9},
0x38 = { 801, 9},
0x3B = { 810, 1},
}

File diff suppressed because it is too large Load Diff

View File

@@ -219,6 +219,52 @@ for _, b in ipairs({{"FCVT_D_W","cvt.d.w","FPR_D","FPR_W"},{"FCVT_S_D","cvt.s.d"
if r then sections[#sections+1]=r end
end
-- ---- DSP ASE two-register (Rd, Rt) ----------------------------------------
for _, b in ipairs({
{"PRECEQU_PH_QBLA","precequ.ph.qbla"},{"PRECEQU_PH_QBRA","precequ.ph.qbra"},
{"PRECEU_PH_QBLA","preceu.ph.qbla"},{"PRECEU_PH_QBRA","preceu.ph.qbra"},
{"REPLV_PH","replv.ph"},{"REPLV_QB","replv.qb"},
}) do
local r = entry(b[1], "{.GPR,.GPR,.NONE,.NONE}", "{.RD,.RT,.NONE,.NONE}", "DSP_R2",
function(v) return string.format("%s $%d,$%d", b[2], v[1], v[2]) end, {31,31})
if r then sections[#sections+1]=r end
end
-- ---- FPU fused multiply-add (COP1X 4-register: fd, fr, fs, ft) -------------
for _, b in ipairs({{"MADD","madd"},{"MSUB","msub"},{"NMADD","nmadd"},{"NMSUB","nmsub"}}) do
for _, f in ipairs({{"S","s","FPR_S"},{"D","d","FPR_D"}}) do
local r = entry(b[1].."_"..f[1], "{."..f[3]..",."..f[3]..",."..f[3]..",."..f[3].."}", "{.FD,.FR,.FS,.FT}", "FPU",
function(v) return string.format("%s.%s $f%d,$f%d,$f%d,$f%d", b[2], f[2], v[1], v[2], v[3], v[4]) end, {31,31,31,31})
if r then sections[#sections+1]=r end
end
end
-- ---- MSA COPY (vector lane -> GPR) and INSERT (GPR -> vector lane) ----------
for _, b in ipairs({{"COPY_S","copy_s"},{"COPY_U","copy_u"}}) do
for _, d in ipairs({{"B","b",15},{"H","h",7},{"W","w",3}}) do
local r = entry(b[1].."_"..d[1], "{.GPR,.MSA_VEC,.IMM5,.NONE}", "{.GPR_AT_6,.WS,.MSA_ELM_IDX,.NONE}", "MSA",
function(v) return string.format("%s.%s $%d,$w%d[%d]", b[2], d[2], v[1], v[2], v[3]) end, {31,31,d[3]})
if r then sections[#sections+1]=r end
end
end
for _, d in ipairs({{"B","b",15},{"H","h",7},{"W","w",3}}) do
local r = entry("INSERT_"..d[1], "{.MSA_VEC,.GPR,.IMM5,.NONE}", "{.WD,.GPR_AT_11,.MSA_ELM_IDX,.NONE}", "MSA",
function(v) return string.format("insert.%s $w%d[%d],$%d", d[2], v[1], v[3], v[2]) end, {31,31,d[3]})
if r then sections[#sections+1]=r end
end
-- ---- Misc control: DI/EI (rt), RDHWR (rt, rd) ------------------------------
for _, b in ipairs({{"DI","di"},{"EI","ei"}}) do
local r = entry(b[1], "{.GPR,.NONE,.NONE,.NONE}", "{.RT,.NONE,.NONE,.NONE}", "MIPS32_R2",
function(v) return string.format("%s $%d", b[2], v[1]) end, {31})
if r then sections[#sections+1]=r end
end
do
local r = entry("RDHWR", "{.GPR,.GPR,.NONE,.NONE}", "{.RT,.RD,.NONE,.NONE}", "MIPS32_R2",
function(v) return string.format("rdhwr $%d,$%d", v[1], v[2]) end, {31,31})
if r then sections[#sections+1]=r end
end
-- ---- splice into the SoT ---------------------------------------------------
local region = " // SPECGEN:BEGIN\n" .. table.concat(sections, "\n") .. "\n // SPECGEN:END"
local fh = assert(io.open(TABLE, "r")); local src = fh:read("*a"); fh:close()