xref: /openbmc/linux/arch/mips/mm/uasm.c (revision e737547e)
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,
2751eec48eSLeonid Yegoshin 	SCIMM = 0x400,
2851eec48eSLeonid Yegoshin 	SIMM9 = 0x800,
29e30ec452SThiemo Seufer };
30e30ec452SThiemo Seufer 
31e30ec452SThiemo Seufer #define OP_MASK		0x3f
32e30ec452SThiemo Seufer #define OP_SH		26
33e30ec452SThiemo Seufer #define RD_MASK		0x1f
34e30ec452SThiemo Seufer #define RD_SH		11
35e30ec452SThiemo Seufer #define RE_MASK		0x1f
36e30ec452SThiemo Seufer #define RE_SH		6
37e30ec452SThiemo Seufer #define IMM_MASK	0xffff
38e30ec452SThiemo Seufer #define IMM_SH		0
39e30ec452SThiemo Seufer #define JIMM_MASK	0x3ffffff
40e30ec452SThiemo Seufer #define JIMM_SH		0
41e30ec452SThiemo Seufer #define FUNC_MASK	0x3f
42e30ec452SThiemo Seufer #define FUNC_SH		0
43e30ec452SThiemo Seufer #define SET_MASK	0x7
44e30ec452SThiemo Seufer #define SET_SH		0
4551eec48eSLeonid Yegoshin #define SIMM9_SH	7
4651eec48eSLeonid Yegoshin #define SIMM9_MASK	0x1ff
47e30ec452SThiemo Seufer 
48e30ec452SThiemo Seufer enum opcode {
4971a1c776SSteven J. Hill 	insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1,
50dc190129SDavid Daney 	insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bgtz, insn_blez,
51dc190129SDavid Daney 	insn_bltz, insn_bltzl, insn_bne, insn_break, insn_cache, insn_cfc1,
52dc190129SDavid Daney 	insn_cfcmsa, insn_ctc1, insn_ctcmsa, insn_daddiu, insn_daddu, insn_ddivu,
530d1d17b9SHassan Naveed 	insn_ddivu_r6, insn_di, insn_dins, insn_dinsm, insn_dinsu, insn_divu,
540d1d17b9SHassan Naveed 	insn_divu_r6, insn_dmfc0, insn_dmodu, insn_dmtc0, insn_dmultu,
550d1d17b9SHassan Naveed 	insn_dmulu, insn_drotr, insn_drotr32, insn_dsbh, insn_dshd, insn_dsll,
560d1d17b9SHassan Naveed 	insn_dsll32, insn_dsllv, insn_dsra, insn_dsra32, insn_dsrav, insn_dsrl,
570d1d17b9SHassan Naveed 	insn_dsrl32, insn_dsrlv, insn_dsubu, insn_eret, insn_ext, insn_ins,
580d1d17b9SHassan Naveed 	insn_j, insn_jal, insn_jalr, insn_jr, insn_lb, insn_lbu, insn_ld,
590d1d17b9SHassan Naveed 	insn_lddir, insn_ldpte, insn_ldx, insn_lh, insn_lhu, insn_ll, insn_lld,
600d1d17b9SHassan Naveed 	insn_lui, insn_lw, insn_lwu, insn_lwx, insn_mfc0, insn_mfhc0, insn_mfhi,
610d1d17b9SHassan Naveed 	insn_mflo, insn_modu, insn_movn, insn_movz, insn_mtc0, insn_mthc0,
62*e737547eSTony Ambardar 	insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_mulu, insn_muhu, insn_nor,
630d1d17b9SHassan Naveed 	insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, insn_sc,
640d1d17b9SHassan Naveed 	insn_scd, insn_seleqz, insn_selnez, insn_sd, insn_sh, insn_sll,
650d1d17b9SHassan Naveed 	insn_sllv, insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra,
660d1d17b9SHassan Naveed 	insn_srav, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync,
670d1d17b9SHassan Naveed 	insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait,
680d1d17b9SHassan Naveed 	insn_wsbh, insn_xor, insn_xori, insn_yield,
69ce807d5fSDavid Daney 	insn_invalid /* insn_invalid must be last */
70e30ec452SThiemo Seufer };
71e30ec452SThiemo Seufer 
72e30ec452SThiemo Seufer struct insn {
73e30ec452SThiemo Seufer 	u32 match;
74e30ec452SThiemo Seufer 	enum fields fields;
75e30ec452SThiemo Seufer };
76e30ec452SThiemo Seufer 
build_rs(u32 arg)77078a55fcSPaul Gortmaker static inline u32 build_rs(u32 arg)
78e30ec452SThiemo Seufer {
798d662c8dSDavid Daney 	WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
80e30ec452SThiemo Seufer 
81e30ec452SThiemo Seufer 	return (arg & RS_MASK) << RS_SH;
82e30ec452SThiemo Seufer }
83e30ec452SThiemo Seufer 
build_rt(u32 arg)84078a55fcSPaul Gortmaker static inline u32 build_rt(u32 arg)
85e30ec452SThiemo Seufer {
868d662c8dSDavid Daney 	WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n");
87e30ec452SThiemo Seufer 
88e30ec452SThiemo Seufer 	return (arg & RT_MASK) << RT_SH;
89e30ec452SThiemo Seufer }
90e30ec452SThiemo Seufer 
build_rd(u32 arg)91078a55fcSPaul Gortmaker static inline u32 build_rd(u32 arg)
92e30ec452SThiemo Seufer {
938d662c8dSDavid Daney 	WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n");
94e30ec452SThiemo Seufer 
95e30ec452SThiemo Seufer 	return (arg & RD_MASK) << RD_SH;
96e30ec452SThiemo Seufer }
97e30ec452SThiemo Seufer 
build_re(u32 arg)98078a55fcSPaul Gortmaker static inline u32 build_re(u32 arg)
99e30ec452SThiemo Seufer {
1008d662c8dSDavid Daney 	WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n");
101e30ec452SThiemo Seufer 
102e30ec452SThiemo Seufer 	return (arg & RE_MASK) << RE_SH;
103e30ec452SThiemo Seufer }
104e30ec452SThiemo Seufer 
build_simm(s32 arg)105078a55fcSPaul Gortmaker static inline u32 build_simm(s32 arg)
106e30ec452SThiemo Seufer {
1078d662c8dSDavid Daney 	WARN(arg > 0x7fff || arg < -0x8000,
1088d662c8dSDavid Daney 	     KERN_WARNING "Micro-assembler field overflow\n");
109e30ec452SThiemo Seufer 
110e30ec452SThiemo Seufer 	return arg & 0xffff;
111e30ec452SThiemo Seufer }
112e30ec452SThiemo Seufer 
build_uimm(u32 arg)113078a55fcSPaul Gortmaker static inline u32 build_uimm(u32 arg)
114e30ec452SThiemo Seufer {
1158d662c8dSDavid Daney 	WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n");
116e30ec452SThiemo Seufer 
117e30ec452SThiemo Seufer 	return arg & IMM_MASK;
118e30ec452SThiemo Seufer }
119e30ec452SThiemo Seufer 
build_scimm(u32 arg)120078a55fcSPaul Gortmaker static inline u32 build_scimm(u32 arg)
12158b9e223SDavid Daney {
1228d662c8dSDavid Daney 	WARN(arg & ~SCIMM_MASK,
1238d662c8dSDavid Daney 	     KERN_WARNING "Micro-assembler field overflow\n");
12458b9e223SDavid Daney 
12558b9e223SDavid Daney 	return (arg & SCIMM_MASK) << SCIMM_SH;
12658b9e223SDavid Daney }
12758b9e223SDavid Daney 
build_scimm9(s32 arg)12851eec48eSLeonid Yegoshin static inline u32 build_scimm9(s32 arg)
12951eec48eSLeonid Yegoshin {
13051eec48eSLeonid Yegoshin 	WARN((arg > 0xff || arg < -0x100),
13151eec48eSLeonid Yegoshin 	       KERN_WARNING "Micro-assembler field overflow\n");
13251eec48eSLeonid Yegoshin 
13351eec48eSLeonid Yegoshin 	return (arg & SIMM9_MASK) << SIMM9_SH;
13451eec48eSLeonid Yegoshin }
13551eec48eSLeonid Yegoshin 
build_func(u32 arg)136078a55fcSPaul Gortmaker static inline u32 build_func(u32 arg)
137e30ec452SThiemo Seufer {
1388d662c8dSDavid Daney 	WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
139e30ec452SThiemo Seufer 
140e30ec452SThiemo Seufer 	return arg & FUNC_MASK;
141e30ec452SThiemo Seufer }
142e30ec452SThiemo Seufer 
build_set(u32 arg)143078a55fcSPaul Gortmaker static inline u32 build_set(u32 arg)
144e30ec452SThiemo Seufer {
1458d662c8dSDavid Daney 	WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n");
146e30ec452SThiemo Seufer 
147e30ec452SThiemo Seufer 	return arg & SET_MASK;
148e30ec452SThiemo Seufer }
149e30ec452SThiemo Seufer 
150078a55fcSPaul Gortmaker static void build_insn(u32 **buf, enum opcode opc, ...);
151e30ec452SThiemo Seufer 
152e30ec452SThiemo Seufer #define I_u1u2u3(op)					\
153e30ec452SThiemo Seufer Ip_u1u2u3(op)						\
154e30ec452SThiemo Seufer {							\
155e30ec452SThiemo Seufer 	build_insn(buf, insn##op, a, b, c);		\
15622b0763aSDavid Daney }							\
15722b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
158e30ec452SThiemo Seufer 
1599d987369SMarkos Chandras #define I_s3s1s2(op)					\
1609d987369SMarkos Chandras Ip_s3s1s2(op)						\
1619d987369SMarkos Chandras {							\
1629d987369SMarkos Chandras 	build_insn(buf, insn##op, b, c, a);		\
1639d987369SMarkos Chandras }							\
1649d987369SMarkos Chandras UASM_EXPORT_SYMBOL(uasm_i##op);
1659d987369SMarkos Chandras 
166e30ec452SThiemo Seufer #define I_u2u1u3(op)					\
167e30ec452SThiemo Seufer Ip_u2u1u3(op)						\
168e30ec452SThiemo Seufer {							\
169e30ec452SThiemo Seufer 	build_insn(buf, insn##op, b, a, c);		\
17022b0763aSDavid Daney }							\
17122b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
172e30ec452SThiemo Seufer 
173beef8e02SMarkos Chandras #define I_u3u2u1(op)					\
174beef8e02SMarkos Chandras Ip_u3u2u1(op)						\
175beef8e02SMarkos Chandras {							\
176beef8e02SMarkos Chandras 	build_insn(buf, insn##op, c, b, a);		\
177beef8e02SMarkos Chandras }							\
178beef8e02SMarkos Chandras UASM_EXPORT_SYMBOL(uasm_i##op);
179beef8e02SMarkos Chandras 
180e30ec452SThiemo Seufer #define I_u3u1u2(op)					\
181e30ec452SThiemo Seufer Ip_u3u1u2(op)						\
182e30ec452SThiemo Seufer {							\
183e30ec452SThiemo Seufer 	build_insn(buf, insn##op, b, c, a);		\
18422b0763aSDavid Daney }							\
18522b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
186e30ec452SThiemo Seufer 
187e30ec452SThiemo Seufer #define I_u1u2s3(op)					\
188e30ec452SThiemo Seufer Ip_u1u2s3(op)						\
189e30ec452SThiemo Seufer {							\
190e30ec452SThiemo Seufer 	build_insn(buf, insn##op, a, b, c);		\
19122b0763aSDavid Daney }							\
19222b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
193e30ec452SThiemo Seufer 
194e30ec452SThiemo Seufer #define I_u2s3u1(op)					\
195e30ec452SThiemo Seufer Ip_u2s3u1(op)						\
196e30ec452SThiemo Seufer {							\
197e30ec452SThiemo Seufer 	build_insn(buf, insn##op, c, a, b);		\
19822b0763aSDavid Daney }							\
19922b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
200e30ec452SThiemo Seufer 
201e30ec452SThiemo Seufer #define I_u2u1s3(op)					\
202e30ec452SThiemo Seufer Ip_u2u1s3(op)						\
203e30ec452SThiemo Seufer {							\
204e30ec452SThiemo Seufer 	build_insn(buf, insn##op, b, a, c);		\
20522b0763aSDavid Daney }							\
20622b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
207e30ec452SThiemo Seufer 
20892078e06SDavid Daney #define I_u2u1msbu3(op)					\
20992078e06SDavid Daney Ip_u2u1msbu3(op)					\
21092078e06SDavid Daney {							\
21192078e06SDavid Daney 	build_insn(buf, insn##op, b, a, c+d-1, c);	\
21222b0763aSDavid Daney }							\
21322b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
21492078e06SDavid Daney 
215c42aef09SDavid Daney #define I_u2u1msb32u3(op)				\
216c42aef09SDavid Daney Ip_u2u1msbu3(op)					\
217c42aef09SDavid Daney {							\
218c42aef09SDavid Daney 	build_insn(buf, insn##op, b, a, c+d-33, c);	\
219c42aef09SDavid Daney }							\
220c42aef09SDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
221c42aef09SDavid Daney 
222dc190129SDavid Daney #define I_u2u1msb32msb3(op)				\
223dc190129SDavid Daney Ip_u2u1msbu3(op)					\
224dc190129SDavid Daney {							\
225dc190129SDavid Daney 	build_insn(buf, insn##op, b, a, c+d-33, c-32);	\
226dc190129SDavid Daney }							\
227dc190129SDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
228dc190129SDavid Daney 
229e6de1a09SSteven J. Hill #define I_u2u1msbdu3(op)				\
230e6de1a09SSteven J. Hill Ip_u2u1msbu3(op)					\
231e6de1a09SSteven J. Hill {							\
232e6de1a09SSteven J. Hill 	build_insn(buf, insn##op, b, a, d-1, c);	\
233e6de1a09SSteven J. Hill }							\
234e6de1a09SSteven J. Hill UASM_EXPORT_SYMBOL(uasm_i##op);
235e6de1a09SSteven J. Hill 
236e30ec452SThiemo Seufer #define I_u1u2(op)					\
237e30ec452SThiemo Seufer Ip_u1u2(op)						\
238e30ec452SThiemo Seufer {							\
239e30ec452SThiemo Seufer 	build_insn(buf, insn##op, a, b);		\
24022b0763aSDavid Daney }							\
24122b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
242e30ec452SThiemo Seufer 
243d674dd14SPaul Burton #define I_u2u1(op)					\
244d674dd14SPaul Burton Ip_u1u2(op)						\
245d674dd14SPaul Burton {							\
246d674dd14SPaul Burton 	build_insn(buf, insn##op, b, a);		\
247d674dd14SPaul Burton }							\
248d674dd14SPaul Burton UASM_EXPORT_SYMBOL(uasm_i##op);
249d674dd14SPaul Burton 
250e30ec452SThiemo Seufer #define I_u1s2(op)					\
251e30ec452SThiemo Seufer Ip_u1s2(op)						\
252e30ec452SThiemo Seufer {							\
253e30ec452SThiemo Seufer 	build_insn(buf, insn##op, a, b);		\
25422b0763aSDavid Daney }							\
25522b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
256e30ec452SThiemo Seufer 
257e30ec452SThiemo Seufer #define I_u1(op)					\
258e30ec452SThiemo Seufer Ip_u1(op)						\
259e30ec452SThiemo Seufer {							\
260e30ec452SThiemo Seufer 	build_insn(buf, insn##op, a);			\
26122b0763aSDavid Daney }							\
26222b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
263e30ec452SThiemo Seufer 
264e30ec452SThiemo Seufer #define I_0(op)						\
265e30ec452SThiemo Seufer Ip_0(op)						\
266e30ec452SThiemo Seufer {							\
267e30ec452SThiemo Seufer 	build_insn(buf, insn##op);			\
26822b0763aSDavid Daney }							\
26922b0763aSDavid Daney UASM_EXPORT_SYMBOL(uasm_i##op);
270e30ec452SThiemo Seufer 
271e30ec452SThiemo Seufer I_u2u1s3(_addiu)
272e30ec452SThiemo Seufer I_u3u1u2(_addu)
273e30ec452SThiemo Seufer I_u2u1u3(_andi)
274e30ec452SThiemo Seufer I_u3u1u2(_and)
275e30ec452SThiemo Seufer I_u1u2s3(_beq)
276e30ec452SThiemo Seufer I_u1u2s3(_beql)
277e30ec452SThiemo Seufer I_u1s2(_bgez)
278e30ec452SThiemo Seufer I_u1s2(_bgezl)
279dc190129SDavid Daney I_u1s2(_bgtz)
280dc190129SDavid Daney I_u1s2(_blez)
281e30ec452SThiemo Seufer I_u1s2(_bltz)
282e30ec452SThiemo Seufer I_u1s2(_bltzl)
283e30ec452SThiemo Seufer I_u1u2s3(_bne)
284dc190129SDavid Daney I_u1(_break)
285fb2a27e7SThiemo Seufer I_u2s3u1(_cache)
286c29732a1SJames Hogan I_u1u2(_cfc1)
28759e3559fSJames Hogan I_u2u1(_cfcmsa)
288c29732a1SJames Hogan I_u1u2(_ctc1)
28959e3559fSJames Hogan I_u2u1(_ctcmsa)
290dc190129SDavid Daney I_u1u2(_ddivu)
2910d1d17b9SHassan Naveed I_u3u1u2(_ddivu_r6)
292e30ec452SThiemo Seufer I_u1u2u3(_dmfc0)
2930d1d17b9SHassan Naveed I_u3u1u2(_dmodu)
294e30ec452SThiemo Seufer I_u1u2u3(_dmtc0)
295dc190129SDavid Daney I_u1u2(_dmultu)
2960d1d17b9SHassan Naveed I_u3u1u2(_dmulu)
297e30ec452SThiemo Seufer I_u2u1s3(_daddiu)
298e30ec452SThiemo Seufer I_u3u1u2(_daddu)
29961c64cf9SJames Hogan I_u1(_di);
3004c12a854SMarkos Chandras I_u1u2(_divu)
3010d1d17b9SHassan Naveed I_u3u1u2(_divu_r6)
302dc190129SDavid Daney I_u2u1(_dsbh);
303dc190129SDavid Daney I_u2u1(_dshd);
304e30ec452SThiemo Seufer I_u2u1u3(_dsll)
305e30ec452SThiemo Seufer I_u2u1u3(_dsll32)
306dc190129SDavid Daney I_u3u2u1(_dsllv)
307e30ec452SThiemo Seufer I_u2u1u3(_dsra)
308dc190129SDavid Daney I_u2u1u3(_dsra32)
309dc190129SDavid Daney I_u3u2u1(_dsrav)
310e30ec452SThiemo Seufer I_u2u1u3(_dsrl)
311e30ec452SThiemo Seufer I_u2u1u3(_dsrl32)
312dc190129SDavid Daney I_u3u2u1(_dsrlv)
31392078e06SDavid Daney I_u2u1u3(_drotr)
314de6d5b55SDavid Daney I_u2u1u3(_drotr32)
315e30ec452SThiemo Seufer I_u3u1u2(_dsubu)
316e30ec452SThiemo Seufer I_0(_eret)
317e6de1a09SSteven J. Hill I_u2u1msbdu3(_ext)
318e6de1a09SSteven J. Hill I_u2u1msbu3(_ins)
319e30ec452SThiemo Seufer I_u1(_j)
320e30ec452SThiemo Seufer I_u1(_jal)
32149e9529bSPaul Burton I_u2u1(_jalr)
322e30ec452SThiemo Seufer I_u1(_jr)
32382488818SMarkos Chandras I_u2s3u1(_lb)
324dc190129SDavid Daney I_u2s3u1(_lbu)
325e30ec452SThiemo Seufer I_u2s3u1(_ld)
326d6b3314bSMarkos Chandras I_u2s3u1(_lh)
327bfbfa9d6SDavid Daney I_u2s3u1(_lhu)
328e30ec452SThiemo Seufer I_u2s3u1(_ll)
329e30ec452SThiemo Seufer I_u2s3u1(_lld)
330e30ec452SThiemo Seufer I_u1s2(_lui)
331e30ec452SThiemo Seufer I_u2s3u1(_lw)
332dc190129SDavid Daney I_u2s3u1(_lwu)
333e30ec452SThiemo Seufer I_u1u2u3(_mfc0)
334e2965cd0SSteven J. Hill I_u1u2u3(_mfhc0)
3350d1d17b9SHassan Naveed I_u3u1u2(_modu)
336dc190129SDavid Daney I_u3u1u2(_movn)
337dc190129SDavid Daney I_u3u1u2(_movz)
338f3ec7a23SMarkos Chandras I_u1(_mfhi)
33916d21a81SMarkos Chandras I_u1(_mflo)
340e30ec452SThiemo Seufer I_u1u2u3(_mtc0)
341e2965cd0SSteven J. Hill I_u1u2u3(_mthc0)
3429f730a60SJames Hogan I_u1(_mthi)
3439f730a60SJames Hogan I_u1(_mtlo)
344a8e897adSMarkos Chandras I_u3u1u2(_mul)
345dc190129SDavid Daney I_u1u2(_multu)
3460d1d17b9SHassan Naveed I_u3u1u2(_mulu)
347*e737547eSTony Ambardar I_u3u1u2(_muhu)
348dc190129SDavid Daney I_u3u1u2(_nor)
3495808184fSRalf Baechle I_u3u1u2(_or)
350dc190129SDavid Daney I_u2u1u3(_ori)
351e30ec452SThiemo Seufer I_0(_rfe)
352dc190129SDavid Daney I_u2s3u1(_sb)
353e30ec452SThiemo Seufer I_u2s3u1(_sc)
354e30ec452SThiemo Seufer I_u2s3u1(_scd)
355e30ec452SThiemo Seufer I_u2s3u1(_sd)
3560d1d17b9SHassan Naveed I_u3u1u2(_seleqz)
3570d1d17b9SHassan Naveed I_u3u1u2(_selnez)
358dc190129SDavid Daney I_u2s3u1(_sh)
359e30ec452SThiemo Seufer I_u2u1u3(_sll)
360bef581baSMarkos Chandras I_u3u2u1(_sllv)
3617682f9e8SMarkos Chandras I_s3s1s2(_slt)
362dc190129SDavid Daney I_u2u1s3(_slti)
363390363edSMarkos Chandras I_u2u1s3(_sltiu)
364e8ef868bSMarkos Chandras I_u3u1u2(_sltu)
365e30ec452SThiemo Seufer I_u2u1u3(_sra)
366ee94b90cSJiong Wang I_u3u2u1(_srav)
367e30ec452SThiemo Seufer I_u2u1u3(_srl)
368f31318fdSMarkos Chandras I_u3u2u1(_srlv)
36932546f38SDavid Daney I_u2u1u3(_rotr)
370e30ec452SThiemo Seufer I_u3u1u2(_subu)
371e30ec452SThiemo Seufer I_u2s3u1(_sw)
372729ff561SPaul Burton I_u1(_sync)
373e30ec452SThiemo Seufer I_0(_tlbp)
37432546f38SDavid Daney I_0(_tlbr)
375e30ec452SThiemo Seufer I_0(_tlbwi)
376e30ec452SThiemo Seufer I_0(_tlbwr)
37753ed1389SPaul Burton I_u1(_wait);
378ab9e4fa0SMarkos Chandras I_u2u1(_wsbh)
379e30ec452SThiemo Seufer I_u3u1u2(_xor)
380e30ec452SThiemo Seufer I_u2u1u3(_xori)
381d674dd14SPaul Burton I_u2u1(_yield)
38292078e06SDavid Daney I_u2u1msbu3(_dins);
383c42aef09SDavid Daney I_u2u1msb32u3(_dinsm);
384dc190129SDavid Daney I_u2u1msb32msb3(_dinsu);
38558b9e223SDavid Daney I_u1(_syscall);
3865b97c3f7SDavid Daney I_u1u2s3(_bbit0);
3875b97c3f7SDavid Daney I_u1u2s3(_bbit1);
388bb3d68c3SDavid Daney I_u3u1u2(_lwx)
I_u3u1u2(_ldx)389bb3d68c3SDavid Daney I_u3u1u2(_ldx)
390380cd582SHuacai Chen I_u1u2(_ldpte)
391380cd582SHuacai Chen I_u2u1u3(_lddir)
392e30ec452SThiemo Seufer 
393c9941158SDavid Daney #ifdef CONFIG_CPU_CAVIUM_OCTEON
394c9941158SDavid Daney #include <asm/octeon/octeon.h>
39533679a50SPaul Burton void uasm_i_pref(u32 **buf, unsigned int a, signed int b,
396c9941158SDavid Daney 			    unsigned int c)
397c9941158SDavid Daney {
3988e7291d6SThomas Bogendoerfer 	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) && a <= 24 && a != 5)
399c9941158SDavid Daney 		/*
400c9941158SDavid Daney 		 * As per erratum Core-14449, replace prefetches 0-4,
401c9941158SDavid Daney 		 * 6-24 with 'pref 28'.
402c9941158SDavid Daney 		 */
403c9941158SDavid Daney 		build_insn(buf, insn_pref, c, 28, b);
404c9941158SDavid Daney 	else
405c9941158SDavid Daney 		build_insn(buf, insn_pref, c, a, b);
406c9941158SDavid Daney }
40733679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_i_pref);
408c9941158SDavid Daney #else
409c9941158SDavid Daney I_u2s3u1(_pref)
410c9941158SDavid Daney #endif
411c9941158SDavid Daney 
412e30ec452SThiemo Seufer /* Handle labels. */
uasm_build_label(struct uasm_label ** lab,u32 * addr,int lid)41333679a50SPaul Burton void uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
414e30ec452SThiemo Seufer {
415e30ec452SThiemo Seufer 	(*lab)->addr = addr;
416e30ec452SThiemo Seufer 	(*lab)->lab = lid;
417e30ec452SThiemo Seufer 	(*lab)++;
418e30ec452SThiemo Seufer }
41933679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_build_label);
420e30ec452SThiemo Seufer 
uasm_in_compat_space_p(long addr)42133679a50SPaul Burton int uasm_in_compat_space_p(long addr)
422e30ec452SThiemo Seufer {
423e30ec452SThiemo Seufer 	/* Is this address in 32bit compat space? */
424f7d9afeaSJames Hogan 	return addr == (int)addr;
425e30ec452SThiemo Seufer }
42633679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_in_compat_space_p);
427e30ec452SThiemo Seufer 
uasm_rel_highest(long val)428078a55fcSPaul Gortmaker static int uasm_rel_highest(long val)
429e30ec452SThiemo Seufer {
430e30ec452SThiemo Seufer #ifdef CONFIG_64BIT
431e30ec452SThiemo Seufer 	return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
432e30ec452SThiemo Seufer #else
433e30ec452SThiemo Seufer 	return 0;
434e30ec452SThiemo Seufer #endif
435e30ec452SThiemo Seufer }
436e30ec452SThiemo Seufer 
uasm_rel_higher(long val)437078a55fcSPaul Gortmaker static int uasm_rel_higher(long val)
438e30ec452SThiemo Seufer {
439e30ec452SThiemo Seufer #ifdef CONFIG_64BIT
440e30ec452SThiemo Seufer 	return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
441e30ec452SThiemo Seufer #else
442e30ec452SThiemo Seufer 	return 0;
443e30ec452SThiemo Seufer #endif
444e30ec452SThiemo Seufer }
445e30ec452SThiemo Seufer 
uasm_rel_hi(long val)44633679a50SPaul Burton int uasm_rel_hi(long val)
447e30ec452SThiemo Seufer {
448e30ec452SThiemo Seufer 	return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
449e30ec452SThiemo Seufer }
45033679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_rel_hi);
451e30ec452SThiemo Seufer 
uasm_rel_lo(long val)45233679a50SPaul Burton int uasm_rel_lo(long val)
453e30ec452SThiemo Seufer {
454e30ec452SThiemo Seufer 	return ((val & 0xffff) ^ 0x8000) - 0x8000;
455e30ec452SThiemo Seufer }
45633679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_rel_lo);
457e30ec452SThiemo Seufer 
UASM_i_LA_mostly(u32 ** buf,unsigned int rs,long addr)45833679a50SPaul Burton void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr)
459e30ec452SThiemo Seufer {
46033679a50SPaul Burton 	if (!uasm_in_compat_space_p(addr)) {
46133679a50SPaul Burton 		uasm_i_lui(buf, rs, uasm_rel_highest(addr));
462e30ec452SThiemo Seufer 		if (uasm_rel_higher(addr))
46333679a50SPaul Burton 			uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr));
46433679a50SPaul Burton 		if (uasm_rel_hi(addr)) {
46533679a50SPaul Burton 			uasm_i_dsll(buf, rs, rs, 16);
46633679a50SPaul Burton 			uasm_i_daddiu(buf, rs, rs,
46733679a50SPaul Burton 					uasm_rel_hi(addr));
46833679a50SPaul Burton 			uasm_i_dsll(buf, rs, rs, 16);
469e30ec452SThiemo Seufer 		} else
47033679a50SPaul Burton 			uasm_i_dsll32(buf, rs, rs, 0);
471e30ec452SThiemo Seufer 	} else
47233679a50SPaul Burton 		uasm_i_lui(buf, rs, uasm_rel_hi(addr));
473e30ec452SThiemo Seufer }
47433679a50SPaul Burton UASM_EXPORT_SYMBOL(UASM_i_LA_mostly);
475e30ec452SThiemo Seufer 
UASM_i_LA(u32 ** buf,unsigned int rs,long addr)47633679a50SPaul Burton void UASM_i_LA(u32 **buf, unsigned int rs, long addr)
477e30ec452SThiemo Seufer {
47833679a50SPaul Burton 	UASM_i_LA_mostly(buf, rs, addr);
47933679a50SPaul Burton 	if (uasm_rel_lo(addr)) {
48033679a50SPaul Burton 		if (!uasm_in_compat_space_p(addr))
48133679a50SPaul Burton 			uasm_i_daddiu(buf, rs, rs,
48233679a50SPaul Burton 					uasm_rel_lo(addr));
483e30ec452SThiemo Seufer 		else
48433679a50SPaul Burton 			uasm_i_addiu(buf, rs, rs,
48533679a50SPaul Burton 					uasm_rel_lo(addr));
486e30ec452SThiemo Seufer 	}
487e30ec452SThiemo Seufer }
48833679a50SPaul Burton UASM_EXPORT_SYMBOL(UASM_i_LA);
489e30ec452SThiemo Seufer 
490e30ec452SThiemo Seufer /* Handle relocations. */
uasm_r_mips_pc16(struct uasm_reloc ** rel,u32 * addr,int lid)49133679a50SPaul Burton void uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid)
492e30ec452SThiemo Seufer {
493e30ec452SThiemo Seufer 	(*rel)->addr = addr;
494e30ec452SThiemo Seufer 	(*rel)->type = R_MIPS_PC16;
495e30ec452SThiemo Seufer 	(*rel)->lab = lid;
496e30ec452SThiemo Seufer 	(*rel)++;
497e30ec452SThiemo Seufer }
49833679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_r_mips_pc16);
499e30ec452SThiemo Seufer 
500078a55fcSPaul Gortmaker static inline void __resolve_relocs(struct uasm_reloc *rel,
501078a55fcSPaul Gortmaker 				    struct uasm_label *lab);
502e30ec452SThiemo Seufer 
uasm_resolve_relocs(struct uasm_reloc * rel,struct uasm_label * lab)50333679a50SPaul Burton void uasm_resolve_relocs(struct uasm_reloc *rel,
504078a55fcSPaul Gortmaker 				  struct uasm_label *lab)
505e30ec452SThiemo Seufer {
506e30ec452SThiemo Seufer 	struct uasm_label *l;
507e30ec452SThiemo Seufer 
508e30ec452SThiemo Seufer 	for (; rel->lab != UASM_LABEL_INVALID; rel++)
509e30ec452SThiemo Seufer 		for (l = lab; l->lab != UASM_LABEL_INVALID; l++)
510e30ec452SThiemo Seufer 			if (rel->lab == l->lab)
511e30ec452SThiemo Seufer 				__resolve_relocs(rel, l);
512e30ec452SThiemo Seufer }
51333679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_resolve_relocs);
514e30ec452SThiemo Seufer 
uasm_move_relocs(struct uasm_reloc * rel,u32 * first,u32 * end,long off)51533679a50SPaul Burton void uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end,
516078a55fcSPaul Gortmaker 			       long off)
517e30ec452SThiemo Seufer {
518e30ec452SThiemo Seufer 	for (; rel->lab != UASM_LABEL_INVALID; rel++)
519e30ec452SThiemo Seufer 		if (rel->addr >= first && rel->addr < end)
520e30ec452SThiemo Seufer 			rel->addr += off;
521e30ec452SThiemo Seufer }
52233679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_move_relocs);
523e30ec452SThiemo Seufer 
uasm_move_labels(struct uasm_label * lab,u32 * first,u32 * end,long off)52433679a50SPaul Burton void uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end,
525078a55fcSPaul Gortmaker 			       long off)
526e30ec452SThiemo Seufer {
527e30ec452SThiemo Seufer 	for (; lab->lab != UASM_LABEL_INVALID; lab++)
528e30ec452SThiemo Seufer 		if (lab->addr >= first && lab->addr < end)
529e30ec452SThiemo Seufer 			lab->addr += off;
530e30ec452SThiemo Seufer }
53133679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_move_labels);
532e30ec452SThiemo Seufer 
uasm_copy_handler(struct uasm_reloc * rel,struct uasm_label * lab,u32 * first,u32 * end,u32 * target)53333679a50SPaul Burton void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab,
534078a55fcSPaul Gortmaker 				u32 *first, u32 *end, u32 *target)
535e30ec452SThiemo Seufer {
536e30ec452SThiemo Seufer 	long off = (long)(target - first);
537e30ec452SThiemo Seufer 
538e30ec452SThiemo Seufer 	memcpy(target, first, (end - first) * sizeof(u32));
539e30ec452SThiemo Seufer 
54033679a50SPaul Burton 	uasm_move_relocs(rel, first, end, off);
54133679a50SPaul Burton 	uasm_move_labels(lab, first, end, off);
542e30ec452SThiemo Seufer }
54333679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_copy_handler);
544e30ec452SThiemo Seufer 
uasm_insn_has_bdelay(struct uasm_reloc * rel,u32 * addr)54533679a50SPaul Burton int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
546e30ec452SThiemo Seufer {
547e30ec452SThiemo Seufer 	for (; rel->lab != UASM_LABEL_INVALID; rel++) {
548e30ec452SThiemo Seufer 		if (rel->addr == addr
549e30ec452SThiemo Seufer 		    && (rel->type == R_MIPS_PC16
550e30ec452SThiemo Seufer 			|| rel->type == R_MIPS_26))
551e30ec452SThiemo Seufer 			return 1;
552e30ec452SThiemo Seufer 	}
553e30ec452SThiemo Seufer 
554e30ec452SThiemo Seufer 	return 0;
555e30ec452SThiemo Seufer }
55633679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay);
557e30ec452SThiemo Seufer 
558e30ec452SThiemo Seufer /* Convenience functions for labeled branches. */
uasm_il_bltz(u32 ** p,struct uasm_reloc ** r,unsigned int reg,int lid)55933679a50SPaul Burton void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg,
560078a55fcSPaul Gortmaker 			   int lid)
561e30ec452SThiemo Seufer {
562e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
56333679a50SPaul Burton 	uasm_i_bltz(p, reg, 0);
564e30ec452SThiemo Seufer }
56533679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bltz);
566e30ec452SThiemo Seufer 
uasm_il_b(u32 ** p,struct uasm_reloc ** r,int lid)56733679a50SPaul Burton void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid)
568e30ec452SThiemo Seufer {
569e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
57033679a50SPaul Burton 	uasm_i_b(p, 0);
571e30ec452SThiemo Seufer }
57233679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_b);
573e30ec452SThiemo Seufer 
uasm_il_beq(u32 ** p,struct uasm_reloc ** r,unsigned int r1,unsigned int r2,int lid)57433679a50SPaul Burton void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int r1,
5758dee5901SPaul Burton 			  unsigned int r2, int lid)
5768dee5901SPaul Burton {
5778dee5901SPaul Burton 	uasm_r_mips_pc16(r, *p, lid);
57833679a50SPaul Burton 	uasm_i_beq(p, r1, r2, 0);
5798dee5901SPaul Burton }
58033679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_beq);
5818dee5901SPaul Burton 
uasm_il_beqz(u32 ** p,struct uasm_reloc ** r,unsigned int reg,int lid)58233679a50SPaul Burton void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg,
583078a55fcSPaul Gortmaker 			   int lid)
584e30ec452SThiemo Seufer {
585e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
58633679a50SPaul Burton 	uasm_i_beqz(p, reg, 0);
587e30ec452SThiemo Seufer }
58833679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_beqz);
589e30ec452SThiemo Seufer 
uasm_il_beqzl(u32 ** p,struct uasm_reloc ** r,unsigned int reg,int lid)59033679a50SPaul Burton void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg,
591078a55fcSPaul Gortmaker 			    int lid)
592e30ec452SThiemo Seufer {
593e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
59433679a50SPaul Burton 	uasm_i_beqzl(p, reg, 0);
595e30ec452SThiemo Seufer }
59633679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_beqzl);
597e30ec452SThiemo Seufer 
uasm_il_bne(u32 ** p,struct uasm_reloc ** r,unsigned int reg1,unsigned int reg2,int lid)59833679a50SPaul Burton void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
599fb2a27e7SThiemo Seufer 			  unsigned int reg2, int lid)
600fb2a27e7SThiemo Seufer {
601fb2a27e7SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
60233679a50SPaul Burton 	uasm_i_bne(p, reg1, reg2, 0);
603fb2a27e7SThiemo Seufer }
60433679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bne);
605fb2a27e7SThiemo Seufer 
uasm_il_bnez(u32 ** p,struct uasm_reloc ** r,unsigned int reg,int lid)60633679a50SPaul Burton void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg,
607078a55fcSPaul Gortmaker 			   int lid)
608e30ec452SThiemo Seufer {
609e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
61033679a50SPaul Burton 	uasm_i_bnez(p, reg, 0);
611e30ec452SThiemo Seufer }
61233679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bnez);
613e30ec452SThiemo Seufer 
uasm_il_bgezl(u32 ** p,struct uasm_reloc ** r,unsigned int reg,int lid)61433679a50SPaul Burton void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg,
615078a55fcSPaul Gortmaker 			    int lid)
616e30ec452SThiemo Seufer {
617e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
61833679a50SPaul Burton 	uasm_i_bgezl(p, reg, 0);
619e30ec452SThiemo Seufer }
62033679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bgezl);
621e30ec452SThiemo Seufer 
uasm_il_bgez(u32 ** p,struct uasm_reloc ** r,unsigned int reg,int lid)62233679a50SPaul Burton void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg,
623078a55fcSPaul Gortmaker 			   int lid)
624e30ec452SThiemo Seufer {
625e30ec452SThiemo Seufer 	uasm_r_mips_pc16(r, *p, lid);
62633679a50SPaul Burton 	uasm_i_bgez(p, reg, 0);
627e30ec452SThiemo Seufer }
62833679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bgez);
6295b97c3f7SDavid Daney 
uasm_il_bbit0(u32 ** p,struct uasm_reloc ** r,unsigned int reg,unsigned int bit,int lid)63033679a50SPaul Burton void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
6315b97c3f7SDavid Daney 			    unsigned int bit, int lid)
6325b97c3f7SDavid Daney {
6335b97c3f7SDavid Daney 	uasm_r_mips_pc16(r, *p, lid);
63433679a50SPaul Burton 	uasm_i_bbit0(p, reg, bit, 0);
6355b97c3f7SDavid Daney }
63633679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bbit0);
6375b97c3f7SDavid Daney 
uasm_il_bbit1(u32 ** p,struct uasm_reloc ** r,unsigned int reg,unsigned int bit,int lid)63833679a50SPaul Burton void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
6395b97c3f7SDavid Daney 			    unsigned int bit, int lid)
6405b97c3f7SDavid Daney {
6415b97c3f7SDavid Daney 	uasm_r_mips_pc16(r, *p, lid);
64233679a50SPaul Burton 	uasm_i_bbit1(p, reg, bit, 0);
6435b97c3f7SDavid Daney }
64433679a50SPaul Burton UASM_EXPORT_SYMBOL(uasm_il_bbit1);
645