aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
authorSteven J. Hill <sjhill@mips.com>2013-02-05 17:52:01 -0500
committerSteven J. Hill <Steven.Hill@imgtec.com>2013-05-01 17:32:45 -0400
commitabc597fe623cfd7d3b18d5235c54f3d567d2c3d3 (patch)
tree05ef12f30fc686793522a5fcb7b4ff4a14390088 /arch/mips/mm
parent2aa9fd06e221da4e69693dc1b5c6c6bc84c76f32 (diff)
MIPS: microMIPS: uasm: Split 'uasm.c' into two files.
Split 'uasm.c' into two files. The new file 'uasm-mips.c' has the functions specific to the classic MIPS ISA. The 'uasm.c' file contains common code that can be used by classic or other ISAs that could be supported by the kernel. Signed-off-by: Steven J. Hill <sjhill@mips.com> Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: kevink@paralogos.com Cc: ddaney.cavm@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/4922/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org> (cherry picked from commit 0961103562ab958fa74f35043bf4f72e51ed6155)
Diffstat (limited to 'arch/mips/mm')
-rw-r--r--arch/mips/mm/Makefile2
-rw-r--r--arch/mips/mm/uasm-mips.c196
-rw-r--r--arch/mips/mm/uasm.c326
3 files changed, 275 insertions, 249 deletions
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 1dcec30ad1c4..9e90c2182aa5 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y += cache.o dma-default.o extable.o fault.o \ 5obj-y += cache.o dma-default.o extable.o fault.o \
6 gup.o init.o mmap.o page.o page-funcs.o \ 6 gup.o init.o mmap.o page.o page-funcs.o \
7 tlbex.o tlbex-fault.o uasm.o 7 tlbex.o tlbex-fault.o uasm-mips.o
8 8
9obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o 9obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
10obj-$(CONFIG_64BIT) += pgtable-64.o 10obj-$(CONFIG_64BIT) += pgtable-64.o
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
new file mode 100644
index 000000000000..e78e74dc3aea
--- /dev/null
+++ b/arch/mips/mm/uasm-mips.c
@@ -0,0 +1,196 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * A small micro-assembler. It is intentionally kept simple, does only
7 * support a subset of instructions, and does not try to hide pipeline
8 * effects like branch delay slots.
9 *
10 * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
11 * Copyright (C) 2005, 2007 Maciej W. Rozycki
12 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
13 * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
14 */
15
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/init.h>
19
20#include <asm/inst.h>
21#include <asm/elf.h>
22#include <asm/bugs.h>
23#include <asm/uasm.h>
24
25#define RS_MASK 0x1f
26#define RS_SH 21
27#define RT_MASK 0x1f
28#define RT_SH 16
29#define SCIMM_MASK 0xfffff
30#define SCIMM_SH 6
31
32/* This macro sets the non-variable bits of an instruction. */
33#define M(a, b, c, d, e, f) \
34 ((a) << OP_SH \
35 | (b) << RS_SH \
36 | (c) << RT_SH \
37 | (d) << RD_SH \
38 | (e) << RE_SH \
39 | (f) << FUNC_SH)
40
41#include "uasm.c"
42
43static struct insn insn_table[] __uasminitdata = {
44 { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
45 { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
46 { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
47 { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
48 { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
49 { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
50 { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
51 { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
52 { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
53 { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
54 { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
55 { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
56 { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
57 { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
58 { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
59 { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
60 { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
61 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
62 { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
63 { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
64 { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
65 { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
66 { insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
67 { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
68 { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
69 { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
70 { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
71 { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
72 { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 },
73 { insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
74 { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
75 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
76 { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
77 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
78 { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
79 { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
80 { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
81 { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
82 { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
83 { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
84 { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
85 { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
86 { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
87 { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
88 { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
89 { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
90 { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
91 { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
92 { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
93 { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
94 { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
95 { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
96 { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
97 { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
98 { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
99 { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
100 { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
101 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
102 { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
103 { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
104 { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
105 { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
106 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
107 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
108 { insn_invalid, 0, 0 }
109};
110
111#undef M
112
113static inline __uasminit u32 build_bimm(s32 arg)
114{
115 WARN(arg > 0x1ffff || arg < -0x20000,
116 KERN_WARNING "Micro-assembler field overflow\n");
117
118 WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
119
120 return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
121}
122
123static inline __uasminit u32 build_jimm(u32 arg)
124{
125 WARN(arg & ~(JIMM_MASK << 2),
126 KERN_WARNING "Micro-assembler field overflow\n");
127
128 return (arg >> 2) & JIMM_MASK;
129}
130
131/*
132 * The order of opcode arguments is implicitly left to right,
133 * starting with RS and ending with FUNC or IMM.
134 */
135static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
136{
137 struct insn *ip = NULL;
138 unsigned int i;
139 va_list ap;
140 u32 op;
141
142 for (i = 0; insn_table[i].opcode != insn_invalid; i++)
143 if (insn_table[i].opcode == opc) {
144 ip = &insn_table[i];
145 break;
146 }
147
148 if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
149 panic("Unsupported Micro-assembler instruction %d", opc);
150
151 op = ip->match;
152 va_start(ap, opc);
153 if (ip->fields & RS)
154 op |= build_rs(va_arg(ap, u32));
155 if (ip->fields & RT)
156 op |= build_rt(va_arg(ap, u32));
157 if (ip->fields & RD)
158 op |= build_rd(va_arg(ap, u32));
159 if (ip->fields & RE)
160 op |= build_re(va_arg(ap, u32));
161 if (ip->fields & SIMM)
162 op |= build_simm(va_arg(ap, s32));
163 if (ip->fields & UIMM)
164 op |= build_uimm(va_arg(ap, u32));
165 if (ip->fields & BIMM)
166 op |= build_bimm(va_arg(ap, s32));
167 if (ip->fields & JIMM)
168 op |= build_jimm(va_arg(ap, u32));
169 if (ip->fields & FUNC)
170 op |= build_func(va_arg(ap, u32));
171 if (ip->fields & SET)
172 op |= build_set(va_arg(ap, u32));
173 if (ip->fields & SCIMM)
174 op |= build_scimm(va_arg(ap, u32));
175 va_end(ap);
176
177 **buf = op;
178 (*buf)++;
179}
180
181static inline void __uasminit
182__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
183{
184 long laddr = (long)lab->addr;
185 long raddr = (long)rel->addr;
186
187 switch (rel->type) {
188 case R_MIPS_PC16:
189 *rel->addr |= build_bimm(laddr - (raddr + 4));
190 break;
191
192 default:
193 panic("Unsupported Micro-assembler relocation %d",
194 rel->type);
195 }
196}
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index 942ff6c2eba2..7eb5e4355d25 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -10,17 +10,9 @@
10 * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer 10 * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
11 * Copyright (C) 2005, 2007 Maciej W. Rozycki 11 * Copyright (C) 2005, 2007 Maciej W. Rozycki
12 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) 12 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
13 * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved.
13 */ 14 */
14 15
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/init.h>
18
19#include <asm/inst.h>
20#include <asm/elf.h>
21#include <asm/bugs.h>
22#include <asm/uasm.h>
23
24enum fields { 16enum fields {
25 RS = 0x001, 17 RS = 0x001,
26 RT = 0x002, 18 RT = 0x002,
@@ -37,10 +29,6 @@ enum fields {
37 29
38#define OP_MASK 0x3f 30#define OP_MASK 0x3f
39#define OP_SH 26 31#define OP_SH 26
40#define RS_MASK 0x1f
41#define RS_SH 21
42#define RT_MASK 0x1f
43#define RT_SH 16
44#define RD_MASK 0x1f 32#define RD_MASK 0x1f
45#define RD_SH 11 33#define RD_SH 11
46#define RE_MASK 0x1f 34#define RE_MASK 0x1f
@@ -53,8 +41,6 @@ enum fields {
53#define FUNC_SH 0 41#define FUNC_SH 0
54#define SET_MASK 0x7 42#define SET_MASK 0x7
55#define SET_SH 0 43#define SET_SH 0
56#define SCIMM_MASK 0xfffff
57#define SCIMM_SH 6
58 44
59enum opcode { 45enum opcode {
60 insn_invalid, 46 insn_invalid,
@@ -77,85 +63,6 @@ struct insn {
77 enum fields fields; 63 enum fields fields;
78}; 64};
79 65
80/* This macro sets the non-variable bits of an instruction. */
81#define M(a, b, c, d, e, f) \
82 ((a) << OP_SH \
83 | (b) << RS_SH \
84 | (c) << RT_SH \
85 | (d) << RD_SH \
86 | (e) << RE_SH \
87 | (f) << FUNC_SH)
88
89static struct insn insn_table[] __uasminitdata = {
90 { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
91 { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
92 { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
93 { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
94 { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
95 { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
96 { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
97 { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
98 { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
99 { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
100 { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
101 { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
102 { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
103 { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
104 { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
105 { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
106 { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
107 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
108 { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
109 { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
110 { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
111 { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
112 { insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
113 { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
114 { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
115 { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
116 { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
117 { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
118 { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 },
119 { insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
120 { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
121 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
122 { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
123 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
124 { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
125 { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
126 { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
127 { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
128 { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
129 { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
130 { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
131 { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
132 { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
133 { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
134 { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
135 { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
136 { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
137 { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
138 { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
139 { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
140 { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
141 { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
142 { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
143 { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
144 { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
145 { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
146 { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
147 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
148 { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
149 { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
150 { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
151 { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
152 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
153 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
154 { insn_invalid, 0, 0 }
155};
156
157#undef M
158
159static inline __uasminit u32 build_rs(u32 arg) 66static inline __uasminit u32 build_rs(u32 arg)
160{ 67{
161 WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n"); 68 WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
@@ -199,24 +106,6 @@ static inline __uasminit u32 build_uimm(u32 arg)
199 return arg & IMM_MASK; 106 return arg & IMM_MASK;
200} 107}
201 108
202static inline __uasminit u32 build_bimm(s32 arg)
203{
204 WARN(arg > 0x1ffff || arg < -0x20000,
205 KERN_WARNING "Micro-assembler field overflow\n");
206
207 WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
208
209 return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
210}
211
212static inline __uasminit u32 build_jimm(u32 arg)
213{
214 WARN(arg & ~(JIMM_MASK << 2),
215 KERN_WARNING "Micro-assembler field overflow\n");
216
217 return (arg >> 2) & JIMM_MASK;
218}
219
220static inline __uasminit u32 build_scimm(u32 arg) 109static inline __uasminit u32 build_scimm(u32 arg)
221{ 110{
222 WARN(arg & ~SCIMM_MASK, 111 WARN(arg & ~SCIMM_MASK,
@@ -239,55 +128,7 @@ static inline __uasminit u32 build_set(u32 arg)
239 return arg & SET_MASK; 128 return arg & SET_MASK;
240} 129}
241 130
242/* 131static void __uasminit build_insn(u32 **buf, enum opcode opc, ...);
243 * The order of opcode arguments is implicitly left to right,
244 * starting with RS and ending with FUNC or IMM.
245 */
246static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
247{
248 struct insn *ip = NULL;
249 unsigned int i;
250 va_list ap;
251 u32 op;
252
253 for (i = 0; insn_table[i].opcode != insn_invalid; i++)
254 if (insn_table[i].opcode == opc) {
255 ip = &insn_table[i];
256 break;
257 }
258
259 if (!ip || (opc == insn_daddiu && r4k_daddiu_bug()))
260 panic("Unsupported Micro-assembler instruction %d", opc);
261
262 op = ip->match;
263 va_start(ap, opc);
264 if (ip->fields & RS)
265 op |= build_rs(va_arg(ap, u32));
266 if (ip->fields & RT)
267 op |= build_rt(va_arg(ap, u32));
268 if (ip->fields & RD)
269 op |= build_rd(va_arg(ap, u32));
270 if (ip->fields & RE)
271 op |= build_re(va_arg(ap, u32));
272 if (ip->fields & SIMM)
273 op |= build_simm(va_arg(ap, s32));
274 if (ip->fields & UIMM)
275 op |= build_uimm(va_arg(ap, u32));
276 if (ip->fields & BIMM)
277 op |= build_bimm(va_arg(ap, s32));
278 if (ip->fields & JIMM)
279 op |= build_jimm(va_arg(ap, u32));
280 if (ip->fields & FUNC)
281 op |= build_func(va_arg(ap, u32));
282 if (ip->fields & SET)
283 op |= build_set(va_arg(ap, u32));
284 if (ip->fields & SCIMM)
285 op |= build_scimm(va_arg(ap, u32));
286 va_end(ap);
287
288 **buf = op;
289 (*buf)++;
290}
291 132
292#define I_u1u2u3(op) \ 133#define I_u1u2u3(op) \
293Ip_u1u2u3(op) \ 134Ip_u1u2u3(op) \
@@ -445,7 +286,7 @@ I_u3u1u2(_ldx)
445 286
446#ifdef CONFIG_CPU_CAVIUM_OCTEON 287#ifdef CONFIG_CPU_CAVIUM_OCTEON
447#include <asm/octeon/octeon.h> 288#include <asm/octeon/octeon.h>
448void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b, 289void __uasminit ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
449 unsigned int c) 290 unsigned int c)
450{ 291{
451 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5) 292 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5)
@@ -457,21 +298,21 @@ void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
457 else 298 else
458 build_insn(buf, insn_pref, c, a, b); 299 build_insn(buf, insn_pref, c, a, b);
459} 300}
460UASM_EXPORT_SYMBOL(uasm_i_pref); 301UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref));
461#else 302#else
462I_u2s3u1(_pref) 303I_u2s3u1(_pref)
463#endif 304#endif
464 305
465/* Handle labels. */ 306/* Handle labels. */
466void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) 307void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid)
467{ 308{
468 (*lab)->addr = addr; 309 (*lab)->addr = addr;
469 (*lab)->lab = lid; 310 (*lab)->lab = lid;
470 (*lab)++; 311 (*lab)++;
471} 312}
472UASM_EXPORT_SYMBOL(uasm_build_label); 313UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label));
473 314
474int __uasminit uasm_in_compat_space_p(long addr) 315int __uasminit ISAFUNC(uasm_in_compat_space_p)(long addr)
475{ 316{
476 /* Is this address in 32bit compat space? */ 317 /* Is this address in 32bit compat space? */
477#ifdef CONFIG_64BIT 318#ifdef CONFIG_64BIT
@@ -480,7 +321,7 @@ int __uasminit uasm_in_compat_space_p(long addr)
480 return 1; 321 return 1;
481#endif 322#endif
482} 323}
483UASM_EXPORT_SYMBOL(uasm_in_compat_space_p); 324UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p));
484 325
485static int __uasminit uasm_rel_highest(long val) 326static int __uasminit uasm_rel_highest(long val)
486{ 327{
@@ -500,77 +341,66 @@ static int __uasminit uasm_rel_higher(long val)
500#endif 341#endif
501} 342}
502 343
503int __uasminit uasm_rel_hi(long val) 344int __uasminit ISAFUNC(uasm_rel_hi)(long val)
504{ 345{
505 return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; 346 return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
506} 347}
507UASM_EXPORT_SYMBOL(uasm_rel_hi); 348UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi));
508 349
509int __uasminit uasm_rel_lo(long val) 350int __uasminit ISAFUNC(uasm_rel_lo)(long val)
510{ 351{
511 return ((val & 0xffff) ^ 0x8000) - 0x8000; 352 return ((val & 0xffff) ^ 0x8000) - 0x8000;
512} 353}
513UASM_EXPORT_SYMBOL(uasm_rel_lo); 354UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo));
514 355
515void __uasminit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) 356void __uasminit ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr)
516{ 357{
517 if (!uasm_in_compat_space_p(addr)) { 358 if (!ISAFUNC(uasm_in_compat_space_p)(addr)) {
518 uasm_i_lui(buf, rs, uasm_rel_highest(addr)); 359 ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr));
519 if (uasm_rel_higher(addr)) 360 if (uasm_rel_higher(addr))
520 uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr)); 361 ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr));
521 if (uasm_rel_hi(addr)) { 362 if (ISAFUNC(uasm_rel_hi(addr))) {
522 uasm_i_dsll(buf, rs, rs, 16); 363 ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
523 uasm_i_daddiu(buf, rs, rs, uasm_rel_hi(addr)); 364 ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
524 uasm_i_dsll(buf, rs, rs, 16); 365 ISAFUNC(uasm_rel_hi)(addr));
366 ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
525 } else 367 } else
526 uasm_i_dsll32(buf, rs, rs, 0); 368 ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0);
527 } else 369 } else
528 uasm_i_lui(buf, rs, uasm_rel_hi(addr)); 370 ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr)));
529} 371}
530UASM_EXPORT_SYMBOL(UASM_i_LA_mostly); 372UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly));
531 373
532void __uasminit UASM_i_LA(u32 **buf, unsigned int rs, long addr) 374void __uasminit ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr)
533{ 375{
534 UASM_i_LA_mostly(buf, rs, addr); 376 ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr);
535 if (uasm_rel_lo(addr)) { 377 if (ISAFUNC(uasm_rel_lo(addr))) {
536 if (!uasm_in_compat_space_p(addr)) 378 if (!ISAFUNC(uasm_in_compat_space_p)(addr))
537 uasm_i_daddiu(buf, rs, rs, uasm_rel_lo(addr)); 379 ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
380 ISAFUNC(uasm_rel_lo(addr)));
538 else 381 else
539 uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr)); 382 ISAFUNC(uasm_i_addiu)(buf, rs, rs,
383 ISAFUNC(uasm_rel_lo(addr)));
540 } 384 }
541} 385}
542UASM_EXPORT_SYMBOL(UASM_i_LA); 386UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA));
543 387
544/* Handle relocations. */ 388/* Handle relocations. */
545void __uasminit 389void __uasminit
546uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) 390ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid)
547{ 391{
548 (*rel)->addr = addr; 392 (*rel)->addr = addr;
549 (*rel)->type = R_MIPS_PC16; 393 (*rel)->type = R_MIPS_PC16;
550 (*rel)->lab = lid; 394 (*rel)->lab = lid;
551 (*rel)++; 395 (*rel)++;
552} 396}
553UASM_EXPORT_SYMBOL(uasm_r_mips_pc16); 397UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16));
554 398
555static inline void __uasminit 399static inline void __uasminit
556__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) 400__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab);
557{
558 long laddr = (long)lab->addr;
559 long raddr = (long)rel->addr;
560
561 switch (rel->type) {
562 case R_MIPS_PC16:
563 *rel->addr |= build_bimm(laddr - (raddr + 4));
564 break;
565
566 default:
567 panic("Unsupported Micro-assembler relocation %d",
568 rel->type);
569 }
570}
571 401
572void __uasminit 402void __uasminit
573uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) 403ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, struct uasm_label *lab)
574{ 404{
575 struct uasm_label *l; 405 struct uasm_label *l;
576 406
@@ -579,40 +409,40 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
579 if (rel->lab == l->lab) 409 if (rel->lab == l->lab)
580 __resolve_relocs(rel, l); 410 __resolve_relocs(rel, l);
581} 411}
582UASM_EXPORT_SYMBOL(uasm_resolve_relocs); 412UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs));
583 413
584void __uasminit 414void __uasminit
585uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) 415ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, long off)
586{ 416{
587 for (; rel->lab != UASM_LABEL_INVALID; rel++) 417 for (; rel->lab != UASM_LABEL_INVALID; rel++)
588 if (rel->addr >= first && rel->addr < end) 418 if (rel->addr >= first && rel->addr < end)
589 rel->addr += off; 419 rel->addr += off;
590} 420}
591UASM_EXPORT_SYMBOL(uasm_move_relocs); 421UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs));
592 422
593void __uasminit 423void __uasminit
594uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) 424ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, long off)
595{ 425{
596 for (; lab->lab != UASM_LABEL_INVALID; lab++) 426 for (; lab->lab != UASM_LABEL_INVALID; lab++)
597 if (lab->addr >= first && lab->addr < end) 427 if (lab->addr >= first && lab->addr < end)
598 lab->addr += off; 428 lab->addr += off;
599} 429}
600UASM_EXPORT_SYMBOL(uasm_move_labels); 430UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels));
601 431
602void __uasminit 432void __uasminit
603uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, 433ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first,
604 u32 *end, u32 *target) 434 u32 *end, u32 *target)
605{ 435{
606 long off = (long)(target - first); 436 long off = (long)(target - first);
607 437
608 memcpy(target, first, (end - first) * sizeof(u32)); 438 memcpy(target, first, (end - first) * sizeof(u32));
609 439
610 uasm_move_relocs(rel, first, end, off); 440 ISAFUNC(uasm_move_relocs(rel, first, end, off));
611 uasm_move_labels(lab, first, end, off); 441 ISAFUNC(uasm_move_labels(lab, first, end, off));
612} 442}
613UASM_EXPORT_SYMBOL(uasm_copy_handler); 443UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler));
614 444
615int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) 445int __uasminit ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr)
616{ 446{
617 for (; rel->lab != UASM_LABEL_INVALID; rel++) { 447 for (; rel->lab != UASM_LABEL_INVALID; rel++) {
618 if (rel->addr == addr 448 if (rel->addr == addr
@@ -623,88 +453,88 @@ int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
623 453
624 return 0; 454 return 0;
625} 455}
626UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay); 456UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay));
627 457
628/* Convenience functions for labeled branches. */ 458/* Convenience functions for labeled branches. */
629void __uasminit 459void __uasminit
630uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) 460ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
631{ 461{
632 uasm_r_mips_pc16(r, *p, lid); 462 uasm_r_mips_pc16(r, *p, lid);
633 uasm_i_bltz(p, reg, 0); 463 ISAFUNC(uasm_i_bltz)(p, reg, 0);
634} 464}
635UASM_EXPORT_SYMBOL(uasm_il_bltz); 465UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz));
636 466
637void __uasminit 467void __uasminit
638uasm_il_b(u32 **p, struct uasm_reloc **r, int lid) 468ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
639{ 469{
640 uasm_r_mips_pc16(r, *p, lid); 470 uasm_r_mips_pc16(r, *p, lid);
641 uasm_i_b(p, 0); 471 ISAFUNC(uasm_i_b)(p, 0);
642} 472}
643UASM_EXPORT_SYMBOL(uasm_il_b); 473UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
644 474
645void __uasminit 475void __uasminit
646uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) 476ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
647{ 477{
648 uasm_r_mips_pc16(r, *p, lid); 478 uasm_r_mips_pc16(r, *p, lid);
649 uasm_i_beqz(p, reg, 0); 479 ISAFUNC(uasm_i_beqz)(p, reg, 0);
650} 480}
651UASM_EXPORT_SYMBOL(uasm_il_beqz); 481UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz));
652 482
653void __uasminit 483void __uasminit
654uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) 484ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
655{ 485{
656 uasm_r_mips_pc16(r, *p, lid); 486 uasm_r_mips_pc16(r, *p, lid);
657 uasm_i_beqzl(p, reg, 0); 487 ISAFUNC(uasm_i_beqzl)(p, reg, 0);
658} 488}
659UASM_EXPORT_SYMBOL(uasm_il_beqzl); 489UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl));
660 490
661void __uasminit 491void __uasminit
662uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, 492ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1,
663 unsigned int reg2, int lid) 493 unsigned int reg2, int lid)
664{ 494{
665 uasm_r_mips_pc16(r, *p, lid); 495 uasm_r_mips_pc16(r, *p, lid);
666 uasm_i_bne(p, reg1, reg2, 0); 496 ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0);
667} 497}
668UASM_EXPORT_SYMBOL(uasm_il_bne); 498UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne));
669 499
670void __uasminit 500void __uasminit
671uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) 501ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
672{ 502{
673 uasm_r_mips_pc16(r, *p, lid); 503 uasm_r_mips_pc16(r, *p, lid);
674 uasm_i_bnez(p, reg, 0); 504 ISAFUNC(uasm_i_bnez)(p, reg, 0);
675} 505}
676UASM_EXPORT_SYMBOL(uasm_il_bnez); 506UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez));
677 507
678void __uasminit 508void __uasminit
679uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) 509ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
680{ 510{
681 uasm_r_mips_pc16(r, *p, lid); 511 uasm_r_mips_pc16(r, *p, lid);
682 uasm_i_bgezl(p, reg, 0); 512 ISAFUNC(uasm_i_bgezl)(p, reg, 0);
683} 513}
684UASM_EXPORT_SYMBOL(uasm_il_bgezl); 514UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl));
685 515
686void __uasminit 516void __uasminit
687uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) 517ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
688{ 518{
689 uasm_r_mips_pc16(r, *p, lid); 519 uasm_r_mips_pc16(r, *p, lid);
690 uasm_i_bgez(p, reg, 0); 520 ISAFUNC(uasm_i_bgez)(p, reg, 0);
691} 521}
692UASM_EXPORT_SYMBOL(uasm_il_bgez); 522UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez));
693 523
694void __uasminit 524void __uasminit
695uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, 525ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg,
696 unsigned int bit, int lid) 526 unsigned int bit, int lid)
697{ 527{
698 uasm_r_mips_pc16(r, *p, lid); 528 uasm_r_mips_pc16(r, *p, lid);
699 uasm_i_bbit0(p, reg, bit, 0); 529 ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0);
700} 530}
701UASM_EXPORT_SYMBOL(uasm_il_bbit0); 531UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0));
702 532
703void __uasminit 533void __uasminit
704uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, 534ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg,
705 unsigned int bit, int lid) 535 unsigned int bit, int lid)
706{ 536{
707 uasm_r_mips_pc16(r, *p, lid); 537 uasm_r_mips_pc16(r, *p, lid);
708 uasm_i_bbit1(p, reg, bit, 0); 538 ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0);
709} 539}
710UASM_EXPORT_SYMBOL(uasm_il_bbit1); 540UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1));