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