1 #ifndef XTENSA_COREASM_H
2 #define XTENSA_COREASM_H
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
7 * include/asm-xtensa/xtensa/coreasm.h -- assembler-specific
8 * definitions that depend on CORE configuration.
10 * Source for configuration-independent binaries (which link in a
11 * configuration-specific HAL library) must NEVER include this file.
12 * It is perfectly normal, however, for the HAL itself to include this
15 * This file must NOT include xtensa/config/system.h. Any assembler
16 * header file that depends on system information should likely go in
17 * a new systemasm.h (or sysasm.h) header file.
19 * NOTE: macro beqi32 is NOT configuration-dependent, and is placed
20 * here til we will have configuration-independent header file.
22 * This file is subject to the terms and conditions of the GNU General
23 * Public License. See the file "COPYING" in the main directory of
24 * this archive for more details.
26 * Copyright (C) 2002 Tensilica Inc.
30 #include <xtensa/config/core.h>
31 #include <xtensa/config/specreg.h>
34 * Assembly-language specific definitions (assembly macros, etc.).
37 /*----------------------------------------------------------------------
40 * This macro finds the most significant bit that is set in <as>
41 * and return its index + <base> in <ad>, or <base> - 1 if <as> is zero.
42 * The index counts starting at zero for the lsbit, so the return
43 * value ranges from <base>-1 (no bit set) to <base>+31 (msbit set).
46 * <ad> destination address register (any register)
47 * <as> source address register
48 * <at> temporary address register (must be different than <as>)
49 * <base> constant value added to result (usually 0 or 1)
51 * <ad> = undefined if different than <as>
52 * <as> = value whose most significant set bit is to be found
54 * no other registers are used by this macro.
56 * <ad> = <base> + index of msbit set in original <as>,
57 * = <base> - 1 if original <as> was zero.
58 * <as> clobbered (if not <ad>)
59 * <at> clobbered (if not <ad>)
61 * find_ms_setbit a0, a4, a0, 0 -- return in a0 index of msbit set in a4
64 .macro find_ms_setbit ad
, as
, at
, base
67 nsau
\as
, \as
// get index of \as, numbered from msbit (32 if absent)
68 sub
\ad
, \at
, \as
// get numbering from lsbit (0..31, -1 if absent)
69 #else /* XCHAL_HAVE_NSA */
70 movi
\at
, \base
// start with result of 0 (point to lsbit of 32)
72 beqz
\as
, 2f
// special case for zero argument: return -1
73 bltui
\as
, 0x10000, 1f
// is it one of the 16 lsbits? (if so, check lower 16 bits)
74 addi
\at
, \at
, 16 // no, increment result to upper 16 bits (of 32)
75 //srli \as, \as, 16 // check upper half (shift right 16 bits)
76 extui
\as
, \as
, 16, 16 // check upper half (shift right 16 bits)
77 1: bltui
\as
, 0x100, 1f
// is it one of the 8 lsbits? (if so, check lower 8 bits)
78 addi
\at
, \at
, 8 // no, increment result to upper 8 bits (of 16)
79 srli
\as
, \as
, 8 // shift right to check upper 8 bits
80 1: bltui
\as
, 0x10, 1f
// is it one of the 4 lsbits? (if so, check lower 4 bits)
81 addi
\at
, \at
, 4 // no, increment result to upper 4 bits (of 8)
82 srli
\as
, \as
, 4 // shift right 4 bits to check upper half
83 1: bltui
\as
, 0x4, 1f
// is it one of the 2 lsbits? (if so, check lower 2 bits)
84 addi
\at
, \at
, 2 // no, increment result to upper 2 bits (of 4)
85 srli
\as
, \as
, 2 // shift right 2 bits to check upper half
86 1: bltui
\as
, 0x2, 1f
// is it the lsbit?
87 addi
\at
, \at
, 2 // no, increment result to upper bit (of 2)
88 2: addi
\at
, \at
, -1 // (from just above: add 1; from beqz: return -1)
90 1: // done! \at contains index of msbit set (or -1 if none set)
91 .if 0x
\ad
- 0x
\at
// destination different than \at ? (works because regs are a0-a15)
92 mov
\ad
, \at
// then move result to \ad
94 #endif /* XCHAL_HAVE_NSA */
95 .endm
// find_ms_setbit
97 /*----------------------------------------------------------------------
100 * This macro finds the least significant bit that is set in <as>,
101 * and return its index in <ad>.
102 * Usage is the same as for the find_ms_setbit macro.
104 * find_ls_setbit a0, a4, a0, 0 -- return in a0 index of lsbit set in a4
107 .macro find_ls_setbit ad
, as
, at
, base
108 neg
\at
, \as
// keep only the least-significant bit that is set...
109 and \as
, \at
, \as
// ... in \as
110 find_ms_setbit
\ad
, \as
, \at
, \base
111 .endm
// find_ls_setbit
113 /*----------------------------------------------------------------------
116 * Same as find_ls_setbit with base zero.
117 * Source (as) and destination (ad) registers must be different.
118 * Provided for backward compatibility.
121 .macro find_ls_one ad
, as
122 find_ls_setbit
\ad
, \as
, \ad
, 0
125 /*----------------------------------------------------------------------
126 * floop, floopnez, floopgtz, floopend
128 * These macros are used for fast inner loops that
129 * work whether or not the Loops options is configured.
130 * If the Loops option is configured, they simply use
131 * the zero-overhead LOOP instructions; otherwise
132 * they use explicit decrement and branch instructions.
134 * They are used in pairs, with floop, floopnez or floopgtz
135 * at the beginning of the loop, and floopend at the end.
137 * Each pair of loop macro calls must be given the loop count
138 * address register and a unique label for that loop.
142 * movi a3, 16 // loop 16 times
145 * bnez a7, end1 // exit loop if a7 != 0
147 * floopend a3, myloop1
150 * Like the LOOP instructions, these macros cannot be
151 * nested, must include at least one instruction,
152 * cannot call functions inside the loop, etc.
153 * The loop can be exited by jumping to the instruction
154 * following floopend (or elsewhere outside the loop),
155 * or continued by jumping to a NOP instruction placed
156 * immediately before floopend.
158 * Unlike LOOP instructions, the register passed to floop*
159 * cannot be used inside the loop, because it is used as
160 * the loop counter if the Loops option is not configured.
161 * And its value is undefined after exiting the loop.
162 * And because the loop counter register is active inside
163 * the loop, you can't easily use this construct to loop
164 * across a register file using ROTW as you might with LOOP
165 * instructions, unless you copy the loop register along.
168 /* Named label version of the macros: */
170 .macro floop ar
, endlabel
171 floop_
\ar
, .Lfloopstart_\endlabel
, .Lfloopend_\endlabel
174 .macro floopnez ar
, endlabel
175 floopnez_
\ar
, .Lfloopstart_\endlabel
, .Lfloopend_\endlabel
178 .macro floopgtz ar
, endlabel
179 floopgtz_
\ar
, .Lfloopstart_\endlabel
, .Lfloopend_\endlabel
182 .macro floopend ar
, endlabel
183 floopend_
\ar
, .Lfloopstart_\endlabel
, .Lfloopend_\endlabel
186 /* Numbered local label version of the macros: */
205 /* Underlying version of the macros: */
207 .macro floop_ ar
, startlabel
, endlabelref
210 .err
// Error: floop cannot be nested
215 loop
\ar
, \endlabelref
216 #else /* XCHAL_HAVE_LOOPS */
219 #endif /* XCHAL_HAVE_LOOPS */
222 .macro floopnez_ ar
, startlabel
, endlabelref
225 .err
// Error: floopnez cannot be nested
230 loopnez
\ar
, \endlabelref
231 #else /* XCHAL_HAVE_LOOPS */
232 beqz
\ar
, \endlabelref
235 #endif /* XCHAL_HAVE_LOOPS */
238 .macro floopgtz_ ar
, startlabel
, endlabelref
241 .err
// Error: floopgtz cannot be nested
246 loopgtz
\ar
, \endlabelref
247 #else /* XCHAL_HAVE_LOOPS */
248 bltz
\ar
, \endlabelref
249 beqz
\ar
, \endlabelref
252 #endif /* XCHAL_HAVE_LOOPS */
256 .macro floopend_ ar
, startlabelref
, endlabel
258 .err
// Error: floopend without matching floopXXX
261 .err
// Error: floopend without matching floopXXX
264 #if ! XCHAL_HAVE_LOOPS
265 bnez
\ar
, \startlabelref
266 #endif /* XCHAL_HAVE_LOOPS */
270 /*----------------------------------------------------------------------
271 * crsil -- conditional RSIL (read/set interrupt level)
273 * Executes the RSIL instruction if it exists, else just reads PS.
274 * The RSIL instruction does not exist in the new exception architecture
275 * if the interrupt option is not selected.
278 .macro crsil ar
, newlevel
279 #if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS
286 /*----------------------------------------------------------------------
287 * window_spill{4,8,12}
289 * These macros spill callers' register windows to the stack.
290 * They work for both privileged and non-privileged tasks.
291 * Must be called from a windowed ABI context, eg. within
292 * a windowed ABI function (ie. valid stack frame, window
293 * exceptions enabled, not in exception mode, etc).
295 * This macro requires a single invocation of the window_spill_common
296 * macro in the same assembly unit and section.
298 * Note that using window_spill{4,8,12} macros is more efficient
299 * than calling a function implemented using window_spill_function,
300 * because the latter needs extra code to figure out the size of
301 * the call to the spilling function.
307 * .global some_function
308 * .type some_function,@function
314 * window_spill4 // spill windows of some_function's callers; preserves a0..a3 only;
315 * // to use window_spill{8,12} in this example function we'd have
316 * // to increase space allocated by the entry instruction, because
317 * // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed
318 * // for call8/window_spill8 or call12/window_spill12 respectively.
323 * window_spill_common // instantiates code used by window_spill4
327 * none (if window_spill4)
328 * stack frame has enough space allocated for call8 (if window_spill8)
329 * stack frame has enough space allocated for call12 (if window_spill12)
331 * a4..a15 clobbered (if window_spill4)
332 * a8..a15 clobbered (if window_spill8)
333 * a12..a15 clobbered (if window_spill12)
334 * no caller windows are in live registers
338 #if XCHAL_HAVE_WINDOWED
339 # if XCHAL_NUM_AREGS == 16
340 movi a15
, 0 // for 16-register files, no need to call to reach the end
341 # elif XCHAL_NUM_AREGS == 32
342 call4
.L__wdwspill_assist28
// call deep enough to clear out any live callers
343 # elif XCHAL_NUM_AREGS == 64
344 call4
.L__wdwspill_assist60
// call deep enough to clear out any live callers
347 .endm
// window_spill4
350 #if XCHAL_HAVE_WINDOWED
351 # if XCHAL_NUM_AREGS == 16
352 movi a15
, 0 // for 16-register files, no need to call to reach the end
353 # elif XCHAL_NUM_AREGS == 32
354 call8
.L__wdwspill_assist24
// call deep enough to clear out any live callers
355 # elif XCHAL_NUM_AREGS == 64
356 call8
.L__wdwspill_assist56
// call deep enough to clear out any live callers
359 .endm
// window_spill8
361 .macro window_spill12
362 #if XCHAL_HAVE_WINDOWED
363 # if XCHAL_NUM_AREGS == 16
364 movi a15
, 0 // for 16-register files, no need to call to reach the end
365 # elif XCHAL_NUM_AREGS == 32
366 call12
.L__wdwspill_assist20
// call deep enough to clear out any live callers
367 # elif XCHAL_NUM_AREGS == 64
368 call12
.L__wdwspill_assist52
// call deep enough to clear out any live callers
371 .endm
// window_spill12
373 /*----------------------------------------------------------------------
374 * window_spill_function
376 * This macro outputs a function that will spill its caller's callers'
377 * register windows to the stack. Eg. it could be used to implement
378 * a version of xthal_window_spill() that works in non-privileged tasks.
379 * This works for both privileged and non-privileged tasks.
385 * .global my_spill_function
386 * .type my_spill_function,@function
388 * window_spill_function
390 * On entry to resulting function:
392 * On exit from resulting function:
393 * none (no caller windows are in live registers)
396 .macro window_spill_function
397 #if XCHAL_HAVE_WINDOWED
398 # if XCHAL_NUM_AREGS == 32
400 bbci
.l a0
, 31, 1f
// branch if called with call4
401 bbsi
.l a0
, 30, 2f
// branch if called with call12
402 call8
.L__wdwspill_assist16
// called with call8, only need another 8
404 1: call12
.L__wdwspill_assist16
// called with call4, only need another 12
406 2: call4
.L__wdwspill_assist16
// called with call12, only need another 4
408 # elif XCHAL_NUM_AREGS == 64
410 bbci
.l a0
, 31, 1f
// branch if called with call4
411 bbsi
.l a0
, 30, 2f
// branch if called with call12
412 call4
.L__wdwspill_assist52
// called with call8, only need a call4
414 1: call8
.L__wdwspill_assist52
// called with call4, only need a call8
416 2: call12
.L__wdwspill_assist40
// called with call12, can skip a call12
418 # elif XCHAL_NUM_AREGS == 16
420 bbci
.l a0
, 31, 1f
// branch if called with call4
421 bbsi
.l a0
, 30, 2f
// branch if called with call12
422 movi a7
, 0 // called with call8
424 1: movi a11
, 0 // called with call4
425 2: retw
// if called with call12, everything already spilled
427 // movi a15, 0 // trick to spill all but the direct caller
429 // // The entry instruction is magical in the assembler (gets auto-aligned)
430 // // so we have to jump to it to avoid falling through the padding.
431 // // We need entry/retw to know where to return.
435 # error "unrecognized address register file size"
437 #endif /* XCHAL_HAVE_WINDOWED */
439 .endm
// window_spill_function
441 /*----------------------------------------------------------------------
442 * window_spill_common
444 * Common code used by any number of invocations of the window_spill##
445 * and window_spill_function macros.
447 * Must be instantiated exactly once within a given assembly unit,
448 * within call/j range of and same section as window_spill##
449 * macro invocations for that assembly unit.
450 * (Is automatically instantiated by the window_spill_function macro.)
453 .macro window_spill_common
454 #if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64)
455 .ifndef
.L__wdwspill_defined
456 # if XCHAL_NUM_AREGS >= 64
457 .L__wdwspill_assist60
:
459 call8
.L__wdwspill_assist52
461 .L__wdwspill_assist56
:
463 call4
.L__wdwspill_assist52
465 .L__wdwspill_assist52
:
467 call12
.L__wdwspill_assist40
469 .L__wdwspill_assist40
:
471 call12
.L__wdwspill_assist28
474 .L__wdwspill_assist28
:
476 call12
.L__wdwspill_assist16
478 .L__wdwspill_assist24
:
480 call8
.L__wdwspill_assist16
482 .L__wdwspill_assist20
:
484 call4
.L__wdwspill_assist16
486 .L__wdwspill_assist16
:
490 .set
.L__wdwspill_defined
, 1
492 #endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */
493 .endm
// window_spill_common
495 /*----------------------------------------------------------------------
498 * macro implements version of beqi for arbitrary 32-bit immidiate value
500 * beqi32 ax, ay, imm32, label
502 * Compares value in register ax with imm32 value and jumps to label if
503 * equal. Clobberes register ay if needed
506 .macro beqi32 ax
, ay
, imm
, label
507 .ifeq ((\imm
-1) & ~7) // 1..8 ?
508 beqi
\ax
, \imm
, \label
510 .ifeq (\imm
+1) // -1 ?
511 beqi
\ax
, \imm
, \label
516 // We could also handle immediates 10,12,16,32,64,128,256
517 // but it would be a long macro...
525 #endif /*XTENSA_COREASM_H*/