Commit | Line | Data |
---|---|---|
e30ec452 TS |
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 | * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer | |
7 | * Copyright (C) 2005 Maciej W. Rozycki | |
8 | * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) | |
9 | */ | |
10 | ||
11 | #include <linux/types.h> | |
12 | ||
13 | #define Ip_u1u2u3(op) \ | |
234fcd14 | 14 | void __cpuinit \ |
e30ec452 TS |
15 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) |
16 | ||
17 | #define Ip_u2u1u3(op) \ | |
234fcd14 | 18 | void __cpuinit \ |
e30ec452 TS |
19 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) |
20 | ||
21 | #define Ip_u3u1u2(op) \ | |
234fcd14 | 22 | void __cpuinit \ |
e30ec452 TS |
23 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) |
24 | ||
25 | #define Ip_u1u2s3(op) \ | |
234fcd14 | 26 | void __cpuinit \ |
e30ec452 TS |
27 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) |
28 | ||
29 | #define Ip_u2s3u1(op) \ | |
234fcd14 | 30 | void __cpuinit \ |
e30ec452 TS |
31 | uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) |
32 | ||
33 | #define Ip_u2u1s3(op) \ | |
234fcd14 | 34 | void __cpuinit \ |
e30ec452 TS |
35 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) |
36 | ||
92078e06 DD |
37 | #define Ip_u2u1msbu3(op) \ |
38 | void __cpuinit \ | |
39 | uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ | |
40 | unsigned int d) | |
41 | ||
e30ec452 | 42 | #define Ip_u1u2(op) \ |
234fcd14 | 43 | void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) |
e30ec452 TS |
44 | |
45 | #define Ip_u1s2(op) \ | |
234fcd14 | 46 | void __cpuinit uasm_i##op(u32 **buf, unsigned int a, signed int b) |
e30ec452 | 47 | |
234fcd14 | 48 | #define Ip_u1(op) void __cpuinit uasm_i##op(u32 **buf, unsigned int a) |
e30ec452 | 49 | |
234fcd14 | 50 | #define Ip_0(op) void __cpuinit uasm_i##op(u32 **buf) |
e30ec452 TS |
51 | |
52 | Ip_u2u1s3(_addiu); | |
53 | Ip_u3u1u2(_addu); | |
54 | Ip_u2u1u3(_andi); | |
55 | Ip_u3u1u2(_and); | |
56 | Ip_u1u2s3(_beq); | |
57 | Ip_u1u2s3(_beql); | |
58 | Ip_u1s2(_bgez); | |
59 | Ip_u1s2(_bgezl); | |
60 | Ip_u1s2(_bltz); | |
61 | Ip_u1s2(_bltzl); | |
62 | Ip_u1u2s3(_bne); | |
fb2a27e7 | 63 | Ip_u2s3u1(_cache); |
e30ec452 TS |
64 | Ip_u1u2u3(_dmfc0); |
65 | Ip_u1u2u3(_dmtc0); | |
66 | Ip_u2u1s3(_daddiu); | |
67 | Ip_u3u1u2(_daddu); | |
68 | Ip_u2u1u3(_dsll); | |
69 | Ip_u2u1u3(_dsll32); | |
70 | Ip_u2u1u3(_dsra); | |
71 | Ip_u2u1u3(_dsrl); | |
72 | Ip_u2u1u3(_dsrl32); | |
92078e06 | 73 | Ip_u2u1u3(_drotr); |
e30ec452 TS |
74 | Ip_u3u1u2(_dsubu); |
75 | Ip_0(_eret); | |
76 | Ip_u1(_j); | |
77 | Ip_u1(_jal); | |
78 | Ip_u1(_jr); | |
79 | Ip_u2s3u1(_ld); | |
80 | Ip_u2s3u1(_ll); | |
81 | Ip_u2s3u1(_lld); | |
82 | Ip_u1s2(_lui); | |
83 | Ip_u2s3u1(_lw); | |
84 | Ip_u1u2u3(_mfc0); | |
85 | Ip_u1u2u3(_mtc0); | |
86 | Ip_u2u1u3(_ori); | |
fb2a27e7 | 87 | Ip_u2s3u1(_pref); |
e30ec452 TS |
88 | Ip_0(_rfe); |
89 | Ip_u2s3u1(_sc); | |
90 | Ip_u2s3u1(_scd); | |
91 | Ip_u2s3u1(_sd); | |
92 | Ip_u2u1u3(_sll); | |
93 | Ip_u2u1u3(_sra); | |
94 | Ip_u2u1u3(_srl); | |
32546f38 | 95 | Ip_u2u1u3(_rotr); |
e30ec452 TS |
96 | Ip_u3u1u2(_subu); |
97 | Ip_u2s3u1(_sw); | |
98 | Ip_0(_tlbp); | |
32546f38 | 99 | Ip_0(_tlbr); |
e30ec452 TS |
100 | Ip_0(_tlbwi); |
101 | Ip_0(_tlbwr); | |
102 | Ip_u3u1u2(_xor); | |
103 | Ip_u2u1u3(_xori); | |
92078e06 | 104 | Ip_u2u1msbu3(_dins); |
58b9e223 | 105 | Ip_u1(_syscall); |
e30ec452 TS |
106 | |
107 | /* Handle labels. */ | |
108 | struct uasm_label { | |
109 | u32 *addr; | |
110 | int lab; | |
111 | }; | |
112 | ||
234fcd14 | 113 | void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); |
e30ec452 | 114 | #ifdef CONFIG_64BIT |
234fcd14 | 115 | int uasm_in_compat_space_p(long addr); |
e30ec452 | 116 | #endif |
234fcd14 RB |
117 | int uasm_rel_hi(long val); |
118 | int uasm_rel_lo(long val); | |
119 | void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); | |
120 | void UASM_i_LA(u32 **buf, unsigned int rs, long addr); | |
e30ec452 TS |
121 | |
122 | #define UASM_L_LA(lb) \ | |
234fcd14 | 123 | static inline void __cpuinit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ |
e30ec452 TS |
124 | { \ |
125 | uasm_build_label(lab, addr, label##lb); \ | |
126 | } | |
127 | ||
128 | /* convenience macros for instructions */ | |
129 | #ifdef CONFIG_64BIT | |
130 | # define UASM_i_LW(buf, rs, rt, off) uasm_i_ld(buf, rs, rt, off) | |
131 | # define UASM_i_SW(buf, rs, rt, off) uasm_i_sd(buf, rs, rt, off) | |
132 | # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh) | |
133 | # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh) | |
134 | # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh) | |
32546f38 | 135 | # define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh) |
e30ec452 TS |
136 | # define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd) |
137 | # define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd) | |
138 | # define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_daddiu(buf, rs, rt, val) | |
139 | # define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_daddu(buf, rs, rt, rd) | |
140 | # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd) | |
141 | # define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off) | |
142 | # define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off) | |
143 | #else | |
144 | # define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off) | |
145 | # define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off) | |
146 | # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh) | |
147 | # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh) | |
148 | # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh) | |
32546f38 | 149 | # define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh) |
e30ec452 TS |
150 | # define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd) |
151 | # define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd) | |
152 | # define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_addiu(buf, rs, rt, val) | |
153 | # define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_addu(buf, rs, rt, rd) | |
154 | # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd) | |
155 | # define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off) | |
156 | # define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off) | |
157 | #endif | |
158 | ||
159 | #define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off) | |
160 | #define uasm_i_beqz(buf, rs, off) uasm_i_beq(buf, rs, 0, off) | |
161 | #define uasm_i_beqzl(buf, rs, off) uasm_i_beql(buf, rs, 0, off) | |
162 | #define uasm_i_bnez(buf, rs, off) uasm_i_bne(buf, rs, 0, off) | |
163 | #define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off) | |
164 | #define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b) | |
165 | #define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0) | |
166 | #define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1) | |
167 | #define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3) | |
168 | ||
169 | /* Handle relocations. */ | |
170 | struct uasm_reloc { | |
171 | u32 *addr; | |
172 | unsigned int type; | |
173 | int lab; | |
174 | }; | |
175 | ||
176 | /* This is zero so we can use zeroed label arrays. */ | |
177 | #define UASM_LABEL_INVALID 0 | |
178 | ||
234fcd14 RB |
179 | void uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid); |
180 | void uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab); | |
181 | void uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off); | |
182 | void uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off); | |
183 | void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, | |
184 | u32 *first, u32 *end, u32 *target); | |
185 | int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr); | |
e30ec452 TS |
186 | |
187 | /* Convenience functions for labeled branches. */ | |
234fcd14 RB |
188 | void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); |
189 | void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid); | |
190 | void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); | |
191 | void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); | |
fb2a27e7 TS |
192 | void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, |
193 | unsigned int reg2, int lid); | |
234fcd14 RB |
194 | void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); |
195 | void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); | |
196 | void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); |