]> git.saurik.com Git - apple/xnu.git/blob - EXTERNAL_HEADERS/architecture/ppc/pseudo_inst.h
xnu-792.10.96.tar.gz
[apple/xnu.git] / EXTERNAL_HEADERS / architecture / ppc / pseudo_inst.h
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1996 NeXT Software, Inc. All rights reserved.
23 *
24 * File: architecture/ppc/pseudo_inst.h
25 * Author: Mike DeMoney
26 *
27 * This header file defines assembler pseudo-instruction macros for
28 * for the ppc.
29 *
30 * NOTE: This is obviously only useful to include in assembly
31 * code source.
32 *
33 * ALSO NOTE: These macros don't attempt to be 64-bit compatable
34 *
35 * HISTORY
36 * 29-Dec-96 Umesh Vaishampayan (umeshv@NeXT.com)
37 * Ported from m98k.
38 * 05-Nov-92 Mike DeMoney (mike@next.com)
39 * Created.
40 */
41
42 #ifndef _ARCH_PPC_PSEUDO_INST_H_
43 #define _ARCH_PPC_PSEUDO_INST_H_
44
45 #include <architecture/ppc/reg_help.h>
46 #include <architecture/ppc/asm_help.h>
47
48 #ifdef __ASSEMBLER__
49
50 /*
51 * Pseudo instruction definitions
52 */
53
54 /*
55 * Macro package initialization
56 */
57 .set __no_at,0 /* allow at by default */
58
59 /*
60 * .at_off -- disable use of at by macros
61 * .at_on -- enable use of at by macros
62 */
63 .macro .at_off
64 .set __no_at,1
65 .endmacro
66
67 .macro .at_on
68 .set __no_at,0
69 .endmacro
70
71 /*
72 * li32 rD,IMMED
73 *
74 * Load 32-bit immediate into rD
75 * FIXME: Need a way to undefine built-in macro for this.
76 */
77 .macro li32 // li32 rD,immed
78 .if $n != 2
79 .abort "invalid operands of li32"
80 .endif
81 .abs __is_abs,$1
82 .if !__is_abs
83 addis $0,0,hi16($1)
84 ori $0,$0,lo16($1)
85 .elseif $1 == 0
86 addi $0,0,0
87 .elseif ($1 & 0xffff) == 0
88 addis $0,0,hi16($1)
89 .elseif ($1 & 0xffff8000) == 0
90 addi $0,0,$1
91 .elseif ($1 & 0xffff8000) == 0xffff8000
92 addi $0,0,$1
93 .else
94 addis $0,0,hi16($1)
95 ori $0,$0,lo16($1)
96 .endif
97 .endmacro
98
99
100 /*
101 * andi32. rD,rS1,IMMED
102 *
103 * Perform "andi." with (possibly) 32-bit immediate
104 */
105 .macro andi32. // andi32. rD,rS1,IMMED
106 .if $n != 3
107 .abort "invalid operands of andi."
108 .endif
109 .set __used_at,0
110 .abs __is_abs,$2
111 .if !__is_abs
112 .set __used_at,1
113 li32 at,$2
114 and. $0,$1,at
115 .elseif ($2 & 0xffff0000) == 0
116 andi. $0,$1,$2
117 .elseif ($2 & 0xffff) == 0
118 andis. $0,$1,hi16($2)
119 .else
120 .set __used_at,1
121 li32 at,$2
122 and. $0,$1,at
123 .endif
124 .if __no_at & __used_at
125 .abort "Macro uses at while .no_at in effect"
126 .endif
127 .endmacro
128
129 /*
130 * ori32 rD,rS1,IMMED
131 *
132 * Perform "ori" with (possibly) 32-bit immediate
133 */
134 .macro ori32 // ori32 rD,rS1,IMMED
135 .if $n != 3
136 .abort "invalid operands of ori"
137 .endif
138 .abs __is_abs,$2
139 .if !__is_abs
140 oris $0,$1,hi16($2)
141 ori $0,$1,lo16($2)
142 .elseif ($2 & 0xffff0000) == 0
143 ori $0,$1,$2
144 .elseif ($2 & 0xffff) == 0
145 oris $0,$1,hi16($2)
146 .else
147 oris $0,$1,hi16($2)
148 ori $0,$1,lo16($2)
149 .endif
150 .endmacro
151
152 /*
153 * xori32 rD,rS1,IMMED
154 *
155 * Perform "xor" with (possibly) 32-bit immediate
156 */
157 .macro xori32 // xori32 rD,rS1,IMMED
158 .if $n != 3
159 .abort "invalid operands of xori"
160 .endif
161 .abs __is_abs,$2
162 .if !__is_abs
163 xoris $0,$1,hi16($2)
164 xori $0,$1,lo16($2)
165 .elseif ($2 & 0xffff0000) == 0
166 xori $0,$1,$2
167 .elseif ($2 & 0xffff) == 0
168 xoris $0,$1,hi16($2)
169 .else
170 xoris $0,$1,hi16($2)
171 xori $0,$1,lo16($2)
172 .endif
173 .endmacro
174
175
176 /*
177 * MEMREF_INST -- macros to memory referencing instructions
178 * "capable" of dealing with 32 bit offsets.
179 *
180 * NOTE: Because the assembler doesn't have any mechanism for easily
181 * parsing the d(rS) syntax of register-displacement form instructions,
182 * these instructions do NOT mirror the normal memory reference
183 * instructions. The following "transformation" is used:
184 * lbz rD,d(rS)
185 * becomes:
186 * lbz32 rD,rS,d
187 * I.e.: "32" is appended to the instruction name and the base register
188 * and displacement become the 2'nd and 3'rd comma-separated operands.
189 *
190 * The forms:
191 * lbz32 rD,d
192 * and:
193 * lbz32 rD,rS
194 * are also recognized and the missing operand is assumed 0.
195 *
196 * ALSO NOTE: r0 or zt should never be used as rS in these instructions.
197 * Use "0" as rS in this case.
198 */
199 #define MEMREF_INST(op) \
200 .macro op ## 32 @\
201 .set __used_at,0 @\
202 .if $n == 3 @\
203 .greg __is_greg,$1 @\
204 .abs __is_abs,$2 @\
205 .if __is_abs @\
206 .if ($2 & 0xffff8000) == 0 @\
207 op $0,$2($1) @\
208 .elseif ($2 & 0xffff8000) == 0xffff8000 @\
209 op $0,$2($1) @\
210 .else @\
211 .if !__is_greg @\
212 .set __used_at,1 @\
213 lis at,ha16($2) @\
214 op $0,lo16($2)(at) @\
215 .else @\
216 .set __used_at,1 @\
217 lis at,ha16($2) @\
218 add at,at,$1 @\
219 op $0,lo16($2)(at) @\
220 .endif @\
221 .endif @\
222 .else @\
223 .if !__is_greg @\
224 .set __used_at,1 @\
225 lis at,ha16($2) @\
226 op $0,lo16($2)(at) @\
227 .else @\
228 .set __used_at,1 @\
229 lis at,ha16($2) @\
230 add at,at,$1 @\
231 op $0,lo16($2)(at) @\
232 .endif @\
233 .endif @\
234 .elseif $n == 2 @\
235 .greg __is_greg,$1 @\
236 .if !__is_greg @\
237 .abs __is_abs,$1 @\
238 .if __is_abs @\
239 .if ($1 & 0xffff8000) == 0 @\
240 op $0,$1(0) @\
241 .elseif ($1 & 0xffff8000) == 0xffff8000 @\
242 op $0,$1(0) @\
243 .else @\
244 .set __used_at,1 @\
245 lis at,ha16($1) @\
246 op $0,lo16($1)(at) @\
247 .endif @\
248 .else @\
249 .set __used_at,1 @\
250 lis at,ha16($1) @\
251 op $0,lo16($1)(at) @\
252 .endif @\
253 .else @\
254 op $0,0($1) @\
255 .endif @\
256 .else @\
257 .abort "Invalid operands of " #op "32" @\
258 .endif @\
259 .if __no_at & __used_at @\
260 .abort "Macro uses at while .no_at in effect" @\
261 .endif @\
262 .endmacro
263
264 MEMREF_INST(lbz)
265 MEMREF_INST(lhz)
266 MEMREF_INST(lha)
267 MEMREF_INST(lwz)
268 MEMREF_INST(lwa)
269 MEMREF_INST(ld)
270
271 MEMREF_INST(stb)
272 MEMREF_INST(sth)
273 MEMREF_INST(stw)
274 MEMREF_INST(std)
275
276 MEMREF_INST(lmw)
277 MEMREF_INST(lmd)
278 MEMREF_INST(stmw)
279 MEMREF_INST(stmd)
280
281 /*
282 * ARITH_INST -- define 32-bit immediate forms of arithmetic
283 * instructions
284 *
285 * E.g. addi32 rD,rS,IMMED
286 */
287 #define ARITH_INST(op, op3, sf) \
288 .macro op ## 32 ## sf @\
289 .if $n != 3 @\
290 .abort "invalid operands to " #op "32" @\
291 .endif @\
292 .abs __is_abs,$2 @\
293 .if __is_abs @\
294 .if ($2 & 0xffff8000) == 0 @\
295 op##sf $0,$1,$2 @\
296 .elseif ($2 & 0xffff8000) == 0xffff8000 @\
297 op##sf $0,$1,$2 @\
298 .elseif __no_at @\
299 .abort "Macro uses at while .no_at in effect" @\
300 .else @\
301 li32 at,$2 @\
302 op3##sf $0,$1,at @\
303 .endif @\
304 .elseif __no_at @\
305 .abort "Macro uses at while .no_at in effect" @\
306 .else @\
307 li32 at,$2 @\
308 op3##sf $0,$1,at @\
309 .endif @\
310 .endmacro
311
312 ARITH_INST(addi, add, )
313 ARITH_INST(subi, sub, )
314 ARITH_INST(addic, addc, )
315 ARITH_INST(subic, subc, )
316 ARITH_INST(addic, addc, .)
317 ARITH_INST(subic, subc, .)
318 ARITH_INST(mulli, mull, )
319
320 /*
321 * CMPEX_INST -- define 32-bit immediate forms of extended compare
322 * instructions
323 *
324 * E.g. cmpwi32 cr3,rS,IMMED
325 * cmpwi32 rS,IMMED
326 */
327 #define CMPEX_INST(op, op3) \
328 .macro op ## 32 @\
329 .if $n == 3 @\
330 .abs __is_abs,$2 @\
331 .if __is_abs @\
332 .if ($2 & 0xffff8000) == 0 @\
333 op $0,$1,$2 @\
334 .elseif ($2 & 0xffff8000) == 0xffff8000 @\
335 op $0,$1,$2 @\
336 .elseif __no_at @\
337 .abort "Macro uses at while .no_at in effect" @\
338 .else @\
339 li32 at,$2 @\
340 op3 $0,$1,at @\
341 .endif @\
342 .elseif __no_at @\
343 .abort "Macro uses at while .no_at in effect" @\
344 .else @\
345 li32 at,$2 @\
346 op3 $0,$1,at @\
347 .endif @\
348 .elseif $n == 2 @\
349 .abs __is_abs,$1 @\
350 .if __is_abs @\
351 .if ($1 & 0xffff8000) == 0 @\
352 op $0,$1 @\
353 .elseif ($1 & 0xffff8000) == 0xffff8000 @\
354 op $0,$1 @\
355 .elseif __no_at @\
356 .abort "Macro uses at while .no_at in effect" @\
357 .else @\
358 li32 at,$1 @\
359 op3 $0,at @\
360 .endif @\
361 .elseif __no_at @\
362 .abort "Macro uses at while .no_at in effect" @\
363 .else @\
364 li32 at,$1 @\
365 op3 $0,at @\
366 .endif @\
367 .else @\
368 .abort "invalid operands to " #op "32" @\
369 .endif @\
370 .endmacro
371
372 CMPEX_INST(cmpdi, cmpd)
373 CMPEX_INST(cmpwi, cmpw)
374 CMPEX_INST(cmpldi, cmpld)
375 CMPEX_INST(cmplwi, cmplw)
376
377 /*
378 * CMP_INST -- define 32-bit immediate forms of standard compare
379 * instructions
380 *
381 * E.g. cmpi32 cr3,0,rS,IMMED
382 */
383 #define CMP_INST(op, op3) \
384 .macro op ## 32 @\
385 .if $n == 4 @\
386 .abs __is_abs,$3 @\
387 .if __is_abs @\
388 .if ($3 & 0xffff8000) == 0 @\
389 op $0,$1,$2,$3 @\
390 .elseif ($3 & 0xffff8000) == 0xffff8000 @\
391 op $0,$1,$2,$3 @\
392 .elseif __no_at @\
393 .abort "Macro uses at while .no_at in effect" @\
394 .else @\
395 li32 at,$3 @\
396 op3 $0,$1,$2,at @\
397 .endif @\
398 .elseif __no_at @\
399 .abort "Macro uses at while .no_at in effect" @\
400 .else @\
401 li32 at,$3 @\
402 op3 $0,$1,$2,at @\
403 .endif @\
404 .else @\
405 .abort "invalid operands to " #op "32" @\
406 .endif @\
407 .endmacro
408
409 CMP_INST(cmpi, cmp)
410 CMP_INST(cmpli, cmpl)
411
412 #endif /* __ASSEMBLER__ */
413
414 #endif /* _ARCH_PPC_PSEUDO_INST_H_ */