2 * Copyright Robert J. Amstadt, 1993
7 #if defined(__NetBSD__) || defined(__FreeBSD__)
13 #define A(addr) _##addr
20 /**********************************************************************
21 * Places to keep info about the current 32-bit stack frame.
23 .globl A( IF1632_Saved32_esp), A(IF1632_Saved32_ebp), A(IF1632_Saved32_ss)
24 A(IF1632_Saved32_esp:)
26 A(IF1632_Saved32_ebp:)
36 /**********************************************************************
37 * Places to keep info about the current 16-bit stack frame.
39 .globl A(IF1632_Saved16_sp),A(IF1632_Saved16_bp),A(IF1632_Saved16_ss)
56 /**********************************************************************
57 * int CallToInit16(unsigned long csip, unsigned long sssp,
69 .globl A(CallToInit16)
78 pushl A(IF1632_Saved32_esp)
79 pushl A(IF1632_Saved32_ebp)
80 pushw A(IF1632_Saved32_ss)
83 /* change to the other code segment */
85 movw %ax, A(IF1632_ELF_KLUDGE)+4
87 andl $0x0000ffff, %eax
88 movl %eax,A(IF1632_ELF_KLUDGE)
89 ljmp A(IF1632_ELF_KLUDGE)
100 * Put stack registers where we can get them after stack switch.
102 movw %ss,A(IF1632_Saved32_ss)
103 movl %esp,A(IF1632_Saved32_esp)
104 movl %ebp,A(IF1632_Saved32_ebp)
107 * Load initial registers
109 movw A(WIN_StackSize),%bx
110 movw A(WIN_HeapSize),%cx
113 movw A(PSPSelector),%ax
137 * Restore old stack and segment registers.
140 * 1. Trust that fs or gs hasn't changed.
141 * 2. Rely on knowledge of Linux use of segments.
143 * I'll opt for choice 2 because who knows what programs we
144 * going to run. Linux should be fairly stable in terms of
154 movw A(IF1632_Saved32_ss),%ss
155 movl A(IF1632_Saved32_esp),%esp
156 movl A(IF1632_Saved32_ebp),%ebp
159 * Restore registers, but do not destroy return value.
161 popw A(IF1632_Saved32_ss)
162 popl A(IF1632_Saved32_ebp)
163 popl A(IF1632_Saved32_esp)
164 movl %eax,return_value
168 movw %ax, A(IF1632_ELF_KLUDGE)+4
170 movl %eax,A(IF1632_ELF_KLUDGE)
171 ljmp A(IF1632_ELF_KLUDGE)
175 movl return_value,%eax
180 /**********************************************************************
181 * int CallTo16 (unsigned long csip, unsigned short ds)
182 * int CallTo16cx(unsigned long csip, unsigned long dscx);
189 * 14 target cx (only CallTo16cx)
193 .globl A(CallTo16), A(CallTo16cx), A(CallToLibMain)
207 * Get target address and new ds
211 /* change code segments */
213 movw %ax, A(IF1632_ELF_KLUDGE)+4
215 andl $0x0000ffff, %eax
216 movl %eax,A(IF1632_ELF_KLUDGE)
217 ljmp A(IF1632_ELF_KLUDGE)
220 /* At this point we have changed segments. */
222 movl %eax,jump_target
228 * Switch to 16-bit stack
230 pushl A(IF1632_Saved32_esp)
231 pushl A(IF1632_Saved32_ebp)
232 pushw A(IF1632_Saved32_ss)
234 movw %ss,A(IF1632_Saved32_ss)
235 movl %esp,A(IF1632_Saved32_esp)
236 movl %ebp,A(IF1632_Saved32_ebp)
238 movw A(IF1632_Saved16_ss),%ss
239 movw A(IF1632_Saved16_sp),%sp
240 movw A(IF1632_Saved16_bp),%bp
251 * Restore old stack and segment registers.
254 * 1. Trust that fs or gs hasn't changed.
255 * 2. Rely on knowledge of Linux use of segments.
257 * I'll opt for choice 2 because who knows what programs we
258 * going to run. Linux should be fairly stable in terms of
269 movw %ss,A(IF1632_Saved16_ss)
270 movw %esp,A(IF1632_Saved16_sp)
271 movw %ebp,A(IF1632_Saved16_bp)
273 movw A(IF1632_Saved32_ss),%ss
274 movl A(IF1632_Saved32_esp),%esp
275 movl A(IF1632_Saved32_ebp),%ebp
277 popw A(IF1632_Saved32_ss)
278 popl A(IF1632_Saved32_ebp)
279 popl A(IF1632_Saved32_esp)
281 movl %eax,return_value
282 movw return_value+2,%dx
283 /* switch segments */
286 movw %ax, A(IF1632_ELF_KLUDGE)+4
288 movl %eax,A(IF1632_ELF_KLUDGE)
289 ljmp A(IF1632_ELF_KLUDGE)
291 /* back in the regular segment set up. */
293 movl return_value, %eax
299 /**********************************************************************
302 * This function is called as a relay point to the built function
303 * handler. KERNEL, USER and GDI calls are dealt with by this
304 * handler. Calls to these DLLs will be mapped to a call handler
305 * which will set EAX to a number indicating which DLL and which
306 * function within that DLL.
308 * This function will pass to the function handler two arguments.
309 * The first argument will be the contents of EAX, the second
310 * argument will be a segment:offset pair that points to the
316 andl $0x0000ffff,%esp
321 * Save registers. 286 mode does not have fs or gs.
327 * Restore segment registers.
336 * Save old stack save variables, save stack registers, reload
339 pushw A(IF1632_Saved16_sp)
340 pushw A(IF1632_Saved16_bp)
341 pushw A(IF1632_Saved16_ss)
343 movw %ss,A(IF1632_Saved16_ss)
344 movw %sp,A(IF1632_Saved16_sp)
345 movw %bp,A(IF1632_Saved16_bp)
347 movw A(IF1632_Saved32_ss),%ss
348 movl A(IF1632_Saved32_esp),%esp
349 movl A(IF1632_Saved32_ebp),%ebp
355 pushw A(IF1632_Saved16_ss)
356 pushw A(IF1632_Saved16_sp)
365 * Restore registers, but do not destroy return value.
367 movw A(IF1632_Saved16_ss),%ss
368 movw A(IF1632_Saved16_sp),%sp
369 movw A(IF1632_Saved16_bp),%bp
371 popw A(IF1632_Saved16_ss)
372 popw A(IF1632_Saved16_bp)
373 popw A(IF1632_Saved16_sp)
380 * Now we need to ditch the parameter bytes that were left on the
381 * stack. We do this by effectively popping the number of bytes,
382 * and the return address, removing the parameters and then putting
383 * the return address back on the stack.
384 * Normally this field is filled in by the relevant function in
385 * the emulation library, since it should know how many bytes to
399 * Last, but not least we need to move the high word from eax to dx
409 /**********************************************************************
412 * This function is same one as CallTo32() except that the high
413 * word of EAX won't be moved to DX.
416 .globl A(CallTo32_16)
418 andl $0x0000ffff,%esp
423 * Save registers. 286 mode does not have fs or gs.
429 * Restore segment registers.
438 * Save old stack save variables, save stack registers, reload
441 pushw A(IF1632_Saved16_sp)
442 pushw A(IF1632_Saved16_bp)
443 pushw A(IF1632_Saved16_ss)
445 movw %ss,A(IF1632_Saved16_ss)
446 movw %esp,A(IF1632_Saved16_sp)
447 movw %ebp,A(IF1632_Saved16_bp)
449 movw A(IF1632_Saved32_ss),%ss
450 movl A(IF1632_Saved32_esp),%esp
451 movl A(IF1632_Saved32_ebp),%ebp
457 pushw A(IF1632_Saved16_ss)
458 pushw A(IF1632_Saved16_sp)
467 * Restore registers, but do not destroy return value.
469 movw A(IF1632_Saved16_ss),%ss
470 movw A(IF1632_Saved16_sp),%sp
471 movw A(IF1632_Saved16_bp),%bp
473 popw A(IF1632_Saved16_ss)
474 popw A(IF1632_Saved16_bp)
475 popw A(IF1632_Saved16_sp)
482 * Now we need to ditch the parameter bytes that were left on the
483 * stack. We do this by effectively popping the number of bytes,
484 * and the return address, removing the parameters and then putting
485 * the return address back on the stack.
486 * Normally this field is filled in by the relevant function in
487 * the emulation library, since it should know how many bytes to
502 /**********************************************************************
503 * ReturnFromRegisterFunc()
505 .globl A(ReturnFromRegisterFunc)
506 A(ReturnFromRegisterFunc:)
508 * Restore 16-bit stack
510 movw A(IF1632_Saved16_ss),%ss
511 movw A(IF1632_Saved16_sp),%sp
512 movw A(IF1632_Saved16_bp),%bp
514 popw A(IF1632_Saved16_ss)
515 popw A(IF1632_Saved16_bp)
516 popw A(IF1632_Saved16_sp)
523 * This leaves us with a stack that has number of arguments,
524 * the return address, the saved registers, and the return
527 add $6,%esp /* argument count, return address */
528 #include "pop.h" /* restore context */
531 * Return to original caller.