^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * A small micro-assembler. It is intentionally kept simple, does only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * support a subset of instructions, and does not try to hide pipeline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * effects like branch delay slots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2005, 2007 Maciej W. Rozycki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/bugs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/uasm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define RS_MASK 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define RS_SH 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define RT_MASK 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define RT_SH 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SCIMM_MASK 0xfffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SCIMM_SH 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* This macro sets the non-variable bits of an instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define M(a, b, c, d, e, f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ((a) << OP_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) | (b) << RS_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) | (c) << RT_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) | (d) << RD_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) | (e) << RE_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) | (f) << FUNC_SH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* This macro sets the non-variable bits of an R6 instruction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define M6(a, b, c, d, e) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ((a) << OP_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) | (b) << RS_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) | (c) << RT_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) | (d) << SIMM9_SH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) | (e) << FUNC_SH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "uasm.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static const struct insn insn_table[insn_invalid] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) [insn_addiu] = {M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) [insn_addu] = {M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [insn_and] = {M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [insn_andi] = {M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [insn_bbit0] = {M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) [insn_bbit1] = {M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) [insn_beq] = {M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) [insn_beql] = {M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) [insn_bgez] = {M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) [insn_bgezl] = {M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [insn_bgtz] = {M(bgtz_op, 0, 0, 0, 0, 0), RS | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) [insn_blez] = {M(blez_op, 0, 0, 0, 0, 0), RS | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) [insn_bltz] = {M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) [insn_bltzl] = {M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) [insn_bne] = {M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) [insn_break] = {M(spec_op, 0, 0, 0, 0, break_op), SCIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) [insn_cache] = {M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) [insn_cache] = {M6(spec3_op, 0, 0, 0, cache6_op), RS | RT | SIMM9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) [insn_cfc1] = {M(cop1_op, cfc_op, 0, 0, 0, 0), RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) [insn_cfcmsa] = {M(msa_op, 0, msa_cfc_op, 0, 0, msa_elm_op), RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) [insn_ctc1] = {M(cop1_op, ctc_op, 0, 0, 0, 0), RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) [insn_ctcmsa] = {M(msa_op, 0, msa_ctc_op, 0, 0, msa_elm_op), RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) [insn_daddiu] = {M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) [insn_daddu] = {M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) [insn_ddivu] = {M(spec_op, 0, 0, 0, 0, ddivu_op), RS | RT},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) [insn_ddivu_r6] = {M(spec_op, 0, 0, 0, ddivu_ddivu6_op, ddivu_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) [insn_di] = {M(cop0_op, mfmc0_op, 0, 12, 0, 0), RT},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) [insn_dins] = {M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) [insn_dinsm] = {M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) [insn_dinsu] = {M(spec3_op, 0, 0, 0, 0, dinsu_op), RS | RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) [insn_divu] = {M(spec_op, 0, 0, 0, 0, divu_op), RS | RT},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) [insn_divu_r6] = {M(spec_op, 0, 0, 0, divu_divu6_op, divu_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) [insn_dmfc0] = {M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) [insn_dmodu] = {M(spec_op, 0, 0, 0, ddivu_dmodu_op, ddivu_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) [insn_dmtc0] = {M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) [insn_dmultu] = {M(spec_op, 0, 0, 0, 0, dmultu_op), RS | RT},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) [insn_dmulu] = {M(spec_op, 0, 0, 0, dmult_dmul_op, dmultu_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) [insn_drotr] = {M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) [insn_drotr32] = {M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) [insn_dsbh] = {M(spec3_op, 0, 0, 0, dsbh_op, dbshfl_op), RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) [insn_dshd] = {M(spec3_op, 0, 0, 0, dshd_op, dbshfl_op), RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) [insn_dsll] = {M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) [insn_dsll32] = {M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) [insn_dsllv] = {M(spec_op, 0, 0, 0, 0, dsllv_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) [insn_dsra] = {M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) [insn_dsra32] = {M(spec_op, 0, 0, 0, 0, dsra32_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) [insn_dsrav] = {M(spec_op, 0, 0, 0, 0, dsrav_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) [insn_dsrl] = {M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) [insn_dsrl32] = {M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) [insn_dsrlv] = {M(spec_op, 0, 0, 0, 0, dsrlv_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) [insn_dsubu] = {M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) [insn_eret] = {M(cop0_op, cop_op, 0, 0, 0, eret_op), 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) [insn_ext] = {M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) [insn_ins] = {M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) [insn_j] = {M(j_op, 0, 0, 0, 0, 0), JIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) [insn_jal] = {M(jal_op, 0, 0, 0, 0, 0), JIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) [insn_jalr] = {M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) [insn_jr] = {M(spec_op, 0, 0, 0, 0, jr_op), RS},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) [insn_jr] = {M(spec_op, 0, 0, 0, 0, jalr_op), RS},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) [insn_lb] = {M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) [insn_lbu] = {M(lbu_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) [insn_ld] = {M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) [insn_lddir] = {M(lwc2_op, 0, 0, 0, lddir_op, mult_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) [insn_ldpte] = {M(lwc2_op, 0, 0, 0, ldpte_op, mult_op), RS | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) [insn_ldx] = {M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) [insn_lh] = {M(lh_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) [insn_lhu] = {M(lhu_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) [insn_ll] = {M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) [insn_lld] = {M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) [insn_ll] = {M6(spec3_op, 0, 0, 0, ll6_op), RS | RT | SIMM9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) [insn_lld] = {M6(spec3_op, 0, 0, 0, lld6_op), RS | RT | SIMM9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) [insn_lui] = {M(lui_op, 0, 0, 0, 0, 0), RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) [insn_lw] = {M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) [insn_lwu] = {M(lwu_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) [insn_lwx] = {M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) [insn_mfc0] = {M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) [insn_mfhc0] = {M(cop0_op, mfhc0_op, 0, 0, 0, 0), RT | RD | SET},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) [insn_mfhi] = {M(spec_op, 0, 0, 0, 0, mfhi_op), RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) [insn_mflo] = {M(spec_op, 0, 0, 0, 0, mflo_op), RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) [insn_modu] = {M(spec_op, 0, 0, 0, divu_modu_op, divu_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) [insn_movn] = {M(spec_op, 0, 0, 0, 0, movn_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) [insn_movz] = {M(spec_op, 0, 0, 0, 0, movz_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) [insn_mtc0] = {M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) [insn_mthc0] = {M(cop0_op, mthc0_op, 0, 0, 0, 0), RT | RD | SET},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) [insn_mthi] = {M(spec_op, 0, 0, 0, 0, mthi_op), RS},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) [insn_mtlo] = {M(spec_op, 0, 0, 0, 0, mtlo_op), RS},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) [insn_mulu] = {M(spec_op, 0, 0, 0, multu_mulu_op, multu_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) [insn_mul] = {M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) [insn_mul] = {M(spec_op, 0, 0, 0, mult_mul_op, mult_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) [insn_multu] = {M(spec_op, 0, 0, 0, 0, multu_op), RS | RT},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) [insn_nor] = {M(spec_op, 0, 0, 0, 0, nor_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) [insn_or] = {M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) [insn_ori] = {M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) [insn_pref] = {M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) [insn_pref] = {M6(spec3_op, 0, 0, 0, pref6_op), RS | RT | SIMM9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) [insn_rfe] = {M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) [insn_rotr] = {M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) [insn_sb] = {M(sb_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #ifndef CONFIG_CPU_MIPSR6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) [insn_sc] = {M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) [insn_scd] = {M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) [insn_sc] = {M6(spec3_op, 0, 0, 0, sc6_op), RS | RT | SIMM9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) [insn_scd] = {M6(spec3_op, 0, 0, 0, scd6_op), RS | RT | SIMM9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) [insn_sd] = {M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) [insn_seleqz] = {M(spec_op, 0, 0, 0, 0, seleqz_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) [insn_selnez] = {M(spec_op, 0, 0, 0, 0, selnez_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) [insn_sh] = {M(sh_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) [insn_sll] = {M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) [insn_sllv] = {M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) [insn_slt] = {M(spec_op, 0, 0, 0, 0, slt_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) [insn_slti] = {M(slti_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) [insn_sltiu] = {M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) [insn_sltu] = {M(spec_op, 0, 0, 0, 0, sltu_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) [insn_sra] = {M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) [insn_srav] = {M(spec_op, 0, 0, 0, 0, srav_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) [insn_srl] = {M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) [insn_srlv] = {M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) [insn_subu] = {M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) [insn_sw] = {M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) [insn_sync] = {M(spec_op, 0, 0, 0, 0, sync_op), RE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) [insn_syscall] = {M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) [insn_tlbp] = {M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) [insn_tlbr] = {M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) [insn_tlbwi] = {M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) [insn_tlbwr] = {M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) [insn_wait] = {M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) [insn_wsbh] = {M(spec3_op, 0, 0, 0, wsbh_op, bshfl_op), RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) [insn_xor] = {M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) [insn_xori] = {M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) [insn_yield] = {M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #undef M
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static inline u32 build_bimm(s32 arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) WARN(arg > 0x1ffff || arg < -0x20000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) KERN_WARNING "Micro-assembler field overflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static inline u32 build_jimm(u32 arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) WARN(arg & ~(JIMM_MASK << 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) KERN_WARNING "Micro-assembler field overflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return (arg >> 2) & JIMM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * The order of opcode arguments is implicitly left to right,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * starting with RS and ending with FUNC or IMM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static void build_insn(u32 **buf, enum opcode opc, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) const struct insn *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u32 op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (opc < 0 || opc >= insn_invalid ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) (opc == insn_daddiu && r4k_daddiu_bug()) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) (insn_table[opc].match == 0 && insn_table[opc].fields == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) panic("Unsupported Micro-assembler instruction %d", opc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ip = &insn_table[opc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) op = ip->match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) va_start(ap, opc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (ip->fields & RS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) op |= build_rs(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (ip->fields & RT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) op |= build_rt(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (ip->fields & RD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) op |= build_rd(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (ip->fields & RE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) op |= build_re(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (ip->fields & SIMM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) op |= build_simm(va_arg(ap, s32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (ip->fields & UIMM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) op |= build_uimm(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (ip->fields & BIMM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) op |= build_bimm(va_arg(ap, s32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (ip->fields & JIMM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) op |= build_jimm(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (ip->fields & FUNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) op |= build_func(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (ip->fields & SET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) op |= build_set(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (ip->fields & SCIMM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) op |= build_scimm(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ip->fields & SIMM9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) op |= build_scimm9(va_arg(ap, u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) **buf = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) (*buf)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) long laddr = (long)lab->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) long raddr = (long)rel->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) switch (rel->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) case R_MIPS_PC16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *rel->addr |= build_bimm(laddr - (raddr + 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) panic("Unsupported Micro-assembler relocation %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) rel->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }