1e30ec452SThiemo Seufer /* 2e30ec452SThiemo Seufer * This file is subject to the terms and conditions of the GNU General Public 3e30ec452SThiemo Seufer * License. See the file "COPYING" in the main directory of this archive 4e30ec452SThiemo Seufer * for more details. 5e30ec452SThiemo Seufer * 6e30ec452SThiemo Seufer * A small micro-assembler. It is intentionally kept simple, does only 7e30ec452SThiemo Seufer * support a subset of instructions, and does not try to hide pipeline 8e30ec452SThiemo Seufer * effects like branch delay slots. 9e30ec452SThiemo Seufer * 10e30ec452SThiemo Seufer * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer 11e30ec452SThiemo Seufer * Copyright (C) 2005, 2007 Maciej W. Rozycki 12e30ec452SThiemo Seufer * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) 13abc597feSSteven J. Hill * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved. 14e30ec452SThiemo Seufer */ 15e30ec452SThiemo Seufer 16e30ec452SThiemo Seufer enum fields { 17e30ec452SThiemo Seufer RS = 0x001, 18e30ec452SThiemo Seufer RT = 0x002, 19e30ec452SThiemo Seufer RD = 0x004, 20e30ec452SThiemo Seufer RE = 0x008, 21e30ec452SThiemo Seufer SIMM = 0x010, 22e30ec452SThiemo Seufer UIMM = 0x020, 23e30ec452SThiemo Seufer BIMM = 0x040, 24e30ec452SThiemo Seufer JIMM = 0x080, 25e30ec452SThiemo Seufer FUNC = 0x100, 2658b9e223SDavid Daney SET = 0x200, 2758b9e223SDavid Daney SCIMM = 0x400 28e30ec452SThiemo Seufer }; 29e30ec452SThiemo Seufer 30e30ec452SThiemo Seufer #define OP_MASK 0x3f 31e30ec452SThiemo Seufer #define OP_SH 26 32e30ec452SThiemo Seufer #define RD_MASK 0x1f 33e30ec452SThiemo Seufer #define RD_SH 11 34e30ec452SThiemo Seufer #define RE_MASK 0x1f 35e30ec452SThiemo Seufer #define RE_SH 6 36e30ec452SThiemo Seufer #define IMM_MASK 0xffff 37e30ec452SThiemo Seufer #define IMM_SH 0 38e30ec452SThiemo Seufer #define JIMM_MASK 0x3ffffff 39e30ec452SThiemo Seufer #define JIMM_SH 0 40e30ec452SThiemo Seufer #define FUNC_MASK 0x3f 41e30ec452SThiemo Seufer #define FUNC_SH 0 42e30ec452SThiemo Seufer #define SET_MASK 0x7 43e30ec452SThiemo Seufer #define SET_SH 0 44e30ec452SThiemo Seufer 45e30ec452SThiemo Seufer enum opcode { 46e30ec452SThiemo Seufer insn_invalid, 4771a1c776SSteven J. Hill insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1, 4871a1c776SSteven J. Hill insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, 4971a1c776SSteven J. Hill insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, 504c12a854SMarkos Chandras insn_divu, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, 5171a1c776SSteven J. Hill insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, 5249e9529bSPaul Burton insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, 5349e9529bSPaul Burton insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, 54f3ec7a23SMarkos Chandras insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, 55390363edSMarkos Chandras insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sltiu, 56e8ef868bSMarkos Chandras insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, 57390363edSMarkos Chandras insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, 58390363edSMarkos Chandras insn_xor, insn_xori, insn_yield, 59e30ec452SThiemo Seufer }; 60e30ec452SThiemo Seufer 61e30ec452SThiemo Seufer struct insn { 62e30ec452SThiemo Seufer enum opcode opcode; 63e30ec452SThiemo Seufer u32 match; 64e30ec452SThiemo Seufer enum fields fields; 65e30ec452SThiemo Seufer }; 66e30ec452SThiemo Seufer 67078a55fcSPaul Gortmaker static inline u32 build_rs(u32 arg) 68e30ec452SThiemo Seufer { 698d662c8dSDavid Daney WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 70e30ec452SThiemo Seufer 71e30ec452SThiemo Seufer return (arg & RS_MASK) << RS_SH; 72e30ec452SThiemo Seufer } 73e30ec452SThiemo Seufer 74078a55fcSPaul Gortmaker static inline u32 build_rt(u32 arg) 75e30ec452SThiemo Seufer { 768d662c8dSDavid Daney WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 77e30ec452SThiemo Seufer 78e30ec452SThiemo Seufer return (arg & RT_MASK) << RT_SH; 79e30ec452SThiemo Seufer } 80e30ec452SThiemo Seufer 81078a55fcSPaul Gortmaker static inline u32 build_rd(u32 arg) 82e30ec452SThiemo Seufer { 838d662c8dSDavid Daney WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 84e30ec452SThiemo Seufer 85e30ec452SThiemo Seufer return (arg & RD_MASK) << RD_SH; 86e30ec452SThiemo Seufer } 87e30ec452SThiemo Seufer 88078a55fcSPaul Gortmaker static inline u32 build_re(u32 arg) 89e30ec452SThiemo Seufer { 908d662c8dSDavid Daney WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 91e30ec452SThiemo Seufer 92e30ec452SThiemo Seufer return (arg & RE_MASK) << RE_SH; 93e30ec452SThiemo Seufer } 94e30ec452SThiemo Seufer 95078a55fcSPaul Gortmaker static inline u32 build_simm(s32 arg) 96e30ec452SThiemo Seufer { 978d662c8dSDavid Daney WARN(arg > 0x7fff || arg < -0x8000, 988d662c8dSDavid Daney KERN_WARNING "Micro-assembler field overflow\n"); 99e30ec452SThiemo Seufer 100e30ec452SThiemo Seufer return arg & 0xffff; 101e30ec452SThiemo Seufer } 102e30ec452SThiemo Seufer 103078a55fcSPaul Gortmaker static inline u32 build_uimm(u32 arg) 104e30ec452SThiemo Seufer { 1058d662c8dSDavid Daney WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 106e30ec452SThiemo Seufer 107e30ec452SThiemo Seufer return arg & IMM_MASK; 108e30ec452SThiemo Seufer } 109e30ec452SThiemo Seufer 110078a55fcSPaul Gortmaker static inline u32 build_scimm(u32 arg) 11158b9e223SDavid Daney { 1128d662c8dSDavid Daney WARN(arg & ~SCIMM_MASK, 1138d662c8dSDavid Daney KERN_WARNING "Micro-assembler field overflow\n"); 11458b9e223SDavid Daney 11558b9e223SDavid Daney return (arg & SCIMM_MASK) << SCIMM_SH; 11658b9e223SDavid Daney } 11758b9e223SDavid Daney 118078a55fcSPaul Gortmaker static inline u32 build_func(u32 arg) 119e30ec452SThiemo Seufer { 1208d662c8dSDavid Daney WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 121e30ec452SThiemo Seufer 122e30ec452SThiemo Seufer return arg & FUNC_MASK; 123e30ec452SThiemo Seufer } 124e30ec452SThiemo Seufer 125078a55fcSPaul Gortmaker static inline u32 build_set(u32 arg) 126e30ec452SThiemo Seufer { 1278d662c8dSDavid Daney WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 128e30ec452SThiemo Seufer 129e30ec452SThiemo Seufer return arg & SET_MASK; 130e30ec452SThiemo Seufer } 131e30ec452SThiemo Seufer 132078a55fcSPaul Gortmaker static void build_insn(u32 **buf, enum opcode opc, ...); 133e30ec452SThiemo Seufer 134e30ec452SThiemo Seufer #define I_u1u2u3(op) \ 135e30ec452SThiemo Seufer Ip_u1u2u3(op) \ 136e30ec452SThiemo Seufer { \ 137e30ec452SThiemo Seufer build_insn(buf, insn##op, a, b, c); \ 13822b0763aSDavid Daney } \ 13922b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 140e30ec452SThiemo Seufer 141e30ec452SThiemo Seufer #define I_u2u1u3(op) \ 142e30ec452SThiemo Seufer Ip_u2u1u3(op) \ 143e30ec452SThiemo Seufer { \ 144e30ec452SThiemo Seufer build_insn(buf, insn##op, b, a, c); \ 14522b0763aSDavid Daney } \ 14622b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 147e30ec452SThiemo Seufer 148beef8e02SMarkos Chandras #define I_u3u2u1(op) \ 149beef8e02SMarkos Chandras Ip_u3u2u1(op) \ 150beef8e02SMarkos Chandras { \ 151beef8e02SMarkos Chandras build_insn(buf, insn##op, c, b, a); \ 152beef8e02SMarkos Chandras } \ 153beef8e02SMarkos Chandras UASM_EXPORT_SYMBOL(uasm_i##op); 154beef8e02SMarkos Chandras 155e30ec452SThiemo Seufer #define I_u3u1u2(op) \ 156e30ec452SThiemo Seufer Ip_u3u1u2(op) \ 157e30ec452SThiemo Seufer { \ 158e30ec452SThiemo Seufer build_insn(buf, insn##op, b, c, a); \ 15922b0763aSDavid Daney } \ 16022b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 161e30ec452SThiemo Seufer 162e30ec452SThiemo Seufer #define I_u1u2s3(op) \ 163e30ec452SThiemo Seufer Ip_u1u2s3(op) \ 164e30ec452SThiemo Seufer { \ 165e30ec452SThiemo Seufer build_insn(buf, insn##op, a, b, c); \ 16622b0763aSDavid Daney } \ 16722b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 168e30ec452SThiemo Seufer 169e30ec452SThiemo Seufer #define I_u2s3u1(op) \ 170e30ec452SThiemo Seufer Ip_u2s3u1(op) \ 171e30ec452SThiemo Seufer { \ 172e30ec452SThiemo Seufer build_insn(buf, insn##op, c, a, b); \ 17322b0763aSDavid Daney } \ 17422b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 175e30ec452SThiemo Seufer 176e30ec452SThiemo Seufer #define I_u2u1s3(op) \ 177e30ec452SThiemo Seufer Ip_u2u1s3(op) \ 178e30ec452SThiemo Seufer { \ 179e30ec452SThiemo Seufer build_insn(buf, insn##op, b, a, c); \ 18022b0763aSDavid Daney } \ 18122b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 182e30ec452SThiemo Seufer 18392078e06SDavid Daney #define I_u2u1msbu3(op) \ 18492078e06SDavid Daney Ip_u2u1msbu3(op) \ 18592078e06SDavid Daney { \ 18692078e06SDavid Daney build_insn(buf, insn##op, b, a, c+d-1, c); \ 18722b0763aSDavid Daney } \ 18822b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 18992078e06SDavid Daney 190c42aef09SDavid Daney #define I_u2u1msb32u3(op) \ 191c42aef09SDavid Daney Ip_u2u1msbu3(op) \ 192c42aef09SDavid Daney { \ 193c42aef09SDavid Daney build_insn(buf, insn##op, b, a, c+d-33, c); \ 194c42aef09SDavid Daney } \ 195c42aef09SDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 196c42aef09SDavid Daney 197e6de1a09SSteven J. Hill #define I_u2u1msbdu3(op) \ 198e6de1a09SSteven J. Hill Ip_u2u1msbu3(op) \ 199e6de1a09SSteven J. Hill { \ 200e6de1a09SSteven J. Hill build_insn(buf, insn##op, b, a, d-1, c); \ 201e6de1a09SSteven J. Hill } \ 202e6de1a09SSteven J. Hill UASM_EXPORT_SYMBOL(uasm_i##op); 203e6de1a09SSteven J. Hill 204e30ec452SThiemo Seufer #define I_u1u2(op) \ 205e30ec452SThiemo Seufer Ip_u1u2(op) \ 206e30ec452SThiemo Seufer { \ 207e30ec452SThiemo Seufer build_insn(buf, insn##op, a, b); \ 20822b0763aSDavid Daney } \ 20922b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 210e30ec452SThiemo Seufer 211d674dd14SPaul Burton #define I_u2u1(op) \ 212d674dd14SPaul Burton Ip_u1u2(op) \ 213d674dd14SPaul Burton { \ 214d674dd14SPaul Burton build_insn(buf, insn##op, b, a); \ 215d674dd14SPaul Burton } \ 216d674dd14SPaul Burton UASM_EXPORT_SYMBOL(uasm_i##op); 217d674dd14SPaul Burton 218e30ec452SThiemo Seufer #define I_u1s2(op) \ 219e30ec452SThiemo Seufer Ip_u1s2(op) \ 220e30ec452SThiemo Seufer { \ 221e30ec452SThiemo Seufer build_insn(buf, insn##op, a, b); \ 22222b0763aSDavid Daney } \ 22322b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 224e30ec452SThiemo Seufer 225e30ec452SThiemo Seufer #define I_u1(op) \ 226e30ec452SThiemo Seufer Ip_u1(op) \ 227e30ec452SThiemo Seufer { \ 228e30ec452SThiemo Seufer build_insn(buf, insn##op, a); \ 22922b0763aSDavid Daney } \ 23022b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 231e30ec452SThiemo Seufer 232e30ec452SThiemo Seufer #define I_0(op) \ 233e30ec452SThiemo Seufer Ip_0(op) \ 234e30ec452SThiemo Seufer { \ 235e30ec452SThiemo Seufer build_insn(buf, insn##op); \ 23622b0763aSDavid Daney } \ 23722b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op); 238e30ec452SThiemo Seufer 239e30ec452SThiemo Seufer I_u2u1s3(_addiu) 240e30ec452SThiemo Seufer I_u3u1u2(_addu) 241e30ec452SThiemo Seufer I_u2u1u3(_andi) 242e30ec452SThiemo Seufer I_u3u1u2(_and) 243e30ec452SThiemo Seufer I_u1u2s3(_beq) 244e30ec452SThiemo Seufer I_u1u2s3(_beql) 245e30ec452SThiemo Seufer I_u1s2(_bgez) 246e30ec452SThiemo Seufer I_u1s2(_bgezl) 247e30ec452SThiemo Seufer I_u1s2(_bltz) 248e30ec452SThiemo Seufer I_u1s2(_bltzl) 249e30ec452SThiemo Seufer I_u1u2s3(_bne) 250fb2a27e7SThiemo Seufer I_u2s3u1(_cache) 251e30ec452SThiemo Seufer I_u1u2u3(_dmfc0) 252e30ec452SThiemo Seufer I_u1u2u3(_dmtc0) 253e30ec452SThiemo Seufer I_u2u1s3(_daddiu) 254e30ec452SThiemo Seufer I_u3u1u2(_daddu) 2554c12a854SMarkos Chandras I_u1u2(_divu) 256e30ec452SThiemo Seufer I_u2u1u3(_dsll) 257e30ec452SThiemo Seufer I_u2u1u3(_dsll32) 258e30ec452SThiemo Seufer I_u2u1u3(_dsra) 259e30ec452SThiemo Seufer I_u2u1u3(_dsrl) 260e30ec452SThiemo Seufer I_u2u1u3(_dsrl32) 26192078e06SDavid Daney I_u2u1u3(_drotr) 262de6d5b55SDavid Daney I_u2u1u3(_drotr32) 263e30ec452SThiemo Seufer I_u3u1u2(_dsubu) 264e30ec452SThiemo Seufer I_0(_eret) 265e6de1a09SSteven J. Hill I_u2u1msbdu3(_ext) 266e6de1a09SSteven J. Hill I_u2u1msbu3(_ins) 267e30ec452SThiemo Seufer I_u1(_j) 268e30ec452SThiemo Seufer I_u1(_jal) 26949e9529bSPaul Burton I_u2u1(_jalr) 270e30ec452SThiemo Seufer I_u1(_jr) 271e30ec452SThiemo Seufer I_u2s3u1(_ld) 272e30ec452SThiemo Seufer I_u2s3u1(_ll) 273e30ec452SThiemo Seufer I_u2s3u1(_lld) 274e30ec452SThiemo Seufer I_u1s2(_lui) 275e30ec452SThiemo Seufer I_u2s3u1(_lw) 276e30ec452SThiemo Seufer I_u1u2u3(_mfc0) 277f3ec7a23SMarkos Chandras I_u1(_mfhi) 278e30ec452SThiemo Seufer I_u1u2u3(_mtc0) 279e30ec452SThiemo Seufer I_u2u1u3(_ori) 2805808184fSRalf Baechle I_u3u1u2(_or) 281e30ec452SThiemo Seufer I_0(_rfe) 282e30ec452SThiemo Seufer I_u2s3u1(_sc) 283e30ec452SThiemo Seufer I_u2s3u1(_scd) 284e30ec452SThiemo Seufer I_u2s3u1(_sd) 285e30ec452SThiemo Seufer I_u2u1u3(_sll) 286bef581baSMarkos Chandras I_u3u2u1(_sllv) 287390363edSMarkos Chandras I_u2u1s3(_sltiu) 288e8ef868bSMarkos Chandras I_u3u1u2(_sltu) 289e30ec452SThiemo Seufer I_u2u1u3(_sra) 290e30ec452SThiemo Seufer I_u2u1u3(_srl) 291f31318fdSMarkos Chandras I_u3u2u1(_srlv) 29232546f38SDavid Daney I_u2u1u3(_rotr) 293e30ec452SThiemo Seufer I_u3u1u2(_subu) 294e30ec452SThiemo Seufer I_u2s3u1(_sw) 295729ff561SPaul Burton I_u1(_sync) 296e30ec452SThiemo Seufer I_0(_tlbp) 29732546f38SDavid Daney I_0(_tlbr) 298e30ec452SThiemo Seufer I_0(_tlbwi) 299e30ec452SThiemo Seufer I_0(_tlbwr) 30053ed1389SPaul Burton I_u1(_wait); 301e30ec452SThiemo Seufer I_u3u1u2(_xor) 302e30ec452SThiemo Seufer I_u2u1u3(_xori) 303d674dd14SPaul Burton I_u2u1(_yield) 30492078e06SDavid Daney I_u2u1msbu3(_dins); 305c42aef09SDavid Daney I_u2u1msb32u3(_dinsm); 30658b9e223SDavid Daney I_u1(_syscall); 3075b97c3f7SDavid Daney I_u1u2s3(_bbit0); 3085b97c3f7SDavid Daney I_u1u2s3(_bbit1); 309bb3d68c3SDavid Daney I_u3u1u2(_lwx) 310bb3d68c3SDavid Daney I_u3u1u2(_ldx) 311e30ec452SThiemo Seufer 312c9941158SDavid Daney #ifdef CONFIG_CPU_CAVIUM_OCTEON 313c9941158SDavid Daney #include <asm/octeon/octeon.h> 314078a55fcSPaul Gortmaker void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b, 315c9941158SDavid Daney unsigned int c) 316c9941158SDavid Daney { 317c9941158SDavid Daney if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5) 318c9941158SDavid Daney /* 319c9941158SDavid Daney * As per erratum Core-14449, replace prefetches 0-4, 320c9941158SDavid Daney * 6-24 with 'pref 28'. 321c9941158SDavid Daney */ 322c9941158SDavid Daney build_insn(buf, insn_pref, c, 28, b); 323c9941158SDavid Daney else 324c9941158SDavid Daney build_insn(buf, insn_pref, c, a, b); 325c9941158SDavid Daney } 326abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref)); 327c9941158SDavid Daney #else 328c9941158SDavid Daney I_u2s3u1(_pref) 329c9941158SDavid Daney #endif 330c9941158SDavid Daney 331e30ec452SThiemo Seufer /* Handle labels. */ 332078a55fcSPaul Gortmaker void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid) 333e30ec452SThiemo Seufer { 334e30ec452SThiemo Seufer (*lab)->addr = addr; 335e30ec452SThiemo Seufer (*lab)->lab = lid; 336e30ec452SThiemo Seufer (*lab)++; 337e30ec452SThiemo Seufer } 338abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label)); 339e30ec452SThiemo Seufer 340078a55fcSPaul Gortmaker int ISAFUNC(uasm_in_compat_space_p)(long addr) 341e30ec452SThiemo Seufer { 342e30ec452SThiemo Seufer /* Is this address in 32bit compat space? */ 343e30ec452SThiemo Seufer #ifdef CONFIG_64BIT 344e30ec452SThiemo Seufer return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L); 345e30ec452SThiemo Seufer #else 346e30ec452SThiemo Seufer return 1; 347e30ec452SThiemo Seufer #endif 348e30ec452SThiemo Seufer } 349abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p)); 350e30ec452SThiemo Seufer 351078a55fcSPaul Gortmaker static int uasm_rel_highest(long val) 352e30ec452SThiemo Seufer { 353e30ec452SThiemo Seufer #ifdef CONFIG_64BIT 354e30ec452SThiemo Seufer return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; 355e30ec452SThiemo Seufer #else 356e30ec452SThiemo Seufer return 0; 357e30ec452SThiemo Seufer #endif 358e30ec452SThiemo Seufer } 359e30ec452SThiemo Seufer 360078a55fcSPaul Gortmaker static int uasm_rel_higher(long val) 361e30ec452SThiemo Seufer { 362e30ec452SThiemo Seufer #ifdef CONFIG_64BIT 363e30ec452SThiemo Seufer return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; 364e30ec452SThiemo Seufer #else 365e30ec452SThiemo Seufer return 0; 366e30ec452SThiemo Seufer #endif 367e30ec452SThiemo Seufer } 368e30ec452SThiemo Seufer 369078a55fcSPaul Gortmaker int ISAFUNC(uasm_rel_hi)(long val) 370e30ec452SThiemo Seufer { 371e30ec452SThiemo Seufer return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; 372e30ec452SThiemo Seufer } 373abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi)); 374e30ec452SThiemo Seufer 375078a55fcSPaul Gortmaker int ISAFUNC(uasm_rel_lo)(long val) 376e30ec452SThiemo Seufer { 377e30ec452SThiemo Seufer return ((val & 0xffff) ^ 0x8000) - 0x8000; 378e30ec452SThiemo Seufer } 379abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo)); 380e30ec452SThiemo Seufer 381078a55fcSPaul Gortmaker void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr) 382e30ec452SThiemo Seufer { 383abc597feSSteven J. Hill if (!ISAFUNC(uasm_in_compat_space_p)(addr)) { 384abc597feSSteven J. Hill ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr)); 385e30ec452SThiemo Seufer if (uasm_rel_higher(addr)) 386abc597feSSteven J. Hill ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr)); 387abc597feSSteven J. Hill if (ISAFUNC(uasm_rel_hi(addr))) { 388abc597feSSteven J. Hill ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16); 389abc597feSSteven J. Hill ISAFUNC(uasm_i_daddiu)(buf, rs, rs, 390abc597feSSteven J. Hill ISAFUNC(uasm_rel_hi)(addr)); 391abc597feSSteven J. Hill ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16); 392e30ec452SThiemo Seufer } else 393abc597feSSteven J. Hill ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0); 394e30ec452SThiemo Seufer } else 395abc597feSSteven J. Hill ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr))); 396e30ec452SThiemo Seufer } 397abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly)); 398e30ec452SThiemo Seufer 399078a55fcSPaul Gortmaker void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr) 400e30ec452SThiemo Seufer { 401abc597feSSteven J. Hill ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr); 402abc597feSSteven J. Hill if (ISAFUNC(uasm_rel_lo(addr))) { 403abc597feSSteven J. Hill if (!ISAFUNC(uasm_in_compat_space_p)(addr)) 404abc597feSSteven J. Hill ISAFUNC(uasm_i_daddiu)(buf, rs, rs, 405abc597feSSteven J. Hill ISAFUNC(uasm_rel_lo(addr))); 406e30ec452SThiemo Seufer else 407abc597feSSteven J. Hill ISAFUNC(uasm_i_addiu)(buf, rs, rs, 408abc597feSSteven J. Hill ISAFUNC(uasm_rel_lo(addr))); 409e30ec452SThiemo Seufer } 410e30ec452SThiemo Seufer } 411abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA)); 412e30ec452SThiemo Seufer 413e30ec452SThiemo Seufer /* Handle relocations. */ 414078a55fcSPaul Gortmaker void ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid) 415e30ec452SThiemo Seufer { 416e30ec452SThiemo Seufer (*rel)->addr = addr; 417e30ec452SThiemo Seufer (*rel)->type = R_MIPS_PC16; 418e30ec452SThiemo Seufer (*rel)->lab = lid; 419e30ec452SThiemo Seufer (*rel)++; 420e30ec452SThiemo Seufer } 421abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16)); 422e30ec452SThiemo Seufer 423078a55fcSPaul Gortmaker static inline void __resolve_relocs(struct uasm_reloc *rel, 424078a55fcSPaul Gortmaker struct uasm_label *lab); 425e30ec452SThiemo Seufer 426078a55fcSPaul Gortmaker void ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, 427078a55fcSPaul Gortmaker struct uasm_label *lab) 428e30ec452SThiemo Seufer { 429e30ec452SThiemo Seufer struct uasm_label *l; 430e30ec452SThiemo Seufer 431e30ec452SThiemo Seufer for (; rel->lab != UASM_LABEL_INVALID; rel++) 432e30ec452SThiemo Seufer for (l = lab; l->lab != UASM_LABEL_INVALID; l++) 433e30ec452SThiemo Seufer if (rel->lab == l->lab) 434e30ec452SThiemo Seufer __resolve_relocs(rel, l); 435e30ec452SThiemo Seufer } 436abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs)); 437e30ec452SThiemo Seufer 438078a55fcSPaul Gortmaker void ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, 439078a55fcSPaul Gortmaker long off) 440e30ec452SThiemo Seufer { 441e30ec452SThiemo Seufer for (; rel->lab != UASM_LABEL_INVALID; rel++) 442e30ec452SThiemo Seufer if (rel->addr >= first && rel->addr < end) 443e30ec452SThiemo Seufer rel->addr += off; 444e30ec452SThiemo Seufer } 445abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs)); 446e30ec452SThiemo Seufer 447078a55fcSPaul Gortmaker void ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, 448078a55fcSPaul Gortmaker long off) 449e30ec452SThiemo Seufer { 450e30ec452SThiemo Seufer for (; lab->lab != UASM_LABEL_INVALID; lab++) 451e30ec452SThiemo Seufer if (lab->addr >= first && lab->addr < end) 452e30ec452SThiemo Seufer lab->addr += off; 453e30ec452SThiemo Seufer } 454abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels)); 455e30ec452SThiemo Seufer 456078a55fcSPaul Gortmaker void ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, 457078a55fcSPaul Gortmaker u32 *first, u32 *end, u32 *target) 458e30ec452SThiemo Seufer { 459e30ec452SThiemo Seufer long off = (long)(target - first); 460e30ec452SThiemo Seufer 461e30ec452SThiemo Seufer memcpy(target, first, (end - first) * sizeof(u32)); 462e30ec452SThiemo Seufer 463abc597feSSteven J. Hill ISAFUNC(uasm_move_relocs(rel, first, end, off)); 464abc597feSSteven J. Hill ISAFUNC(uasm_move_labels(lab, first, end, off)); 465e30ec452SThiemo Seufer } 466abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler)); 467e30ec452SThiemo Seufer 468078a55fcSPaul Gortmaker int ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) 469e30ec452SThiemo Seufer { 470e30ec452SThiemo Seufer for (; rel->lab != UASM_LABEL_INVALID; rel++) { 471e30ec452SThiemo Seufer if (rel->addr == addr 472e30ec452SThiemo Seufer && (rel->type == R_MIPS_PC16 473e30ec452SThiemo Seufer || rel->type == R_MIPS_26)) 474e30ec452SThiemo Seufer return 1; 475e30ec452SThiemo Seufer } 476e30ec452SThiemo Seufer 477e30ec452SThiemo Seufer return 0; 478e30ec452SThiemo Seufer } 479abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay)); 480e30ec452SThiemo Seufer 481e30ec452SThiemo Seufer /* Convenience functions for labeled branches. */ 482078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, 483078a55fcSPaul Gortmaker int lid) 484e30ec452SThiemo Seufer { 485e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 486abc597feSSteven J. Hill ISAFUNC(uasm_i_bltz)(p, reg, 0); 487e30ec452SThiemo Seufer } 488abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz)); 489e30ec452SThiemo Seufer 490078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) 491e30ec452SThiemo Seufer { 492e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 493abc597feSSteven J. Hill ISAFUNC(uasm_i_b)(p, 0); 494e30ec452SThiemo Seufer } 495abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); 496e30ec452SThiemo Seufer 4978dee5901SPaul Burton void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int r1, 4988dee5901SPaul Burton unsigned int r2, int lid) 4998dee5901SPaul Burton { 5008dee5901SPaul Burton uasm_r_mips_pc16(r, *p, lid); 5018dee5901SPaul Burton ISAFUNC(uasm_i_beq)(p, r1, r2, 0); 5028dee5901SPaul Burton } 5038dee5901SPaul Burton UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq)); 5048dee5901SPaul Burton 505078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, 506078a55fcSPaul Gortmaker int lid) 507e30ec452SThiemo Seufer { 508e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 509abc597feSSteven J. Hill ISAFUNC(uasm_i_beqz)(p, reg, 0); 510e30ec452SThiemo Seufer } 511abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz)); 512e30ec452SThiemo Seufer 513078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, 514078a55fcSPaul Gortmaker int lid) 515e30ec452SThiemo Seufer { 516e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 517abc597feSSteven J. Hill ISAFUNC(uasm_i_beqzl)(p, reg, 0); 518e30ec452SThiemo Seufer } 519abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl)); 520e30ec452SThiemo Seufer 521078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1, 522fb2a27e7SThiemo Seufer unsigned int reg2, int lid) 523fb2a27e7SThiemo Seufer { 524fb2a27e7SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 525abc597feSSteven J. Hill ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0); 526fb2a27e7SThiemo Seufer } 527abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne)); 528fb2a27e7SThiemo Seufer 529078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, 530078a55fcSPaul Gortmaker int lid) 531e30ec452SThiemo Seufer { 532e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 533abc597feSSteven J. Hill ISAFUNC(uasm_i_bnez)(p, reg, 0); 534e30ec452SThiemo Seufer } 535abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez)); 536e30ec452SThiemo Seufer 537078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, 538078a55fcSPaul Gortmaker int lid) 539e30ec452SThiemo Seufer { 540e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 541abc597feSSteven J. Hill ISAFUNC(uasm_i_bgezl)(p, reg, 0); 542e30ec452SThiemo Seufer } 543abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl)); 544e30ec452SThiemo Seufer 545078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, 546078a55fcSPaul Gortmaker int lid) 547e30ec452SThiemo Seufer { 548e30ec452SThiemo Seufer uasm_r_mips_pc16(r, *p, lid); 549abc597feSSteven J. Hill ISAFUNC(uasm_i_bgez)(p, reg, 0); 550e30ec452SThiemo Seufer } 551abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez)); 5525b97c3f7SDavid Daney 553078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg, 5545b97c3f7SDavid Daney unsigned int bit, int lid) 5555b97c3f7SDavid Daney { 5565b97c3f7SDavid Daney uasm_r_mips_pc16(r, *p, lid); 557abc597feSSteven J. Hill ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0); 5585b97c3f7SDavid Daney } 559abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0)); 5605b97c3f7SDavid Daney 561078a55fcSPaul Gortmaker void ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg, 5625b97c3f7SDavid Daney unsigned int bit, int lid) 5635b97c3f7SDavid Daney { 5645b97c3f7SDavid Daney uasm_r_mips_pc16(r, *p, lid); 565abc597feSSteven J. Hill ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0); 5665b97c3f7SDavid Daney } 567abc597feSSteven J. Hill UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1)); 568