• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7/* vsscanf, vswscanf, vfscanf, and vfwscanf all come here for i386 and arm.
8
9   The goal of this routine is to turn a call to v*scanf into a call to
10   s*scanf.  This is needed because mingw-w64 uses msvcr100.dll, which doesn't
11   support the v*scanf functions instead of msvcr120.dll which does.
12   Unfortunately, there is no defined way to know exactly how big a va_list
13   is, so we use a hard-coded buffer.
14
15   I suppose a sufficiently-motivated person could try to parse the format
16   to figure out how many tokens there are... */
17
18/* The function prototype here is (essentially):
19
20   int __ms_vsscanf_internal (void *s,
21			     void *format,
22			     void *arg,
23			     void *func);
24
25   I say 'essentially' because passing a function pointer as void in ISO
26   is not supported.  But in the end, I take the first parameter (which
27   may be a char *, a wchar_t *, or a FILE *) and put it into the newly
28   formed stack, and eventually call the address in func.  */
29
30#if defined (__x86_64__)
31
32    .text
33    .align 16
34
35    /* scl   2: C_EXT  - External (public) symbol - covers globals and externs
36       type 32: DT_FCN - function returning T
37	 */
38    .def __argtos;    .scl    2;    .type    32;    .endef
39
40    /* The max number of pointers we support.  Must be an even number
41       to keep the 64bit stack 16byte aligned.  Must not be less than 4.  */
42    .equ entries, 30
43
44    /* 64bit pointers are 8 bytes.  */
45    .equ sizeof, 8
46
47    /* Size of our buffer.  */
48    .equ iBytes, entries * sizeof
49
50    /* Stack space for first 2 args to s*scanf.  */
51    .equ iOffset, (2 * sizeof)
52
53    .seh_proc __argtos
54__argtos:
55
56    /* When we are done:
57      - s must be in rcx.  That's where it is on entry.
58      - format must be in rdx.  That's where it is on entry.
59      - The first pointer in arg must be in r8. arg is in r8 on entry.
60      - The second pointer in arg must be in r9. arg is in r8 on entry.
61      - The ($entries - 2) other pointers in arg must be on the stack,
62	starting 32bytes into rsp.  */
63
64    /* We need enough room to shadow (s + format)
65       + (enough room for all the other args).  */
66    subq $(iOffset + iBytes), %rsp
67    .seh_stackalloc iOffset + iBytes
68
69    .seh_endprologue
70
71    /* We are going to copy $entries pointers from arg to our
72       local stack.  Except the first 2, since they will be
73       loaded in registers.  */
74    movq $entries - 2, %r10 /* # of ptrs to copy.  */
75
76    /* The first 32 bytes are in registers, but by spec, space
77	   must still be reserved for them on the stack.  Put the
78       rest of the pointers in the stack after that.  */
79    lea 32(%rsp), %r11 /* dst.  */
80
81.LOOP:
82    subq $1, %r10
83
84    /* Use 16 to skip over the first 2 pointers.  */
85    movq 16(%r8, %r10, 8), %rax
86    movq %rax, (%r11, %r10, 8)
87    jnz .LOOP
88
89    /* r9 contains the routine we are going to call.  Since we are about to
90       overwrite it, move it somewhere safe.  */
91    movq %r9, %r10
92
93    /* The stack is now correctly populated, and so are rcx and rdx.
94       But we need to load the last 2 regs before making the call.  */
95    movq 0x8(%r8), %r9 /* 2nd dest location (may be garbage if only 1 arg).  */
96    movq (%r8), %r8 /* 1st dest location.  */
97
98    /* Make the call.  */
99    callq *%r10
100
101    addq $(iOffset + iBytes), %rsp
102
103    retq
104    .seh_endproc
105
106#elif defined (_X86_)
107
108    .text
109    .align 16
110
111    /* scl   2: C_EXT  - External (public) symbol - covers globals and externs
112       type 32: DT_FCN - function returning T
113	 */
114    .def __argtos;    .scl    2;    .type    32;    .endef
115
116    /* The max number of pointers we support.  Must not be less than 1.  */
117    .equ entries, 30
118
119    /* 64bit pointers are 8 bytes.  */
120    .equ sizeof, 4
121
122    /* Size of our buffer.  */
123    .set iBytes, entries * sizeof
124
125    /* Stack space for first 2 args to s*scanf.  */
126    .equ iOffset, (2 * sizeof)
127
128__argtos:
129    pushl %ebp
130    movl %esp, %ebp
131    pushl %edi
132
133    /* Reserve enough stack space for everything.
134
135       Stack usage will look like:
136       4 bytes - s
137       4 bytes - format
138       (iBytes) bytes - variable # of parameters for sscanf (all ptrs).  */
139
140    subl $(iOffset + iBytes), %esp
141
142    /* Write out s and format where they need to be for the sscanf call.  */
143    movl 8(%ebp), %eax
144    movl %eax, (%esp)  /* s.  */
145    movl 12(%ebp), %edx
146    movl %edx, 0x4(%esp)  /* format.  */
147
148    /* We are going to copy $entries pointers from arg to our
149       local stack.  */
150    movl $entries, %ecx /* # of ptrs to copy.  */
151    lea iOffset(%esp), %edi /* dst.  */
152    movl 16(%ebp), %edx /* src.  */
153
154.LOOP:
155    subl $1, %ecx
156
157    movl (%edx, %ecx, 4), %eax
158    movl %eax, (%edi, %ecx, 4)
159    jnz .LOOP
160
161    /* The stack is now correctly populated.  */
162
163    /* Make the call.  */
164    call *20(%ebp)
165
166    /* Restore stack.  */
167    addl $(iOffset + iBytes), %esp
168    popl %edi
169    leave
170
171    ret
172
173#elif defined (__arm__)
174
175    .text
176    .align 2
177    .thumb_func
178    .globl __argtos
179
180__argtos:
181    push    {r4-r7, lr}
182    sub     sp, sp, #128
183    mov     r12, r3
184    mov     r4, sp
185
186    ldr     r5, [r2], #4
187    ldr     r6, [r2], #4
188
189    mov     r3, #116
1901:  ldr     r7, [r2], #4
191    str     r7, [r4], #4
192    subs    r3, r3, #4
193    bne     1b
194
195    mov     r2, r5
196    mov     r3, r6
197    blx     r12
198    add     sp, sp, #128
199    pop     {r4-r7, pc}
200
201#elif defined (__aarch64__)
202
203    .text
204    .align 2
205    .globl __argtos
206
207__argtos:
208    stp     x29, x30, [sp, #-16]!
209    mov     x29, sp
210    sub     sp, sp, #256
211    mov     x9, sp
212    mov     x10, x2
213    mov     x11, x3
214
215    ldr     x2, [x10], #8
216    ldr     x3, [x10], #8
217    ldr     x4, [x10], #8
218    ldr     x5, [x10], #8
219    ldr     x6, [x10], #8
220    ldr     x7, [x10], #8
221
222    mov     x12, #240
2231:  ldr     x13, [x10], #8
224    str     x13, [x9], #8
225    subs    x12, x12, #8
226    b.ne    1b
227
228    blr     x11
229    mov     sp, x29
230    ldp     x29, x30, [sp], #16
231    ret
232
233#endif
234