VirtualBox

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

Last change on this file since 96368 was 96368, checked in by vboxsync, 2 years ago

iprt/asmdefs.mac,IPRT/nocrt: Mangling fixes for fastcall compiler support procedures. bugref:10261

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