VirtualBox

source: vbox/trunk/include/iprt/asmdefs.mac@ 99739

Last change on this file since 99739 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.6 KB
Line 
1;; @file
2; IPRT - Global YASM/NASM macros
3;
4
5;
6; Copyright (C) 2006-2023 Oracle and/or its affiliates.
7;
8; This file is part of VirtualBox base platform packages, as
9; available from https://www.virtualbox.org.
10;
11; This program is free software; you can redistribute it and/or
12; modify it under the terms of the GNU General Public License
13; as published by the Free Software Foundation, in version 3 of the
14; License.
15;
16; This program is distributed in the hope that it will be useful, but
17; WITHOUT ANY WARRANTY; without even the implied warranty of
18; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19; General Public License for more details.
20;
21; You should have received a copy of the GNU General Public License
22; along with this program; if not, see <https://www.gnu.org/licenses>.
23;
24; The contents of this file may alternatively be used under the terms
25; of the Common Development and Distribution License Version 1.0
26; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27; in the VirtualBox distribution, in which case the provisions of the
28; CDDL are applicable instead of those of the GPL.
29;
30; You may elect to license modified versions of this file under the
31; terms and conditions of either the GPL or the CDDL or both.
32;
33; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34;
35
36; Special hack for bs3kit.
37%ifdef RT_ASMDEFS_INC_FIRST_FILE
38 %include "asmdefs-first.mac"
39%endif
40
41%ifndef ___iprt_asmdefs_mac
42%define ___iprt_asmdefs_mac
43
44
45;; @defgroup grp_rt_cdefs_size Size Constants
46; (Of course, these are binary computer terms, not SI.)
47; @{
48;; 1 K (Kilo) (1 024).
49%define _1K 000000400h
50;; 4 K (Kilo) (4 096).
51%define _4K 000001000h
52;; 8 K (Kilo) (8 192).
53%define _8K 000002000h
54;; 16 K (Kilo) (16 384).
55%define _16K 000004000h
56;; 32 K (Kilo) (32 768).
57%define _32K 000008000h
58;; 64 K (Kilo) (65 536).
59%define _64K 000010000h
60;; 128 K (Kilo) (131 072).
61%define _128K 000020000h
62;; 256 K (Kilo) (262 144).
63%define _256K 000040000h
64;; 512 K (Kilo) (524 288).
65%define _512K 000080000h
66;; 1 M (Mega) (1 048 576).
67%define _1M 000100000h
68;; 2 M (Mega) (2 097 152).
69%define _2M 000200000h
70;; 4 M (Mega) (4 194 304).
71%define _4M 000400000h
72;; 1 G (Giga) (1 073 741 824).
73%define _1G 040000000h
74;; 2 G (Giga) (2 147 483 648).
75%define _2G 00000000080000000h
76;; 4 G (Giga) (4 294 967 296).
77%define _4G 00000000100000000h
78;; 1 T (Tera) (1 099 511 627 776).
79%define _1T 00000010000000000h
80;; 1 P (Peta) (1 125 899 906 842 624).
81%define _1P 00004000000000000h
82;; 1 E (Exa) (1 152 921 504 606 846 976).
83%define _1E 01000000000000000h
84;; 2 E (Exa) (2 305 843 009 213 693 952).
85%define _2E 02000000000000000h
86;; @}
87
88
89;;
90; Define RT_STRICT for debug builds like iprt/cdefs.h does.
91%ifndef RT_STRICT
92 %ifdef DEBUG
93 %define RT_STRICT
94 %endif
95%endif
96%ifdef RT_NO_STRICT
97 %undef RT_STRICT
98%endif
99
100;;
101; Make the mask for the given bit.
102%define RT_BIT(bit) (1 << bit)
103
104;;
105; Make the mask for the given bit.
106%define RT_BIT_32(bit) (1 << bit)
107;;
108; Make the mask for the given bit.
109%define RT_BIT_64(bit) (1 << bit)
110
111;;
112; Makes a 32-bit unsigned (not type safe, but whatever) out of four byte values.
113%define RT_MAKE_U32_FROM_U8(b0, b1, b2, b3) ( (b3 << 24) | (b2 << 16) | (b1 << 8) | b0 )
114
115;; Preprocessor concatenation macro.
116%define RT_CONCAT(a_1,a_2) a_1 %+ a_2
117
118;; Preprocessor concatenation macro, three arguments.
119%define RT_CONCAT3(a_1,a_2,a_3) a_1 %+ a_2 %+ a_3
120
121;; Preprocessor concatenation macro, four arguments.
122%define RT_CONCAT4(a_1,a_2,a_3,a_4) a_1 %+ a_2 %+ a_3 %+ a_4
123
124;;
125; Trick for using RT_CONCAT and the like on %define names.
126; @param 1 The name (expression.
127; @param 2 The value.
128%macro RT_DEFINE_EX 2
129 %error 1=%1 2=%2
130 %define %1 %2
131%endmacro
132
133;;
134; Trick for using RT_CONCAT and the like on %xdefine names.
135; @param 1 The name (expression.
136; @param 2 The value.
137%macro RT_XDEFINE_EX 2
138 %xdefine %1 %2
139%endmacro
140
141;;
142; Trick for using RT_CONCAT and the like on %undef names.
143; @param 1 The name (expression.
144%macro RT_UNDEF_EX 1
145 %error 1=%1
146 %undef %1
147%endmacro
148
149;;
150; Empty define
151%define RT_NOTHING
152
153;; Define ASM_FORMAT_PE64 if applicable.
154%ifdef ASM_FORMAT_PE
155 %ifdef RT_ARCH_AMD64
156 %define ASM_FORMAT_PE64 1
157 %endif
158%endif
159
160;;
161; SEH64 macros.
162%ifdef RT_ASM_WITH_SEH64
163 %ifndef ASM_FORMAT_PE64
164 %undef RT_ASM_WITH_SEH64
165 %endif
166%endif
167
168%ifdef RT_ASM_WITH_SEH64_ALT
169 %ifdef ASM_FORMAT_PE64
170 ;; @name Register numbers. Used with RT_CONCAT to convert macro inputs to numbers.
171 ;; @{
172 %define SEH64_PE_GREG_rax 0
173 %define SEH64_PE_GREG_xAX 0
174 %define SEH64_PE_GREG_rcx 1
175 %define SEH64_PE_GREG_xCX 1
176 %define SEH64_PE_GREG_rdx 2
177 %define SEH64_PE_GREG_xDX 2
178 %define SEH64_PE_GREG_rbx 3
179 %define SEH64_PE_GREG_xBX 3
180 %define SEH64_PE_GREG_rsp 4
181 %define SEH64_PE_GREG_xSP 4
182 %define SEH64_PE_GREG_rbp 5
183 %define SEH64_PE_GREG_xBP 5
184 %define SEH64_PE_GREG_rsi 6
185 %define SEH64_PE_GREG_xSI 6
186 %define SEH64_PE_GREG_rdi 7
187 %define SEH64_PE_GREG_xDI 7
188 %define SEH64_PE_GREG_r8 8
189 %define SEH64_PE_GREG_r9 9
190 %define SEH64_PE_GREG_r10 10
191 %define SEH64_PE_GREG_r11 11
192 %define SEH64_PE_GREG_r12 12
193 %define SEH64_PE_GREG_r13 13
194 %define SEH64_PE_GREG_r14 14
195 %define SEH64_PE_GREG_r15 15
196 ;; @}
197
198 ;; @name PE unwind operations.
199 ;; @{
200 %define SEH64_PE_PUSH_NONVOL 0
201 %define SEH64_PE_ALLOC_LARGE 1
202 %define SEH64_PE_ALLOC_SMALL 2
203 %define SEH64_PE_SET_FPREG 3
204 %define SEH64_PE_SAVE_NONVOL 4
205 %define SEH64_PE_SAVE_NONVOL_FAR 5
206 %define SEH64_PE_SAVE_XMM128 8
207 %define SEH64_PE_SAVE_XMM128_FAR 9
208 ;; @}
209
210 ;;
211 ; Starts the unwind info for the manual SEH64 info generation.
212 ; @param 1 Function name.
213 %macro SEH64_ALT_START_UNWIND_INFO 1
214 %assign seh64_idxOps 0
215 %assign seh64_FrameReg SEH64_PE_GREG_rsp
216 %assign seh64_offFrame 0
217 %define asm_seh64_proc %1
218 %undef seh64_slot_bytes
219 %endmacro
220
221 ;; We keep the unwind bytes in the seh64_slot_bytes (x)define, in reverse order as per spec.
222 %macro SEH64_APPEND_SLOT_PAIR 2
223 %ifdef seh64_slot_bytes
224 %xdefine seh64_slot_bytes %1, %2, seh64_slot_bytes
225 %else
226 %xdefine seh64_slot_bytes %1, %2
227 %endif
228 %endmacro
229
230 ;; For multi-slot unwind info.
231 %macro SEH64_APPEND_SLOT_BYTES 2+
232 %rep %0
233 %rotate -1
234 %ifdef seh64_slot_bytes
235 %xdefine seh64_slot_bytes %1, seh64_slot_bytes
236 %else
237 %xdefine seh64_slot_bytes %1
238 %endif
239 %endrep
240 %endmacro
241
242 %else
243 %undef RT_ASM_WITH_SEH64_ALT
244 %endif
245%endif
246
247;;
248; Records a xBP push.
249%macro SEH64_PUSH_xBP 0
250 %ifdef RT_ASM_WITH_SEH64
251 [pushreg rbp]
252
253 %elifdef RT_ASM_WITH_SEH64_ALT
254RT_CONCAT(.seh64_op_label_,seh64_idxOps):
255 %ifdef ASM_FORMAT_PE64
256 SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
257 SEH64_PE_PUSH_NONVOL | (SEH64_PE_GREG_rbp << 4)
258 %endif
259 %assign seh64_idxOps seh64_idxOps + 1
260 %endif
261%endmacro
262
263;;
264; Records a general register push.
265; @param 1 Register name.
266%macro SEH64_PUSH_GREG 1
267 %ifdef RT_ASM_WITH_SEH64
268 [pushreg %1]
269
270 %elifdef RT_ASM_WITH_SEH64_ALT
271RT_CONCAT(.seh64_op_label_,seh64_idxOps):
272 %ifdef ASM_FORMAT_PE64
273 SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
274 SEH64_PE_PUSH_NONVOL | (RT_CONCAT(SEH64_PE_GREG_,%1) << 4)
275 %endif
276 %assign seh64_idxOps seh64_idxOps + 1
277 %endif
278%endmacro
279
280;;
281; Sets xBP as frame pointer that's pointing to a stack position %1 relative to xBP.
282%macro SEH64_SET_FRAME_xBP 1
283 %ifdef RT_ASM_WITH_SEH64
284 [setframe rbp, %1]
285
286 %elifdef RT_ASM_WITH_SEH64_ALT
287RT_CONCAT(.seh64_op_label_,seh64_idxOps):
288 %ifdef ASM_FORMAT_PE64
289 SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
290 SEH64_PE_SET_FPREG | 0 ; vs2019 seems to put the offset in the info field
291 %assign seh64_FrameReg SEH64_PE_GREG_rbp
292 %assign seh64_offFrame %1
293 %endif
294 %assign seh64_idxOps seh64_idxOps + 1
295 %endif
296%endmacro
297
298;;
299; Records an ADD xSP, %1.
300%macro SEH64_ALLOCATE_STACK 1
301 %ifdef RT_ASM_WITH_SEH64
302 [allocstack %1]
303
304 %elifdef RT_ASM_WITH_SEH64_ALT
305RT_CONCAT(.seh64_op_label_,seh64_idxOps):
306 %ifdef ASM_FORMAT_PE64
307 %if (%1) & 7
308 %error "SEH64_ALLOCATE_STACK must be a multiple of 8"
309 %endif
310 %if (%1) < 8
311 %error "SEH64_ALLOCATE_STACK must have an argument that's 8 or higher."
312 %elif (%1) <= 128
313 SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
314 SEH64_PE_ALLOC_SMALL | ((((%1) / 8) - 1) << 4)
315 %elif (%1) < 512
316 SEH64_APPEND_SLOT_BYTES RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
317 SEH64_PE_ALLOC_LARGE | 0, \
318 ((%1) / 8) & 0xff, ((%1) / 8) >> 8
319 %else
320 SEH64_APPEND_SLOT_BYTES RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
321 SEH64_PE_ALLOC_LARGE | 1, \
322 (%1) & 0xff, ((%1) >> 8) & 0xff, ((%1) >> 16) & 0xff, ((%1) >> 24) & 0xff
323 %endif
324 %endif
325 %assign seh64_idxOps seh64_idxOps + 1
326 %endif
327%endmacro
328
329%macro SEH64_INFO_HELPER 1
330%if defined(%1)
331 dw %1
332%endif
333%endmacro
334
335;;
336; Ends the prologue.
337%macro SEH64_END_PROLOGUE 0
338.end_of_prologue:
339 %ifdef RT_ASM_WITH_SEH64
340 [endprolog]
341
342 %elifdef RT_ASM_WITH_SEH64_ALT
343 %ifdef ASM_FORMAT_PE
344 ; Emit the unwind info now.
345 %ifndef ASM_DEFINED_XDATA_SECTION
346 %define ASM_DEFINED_XDATA_SECTION
347 section .xdata rdata align=4
348 %else
349 section .xdata
350 align 4, db 0
351 %endif
352.unwind_info:
353 db 1 ; version 1 (3 bit), no flags (5 bits)
354 db .end_of_prologue - .start_of_prologue
355
356 db (.unwind_info_array_end - .unwind_info_array) / 2
357 db seh64_FrameReg | (seh64_offFrame & 0xf0) ; framereg and offset/16.
358.unwind_info_array:
359 %ifdef seh64_slot_bytes
360 db seh64_slot_bytes
361 %undef seh64_slot_bytes
362 %endif
363.unwind_info_array_end:
364
365 ; Reset the segment
366 BEGINCODE
367 %endif
368 %endif
369%endmacro
370
371
372;;
373; Align code, pad with INT3.
374%define ALIGNCODE(alignment) align alignment, db 0cch
375
376;;
377; Align data, pad with ZEROs.
378%define ALIGNDATA(alignment) align alignment, db 0
379
380;;
381; Align BSS, pad with ZEROs.
382%define ALIGNBSS(alignment) align alignment, resb 1
383
384;;
385; NAME_OVERLOAD can be defined by a .asm module to modify all the
386; names created using the name macros in this files.
387; This is handy when you've got some kind of template code.
388%ifndef NAME_OVERLOAD
389 %ifdef RT_MANGLER_PREFIX
390 %define NAME_OVERLOAD(name) RT_MANGLER_PREFIX %+ name
391 %else
392 %define NAME_OVERLOAD(name) name
393 %endif
394%endif
395
396;;
397; Mangles the given name so it can be referenced using DECLASM() in the
398; C/C++ world.
399%ifndef ASM_FORMAT_BIN
400 %ifdef RT_ARCH_X86
401 %ifdef RT_OS_OS2
402 %define NAME(name) _ %+ NAME_OVERLOAD(name)
403 %endif
404 %ifdef RT_OS_WINDOWS
405 %define NAME(name) _ %+ NAME_OVERLOAD(name)
406 %endif
407 %endif
408 %ifdef RT_OS_DARWIN
409 %define NAME(name) _ %+ NAME_OVERLOAD(name)
410 %endif
411%endif
412%ifndef NAME
413 %define NAME(name) NAME_OVERLOAD(name)
414%endif
415
416;;
417; Mangles the given C name so it will _import_ the right symbol.
418%ifdef ASM_FORMAT_PE
419 %define IMPNAME(name) __imp_ %+ NAME(name)
420%else
421 %define IMPNAME(name) NAME(name)
422%endif
423
424;;
425; Gets the pointer to an imported object.
426%ifdef ASM_FORMAT_PE
427 %ifdef RT_ARCH_AMD64
428 %define IMP(name) qword [IMPNAME(name) wrt rip]
429 %else
430 %define IMP(name) dword [IMPNAME(name)]
431 %endif
432%else
433 %define IMP(name) IMPNAME(name)
434%endif
435
436;;
437; Gets the pointer to an imported object.
438%ifdef ASM_FORMAT_PE
439 %ifdef RT_ARCH_AMD64
440 %define IMP_SEG(SegOverride, name) qword [SegOverride:IMPNAME(name) wrt rip]
441 %else
442 %define IMP_SEG(SegOverride, name) dword [SegOverride:IMPNAME(name)]
443 %endif
444%else
445 %define IMP_SEG(SegOverride, name) IMPNAME(name)
446%endif
447
448;;
449; Declares an imported object for use with IMP2.
450; @note May change the current section!
451%macro EXTERN_IMP2 1
452 extern IMPNAME(%1)
453 BEGINDATA
454 %ifdef ASM_FORMAT_MACHO
455 g_Imp2_ %+ %1: RTCCPTR_DEF IMPNAME(%1)
456 %endif
457%endmacro
458
459;;
460; Gets the pointer to an imported object, version 2.
461%ifdef ASM_FORMAT_PE
462 %ifdef RT_ARCH_AMD64
463 %define IMP2(name) qword [IMPNAME(name) wrt rip]
464 %else
465 %define IMP2(name) dword [IMPNAME(name)]
466 %endif
467%elifdef ASM_FORMAT_ELF
468 %ifdef PIC
469 %ifdef RT_ARCH_AMD64
470 %define IMP2(name) qword [rel IMPNAME(name) wrt ..got]
471 %else
472 %define IMP2(name) IMPNAME(name) wrt ..plt
473 %endif
474 %endif
475%elifdef ASM_FORMAT_MACHO
476 %define IMP2(name) RTCCPTR_PRE [g_Imp2_ %+ name xWrtRIP]
477%endif
478%ifndef IMP2
479 %define IMP2(name) IMPNAME(name)
480%endif
481
482
483;;
484; Define a label as given, with a '$' prepended to permit using instruction
485; names like fdiv as labels.
486%macro SAFE_LABEL 1
487$%1:
488%endmacro
489
490;;
491; Global marker which is DECLASM() compatible.
492%macro GLOBALNAME 1
493%ifndef ASM_FORMAT_BIN
494global NAME(%1)
495%endif
496SAFE_LABEL NAME(%1)
497%endmacro
498
499;;
500; Global exported marker which is DECLASM() compatible.
501%macro EXPORTEDNAME 1
502 %ifdef ASM_FORMAT_PE
503 export %1=NAME(%1)
504 %endif
505 %ifdef __NASM__
506 %ifdef ASM_FORMAT_OMF
507 export NAME(%1) NAME(%1)
508 %endif
509%endif
510GLOBALNAME %1
511%endmacro
512
513;;
514; Same as GLOBALNAME_EX, but without the name mangling.
515;
516; @param %1 The symbol name - subjected to NAME().
517; @param %2 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
518; PE ignores all but 'function' (yasm only). Other formats ignores
519; this completely.
520; @param %3 Symbol visibility: 'hidden', 'protected', 'internal', and
521; RT_NOTHING (for 'default' visibility).
522; These are ELF attributes, but 'hidden' is translated to
523; 'private_extern' for the Macho-O format.
524; Ignored by other formats.
525;
526%macro GLOBALNAME_RAW 3
527%ifdef ASM_FORMAT_ELF
528global %1:%2 %3
529
530%elifdef ASM_FORMAT_PE
531 %ifidn %2,function
532 %ifdef __YASM__ ; nasm does not support any attributes, it errors out. So, nasm is no good with control flow guard atm.
533global %1:function
534 %else
535global %1
536 %endif
537 %else
538global %1
539 %endif
540
541%elifdef ASM_FORMAT_MACHO
542 %ifidn %3,hidden
543global %1:private_extern
544 %else
545global %1
546 %endif
547
548%elifndef ASM_FORMAT_BIN
549global %1
550
551%endif
552
553%1:
554%endmacro
555
556;;
557; Global marker which is DECLASM() compatible.
558;
559; @param %1 The symbol name - subjected to NAME().
560; @param %2 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
561; PE ignores all but 'function' (yasm only). Other formats ignores
562; this completely.
563; @param %3 Symbol visibility: 'hidden', 'protected', 'internal', and
564; RT_NOTHING (for 'default' visibility).
565; These are ELF attributes, but 'hidden' is translated to
566; 'private_extern' for the Macho-O format.
567; Ignored by other formats.
568;
569%macro GLOBALNAME_EX 3
570GLOBALNAME_RAW NAME(%1), %2, %3
571%endmacro
572
573
574;;
575; Global exported marker, raw version w/o automatic name mangling.
576;
577; @param %1 The internal symbol name.
578; @param %2 The external symbol name.
579; @param %3 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
580; PE ignores all but 'function' (yasm only). Other formats ignores
581; this completely.
582;
583%macro EXPORTEDNAME_RAW 3
584 %ifdef ASM_FORMAT_PE
585 export %2=%1
586 %endif
587 %ifdef __NASM__
588 %ifdef ASM_FORMAT_OMF
589 export %1 %2
590 %endif
591%endif
592GLOBALNAME_RAW %1, %3, RT_NOTHING
593%endmacro
594
595;;
596; Global exported marker which is DECLASM() compatible.
597;
598; @param %1 The symbol name - subjected to NAME().
599; @param %2 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
600; PE ignores all but 'function' (yasm only). Other formats ignores
601; this completely.
602;
603%macro EXPORTEDNAME_EX 2
604EXPORTEDNAME_RAW NAME(%1), %1, %2
605%endmacro
606
607
608;;
609; Begins a procedure, raw version w/o automatic name mangling.
610%macro BEGINPROC_RAW 1
611 %ifdef RT_ASM_WITH_SEH64_ALT
612 SEH64_ALT_START_UNWIND_INFO %1
613 %endif
614 %ifdef RT_ASM_WITH_SEH64
615global %1:function
616proc_frame %1
617 %else
618GLOBALNAME_RAW %1, function, hidden
619 %endif
620.start_of_prologue:
621%endmacro
622
623;;
624; Begins a C callable (DECLASM) procedure.
625%macro BEGINPROC 1
626BEGINPROC_RAW NAME(%1)
627%endmacro
628
629
630;;
631; Begins a exported procedure, raw version w/o automatic name mangling.
632; @param 1 Internal name.
633; @param 2 Exported name.
634%macro BEGINPROC_EXPORTED_RAW 2
635 %ifdef RT_ASM_WITH_SEH64_ALT
636 SEH64_ALT_START_UNWIND_INFO %1
637 %endif
638 %ifdef RT_ASM_WITH_SEH64
639 %ifdef ASM_FORMAT_PE
640export %2=%1
641 %endif
642global %1:function
643proc_frame %1
644 %else
645EXPORTEDNAME_RAW %1, %2, function
646 %endif
647.start_of_prologue:
648%endmacro
649
650;;
651; Begins a C callable (DECLASM) exported procedure.
652%macro BEGINPROC_EXPORTED 1
653BEGINPROC_EXPORTED_RAW NAME(%1), %1
654%endmacro
655
656
657;;
658; Ends a procedure, raw version w/o automatic name mangling.
659%macro ENDPROC_RAW 1
660 %ifdef RT_ASM_WITH_SEH64
661endproc_frame
662 %endif
663GLOBALNAME_RAW %1 %+ _EndProc, , hidden ; no function here, this isn't a valid code flow target.
664%ifdef ASM_FORMAT_ELF
665 %ifndef __NASM__ ; nasm does this in the global directive.
666size %1 %1 %+ _EndProc - %1
667size %1 %+ _EndProc 4 ; make it non-zero to shut up warnigns from Linux's objtool.
668 %endif
669%endif
670 db 0xCC, 0xCC, 0xCC, 0xCC
671
672 %ifdef RT_ASM_WITH_SEH64_ALT
673 %ifdef ASM_FORMAT_PE
674 ; Emit the RUNTIME_FUNCTION entry. The linker is picky here, no label.
675 %ifndef ASM_DEFINED_PDATA_SECTION
676 %define ASM_DEFINED_PDATA_SECTION
677 section .pdata rdata align=4
678 %else
679 section .pdata
680 %endif
681 dd %1 wrt ..imagebase
682 dd %1 %+ _EndProc wrt ..imagebase
683 dd %1 %+ .unwind_info wrt ..imagebase
684
685 ; Restore code section.
686 BEGINCODE
687 %endif
688 %endif
689%endmacro
690
691;;
692; Ends a C callable procedure.
693%macro ENDPROC 1
694ENDPROC_RAW NAME(%1)
695%endmacro
696
697
698;
699; Do OMF and Mach-O/Yasm segment definitions
700;
701; Both format requires this to get the segment order right, in the Mach-O/Yasm case
702; it's only to make sure the .bss section ends up last (it's not declared here).
703;
704%ifdef ASM_FORMAT_OMF
705 %ifndef RT_NOINC_SEGMENTS
706
707 ; 16-bit segments first (OMF / OS/2 specific).
708 %ifdef RT_INCL_16BIT_SEGMENTS
709 segment DATA16 public CLASS=FAR_DATA align=16 use16
710 segment DATA16_INIT public CLASS=FAR_DATA align=16 use16
711 group DGROUP16 DATA16 DATA16_INIT
712
713 ;;
714 ; Begins 16-bit data
715 %macro BEGINDATA16 0
716 segment DATA16
717 %endmacro
718
719 ;;
720 ; Begins 16-bit init data
721 %macro BEGINDATA16INIT 0
722 segment DATA16_INIT
723 %endmacro
724
725 segment CODE16 public CLASS=FAR_CODE align=16 use16
726 segment CODE16_INIT public CLASS=FAR_CODE align=16 use16
727 group CGROUP16 CODE16 CODE16_INIT
728
729 ;;
730 ; Begins 16-bit code
731 %macro BEGINCODE16 0
732 segment CODE16
733 %endmacro
734
735 ;;
736 ; Begins 16-bit init code
737 %macro BEGINCODE16INIT 0
738 segment CODE16_INIT
739 %endmacro
740
741 %endif
742
743 ; 32-bit segments.
744 segment TEXT32 public CLASS=CODE align=16 use32 flat
745 segment DATA32 public CLASS=DATA align=16 use32 flat
746 segment BSS32 public CLASS=BSS align=16 use32 flat
747
748 ; Make the TEXT32 segment default.
749 segment TEXT32
750 %endif ; RT_NOINC_SEGMENTS
751%endif
752
753%ifdef ASM_FORMAT_MACHO
754 %ifdef __YASM__
755 section .text
756 section .data
757 %endif
758%endif
759
760
761;;
762; Begins code
763%ifdef ASM_FORMAT_OMF
764 %macro BEGINCODE 0
765 segment TEXT32
766 %endmacro
767%else
768%macro BEGINCODE 0
769 section .text
770%endmacro
771%endif
772
773;;
774; Begins constant (read-only) data
775;
776; @remarks This is mapped to the CODE section/segment when there isn't
777; any dedicated const section/segment. (There is code that
778; assumes this, so don't try change it.)
779%ifdef ASM_FORMAT_OMF
780 %macro BEGINCONST 0
781 segment TEXT32
782 %endmacro
783%else
784 %macro BEGINCONST 0
785 %ifdef ASM_FORMAT_MACHO ;; @todo check the other guys too.
786 section .rodata
787 %else
788 section .text
789 %endif
790 %endmacro
791%endif
792
793;;
794; Begins initialized data
795%ifdef ASM_FORMAT_OMF
796 %macro BEGINDATA 0
797 segment DATA32
798 %endmacro
799%else
800%macro BEGINDATA 0
801 section .data
802%endmacro
803%endif
804
805;;
806; Begins uninitialized data
807%ifdef ASM_FORMAT_OMF
808 %macro BEGINBSS 0
809 segment BSS32
810 %endmacro
811%else
812%macro BEGINBSS 0
813 section .bss
814%endmacro
815%endif
816
817
818
819;; @def ARCH_BITS
820; Defines the bit count of the current context.
821%ifndef ARCH_BITS
822 %ifdef RT_ARCH_AMD64
823 %define ARCH_BITS 64
824 %else
825 %define ARCH_BITS 32
826 %endif
827%endif
828
829;; @def HC_ARCH_BITS
830; Defines the host architechture bit count.
831%ifndef HC_ARCH_BITS
832 %ifndef IN_RC
833 %define HC_ARCH_BITS ARCH_BITS
834 %else
835 %define HC_ARCH_BITS 32
836 %endif
837%endif
838
839;; @def R3_ARCH_BITS
840; Defines the host ring-3 architechture bit count.
841%ifndef R3_ARCH_BITS
842 %ifdef IN_RING3
843 %define R3_ARCH_BITS ARCH_BITS
844 %else
845 %define R3_ARCH_BITS HC_ARCH_BITS
846 %endif
847%endif
848
849;; @def R0_ARCH_BITS
850; Defines the host ring-0 architechture bit count.
851%ifndef R0_ARCH_BITS
852 %ifdef IN_RING0
853 %define R0_ARCH_BITS ARCH_BITS
854 %else
855 %define R0_ARCH_BITS HC_ARCH_BITS
856 %endif
857%endif
858
859;; @def GC_ARCH_BITS
860; Defines the guest architechture bit count.
861%ifndef GC_ARCH_BITS
862 %ifdef IN_RC
863 %define GC_ARCH_BITS ARCH_BITS
864 %else
865 %define GC_ARCH_BITS 32
866 %endif
867%endif
868
869
870
871;; @def RTHCPTR_DEF
872; The pesudo-instruction used to declare an initialized pointer variable in the host context.
873%if HC_ARCH_BITS == 64
874 %define RTHCPTR_DEF dq
875%else
876 %define RTHCPTR_DEF dd
877%endif
878
879;; @def RTHCPTR_RES
880; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
881; variable of the host context.
882%if HC_ARCH_BITS == 64
883 %define RTHCPTR_RES resq
884%else
885 %define RTHCPTR_RES resd
886%endif
887
888;; @def RTHCPTR_PRE
889; The memory operand prefix used for a pointer in the host context.
890%if HC_ARCH_BITS == 64
891 %define RTHCPTR_PRE qword
892%else
893 %define RTHCPTR_PRE dword
894%endif
895
896;; @def RTHCPTR_CB
897; The size in bytes of a pointer in the host context.
898%if HC_ARCH_BITS == 64
899 %define RTHCPTR_CB 8
900%else
901 %define RTHCPTR_CB 4
902%endif
903
904
905
906;; @def RTR0PTR_DEF
907; The pesudo-instruction used to declare an initialized pointer variable in the ring-0 host context.
908%if R0_ARCH_BITS == 64
909 %define RTR0PTR_DEF dq
910%else
911 %define RTR0PTR_DEF dd
912%endif
913
914;; @def RTR0PTR_RES
915; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
916; variable of the ring-0 host context.
917%if R0_ARCH_BITS == 64
918 %define RTR0PTR_RES resq
919%else
920 %define RTR0PTR_RES resd
921%endif
922
923;; @def RTR0PTR_PRE
924; The memory operand prefix used for a pointer in the ring-0 host context.
925%if R0_ARCH_BITS == 64
926 %define RTR0PTR_PRE qword
927%else
928 %define RTR0PTR_PRE dword
929%endif
930
931;; @def RTR0PTR_CB
932; The size in bytes of a pointer in the ring-0 host context.
933%if R0_ARCH_BITS == 64
934 %define RTR0PTR_CB 8
935%else
936 %define RTR0PTR_CB 4
937%endif
938
939
940
941;; @def RTR3PTR_DEF
942; The pesudo-instruction used to declare an initialized pointer variable in the ring-3 host context.
943%if R3_ARCH_BITS == 64
944 %define RTR3PTR_DEF dq
945%else
946 %define RTR3PTR_DEF dd
947%endif
948
949;; @def RTR3PTR_RES
950; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
951; variable of the ring-3 host context.
952%if R3_ARCH_BITS == 64
953 %define RTR3PTR_RES resq
954%else
955 %define RTR3PTR_RES resd
956%endif
957
958;; @def RTR3PTR_PRE
959; The memory operand prefix used for a pointer in the ring-3 host context.
960%if R3_ARCH_BITS == 64
961 %define RTR3PTR_PRE qword
962%else
963 %define RTR3PTR_PRE dword
964%endif
965
966;; @def RTR3PTR_CB
967; The size in bytes of a pointer in the ring-3 host context.
968%if R3_ARCH_BITS == 64
969 %define RTR3PTR_CB 8
970%else
971 %define RTR3PTR_CB 4
972%endif
973
974
975
976;; @def RTGCPTR_DEF
977; The pesudo-instruction used to declare an initialized pointer variable in the guest context.
978%if GC_ARCH_BITS == 64
979 %define RTGCPTR_DEF dq
980%else
981 %define RTGCPTR_DEF dd
982%endif
983
984;; @def RTGCPTR_RES
985; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
986; variable of the guest context.
987%if GC_ARCH_BITS == 64
988 %define RTGCPTR_RES resq
989%else
990 %define RTGCPTR_RES resd
991%endif
992
993%define RTGCPTR32_RES resd
994%define RTGCPTR64_RES resq
995
996;; @def RTGCPTR_PRE
997; The memory operand prefix used for a pointer in the guest context.
998%if GC_ARCH_BITS == 64
999 %define RTGCPTR_PRE qword
1000%else
1001 %define RTGCPTR_PRE dword
1002%endif
1003
1004;; @def RTGCPTR_CB
1005; The size in bytes of a pointer in the guest context.
1006%if GC_ARCH_BITS == 64
1007 %define RTGCPTR_CB 8
1008%else
1009 %define RTGCPTR_CB 4
1010%endif
1011
1012
1013;; @def RTRCPTR_DEF
1014; The pesudo-instruction used to declare an initialized pointer variable in the raw mode context.
1015%define RTRCPTR_DEF dd
1016
1017;; @def RTRCPTR_RES
1018; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
1019; variable of the raw mode context.
1020%define RTRCPTR_RES resd
1021
1022;; @def RTRCPTR_PRE
1023; The memory operand prefix used for a pointer in the raw mode context.
1024%define RTRCPTR_PRE dword
1025
1026;; @def RTRCPTR_CB
1027; The size in bytes of a pointer in the raw mode context.
1028%define RTRCPTR_CB 4
1029
1030
1031;; @def RT_CCPTR_DEF
1032; The pesudo-instruction used to declare an initialized pointer variable in the current context.
1033
1034;; @def RT_CCPTR_RES
1035; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
1036; variable of the current context.
1037
1038;; @def RT_CCPTR_PRE
1039; The memory operand prefix used for a pointer in the current context.
1040
1041;; @def RT_CCPTR_CB
1042; The size in bytes of a pointer in the current context.
1043
1044%ifdef IN_RC
1045 %define RTCCPTR_DEF RTRCPTR_DEF
1046 %define RTCCPTR_RES RTRCPTR_RES
1047 %define RTCCPTR_PRE RTRCPTR_PRE
1048 %define RTCCPTR_CB RTRCPTR_CB
1049%else
1050 %ifdef IN_RING0
1051 %define RTCCPTR_DEF RTR0PTR_DEF
1052 %define RTCCPTR_RES RTR0PTR_RES
1053 %define RTCCPTR_PRE RTR0PTR_PRE
1054 %define RTCCPTR_CB RTR0PTR_CB
1055 %else
1056 %define RTCCPTR_DEF RTR3PTR_DEF
1057 %define RTCCPTR_RES RTR3PTR_RES
1058 %define RTCCPTR_PRE RTR3PTR_PRE
1059 %define RTCCPTR_CB RTR3PTR_CB
1060 %endif
1061%endif
1062
1063
1064
1065;; @def RTHCPHYS_DEF
1066; The pesudo-instruction used to declare an initialized host physical address.
1067%define RTHCPHYS_DEF dq
1068
1069;; @def RTHCPTR_RES
1070; The pesudo-instruction used to declare (=reserve space for) an uninitialized
1071; host physical address variable
1072%define RTHCPHYS_RES resq
1073
1074;; @def RTHCPTR_PRE
1075; The memory operand prefix used for a host physical address.
1076%define RTHCPHYS_PRE qword
1077
1078;; @def RTHCPHYS_CB
1079; The size in bytes of a host physical address.
1080%define RTHCPHYS_CB 8
1081
1082
1083
1084;; @def RTGCPHYS_DEF
1085; The pesudo-instruction used to declare an initialized guest physical address.
1086%define RTGCPHYS_DEF dq
1087
1088;; @def RTGCPHYS_RES
1089; The pesudo-instruction used to declare (=reserve space for) an uninitialized
1090; guest physical address variable
1091%define RTGCPHYS_RES resq
1092
1093;; @def RTGCPTR_PRE
1094; The memory operand prefix used for a guest physical address.
1095%define RTGCPHYS_PRE qword
1096
1097;; @def RTGCPHYS_CB
1098; The size in bytes of a guest physical address.
1099%define RTGCPHYS_CB 8
1100
1101
1102
1103;;
1104; The size of the long double C/C++ type.
1105; On 32-bit Darwin this is 16 bytes, on L4, Linux, OS/2 and Windows
1106; it's 12 bytes.
1107; @todo figure out what 64-bit Windows does (I don't recall right now).
1108%ifdef RT_ARCH_X86
1109 %ifdef RT_OS_DARWIN
1110 %define RTLRD_CB 16
1111 %else
1112 %define RTLRD_CB 12
1113 %endif
1114%else
1115 %define RTLRD_CB 16
1116%endif
1117
1118;; @name Floating point constants along the lines of the iprt/types.h types.
1119; @note YASM does support special the __Infinity__ and __NaN__ nasm tokens.
1120; @{
1121%define RTFLOAT32U_QNAN_PLUS 0x7fc00000
1122%define RTFLOAT32U_QNAN_MINUS 0xffc00000
1123%define RTFLOAT32U_INF_PLUS 0x7f800000
1124%define RTFLOAT32U_INF_MINUS 0xff800000
1125
1126%define RTFLOAT64U_QNAN_PLUS 0x7ff8000000000000
1127%define RTFLOAT64U_QNAN_MINUS 0xfff8000000000000
1128%define RTFLOAT64U_INF_PLUS 0x7ff0000000000000
1129%define RTFLOAT64U_INF_MINUS 0xfff0000000000000
1130; @}
1131
1132
1133
1134;; @def ASM_CALL64_GCC
1135; Indicates that we're using the GCC 64-bit calling convention.
1136; @see @ref sec_vboxrem_amd64_compare (in VBoxREMWrapper.cpp) for an ABI description.
1137
1138;; @def ASM_CALL64_MSC
1139; Indicates that we're using the Microsoft 64-bit calling convention (fastcall on steroids).
1140; @see @ref sec_vboxrem_amd64_compare (in VBoxREMWrapper.cpp) for an ABI description.
1141
1142; Note: On X86 we're using cdecl unconditionally. There is not yet any common
1143; calling convention on AMD64, that's why we need to support two different ones.)
1144
1145%ifdef RT_ARCH_AMD64
1146 %ifndef ASM_CALL64_GCC
1147 %ifndef ASM_CALL64_MSC
1148 ; define it based on the object format.
1149 %ifdef ASM_FORMAT_PE
1150 %define ASM_CALL64_MSC
1151 %else
1152 %define ASM_CALL64_GCC
1153 %endif
1154 %endif
1155 %else
1156 ; sanity check.
1157 %ifdef ASM_CALL64_MSC
1158 %error "Only one of the ASM_CALL64_* defines should be defined!"
1159 %endif
1160 %endif
1161%else
1162 ;later; %ifdef ASM_CALL64_GCC
1163 ;later; %error "ASM_CALL64_GCC is defined without RT_ARCH_AMD64!" ASM_CALL64_GCC
1164 ;later; %endif
1165 ;later; %ifdef ASM_CALL64_MSC
1166 ;later; %error "ASM_CALL64_MSC is defined without RT_ARCH_AMD64!" ASM_CALL64_MSC
1167 ;later; %endif
1168%endif
1169
1170
1171;; @def RT_BEGINPROC
1172; Starts an IPRT procedure that should be exported unless IN_RT_STATIC is defined.
1173;
1174; @param 1 The function name. Will apply NAME macro to it.
1175%macro RT_BEGINPROC 1
1176 %ifdef IN_RT_STATIC
1177BEGINPROC %1
1178 %else
1179BEGINPROC_EXPORTED %1
1180 %endif
1181%endmacro ; RT_BEGINPROC
1182
1183
1184;; @def RT_NOCRT
1185; Symbol name wrapper for the No-CRT bits.
1186;
1187; In order to coexist in the same process as other CRTs, we need to
1188; decorate the symbols such that they don't conflict the ones in the
1189; other CRTs. The result of such conflicts / duplicate symbols can
1190; confuse the dynamic loader on unix like systems.
1191;
1192; @remark Always feed the name to this macro first and then pass the result
1193; on to the next *NAME* macro.
1194;
1195%ifndef RT_WITHOUT_NOCRT_WRAPPERS
1196 %define RT_NOCRT(name) nocrt_ %+ name
1197%else
1198 %define RT_NOCRT(name) name
1199%endif
1200
1201;; @def RT_NOCRT_BEGINPROC
1202; Starts a NOCRT procedure, taking care of name wrapping and aliasing.
1203;
1204; Weak aliases for regular crt (%1) names to the nocrt_ prefixed ones will be
1205; added when RT_WITH_NOCRT_ALIASES is defined and the output is ELF. If
1206; RT_WITH_GENALIAS_NOCRT_ALIASES is undefined, strong aliases will be added for
1207; for non-ELF targets, otherwise it's assumed the genalias build tool will do
1208; the weak aliasing for us.
1209;
1210%macro RT_NOCRT_BEGINPROC 1
1211 %ifdef RT_WITH_NOCRT_ALIASES
1212BEGINPROC_EXPORTED RT_NOCRT(%1)
1213 %ifdef ASM_FORMAT_ELF
1214 ; ELF
1215 %ifdef RT_WITH_NOCRT_UNDERSCORE_ALIASES
1216global NAME(_ %+ %1):function
1217weak NAME(_ %+ %1)
1218SAFE_LABEL NAME(_ %+ %1)
1219 %endif
1220global NAME(%1):function
1221weak NAME(%1)
1222SAFE_LABEL NAME(%1)
1223
1224 %elifndef RT_WITH_GENALIAS_NOCRT_ALIASES
1225 ; non-ELF when not using genalias.
1226 %ifdef RT_WITH_NOCRT_UNDERSCORE_ALIASES
1227GLOBALNAME _%1
1228 %endif
1229GLOBALNAME %1
1230 %endif
1231 %else ; !RT_WITH_NOCRT_ALIASES
1232BEGINPROC_EXPORTED RT_NOCRT(%1)
1233 %endif ; !RT_WITH_NOCRT_ALIASES
1234%endmacro ; RT_NOCRT_BEGINPROC
1235
1236
1237
1238;; @def xCB
1239; The stack unit size / The register unit size.
1240
1241;; @def xSP
1242; The stack pointer register (RSP or ESP).
1243
1244;; @def xBP
1245; The base pointer register (RBP or ESP).
1246
1247;; @def xAX
1248; RAX or EAX depending on context.
1249
1250;; @def xBX
1251; RBX or EBX depending on context.
1252
1253;; @def xCX
1254; RCX or ECX depending on context.
1255
1256;; @def xDX
1257; RDX or EDX depending on context.
1258
1259;; @def xDI
1260; RDI or EDI depending on context.
1261
1262;; @def xSI
1263; RSI or ESI depending on context.
1264
1265;; @def xWrtRIP
1266; 'wrt rip' for AMD64 targets, nothing for x86 ones.
1267
1268%ifdef RT_ARCH_AMD64
1269 %define xCB 8
1270 %define xSP rsp
1271 %define xBP rbp
1272 %define xAX rax
1273 %define xBX rbx
1274 %define xCX rcx
1275 %define xDX rdx
1276 %define xDI rdi
1277 %define xSI rsi
1278 %define xWrtRIP wrt rip
1279%else
1280 %define xCB 4
1281 %define xSP esp
1282 %define xBP ebp
1283 %define xAX eax
1284 %define xBX ebx
1285 %define xCX ecx
1286 %define xDX edx
1287 %define xDI edi
1288 %define xSI esi
1289 %define xWrtRIP
1290%endif
1291
1292
1293;
1294; NASM sets __PASS__ to 0 in preprocess-only mode, and to 3 when only generating dependencies.
1295; YASM has no such setting which is why we must rely on kBuild to tell us what we're doing.
1296; For simplicity, we'll set the kBuild macro when using NASM.
1297;
1298%ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1299 %ifdef __NASM__
1300 %if __PASS__ == 0 || __PASS__ == 3
1301 %define KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1302 %endif
1303 %endif
1304%endif
1305
1306
1307;
1308; Some simple compile time assertions.
1309;
1310; Note! Requires new kBuild to work with YASM (see above).
1311;
1312
1313;;
1314; Structure size assertion macro.
1315%define AssertCompileSize(a_Type, a_Size) AssertCompileSizeML a_Type, a_Size
1316%macro AssertCompileSizeML 2
1317 %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1318 %assign AssertVar_cbActual %1 %+ _size
1319 %assign AssertVar_cbExpected %2
1320 %if AssertVar_cbActual != AssertVar_cbExpected
1321 %error %1 is AssertVar_cbActual bytes instead of AssertVar_cbExpected
1322 %endif
1323 %endif
1324%endmacro
1325
1326;;
1327; Structure size alignment assertion macro.
1328
1329%define AssertCompileSizeAlignment(a_Type, a_Align) AssertCompileSizeAlignmentML a_Type, a_Align
1330%macro AssertCompileSizeAlignmentML 2
1331 %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1332 %assign AssertVar_cbActual %1 %+ _size
1333 %assign AssertVar_cbAlignment %2
1334 %if (AssertVar_cbActual & (AssertVar_cbAlignment - 1)) != 0
1335 %error %1 is AssertVar_cbActual bytes, expected size with AssertVar_cbAlignment bytes alignment.
1336 %endif
1337 %endif
1338%endmacro
1339
1340;;
1341; Structure member offset assertion macro.
1342%define AssertCompileMemberOffset(a_Type, a_Member, a_off) AssertCompileMemberOffsetML a_Type, a_Member, a_off
1343%macro AssertCompileMemberOffsetML 3
1344 %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1345 %assign AssertVar_offActual %1 %+ . %+ %2
1346 %assign AssertVar_offExpected %3
1347 %if AssertVar_offActual != AssertVar_offExpected
1348 %error %1 %+ . %+ %2 is at AssertVar_offActual instead of AssertVar_offExpected
1349 %endif
1350 %endif
1351%endmacro
1352
1353;;
1354; Structure member alignment assertion macro.
1355%define AssertCompileMemberAlignment(a_Type, a_Member, a_cbAlign) AssertCompileMemberAlignmentML a_Type, a_Member, a_cbAlign
1356%macro AssertCompileMemberAlignmentML 3
1357 %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1358 %assign AssertVar_offActual %1 %+ . %+ %2
1359 %assign AssertVar_cbAlign %3
1360 %if AssertVar_offActual & (AssertVar_cbAlign - 1)
1361 %error %1 %+ . %+ %2 is at AssertVar_offActual, expected AssertVar_cbAlign alignment
1362 %endif
1363 %endif
1364%endmacro
1365
1366;;
1367; Generic compile time expression assertion.
1368%define AssertCompile(a_Expr) AssertCompileML { a_Expr }
1369%macro AssertCompileML 1
1370 %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
1371 %if (%1) != 1
1372 %assign AssertVar_uResult %1
1373 %error %1 => AssertVar_uResult
1374 %endif
1375 %endif
1376%endmacro
1377
1378%endif
1379
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette