diff --git a/rtl/go32v2/v2prt0.as b/rtl/go32v2/v2prt0.as index 46ec3b943a..a1998eef77 100644 --- a/rtl/go32v2/v2prt0.as +++ b/rtl/go32v2/v2prt0.as @@ -1 +1,3715 @@ -/* $Id$ */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /*****************************************************************************\ * Interface to 32-bit executable (from stub.asm) * * cs:eip according to COFF header * ds 32-bit data segment for COFF program * fs selector for our data segment (fs:0 is stubinfo) * ss:sp our stack (ss to be freed) * All unspecified registers have unspecified values in them. \*****************************************************************************/ /* modified by Pierre Muller to become the prt0.s for FPC Pascal */ .file "v2prt0.as" /* #include "stubinfo.h" */ STUBINFO = 0 STUBINFO_MAGIC = 0 STUBINFO_SIZE = 0x10 STUBINFO_MINSTACK = 0x14 STUBINFO_MEMORY_HANDLE = 0x18 STUBINFO_INITIAL_SIZE = 0x1c STUBINFO_MINKEEP = 0x20 STUBINFO_DS_SELECTOR = 0x22 STUBINFO_DS_SEGMENT = 0x24 STUBINFO_PSP_SELECTOR = 0x26 STUBINFO_CS_SELECTOR = 0x28 STUBINFO_ENV_SIZE = 0x2a STUBINFO_BASENAME = 0x2c STUBINFO_ARGV0 = 0x34 STUBINFO_DPMI_SERVER = 0x44 STUBINFO_END = 0x54 /* .comm __stklen, 4 this is added to the compiler so that we can specify the stack size */ .comm __stkbottom,4 .comm __stubinfo, 4 .comm ___djgpp_base_address, 4 .comm ___djgpp_selector_limit, 4 .comm ___djgpp_stack_limit, 4 .lcomm sel_buf, 8 /* ___djgpp_ds_alias defined in go32/exceptn.s */ /* inserted at the end of this file */ /* we use a local copy that will be copied to exceptn.s */ .globl ___v2prt0_ds_alias ___v2prt0_ds_alias: .long 0 /* allocate 32*4 bytes for RMCB under the $ffff limit for Windows NT */ .globl ___v2prt0_rmcb_regs ___v2prt0_rmcb_regs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .data ___djgpp_memory_handle_pointer: .long ___djgpp_memory_handle_list+8 /* Next free, first for stub */ .comm ___djgpp_memory_handle_list, 2048 /* Enough for 256 handles */ /* simply get current state */ ___sbrk_interrupt_state: .long 0x902 sbrk16_first_byte: .include "sbrk16.ah" sbrk16_last_byte: sbrk16_api_ofs: .long 0 sbrk16_api_seg: .word 0 zero: .long 0 exit16_first_byte: .include "exit16.ah" exit16_last_byte: /* hook_387_emulator: .long ___emu387_load_hook */ /* this is for when main comes from a library */ .long _main .text .globl start start: pushl %ds /* set %es same as %ds */ popl %es /* push/pop 4 bytes shorter than ax */ /* Enable NULL pointer protection if DPMI supports it */ testb $0x1, __crt0_startup_flags+1 /* include/crt0.h */ jnz 1f movl $start, %eax cmpl $0x1000, %eax jl 1f movw $0x507, %ax .byte 0x64 /* fs: */ movl STUBINFO_MEMORY_HANDLE, %esi xorl %ebx, %ebx /* Offset 0 in mem block */ movl $1, %ecx /* Set one page */ movl $zero, %edx int $0x31 /* Make null page uncommitted */ jnc 1f call v2prt0_windows 1: /* Create an alias for DS to be used by real-mode callbacks (exception handler messes with DS itself) */ movw %ds, %bx movw $0x000a, %ax int $0x31 jnc ds_alias_ok movb $0x4c, %ah int $0x21 ds_alias_ok: movw %ax, ___v2prt0_ds_alias movl %eax, %ebx movw $0x0009, %ax movw %cs, %cx /* get CPL from %cs */ andl $3, %ecx shll $5, %ecx /* move it into place */ orw $0xc093, %cx int $0x31 /* set access rights for alias */ /* Maybe set our DS limit to 4Gb in size if flag set */ testb $0x80, __crt0_startup_flags /* include/crt0.h */ jz 2f movw $0xffff, %cx movl %ecx, %edx movw $0x0008, %ax /* reset alias limit to -1 */ int $0x31 movw %cs, %bx movw $0x0008, %ax /* reset DS limit to -1 */ int $0x31 movw %ds, %bx movw $0x0008, %ax /* reset DS limit to -1 */ int $0x31 lsl %ebx, %ebx /* Should be -1 */ incl %ebx jz 2f andb $0x7f, __crt0_startup_flags /* clear it if failure */ 2: /* Allocate some DOS memory and copy our sbrk helper into it. */ movl $sbrk16_first_byte, %esi movzwl 8(%esi), %ebx shrl $4, %ebx movw $0x0100, %ax int $0x31 jnc dos_alloc_ok movb $0x4c, %ah int $0x21 dos_alloc_ok: movw %cs, 2(%esi) /* store API information */ movw %ds, 4(%esi) movw %dx, 6(%esi) /* selector for allocated block */ movzwl (%esi), %eax /* calculate API address */ movl %eax, sbrk16_api_ofs pushl %es /* move the data */ movw %dx, %es movl $(sbrk16_last_byte - sbrk16_first_byte), %ecx shrl $2,%ecx xorl %edi, %edi cld rep movsl popl %es movl %edx, %ebx /* dos memory selector */ movw $0x000b, %ax /* get descriptor */ movl $sel_buf, %edi int $0x31 andb $0xbf, sel_buf+6 /* make 16-bit */ andb $0xf0, sel_buf+5 /* remove old type */ orb $0x0a, sel_buf+5 /* set new type to code/read */ xorl %eax, %eax /* allocate new selector */ movw $0x0001, %cx int $0x31 movw %ax, sbrk16_api_seg movl %eax, %ebx movw $0x000c, %ax /* set descriptor */ movl $sel_buf, %edi int $0x31 /* Initialize the brk/sbrk variables */ /* movl $end, __what_size_app_thinks_it_is */ .byte 0x64 /* fs: */ movl STUBINFO_INITIAL_SIZE, %eax movl %eax, __what_size_dpmi_thinks_we_are /* Maybe lock the initial block, expects BX:CX */ movl %ecx,%ebx movl %edx,%ecx addw $4096,%cx /* Skip null page */ adcl $0,%ebx subl $4096,%eax pushl %eax call lock_memory .byte 0x64 /* fs: */ movl STUBINFO_MEMORY_HANDLE, %eax movl %eax, ___djgpp_memory_handle_list .byte 0x64 /* fs: */ /* copy stubinfo into local memory */ movl STUBINFO_SIZE, %eax pushl %eax call ___sbrk movl %eax, __stubinfo movl %eax,U_SYSTEM_STUB_INFO movl %eax, %edi .byte 0x64 /* fs: */ movl STUBINFO_SIZE, %ecx shrl $2, %ecx xorl %esi, %esi /* Zero */ pushl %ds pushl %fs popl %ds cld rep movsl popl %ds movl __stklen, %eax /* get program-requested stack size */ .byte 0x64 /* fs: */ movl STUBINFO_MINSTACK, %ecx /* get stub-requested stack size */ cmpl %ecx, %eax jge use_stubinfo_stack_size /* use the larger of the two */ movl %ecx, %eax movl %eax, __stklen /* store the actual stack length */ use_stubinfo_stack_size: pushl %eax call ___sbrk /* allocate the memory */ cmpl $-1, %eax je no_memory movl %eax, ___djgpp_stack_limit /* Bottom of stack */ addl $256,%eax movl %eax,__stkbottom /* for stack checks */ movl %eax,U_SYSTEM_STACKBOTTOM movl ___djgpp_stack_limit,%eax /* Bottom of stack */ addl __stklen, %eax movw %ds, %dx /* set stack */ movw %dx, %ss andl $0xfffffffc,%eax movl %eax, %esp xorl %ebp, %ebp call ___prt1_startup /* run program */ jmp exit no_memory: movb $0xff, %al jmp exit /*-----------------------------------------------------------------------------*/ /* #define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31 */ .macro FREESEL x movw \x,%bx movw $0x0001,%ax int $0x31 .endm .global ___exit .align 2 ___exit: /* special exit from dpmiexcp.c */ .global __exit __exit: movl 4(%esp),%eax exit: movl %eax,%ecx xorl %eax,%eax movw %ax,%fs movw %ax,%gs cmpl $0,_exception_exit jz no_exception pushl %ecx call *_exception_exit popl %ecx no_exception: cli /* Just in case they didn't unhook ints */ FREESEL U_SYSTEM_GO32_INFO_BLOCK+26 /* selector for linear memory */ FREESEL ___v2prt0_ds_alias /* DS alias for rmcb exceptions */ FREESEL sbrk16_api_seg /* sbrk cs */ movw sbrk16_first_byte+6,%dx /* selector for allocated DOS mem */ movw $0x101, %ax int $0x31 /* Free block and selector */ 9: movl __stubinfo, %edx movl STUBINFO_CS_SELECTOR(%edx), %eax movw %ax, sbrk16_api_seg xorl %edi, %edi movl %edi, sbrk16_api_ofs /* Offset is zero */ movw STUBINFO_DS_SELECTOR(%edx), %es movb %cl, %dl /* Exit status */ movl $exit16_first_byte, %esi movl $(exit16_last_byte - exit16_first_byte), %ecx cld rep movsb movw %es,%ax /* We will free stack! */ movw %ax,%ss movl $0x400,%esp /* Transfer buffer >= 1024 bytes */ xorl %ebp, %ebp /* V1.10 bug fix */ movl ___djgpp_memory_handle_list, %edi movl ___djgpp_memory_handle_list+2, %esi /* Skip word prefixes */ FREESEL %ds movw %cs, %bx /* Call exit procedure with BX=32-bit CS; SI+DI=32-bit handle; DL=exit status */ .byte 0x2e ljmp sbrk16_api_ofs /*-----------------------------------------------------------------------------*/ /* .lcomm __what_size_app_thinks_it_is, 4 */ __what_size_app_thinks_it_is: .long end .lcomm __what_we_return_to_app_as_old_size, 4 .lcomm __what_size_dpmi_thinks_we_are, 4 lock_memory: /* BX:CX should be linear address; size is pushed on stack */ testb $0x10, __crt0_startup_flags+1 /* include/crt0.h */ jz 13f pushl %esi pushl %edi pushl %eax movl 16(%esp),%edi movw 18(%esp),%si movw $0x600,%ax int $0x31 popl %eax popl %edi popl %esi 13: ret $4 /* Pop the argument */ .global ___sbrk .align 2 ___sbrk: movl __what_size_app_thinks_it_is, %eax movl 4(%esp), %ecx /* Increment size */ addl %ecx, %eax jnc brk_common /* Carry is only set if a negative increment or wrap happens. Negative increment is semi-OK, wrap (only for multiple zone sbrk) isn't. */ test $0x80000000, %ecx /* Clears carry */ jnz brk_common stc /* Put carry back */ jmp brk_common .globl ___brk .align 2 ___brk: movl 4(%esp), %eax clc brk_common: pushl %esi pushl %edi pushl %ebx movl __what_size_app_thinks_it_is, %edx /* save info */ movl %edx, __what_we_return_to_app_as_old_size movl %eax, __what_size_app_thinks_it_is jc 10f /* Wrap for multi-zone */ cmpl __what_size_dpmi_thinks_we_are, %eax /* don't bother shrinking */ jbe brk_nochange addl $0x0000ffff, %eax /* round up to 64K block */ andl $0xffff0000, %eax push %eax /* size - save for later */ movl ___djgpp_memory_handle_list, %edi /* request new size */ movw ___djgpp_memory_handle_list+2, %si movl %eax, %ecx /* size not limit */ movl %eax, %ebx /* size not limit */ shrl $16, %ebx /* BX:CX size */ movw $0x0902, %ax /* disable interrupts */ int $0x31 movl %eax,___sbrk_interrupt_state testb %al,%al jz interrupts_already_disabled movw $0x0900,%eax int $0x31 interrupts_already_disabled: lcall sbrk16_api_ofs setc %dl /* Save carry */ /* popl %eax restore interrupts int $0x31 postponed after ds alias is set correctly */ test %dl,%dl popl %edx jne brk_error movl %edi, ___djgpp_memory_handle_list /* store new handle */ movw %si, ___djgpp_memory_handle_list+2 movl %ecx, ___djgpp_base_address /* store new base address */ movw %bx, ___djgpp_base_address+2 movl %edx, %eax movl __what_size_dpmi_thinks_we_are, %ecx subl %ecx, %eax addl ___djgpp_base_address, %ecx movl %ecx, %ebx shrl $16, %ebx /* BX:CX addr */ pushl %eax /* Size */ call lock_memory decl %edx /* limit now, not size */ 5: movl %edx, ___djgpp_selector_limit orw $0x0fff, %dx /* low bits set */ movw $0x0008, %ax /* reset CS limit */ movw %cs, %bx movl %edx, %ecx shrl $16, %ecx int $0x31 /* CX:DX is limit */ testb $0x80, __crt0_startup_flags /* include/crt0.h */ jnz 3f movw $0x0008, %ax /* reset DS limit */ movw %ds, %bx int $0x31 movw $0x0008, %ax /* reset DS alias limit */ movl ___v2prt0_ds_alias, %ebx int $0x31 3: movw $0x0007, %ax /* reset DS alias base */ movl ___v2prt0_ds_alias, %ebx movl ___djgpp_base_address, %edx movw ___djgpp_base_address+2, %cx int $0x31 movl %eax,___sbrk_interrupt_state /* restore interrupts */ testb %al,%al je do_not_enable movw $0x0901,%eax int $0x31 do_not_enable: movl ___djgpp_selector_limit, %edx 12: incl %edx /* Size not limit */ testb $0x60, __crt0_startup_flags /* include/crt0.h */ jz no_fill_sbrk_memory pushl %ds popl %es movl __what_size_dpmi_thinks_we_are, %edi /* set all newly resized bytes zero */ movl %edx, %ecx /* Limit */ subl %edi, %ecx /* Adjust count for base */ xorl %eax, %eax testb $0x40, __crt0_startup_flags jz no_deadbeef movl $0xdeadbeef, %eax /* something really easy to spot */ no_deadbeef: shrl $2, %ecx /* div 4 Longwords not bytes */ cld rep stosl no_fill_sbrk_memory: movl %edx, __what_size_dpmi_thinks_we_are brk_nochange: /* successful return */ movl __what_we_return_to_app_as_old_size, %eax jmp brk_return brk_error: /* error return */ movl __what_we_return_to_app_as_old_size, %eax movl %eax, __what_size_app_thinks_it_is movl $-1, %eax brk_return: popl %ebx popl %edi popl %esi ret /* From here on this are parts of crt1.c converted to assembler and without any call to libc, so that it works without anything else additions made by Pierre Muller*/ /* from dpmidefs.h * / /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /* from include */ /* all macros removed here */ /* #define FUNC(x) .globl x; x: */ /* #define ENTER pushl %ebp; movl %esp,%ebp */ /* #define LEAVE(x) movl %ebp,%esp; popl %ebp; ret $(x) */ /* #define ARG1 8(%ebp) #define ARG1h 10(%ebp) #define ARG2 12(%ebp) #define ARG2h 14(%ebp) #define ARG3 16(%ebp) #define ARG4 20(%ebp) #define ARG5 24(%ebp) #define ARG6 28(%ebp) #define ARG7 32(%ebp) #define ARG8 36(%ebp) */ .comm ___dpmi_error,2 /* from dpmi0000.s */ /* .globl ___dpmi_allocate_ldt_descriptors */ /* using pascal convention => not usabel by C code */ ___dpmi_allocate_ldt_descriptors: pushl %ebp; movl %esp,%ebp movl 8(%ebp), %ecx movl $0x0000, %eax int $0x31 jnc .L_noerror0000 movw %ax,___dpmi_error movl $-1,%eax jmp .L_leave0000 .L_noerror0000: movzwl %ax,%eax .L_leave0000: movl %ebp,%esp popl %ebp ret $4 /* from file dpmi0008.s */ /* .globl ___dpmi_set_segment_limit */ ___dpmi_set_segment_limit: pushl %ebp; movl %esp,%ebp movl 8(%ebp), %ebx movzwl 12(%ebp), %edx movzwl 14(%ebp),%ecx movl $0x0008,%eax int $0x31 jnc .L_noerror0008 movw %ax,___dpmi_error movl $-1,%eax jmp .L_leave0008 .L_noerror0008: xorl %eax,%eax .L_leave0008: movl %ebp,%esp popl %ebp ret $8 /* .globl ___dpmi_get_version */ ___dpmi_get_version: pushl %ebp; movl %esp,%ebp movl $0x0400,%eax int $0x31 jnc .L_noerror0400 movw %ax,___dpmi_error movl $-1,%eax jmp .L_leave0400 .L_noerror0400: movl 8(%ebp), %esi movb %ah, (%esi) movb %al, 1(%esi) movw %bx, 2(%esi) movb %cl, 4(%esi) movb %dh, 5(%esi) movb %dl, 6(%esi) xorl %eax,%eax .L_leave0400: movl %ebp,%esp popl %ebp ret $4 /* .globl ___dpmi_get_segment_base_address*/ ___dpmi_get_segment_base_address: pushl %ebp; movl %esp,%ebp movl 8(%ebp), %ebx movl $0x0006,%eax int $0x31 jnc .L_noerror0006 movw %ax,___dpmi_error movl $-1,%eax jmp .L_leave0006 .L_noerror0006: movl 12(%ebp), %ebx movl %edx, (%ebx) movw %cx, 2(%ebx) xorl %eax,%eax .L_leave0006: movl %ebp,%esp popl %ebp ret $8 .globl ___bss_count .data .align 2 ___bss_count: .long 1 .text .align 2 .globl _setup_core_selector _setup_core_selector: pushl %ebp movl %esp,%ebp pushl $1 call ___dpmi_allocate_ldt_descriptors /* addl $4,%esp */ cmpl $-1,%eax jne .L24 movw $0,U_SYSTEM_GO32_INFO_BLOCK+26 leave ret .align 2,0x90 .L24: movw %ax,U_SYSTEM_GO32_INFO_BLOCK+26 movw %ax,_core_selector pushl $0x10ffff andl $0xffff,%eax pushl %eax call ___dpmi_set_segment_limit leave ret .align 2 .globl _setup_screens _setup_screens: pushl %ebp movl %esp,%ebp movw U_SYSTEM_GO32_INFO_BLOCK+26,%dx movl $1048563,%ecx /APP movw %dx, %gs .byte 0x65 movw (%ecx),%ax /NO_APP cmpw $64896,%ax jne .L26 movl $655360,U_SYSTEM_GO32_INFO_BLOCK+8 movl $655360,U_SYSTEM_GO32_INFO_BLOCK+4 leave ret .align 2,0x90 .L26: movl $1097,%ecx /APP movw %dx,%gs .byte 0x65 movb (%ecx),%al /NO_APP cmpb $7,%al jne .L29 movl $720896,U_SYSTEM_GO32_INFO_BLOCK+4 movl $753664,U_SYSTEM_GO32_INFO_BLOCK+8 leave ret .align 2,0x90 .L29: movl $753664,U_SYSTEM_GO32_INFO_BLOCK+4 movl $720896,U_SYSTEM_GO32_INFO_BLOCK+8 leave ret .align 2 .globl _setup_go32_info_block _setup_go32_info_block: pushl %ebp movl %esp,%ebp subl $8,%esp leal -8(%ebp),%eax pushl %eax call ___dpmi_get_version movl $40,U_SYSTEM_GO32_INFO_BLOCK movl __stubinfo,%edx movzwl 36(%edx),%eax sall $4,%eax movl %eax,U_SYSTEM_GO32_INFO_BLOCK+12 movzwl 32(%edx),%ecx movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+16 movzwl 38(%edx),%ecx movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+20 movb -3(%ebp),%al movb %al,U_SYSTEM_GO32_INFO_BLOCK+24 movb -2(%ebp),%al movb %al,U_SYSTEM_GO32_INFO_BLOCK+25 movl $-1,U_SYSTEM_GO32_INFO_BLOCK+28 pushl $U_SYSTEM_GO32_INFO_BLOCK+32 movzwl 38(%edx),%eax pushl %eax call ___dpmi_get_segment_base_address movw $4,U_SYSTEM_GO32_INFO_BLOCK+36 movb -8(%ebp),%dl salw $8,%dx movzbw -7(%ebp),%ax orw %ax,%dx movw %dx,U_SYSTEM_GO32_INFO_BLOCK+38 call copy_to_c_go32_info_block leave ret copy_to_c_go32_info_block: leal U_SYSTEM_GO32_INFO_BLOCK,%esi leal __go32_info_block,%edi movl $10,%ecx rep movsl ret .data /* fpu codeword */ ___fpucw: .long 0x1332 /* __go32_info_block for C programs */ .align 2 .globl __go32_info_block .comm __go32_info_block,40 /* -- prt1_startup -- */ .text .align 2 .globl ___prt1_startup ___prt1_startup: pushl %ebp movl %esp,%ebp pushl %ebx incl ___bss_count movl $0,___crt0_argv call _setup_core_selector call _setup_screens call _setup_go32_info_block incl ___environ_changed fninit /* initialize fpu */ /* fwait maybe this one is responsible of exceptions */ fldcw ___fpucw pushl U_SYSTEM_ENVP pushl ___crt0_argv pushl ___crt0_argc call _pascal_start pushl %eax /* call _exit changed to */ call exit .align 2,0x90 /* .comm U_SYSTEM_DOS_ARGV0,4 */ .comm ___dos_argv0,4 .comm ___crt0_argc,4 .comm ___crt0_argv,4 .comm ___environ_changed,4 /* ___environ_changed: not in data because it is defined in putenv.c */ /* .long 0 */ .globl _exception_exit _exception_exit: .long 0 .globl _swap_in _swap_in: .long 0 .globl _swap_out _swap_out: .long 0 .global _v2prt0_exceptions_on _v2prt0_exceptions_on: .long 0 // Fill null page with NOPs // and a jmp windows_error at the end .globl v2prt0_windows v2prt0_windows: movl $0x90909090,%eax xorl %edi,%edi movl $0x400,%ecx cld rep stosl movl $0xffB,%edi movb $0xe9,%al stosb movl $_fpc_windows_error-4,%eax subl %edi,%eax stosl ret // Raise SIGILL with UD2 opcode .globl _fpc_windows_error _fpc_windows_error: cmpl $0,_exception_exit je .L_error_216 .byte 0x0f,0x0b .L_error_216: pushl $216 call __exit jmp exit #enif /* this was the prt0.s from the go32v1 version */ // // call as start(argc, argv, envp) (C-calling convention) // .globl _pascal_start _pascal_start: /* %ebx doesn't contain ScreenPrimary */ movl U_SYSTEM_GO32_INFO_BLOCK+4,%ebx movl %ebx,_ScreenPrimary /* core selector in %fs */ /* keep original fs for debuggers !!!!! (PM) */ movw %fs,%ax movw %ax,___v2prt0_start_fs movw _core_selector,%ax movw %ax,%fs // Top of frame movl $0x0,%ebp movl %esp,%ebx movl 12(%ebx),%eax movl %eax,U_SYSTEM_ENVP movl %eax,_environ movl 8(%ebx),%eax movl %eax,_args movl 4(%ebx),%eax movl %eax,_argc call PASCALMAIN movl $0,%eax /* no error if passing here */ /* movl $0x4c00,%eax int $0x21 */ ret .data /* .comm U_SYSTEM_ENVP,4 */ .globl _ScreenPrimary _ScreenPrimary: .long 0 .globl _argc _argc: .long 0 .globl _args _args: .long 0 .globl _run_mode _run_mode: .word 4 .globl _core_selector _core_selector: .word 0 .globl ___v2prt0_start_fs ___v2prt0_start_fs: .word 0 .globl _environ _environ: .long 0 /* Here Pierre Muller added all what was in crt1.c */ /* in assembler */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /* adapted to assembler for FPC by Pierre Muller */ /* Global variables */ /* This gets incremented each time the program is started. Programs (such as Emacs) which dump their code to create a new executable, cause this to be larger than 2. Library functions that cache info in static variables should check the value of `__bss_count' if they need to reinitialize the static storage. */ .data .globl ___bss_count ___bs_count: .long 1 .globl __crt0_startup_flags __crt0_startup_flags: .long 0 .globl __dos_ds __dos_ds: .long 0 .globl ___PROXY ___PROXY: .ascii " !proxy" .byte 0 .globl ___PROXY_LEN ___PROXY_LEN: .long 7 /* $Log: v2prt0.as,v $ Revision 1.7 2000/02/16 13:24:55 pierre * Mouse crash bug fixed !!! Revision 1.6 1999/07/10 23:17:15 pierre merged from fixes branch Revision 1.5.2.1 1999/07/10 23:15:02 pierre * fixes problem with putenv.c Revision 1.5 1999/03/01 15:40:53 peter * use external names * removed all direct assembler modes Revision 1.4 1999/02/19 12:25:37 pierre + ___v2prt0_rmcb_regs in text section for Windows NT + catch of calls into zero page for Windows 95 (creates Run Time error 216 or SIGILL exception if dpmiexcp is loaded !) Revision 1.3 1999/01/05 10:44:59 pierre * suppressed fwaits to avoid FPU not present exceptions Revision 1.2 1998/12/21 14:14:21 pierre added some c vars needed to avoid loading od crt1.o Revision 1.1 1998/12/21 13:07:03 peter * use -FE Revision 1.4 1998/10/14 21:28:45 peter * initialize fpu so sigfpe is finally generated for fpu errors Revision 1.3 1998/08/19 10:56:35 pierre + added some special code for C interface to avoid loading of crt1.o or dpmiexcp.o from the libc.a Revision 1.2 1998/05/22 00:39:38 peter * go32v1, go32v2 recompiles with the new objects * remake3 works again with go32v2 - removed some "optimizes" from daniel which were wrong */ \ No newline at end of file +/* + $Id$ +*/ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/*****************************************************************************\ + * Interface to 32-bit executable (from stub.asm) + * + * cs:eip according to COFF header + * ds 32-bit data segment for COFF program + * fs selector for our data segment (fs:0 is stubinfo) + * ss:sp our stack (ss to be freed) + * All unspecified registers have unspecified values in them. +\*****************************************************************************/ +/* modified by Pierre Muller to become the prt0.s for FPC Pascal */ + + .file "v2prt0.as" + +/* #include "stubinfo.h" */ + STUBINFO = 0 + STUBINFO_MAGIC = 0 + STUBINFO_SIZE = 0x10 + STUBINFO_MINSTACK = 0x14 + STUBINFO_MEMORY_HANDLE = 0x18 + STUBINFO_INITIAL_SIZE = 0x1c + STUBINFO_MINKEEP = 0x20 + STUBINFO_DS_SELECTOR = 0x22 + STUBINFO_DS_SEGMENT = 0x24 + STUBINFO_PSP_SELECTOR = 0x26 + STUBINFO_CS_SELECTOR = 0x28 + STUBINFO_ENV_SIZE = 0x2a + STUBINFO_BASENAME = 0x2c + STUBINFO_ARGV0 = 0x34 + STUBINFO_DPMI_SERVER = 0x44 + STUBINFO_END = 0x54 + + +/* .comm __stklen, 4 + this is added to the compiler so that we can specify + the stack size */ + .comm __stkbottom,4 + .comm __stubinfo, 4 + .comm ___djgpp_base_address, 4 + .comm ___djgpp_selector_limit, 4 + .comm ___djgpp_stack_limit, 4 + .lcomm sel_buf, 8 + +/* ___djgpp_ds_alias defined in go32/exceptn.s */ +/* inserted at the end of this file */ +/* we use a local copy that will be copied to exceptn.s */ + .globl ___v2prt0_ds_alias +___v2prt0_ds_alias: + .long 0 +/* allocate 32*4 bytes for RMCB under the $ffff limit for Windows NT */ + .globl ___v2prt0_rmcb_regs +___v2prt0_rmcb_regs: + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.data + +___djgpp_memory_handle_pointer: + .long ___djgpp_memory_handle_list+8 /* Next free, first for stub */ + .comm ___djgpp_memory_handle_list, 2048 /* Enough for 256 handles */ + + /* simply get current state */ +___sbrk_interrupt_state: + .long 0x902 + +sbrk16_first_byte: +.include "sbrk16.ah" +sbrk16_last_byte: + +sbrk16_api_ofs: + .long 0 +sbrk16_api_seg: + .word 0 +zero: + .long 0 + +exit16_first_byte: +.include "exit16.ah" +exit16_last_byte: + +/* hook_387_emulator: + .long ___emu387_load_hook */ + +/* this is for when main comes from a library */ + .long _main + + +.text + .globl start +start: + pushl %ds /* set %es same as %ds */ + popl %es /* push/pop 4 bytes shorter than ax */ + +/* Enable NULL pointer protection if DPMI supports it */ + testb $0x1, __crt0_startup_flags+1 /* include/crt0.h */ + jnz 1f + movl $start, %eax + cmpl $0x1000, %eax + jl 1f + movw $0x507, %ax + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %esi + xorl %ebx, %ebx /* Offset 0 in mem block */ + movl $1, %ecx /* Set one page */ + movl $zero, %edx + int $0x31 /* Make null page uncommitted */ + jnc 1f + call v2prt0_windows +1: +/* Create an alias for DS to be used by real-mode callbacks (exception handler messes with DS itself) */ + + movw %ds, %bx + movw $0x000a, %ax + int $0x31 + jnc ds_alias_ok + movb $0x4c, %ah + int $0x21 + +ds_alias_ok: + movw %ax, ___v2prt0_ds_alias + movl %eax, %ebx + movw $0x0009, %ax + movw %cs, %cx /* get CPL from %cs */ + andl $3, %ecx + shll $5, %ecx /* move it into place */ + orw $0xc093, %cx + int $0x31 /* set access rights for alias */ + +/* Maybe set our DS limit to 4Gb in size if flag set */ + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jz 2f + movw $0xffff, %cx + movl %ecx, %edx + movw $0x0008, %ax /* reset alias limit to -1 */ + int $0x31 + movw %cs, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + movw %ds, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + lsl %ebx, %ebx /* Should be -1 */ + incl %ebx + jz 2f + andb $0x7f, __crt0_startup_flags /* clear it if failure */ +2: +/* Allocate some DOS memory and copy our sbrk helper into it. */ + movl $sbrk16_first_byte, %esi + movzwl 8(%esi), %ebx + shrl $4, %ebx + movw $0x0100, %ax + int $0x31 + jnc dos_alloc_ok + movb $0x4c, %ah + int $0x21 + +dos_alloc_ok: + movw %cs, 2(%esi) +/* store API information */ + movw %ds, 4(%esi) + movw %dx, 6(%esi) +/* selector for allocated block */ + + movzwl (%esi), %eax /* calculate API address */ + movl %eax, sbrk16_api_ofs + + pushl %es /* move the data */ + movw %dx, %es + movl $(sbrk16_last_byte - sbrk16_first_byte), %ecx + shrl $2,%ecx + xorl %edi, %edi + cld + rep + movsl + popl %es + + movl %edx, %ebx /* dos memory selector */ + movw $0x000b, %ax /* get descriptor */ + movl $sel_buf, %edi + int $0x31 + + andb $0xbf, sel_buf+6 /* make 16-bit */ + andb $0xf0, sel_buf+5 /* remove old type */ + orb $0x0a, sel_buf+5 /* set new type to code/read */ + + xorl %eax, %eax /* allocate new selector */ + movw $0x0001, %cx + int $0x31 + movw %ax, sbrk16_api_seg + + movl %eax, %ebx + movw $0x000c, %ax /* set descriptor */ + movl $sel_buf, %edi + int $0x31 + +/* Initialize the brk/sbrk variables */ + +/* movl $end, __what_size_app_thinks_it_is */ + .byte 0x64 /* fs: */ + movl STUBINFO_INITIAL_SIZE, %eax + movl %eax, __what_size_dpmi_thinks_we_are + +/* Maybe lock the initial block, expects BX:CX */ + movl %ecx,%ebx + movl %edx,%ecx + addw $4096,%cx /* Skip null page */ + adcl $0,%ebx + subl $4096,%eax + pushl %eax + call lock_memory + + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %eax + movl %eax, ___djgpp_memory_handle_list + + .byte 0x64 /* fs: */ /* copy stubinfo into local memory */ + movl STUBINFO_SIZE, %eax + pushl %eax + call ___sbrk + movl %eax, __stubinfo + movl %eax,U_SYSTEM_STUB_INFO + movl %eax, %edi + .byte 0x64 /* fs: */ + movl STUBINFO_SIZE, %ecx + shrl $2, %ecx + xorl %esi, %esi /* Zero */ + pushl %ds + pushl %fs + popl %ds + cld + rep + movsl + popl %ds + movl __stklen, %eax /* get program-requested stack size */ + .byte 0x64 /* fs: */ + movl STUBINFO_MINSTACK, %ecx /* get stub-requested stack size */ + cmpl %ecx, %eax + jge use_stubinfo_stack_size /* use the larger of the two */ + movl %ecx, %eax + movl %eax, __stklen /* store the actual stack length */ +use_stubinfo_stack_size: + pushl %eax + call ___sbrk /* allocate the memory */ + cmpl $-1, %eax + je no_memory + movl %eax, ___djgpp_stack_limit /* Bottom of stack */ + addl $256,%eax + movl %eax,__stkbottom /* for stack checks */ + movl %eax,U_SYSTEM_STACKBOTTOM + + movl ___djgpp_stack_limit,%eax /* Bottom of stack */ + addl __stklen, %eax + movw %ds, %dx /* set stack */ + movw %dx, %ss + andl $0xfffffffc,%eax + movl %eax, %esp + + xorl %ebp, %ebp + call ___prt1_startup /* run program */ + jmp exit + +no_memory: + movb $0xff, %al + jmp exit + +/*-----------------------------------------------------------------------------*/ + +/* #define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31 */ + .macro FREESEL x + movw \x,%bx + movw $0x0001,%ax + int $0x31 + .endm + + .global ___exit + .align 2 +___exit: +/* special exit from dpmiexcp.c */ + .global __exit +__exit: + movl 4(%esp),%eax +exit: + movl %eax,%ecx + xorl %eax,%eax + movw %ax,%fs + movw %ax,%gs + cmpl $0,_exception_exit + jz no_exception + pushl %ecx + call *_exception_exit + popl %ecx +no_exception: + cli /* Just in case they didn't unhook ints */ + FREESEL U_SYSTEM_GO32_INFO_BLOCK+26 /* selector for linear memory */ + FREESEL ___v2prt0_ds_alias /* DS alias for rmcb exceptions */ + FREESEL sbrk16_api_seg /* sbrk cs */ + movw sbrk16_first_byte+6,%dx /* selector for allocated DOS mem */ + movw $0x101, %ax + int $0x31 /* Free block and selector */ +9: + movl __stubinfo, %edx + movl STUBINFO_CS_SELECTOR(%edx), %eax + movw %ax, sbrk16_api_seg + xorl %edi, %edi + movl %edi, sbrk16_api_ofs /* Offset is zero */ + + movw STUBINFO_DS_SELECTOR(%edx), %es + movb %cl, %dl /* Exit status */ + movl $exit16_first_byte, %esi + movl $(exit16_last_byte - exit16_first_byte), %ecx + cld + rep + movsb + + movw %es,%ax /* We will free stack! */ + movw %ax,%ss + movl $0x400,%esp /* Transfer buffer >= 1024 bytes */ + + xorl %ebp, %ebp /* V1.10 bug fix */ + movl ___djgpp_memory_handle_list, %edi + movl ___djgpp_memory_handle_list+2, %esi /* Skip word prefixes */ + + FREESEL %ds + movw %cs, %bx +/* Call exit procedure with BX=32-bit CS; SI+DI=32-bit handle; DL=exit status */ + .byte 0x2e + ljmp sbrk16_api_ofs + +/*-----------------------------------------------------------------------------*/ + +/* .lcomm __what_size_app_thinks_it_is, 4 */ +__what_size_app_thinks_it_is: + .long end + .lcomm __what_we_return_to_app_as_old_size, 4 + .lcomm __what_size_dpmi_thinks_we_are, 4 + +lock_memory: + /* BX:CX should be linear address; size is pushed on stack */ + testb $0x10, __crt0_startup_flags+1 /* include/crt0.h */ + jz 13f + pushl %esi + pushl %edi + pushl %eax + movl 16(%esp),%edi + movw 18(%esp),%si + movw $0x600,%ax + int $0x31 + popl %eax + popl %edi + popl %esi +13: ret $4 /* Pop the argument */ + + + .global ___sbrk + .align 2 +___sbrk: + movl __what_size_app_thinks_it_is, %eax + movl 4(%esp), %ecx /* Increment size */ + addl %ecx, %eax + jnc brk_common + /* Carry is only set if a negative increment or wrap happens. Negative + increment is semi-OK, wrap (only for multiple zone sbrk) isn't. */ + test $0x80000000, %ecx /* Clears carry */ + jnz brk_common + stc /* Put carry back */ + jmp brk_common + + .globl ___brk + .align 2 +___brk: + movl 4(%esp), %eax + clc + +brk_common: + pushl %esi + pushl %edi + pushl %ebx + + movl __what_size_app_thinks_it_is, %edx /* save info */ + movl %edx, __what_we_return_to_app_as_old_size + movl %eax, __what_size_app_thinks_it_is + + jc 10f /* Wrap for multi-zone */ + cmpl __what_size_dpmi_thinks_we_are, %eax /* don't bother shrinking */ + jbe brk_nochange + + addl $0x0000ffff, %eax /* round up to 64K block */ + andl $0xffff0000, %eax + push %eax /* size - save for later */ + + movl ___djgpp_memory_handle_list, %edi /* request new size */ + movw ___djgpp_memory_handle_list+2, %si + movl %eax, %ecx /* size not limit */ + movl %eax, %ebx /* size not limit */ + shrl $16, %ebx /* BX:CX size */ + + movw $0x0902, %ax /* disable interrupts */ + int $0x31 + movl %eax,___sbrk_interrupt_state + testb %al,%al + jz interrupts_already_disabled + movw $0x0900,%eax + int $0x31 +interrupts_already_disabled: + + lcall sbrk16_api_ofs + setc %dl /* Save carry */ + + /* popl %eax restore interrupts + int $0x31 postponed after ds alias is set correctly */ + + test %dl,%dl + popl %edx + jne brk_error + + movl %edi, ___djgpp_memory_handle_list /* store new handle */ + movw %si, ___djgpp_memory_handle_list+2 + movl %ecx, ___djgpp_base_address /* store new base address */ + movw %bx, ___djgpp_base_address+2 + + movl %edx, %eax + movl __what_size_dpmi_thinks_we_are, %ecx + subl %ecx, %eax + + addl ___djgpp_base_address, %ecx + movl %ecx, %ebx + shrl $16, %ebx /* BX:CX addr */ + pushl %eax /* Size */ + call lock_memory + + decl %edx /* limit now, not size */ +5: movl %edx, ___djgpp_selector_limit + orw $0x0fff, %dx /* low bits set */ + movw $0x0008, %ax /* reset CS limit */ + movw %cs, %bx + movl %edx, %ecx + shrl $16, %ecx + int $0x31 /* CX:DX is limit */ + + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jnz 3f + movw $0x0008, %ax /* reset DS limit */ + movw %ds, %bx + int $0x31 + + movw $0x0008, %ax /* reset DS alias limit */ + movl ___v2prt0_ds_alias, %ebx + int $0x31 +3: + movw $0x0007, %ax /* reset DS alias base */ + movl ___v2prt0_ds_alias, %ebx + movl ___djgpp_base_address, %edx + movw ___djgpp_base_address+2, %cx + int $0x31 + + movl %eax,___sbrk_interrupt_state /* restore interrupts */ + testb %al,%al + je do_not_enable + movw $0x0901,%eax + int $0x31 +do_not_enable: + movl ___djgpp_selector_limit, %edx +12: incl %edx /* Size not limit */ + testb $0x60, __crt0_startup_flags /* include/crt0.h */ + jz no_fill_sbrk_memory + pushl %ds + popl %es + + movl __what_size_dpmi_thinks_we_are, %edi /* set all newly resized bytes zero */ + movl %edx, %ecx /* Limit */ + subl %edi, %ecx /* Adjust count for base */ + xorl %eax, %eax + testb $0x40, __crt0_startup_flags + jz no_deadbeef + movl $0xdeadbeef, %eax /* something really easy to spot */ +no_deadbeef: + shrl $2, %ecx /* div 4 Longwords not bytes */ + cld + rep + stosl +no_fill_sbrk_memory: + movl %edx, __what_size_dpmi_thinks_we_are + +brk_nochange: /* successful return */ + movl __what_we_return_to_app_as_old_size, %eax + jmp brk_return + +brk_error: /* error return */ + movl __what_we_return_to_app_as_old_size, %eax + movl %eax, __what_size_app_thinks_it_is + movl $-1, %eax + +brk_return: + popl %ebx + popl %edi + popl %esi + ret + +/* From here on this are parts of crt1.c converted to assembler +and without any call to libc, so that it works without anything else +additions made by Pierre Muller*/ +/* from dpmidefs.h * / +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* from include */ +/* all macros removed here */ +/* #define FUNC(x) .globl x; x: */ + +/* #define ENTER pushl %ebp; movl %esp,%ebp */ + +/* #define LEAVE(x) movl %ebp,%esp; popl %ebp; ret $(x) */ +/* #define ARG1 8(%ebp) +#define ARG1h 10(%ebp) +#define ARG2 12(%ebp) +#define ARG2h 14(%ebp) +#define ARG3 16(%ebp) +#define ARG4 20(%ebp) +#define ARG5 24(%ebp) +#define ARG6 28(%ebp) +#define ARG7 32(%ebp) +#define ARG8 36(%ebp) */ + + .comm ___dpmi_error,2 + +/* from dpmi0000.s */ +/* .globl ___dpmi_allocate_ldt_descriptors */ +/* using pascal convention => not usabel by C code */ +___dpmi_allocate_ldt_descriptors: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ecx + movl $0x0000, %eax + int $0x31 + jnc .L_noerror0000 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0000 +.L_noerror0000: + movzwl %ax,%eax +.L_leave0000: + movl %ebp,%esp + popl %ebp + ret $4 + +/* from file dpmi0008.s */ +/* .globl ___dpmi_set_segment_limit */ +___dpmi_set_segment_limit: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movzwl 12(%ebp), %edx + movzwl 14(%ebp),%ecx + + movl $0x0008,%eax + int $0x31 + jnc .L_noerror0008 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0008 +.L_noerror0008: + xorl %eax,%eax +.L_leave0008: + movl %ebp,%esp + popl %ebp + ret $8 + +/* .globl ___dpmi_get_version */ +___dpmi_get_version: + pushl %ebp; movl %esp,%ebp + + movl $0x0400,%eax + int $0x31 + jnc .L_noerror0400 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0400 +.L_noerror0400: + movl 8(%ebp), %esi + movb %ah, (%esi) + movb %al, 1(%esi) + movw %bx, 2(%esi) + movb %cl, 4(%esi) + movb %dh, 5(%esi) + movb %dl, 6(%esi) + + xorl %eax,%eax +.L_leave0400: + + movl %ebp,%esp + popl %ebp + ret $4 + +/* .globl ___dpmi_get_segment_base_address*/ +___dpmi_get_segment_base_address: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movl $0x0006,%eax + int $0x31 + jnc .L_noerror0006 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0006 +.L_noerror0006: + + movl 12(%ebp), %ebx + movl %edx, (%ebx) + movw %cx, 2(%ebx) + + xorl %eax,%eax +.L_leave0006: + movl %ebp,%esp + popl %ebp + ret $8 + +.globl ___bss_count +.data + .align 2 +___bss_count: + .long 1 +.text + .align 2 + .globl _setup_core_selector +_setup_core_selector: + pushl %ebp + movl %esp,%ebp + pushl $1 + call ___dpmi_allocate_ldt_descriptors + /* addl $4,%esp */ + cmpl $-1,%eax + jne .L24 + movw $0,U_SYSTEM_GO32_INFO_BLOCK+26 + leave + ret + .align 2,0x90 +.L24: + movw %ax,U_SYSTEM_GO32_INFO_BLOCK+26 + movw %ax,_core_selector + pushl $0x10ffff + andl $0xffff,%eax + pushl %eax + call ___dpmi_set_segment_limit + leave + ret + .align 2 + .globl _setup_screens +_setup_screens: + pushl %ebp + movl %esp,%ebp + movw U_SYSTEM_GO32_INFO_BLOCK+26,%dx + movl $1048563,%ecx +/APP + movw %dx, %gs + .byte 0x65 + movw (%ecx),%ax +/NO_APP + cmpw $64896,%ax + jne .L26 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+8 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+4 + leave + ret + .align 2,0x90 +.L26: + movl $1097,%ecx +/APP + movw %dx,%gs + .byte 0x65 + movb (%ecx),%al +/NO_APP + cmpb $7,%al + jne .L29 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + .align 2,0x90 +.L29: + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + + .align 2 + .globl _setup_go32_info_block +_setup_go32_info_block: + pushl %ebp + movl %esp,%ebp + subl $8,%esp + leal -8(%ebp),%eax + pushl %eax + call ___dpmi_get_version + movl $40,U_SYSTEM_GO32_INFO_BLOCK + movl __stubinfo,%edx + movzwl 36(%edx),%eax + sall $4,%eax + movl %eax,U_SYSTEM_GO32_INFO_BLOCK+12 + movzwl 32(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+16 + movzwl 38(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+20 + movb -3(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+24 + movb -2(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+25 + movl $-1,U_SYSTEM_GO32_INFO_BLOCK+28 + pushl $U_SYSTEM_GO32_INFO_BLOCK+32 + movzwl 38(%edx),%eax + pushl %eax + call ___dpmi_get_segment_base_address + movw $4,U_SYSTEM_GO32_INFO_BLOCK+36 + movb -8(%ebp),%dl + salw $8,%dx + movzbw -7(%ebp),%ax + orw %ax,%dx + movw %dx,U_SYSTEM_GO32_INFO_BLOCK+38 + call copy_to_c_go32_info_block + leave + ret + +copy_to_c_go32_info_block: + leal U_SYSTEM_GO32_INFO_BLOCK,%esi + leal __go32_info_block,%edi + movl $10,%ecx + rep + movsl + ret + +.data + /* fpu codeword */ +___fpucw: + .long 0x1332 + /* __go32_info_block for C programs */ + .align 2 + .globl __go32_info_block +.comm __go32_info_block,40 + +/* + -- prt1_startup -- +*/ +.text + .align 2 + .globl ___prt1_startup +___prt1_startup: + pushl %ebp + movl %esp,%ebp + pushl %ebx + incl ___bss_count + movl $0,___crt0_argv + call _setup_core_selector + call _setup_screens + call _setup_go32_info_block + incl ___environ_changed + + fninit /* initialize fpu */ + /* fwait maybe this one is responsible of exceptions */ + fldcw ___fpucw + + pushl U_SYSTEM_ENVP + pushl ___crt0_argv + pushl ___crt0_argc + call _pascal_start + pushl %eax +/* call _exit changed to */ + call exit + .align 2,0x90 +/* .comm U_SYSTEM_DOS_ARGV0,4 */ + .comm ___dos_argv0,4 + .comm ___crt0_argc,4 + .comm ___crt0_argv,4 + .comm ___environ_changed,4 +/* ___environ_changed: not in data because it is defined in putenv.c */ +/* .long 0 */ + .globl _exception_exit +_exception_exit: + .long 0 + .globl _swap_in +_swap_in: + .long 0 + .globl _swap_out +_swap_out: + .long 0 + .global _v2prt0_exceptions_on +_v2prt0_exceptions_on: + .long 0 + +// Fill null page with NOPs +// and a jmp windows_error at the end + .globl v2prt0_windows +v2prt0_windows: + movl $0x90909090,%eax + xorl %edi,%edi + movl $0x400,%ecx + cld + rep + stosl + movl $0xffB,%edi + movb $0xe9,%al + stosb + movl $_fpc_windows_error-4,%eax + subl %edi,%eax + stosl + ret + +// Raise SIGILL with UD2 opcode + + .globl _fpc_windows_error +_fpc_windows_error: + cmpl $0,_exception_exit + je .L_error_216 + .byte 0x0f,0x0b +.L_error_216: + pushl $216 + call __exit + jmp exit +#enif + +/* this was the prt0.s from the go32v1 version */ +// +// call as start(argc, argv, envp) (C-calling convention) +// + .globl _pascal_start +_pascal_start: + /* %ebx doesn't contain ScreenPrimary */ + movl U_SYSTEM_GO32_INFO_BLOCK+4,%ebx + movl %ebx,_ScreenPrimary + /* core selector in %fs */ + /* keep original fs for debuggers !!!!! (PM) */ + movw %fs,%ax + movw %ax,___v2prt0_start_fs + + movw _core_selector,%ax + movw %ax,%fs + +// Top of frame + movl $0x0,%ebp + movl %esp,%ebx + movl 12(%ebx),%eax + movl %eax,U_SYSTEM_ENVP + movl %eax,_environ + movl 8(%ebx),%eax + movl %eax,_args + movl 4(%ebx),%eax + movl %eax,_argc + + call PASCALMAIN + movl $0,%eax + /* no error if passing here */ +/* movl $0x4c00,%eax + int $0x21 */ + + ret + + .data + +/* .comm U_SYSTEM_ENVP,4 */ + .globl _ScreenPrimary +_ScreenPrimary: + .long 0 + .globl _argc +_argc: + .long 0 + .globl _args +_args: + .long 0 + .globl _run_mode +_run_mode: + .word 4 + .globl _core_selector +_core_selector: + .word 0 + .globl ___v2prt0_start_fs +___v2prt0_start_fs: + .word 0 + .globl _environ +_environ: + .long 0 + +/* Here Pierre Muller added all what was in crt1.c */ +/* in assembler */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* adapted to assembler for FPC by Pierre Muller */ + +/* Global variables */ + + +/* This gets incremented each time the program is started. + Programs (such as Emacs) which dump their code to create + a new executable, cause this to be larger than 2. Library + functions that cache info in static variables should check + the value of `__bss_count' if they need to reinitialize + the static storage. */ + .data + .globl ___bss_count +___bs_count: + .long 1 + + .globl __crt0_startup_flags +__crt0_startup_flags: + .long 0 + + .globl __dos_ds +__dos_ds: + .long 0 + + .globl ___PROXY +___PROXY: + .ascii " !proxy" + .byte 0 + + .globl ___PROXY_LEN +___PROXY_LEN: + .long 7 + +/* + $Log$ + Revision 1.9 2000-02-23 07:12:41 jonas + * fixed wrong line breaks + +/* + $Id$ +*/ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/*****************************************************************************\ + * Interface to 32-bit executable (from stub.asm) + * + * cs:eip according to COFF header + * ds 32-bit data segment for COFF program + * fs selector for our data segment (fs:0 is stubinfo) + * ss:sp our stack (ss to be freed) + * All unspecified registers have unspecified values in them. +\*****************************************************************************/ +/* modified by Pierre Muller to become the prt0.s for FPC Pascal */ + + .file "v2prt0.as" + +/* #include "stubinfo.h" */ + STUBINFO = 0 + STUBINFO_MAGIC = 0 + STUBINFO_SIZE = 0x10 + STUBINFO_MINSTACK = 0x14 + STUBINFO_MEMORY_HANDLE = 0x18 + STUBINFO_INITIAL_SIZE = 0x1c + STUBINFO_MINKEEP = 0x20 + STUBINFO_DS_SELECTOR = 0x22 + STUBINFO_DS_SEGMENT = 0x24 + STUBINFO_PSP_SELECTOR = 0x26 + STUBINFO_CS_SELECTOR = 0x28 + STUBINFO_ENV_SIZE = 0x2a + STUBINFO_BASENAME = 0x2c + STUBINFO_ARGV0 = 0x34 + STUBINFO_DPMI_SERVER = 0x44 + STUBINFO_END = 0x54 + + +/* .comm __stklen, 4 + this is added to the compiler so that we can specify + the stack size */ + .comm __stkbottom,4 + .comm __stubinfo, 4 + .comm ___djgpp_base_address, 4 + .comm ___djgpp_selector_limit, 4 + .comm ___djgpp_stack_limit, 4 + .lcomm sel_buf, 8 + +/* ___djgpp_ds_alias defined in go32/exceptn.s */ +/* inserted at the end of this file */ +/* we use a local copy that will be copied to exceptn.s */ + .globl ___v2prt0_ds_alias +___v2prt0_ds_alias: + .long 0 +/* allocate 32*4 bytes for RMCB under the $ffff limit for Windows NT */ + .globl ___v2prt0_rmcb_regs +___v2prt0_rmcb_regs: + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.data + +___djgpp_memory_handle_pointer: + .long ___djgpp_memory_handle_list+8 /* Next free, first for stub */ + .comm ___djgpp_memory_handle_list, 2048 /* Enough for 256 handles */ + + /* simply get current state */ +___sbrk_interrupt_state: + .long 0x902 + +sbrk16_first_byte: +.include "sbrk16.ah" +sbrk16_last_byte: + +sbrk16_api_ofs: + .long 0 +sbrk16_api_seg: + .word 0 +zero: + .long 0 + +exit16_first_byte: +.include "exit16.ah" +exit16_last_byte: + +/* hook_387_emulator: + .long ___emu387_load_hook */ + +/* this is for when main comes from a library */ + .long _main + + +.text + .globl start +start: + pushl %ds /* set %es same as %ds */ + popl %es /* push/pop 4 bytes shorter than ax */ + +/* Enable NULL pointer protection if DPMI supports it */ + testb $0x1, __crt0_startup_flags+1 /* include/crt0.h */ + jnz 1f + movl $start, %eax + cmpl $0x1000, %eax + jl 1f + movw $0x507, %ax + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %esi + xorl %ebx, %ebx /* Offset 0 in mem block */ + movl $1, %ecx /* Set one page */ + movl $zero, %edx + int $0x31 /* Make null page uncommitted */ + jnc 1f + call v2prt0_windows +1: +/* Create an alias for DS to be used by real-mode callbacks (exception handler messes with DS itself) */ + + movw %ds, %bx + movw $0x000a, %ax + int $0x31 + jnc ds_alias_ok + movb $0x4c, %ah + int $0x21 + +ds_alias_ok: + movw %ax, ___v2prt0_ds_alias + movl %eax, %ebx + movw $0x0009, %ax + movw %cs, %cx /* get CPL from %cs */ + andl $3, %ecx + shll $5, %ecx /* move it into place */ + orw $0xc093, %cx + int $0x31 /* set access rights for alias */ + +/* Maybe set our DS limit to 4Gb in size if flag set */ + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jz 2f + movw $0xffff, %cx + movl %ecx, %edx + movw $0x0008, %ax /* reset alias limit to -1 */ + int $0x31 + movw %cs, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + movw %ds, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + lsl %ebx, %ebx /* Should be -1 */ + incl %ebx + jz 2f + andb $0x7f, __crt0_startup_flags /* clear it if failure */ +2: +/* Allocate some DOS memory and copy our sbrk helper into it. */ + movl $sbrk16_first_byte, %esi + movzwl 8(%esi), %ebx + shrl $4, %ebx + movw $0x0100, %ax + int $0x31 + jnc dos_alloc_ok + movb $0x4c, %ah + int $0x21 + +dos_alloc_ok: + movw %cs, 2(%esi) +/* store API information */ + movw %ds, 4(%esi) + movw %dx, 6(%esi) +/* selector for allocated block */ + + movzwl (%esi), %eax /* calculate API address */ + movl %eax, sbrk16_api_ofs + + pushl %es /* move the data */ + movw %dx, %es + movl $(sbrk16_last_byte - sbrk16_first_byte), %ecx + shrl $2,%ecx + xorl %edi, %edi + cld + rep + movsl + popl %es + + movl %edx, %ebx /* dos memory selector */ + movw $0x000b, %ax /* get descriptor */ + movl $sel_buf, %edi + int $0x31 + + andb $0xbf, sel_buf+6 /* make 16-bit */ + andb $0xf0, sel_buf+5 /* remove old type */ + orb $0x0a, sel_buf+5 /* set new type to code/read */ + + xorl %eax, %eax /* allocate new selector */ + movw $0x0001, %cx + int $0x31 + movw %ax, sbrk16_api_seg + + movl %eax, %ebx + movw $0x000c, %ax /* set descriptor */ + movl $sel_buf, %edi + int $0x31 + +/* Initialize the brk/sbrk variables */ + +/* movl $end, __what_size_app_thinks_it_is */ + .byte 0x64 /* fs: */ + movl STUBINFO_INITIAL_SIZE, %eax + movl %eax, __what_size_dpmi_thinks_we_are + +/* Maybe lock the initial block, expects BX:CX */ + movl %ecx,%ebx + movl %edx,%ecx + addw $4096,%cx /* Skip null page */ + adcl $0,%ebx + subl $4096,%eax + pushl %eax + call lock_memory + + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %eax + movl %eax, ___djgpp_memory_handle_list + + .byte 0x64 /* fs: */ /* copy stubinfo into local memory */ + movl STUBINFO_SIZE, %eax + pushl %eax + call ___sbrk + movl %eax, __stubinfo + movl %eax,U_SYSTEM_STUB_INFO + movl %eax, %edi + .byte 0x64 /* fs: */ + movl STUBINFO_SIZE, %ecx + shrl $2, %ecx + xorl %esi, %esi /* Zero */ + pushl %ds + pushl %fs + popl %ds + cld + rep + movsl + popl %ds + movl __stklen, %eax /* get program-requested stack size */ + .byte 0x64 /* fs: */ + movl STUBINFO_MINSTACK, %ecx /* get stub-requested stack size */ + cmpl %ecx, %eax + jge use_stubinfo_stack_size /* use the larger of the two */ + movl %ecx, %eax + movl %eax, __stklen /* store the actual stack length */ +use_stubinfo_stack_size: + pushl %eax + call ___sbrk /* allocate the memory */ + cmpl $-1, %eax + je no_memory + movl %eax, ___djgpp_stack_limit /* Bottom of stack */ + addl $256,%eax + movl %eax,__stkbottom /* for stack checks */ + movl %eax,U_SYSTEM_STACKBOTTOM + + movl ___djgpp_stack_limit,%eax /* Bottom of stack */ + addl __stklen, %eax + movw %ds, %dx /* set stack */ + movw %dx, %ss + andl $0xfffffffc,%eax + movl %eax, %esp + + xorl %ebp, %ebp + call ___prt1_startup /* run program */ + jmp exit + +no_memory: + movb $0xff, %al + jmp exit + +/*-----------------------------------------------------------------------------*/ + +/* #define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31 */ + .macro FREESEL x + movw \x,%bx + movw $0x0001,%ax + int $0x31 + .endm + + .global ___exit + .align 2 +___exit: +/* special exit from dpmiexcp.c */ + .global __exit +__exit: + movl 4(%esp),%eax +exit: + movl %eax,%ecx + xorl %eax,%eax + movw %ax,%fs + movw %ax,%gs + cmpl $0,_exception_exit + jz no_exception + pushl %ecx + call *_exception_exit + popl %ecx +no_exception: + cli /* Just in case they didn't unhook ints */ + FREESEL U_SYSTEM_GO32_INFO_BLOCK+26 /* selector for linear memory */ + FREESEL ___v2prt0_ds_alias /* DS alias for rmcb exceptions */ + FREESEL sbrk16_api_seg /* sbrk cs */ + movw sbrk16_first_byte+6,%dx /* selector for allocated DOS mem */ + movw $0x101, %ax + int $0x31 /* Free block and selector */ +9: + movl __stubinfo, %edx + movl STUBINFO_CS_SELECTOR(%edx), %eax + movw %ax, sbrk16_api_seg + xorl %edi, %edi + movl %edi, sbrk16_api_ofs /* Offset is zero */ + + movw STUBINFO_DS_SELECTOR(%edx), %es + movb %cl, %dl /* Exit status */ + movl $exit16_first_byte, %esi + movl $(exit16_last_byte - exit16_first_byte), %ecx + cld + rep + movsb + + movw %es,%ax /* We will free stack! */ + movw %ax,%ss + movl $0x400,%esp /* Transfer buffer >= 1024 bytes */ + + xorl %ebp, %ebp /* V1.10 bug fix */ + movl ___djgpp_memory_handle_list, %edi + movl ___djgpp_memory_handle_list+2, %esi /* Skip word prefixes */ + + FREESEL %ds + movw %cs, %bx +/* Call exit procedure with BX=32-bit CS; SI+DI=32-bit handle; DL=exit status */ + .byte 0x2e + ljmp sbrk16_api_ofs + +/*-----------------------------------------------------------------------------*/ + +/* .lcomm __what_size_app_thinks_it_is, 4 */ +__what_size_app_thinks_it_is: + .long end + .lcomm __what_we_return_to_app_as_old_size, 4 + .lcomm __what_size_dpmi_thinks_we_are, 4 + +lock_memory: + /* BX:CX should be linear address; size is pushed on stack */ + testb $0x10, __crt0_startup_flags+1 /* include/crt0.h */ + jz 13f + pushl %esi + pushl %edi + pushl %eax + movl 16(%esp),%edi + movw 18(%esp),%si + movw $0x600,%ax + int $0x31 + popl %eax + popl %edi + popl %esi +13: ret $4 /* Pop the argument */ + + + .global ___sbrk + .align 2 +___sbrk: + movl __what_size_app_thinks_it_is, %eax + movl 4(%esp), %ecx /* Increment size */ + addl %ecx, %eax + jnc brk_common + /* Carry is only set if a negative increment or wrap happens. Negative + increment is semi-OK, wrap (only for multiple zone sbrk) isn't. */ + test $0x80000000, %ecx /* Clears carry */ + jnz brk_common + stc /* Put carry back */ + jmp brk_common + + .globl ___brk + .align 2 +___brk: + movl 4(%esp), %eax + clc + +brk_common: + pushl %esi + pushl %edi + pushl %ebx + + movl __what_size_app_thinks_it_is, %edx /* save info */ + movl %edx, __what_we_return_to_app_as_old_size + movl %eax, __what_size_app_thinks_it_is + + jc 10f /* Wrap for multi-zone */ + cmpl __what_size_dpmi_thinks_we_are, %eax /* don't bother shrinking */ + jbe brk_nochange + + addl $0x0000ffff, %eax /* round up to 64K block */ + andl $0xffff0000, %eax + push %eax /* size - save for later */ + + movl ___djgpp_memory_handle_list, %edi /* request new size */ + movw ___djgpp_memory_handle_list+2, %si + movl %eax, %ecx /* size not limit */ + movl %eax, %ebx /* size not limit */ + shrl $16, %ebx /* BX:CX size */ + + movw $0x0902, %ax /* disable interrupts */ + int $0x31 + movl %eax,___sbrk_interrupt_state + testb %al,%al + jz interrupts_already_disabled + movw $0x0900,%eax + int $0x31 +interrupts_already_disabled: + + lcall sbrk16_api_ofs + setc %dl /* Save carry */ + + /* popl %eax restore interrupts + int $0x31 postponed after ds alias is set correctly */ + + test %dl,%dl + popl %edx + jne brk_error + + movl %edi, ___djgpp_memory_handle_list /* store new handle */ + movw %si, ___djgpp_memory_handle_list+2 + movl %ecx, ___djgpp_base_address /* store new base address */ + movw %bx, ___djgpp_base_address+2 + + movl %edx, %eax + movl __what_size_dpmi_thinks_we_are, %ecx + subl %ecx, %eax + + addl ___djgpp_base_address, %ecx + movl %ecx, %ebx + shrl $16, %ebx /* BX:CX addr */ + pushl %eax /* Size */ + call lock_memory + + decl %edx /* limit now, not size */ +5: movl %edx, ___djgpp_selector_limit + orw $0x0fff, %dx /* low bits set */ + movw $0x0008, %ax /* reset CS limit */ + movw %cs, %bx + movl %edx, %ecx + shrl $16, %ecx + int $0x31 /* CX:DX is limit */ + + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jnz 3f + movw $0x0008, %ax /* reset DS limit */ + movw %ds, %bx + int $0x31 + + movw $0x0008, %ax /* reset DS alias limit */ + movl ___v2prt0_ds_alias, %ebx + int $0x31 +3: + movw $0x0007, %ax /* reset DS alias base */ + movl ___v2prt0_ds_alias, %ebx + movl ___djgpp_base_address, %edx + movw ___djgpp_base_address+2, %cx + int $0x31 + + movl %eax,___sbrk_interrupt_state /* restore interrupts */ + testb %al,%al + je do_not_enable + movw $0x0901,%eax + int $0x31 +do_not_enable: + movl ___djgpp_selector_limit, %edx +12: incl %edx /* Size not limit */ + testb $0x60, __crt0_startup_flags /* include/crt0.h */ + jz no_fill_sbrk_memory + pushl %ds + popl %es + + movl __what_size_dpmi_thinks_we_are, %edi /* set all newly resized bytes zero */ + movl %edx, %ecx /* Limit */ + subl %edi, %ecx /* Adjust count for base */ + xorl %eax, %eax + testb $0x40, __crt0_startup_flags + jz no_deadbeef + movl $0xdeadbeef, %eax /* something really easy to spot */ +no_deadbeef: + shrl $2, %ecx /* div 4 Longwords not bytes */ + cld + rep + stosl +no_fill_sbrk_memory: + movl %edx, __what_size_dpmi_thinks_we_are + +brk_nochange: /* successful return */ + movl __what_we_return_to_app_as_old_size, %eax + jmp brk_return + +brk_error: /* error return */ + movl __what_we_return_to_app_as_old_size, %eax + movl %eax, __what_size_app_thinks_it_is + movl $-1, %eax + +brk_return: + popl %ebx + popl %edi + popl %esi + ret + +/* From here on this are parts of crt1.c converted to assembler +and without any call to libc, so that it works without anything else +additions made by Pierre Muller*/ +/* from dpmidefs.h * / +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* from include */ +/* all macros removed here */ +/* #define FUNC(x) .globl x; x: */ + +/* #define ENTER pushl %ebp; movl %esp,%ebp */ + +/* #define LEAVE(x) movl %ebp,%esp; popl %ebp; ret $(x) */ +/* #define ARG1 8(%ebp) +#define ARG1h 10(%ebp) +#define ARG2 12(%ebp) +#define ARG2h 14(%ebp) +#define ARG3 16(%ebp) +#define ARG4 20(%ebp) +#define ARG5 24(%ebp) +#define ARG6 28(%ebp) +#define ARG7 32(%ebp) +#define ARG8 36(%ebp) */ + + .comm ___dpmi_error,2 + +/* from dpmi0000.s */ +/* .globl ___dpmi_allocate_ldt_descriptors */ +/* using pascal convention => not usabel by C code */ +___dpmi_allocate_ldt_descriptors: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ecx + movl $0x0000, %eax + int $0x31 + jnc .L_noerror0000 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0000 +.L_noerror0000: + movzwl %ax,%eax +.L_leave0000: + movl %ebp,%esp + popl %ebp + ret $4 + +/* from file dpmi0008.s */ +/* .globl ___dpmi_set_segment_limit */ +___dpmi_set_segment_limit: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movzwl 12(%ebp), %edx + movzwl 14(%ebp),%ecx + + movl $0x0008,%eax + int $0x31 + jnc .L_noerror0008 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0008 +.L_noerror0008: + xorl %eax,%eax +.L_leave0008: + movl %ebp,%esp + popl %ebp + ret $8 + +/* .globl ___dpmi_get_version */ +___dpmi_get_version: + pushl %ebp; movl %esp,%ebp + + movl $0x0400,%eax + int $0x31 + jnc .L_noerror0400 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0400 +.L_noerror0400: + movl 8(%ebp), %esi + movb %ah, (%esi) + movb %al, 1(%esi) + movw %bx, 2(%esi) + movb %cl, 4(%esi) + movb %dh, 5(%esi) + movb %dl, 6(%esi) + + xorl %eax,%eax +.L_leave0400: + + movl %ebp,%esp + popl %ebp + ret $4 + +/* .globl ___dpmi_get_segment_base_address*/ +___dpmi_get_segment_base_address: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movl $0x0006,%eax + int $0x31 + jnc .L_noerror0006 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0006 +.L_noerror0006: + + movl 12(%ebp), %ebx + movl %edx, (%ebx) + movw %cx, 2(%ebx) + + xorl %eax,%eax +.L_leave0006: + movl %ebp,%esp + popl %ebp + ret $8 + +.globl ___bss_count +.data + .align 2 +___bss_count: + .long 1 +.text + .align 2 + .globl _setup_core_selector +_setup_core_selector: + pushl %ebp + movl %esp,%ebp + pushl $1 + call ___dpmi_allocate_ldt_descriptors + /* addl $4,%esp */ + cmpl $-1,%eax + jne .L24 + movw $0,U_SYSTEM_GO32_INFO_BLOCK+26 + leave + ret + .align 2,0x90 +.L24: + movw %ax,U_SYSTEM_GO32_INFO_BLOCK+26 + movw %ax,_core_selector + pushl $0x10ffff + andl $0xffff,%eax + pushl %eax + call ___dpmi_set_segment_limit + leave + ret + .align 2 + .globl _setup_screens +_setup_screens: + pushl %ebp + movl %esp,%ebp + movw U_SYSTEM_GO32_INFO_BLOCK+26,%dx + movl $1048563,%ecx +/APP + movw %dx, %gs + .byte 0x65 + movw (%ecx),%ax +/NO_APP + cmpw $64896,%ax + jne .L26 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+8 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+4 + leave + ret + .align 2,0x90 +.L26: + movl $1097,%ecx +/APP + movw %dx,%gs + .byte 0x65 + movb (%ecx),%al +/NO_APP + cmpb $7,%al + jne .L29 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + .align 2,0x90 +.L29: + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + + .align 2 + .globl _setup_go32_info_block +_setup_go32_info_block: + pushl %ebp + movl %esp,%ebp + subl $8,%esp + leal -8(%ebp),%eax + pushl %eax + call ___dpmi_get_version + movl $40,U_SYSTEM_GO32_INFO_BLOCK + movl __stubinfo,%edx + movzwl 36(%edx),%eax + sall $4,%eax + movl %eax,U_SYSTEM_GO32_INFO_BLOCK+12 + movzwl 32(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+16 + movzwl 38(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+20 + movb -3(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+24 + movb -2(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+25 + movl $-1,U_SYSTEM_GO32_INFO_BLOCK+28 + pushl $U_SYSTEM_GO32_INFO_BLOCK+32 + movzwl 38(%edx),%eax + pushl %eax + call ___dpmi_get_segment_base_address + movw $4,U_SYSTEM_GO32_INFO_BLOCK+36 + movb -8(%ebp),%dl + salw $8,%dx + movzbw -7(%ebp),%ax + orw %ax,%dx + movw %dx,U_SYSTEM_GO32_INFO_BLOCK+38 + call copy_to_c_go32_info_block + leave + ret + +copy_to_c_go32_info_block: + leal U_SYSTEM_GO32_INFO_BLOCK,%esi + leal __go32_info_block,%edi + movl $10,%ecx + rep + movsl + ret + +.data + /* fpu codeword */ +___fpucw: + .long 0x1332 + /* __go32_info_block for C programs */ + .align 2 + .globl __go32_info_block +.comm __go32_info_block,40 + +/* + -- prt1_startup -- +*/ +.text + .align 2 + .globl ___prt1_startup +___prt1_startup: + pushl %ebp + movl %esp,%ebp + pushl %ebx + incl ___bss_count + movl $0,___crt0_argv + call _setup_core_selector + call _setup_screens + call _setup_go32_info_block + incl ___environ_changed + + fninit /* initialize fpu */ + /* fwait maybe this one is responsible of exceptions */ + fldcw ___fpucw + + pushl U_SYSTEM_ENVP + pushl ___crt0_argv + pushl ___crt0_argc + call _pascal_start + pushl %eax +/* call _exit changed to */ + call exit + .align 2,0x90 +/* .comm U_SYSTEM_DOS_ARGV0,4 */ + .comm ___dos_argv0,4 + .comm ___crt0_argc,4 + .comm ___crt0_argv,4 + .comm ___environ_changed,4 +/* ___environ_changed: not in data because it is defined in putenv.c */ +/* .long 0 */ + .globl _exception_exit +_exception_exit: + .long 0 + .globl _swap_in +_swap_in: + .long 0 + .globl _swap_out +_swap_out: + .long 0 + .global _v2prt0_exceptions_on +_v2prt0_exceptions_on: + .long 0 + +// Fill null page with NOPs +// and a jmp windows_error at the end + .globl v2prt0_windows +v2prt0_windows: + movl $0x90909090,%eax + xorl %edi,%edi + movl $0x400,%ecx + cld + rep + stosl + movl $0xffB,%edi + movb $0xe9,%al + stosb + movl $_fpc_windows_error-4,%eax + subl %edi,%eax + stosl + ret + +// Raise SIGILL with UD2 opcode + + .globl _fpc_windows_error +_fpc_windows_error: + cmpl $0,_exception_exit + je .L_error_216 + .byte 0x0f,0x0b +.L_error_216: + pushl $216 + call __exit + jmp exit +#enif + +/* this was the prt0.s from the go32v1 version */ +// +// call as start(argc, argv, envp) (C-calling convention) +// + .globl _pascal_start +_pascal_start: + /* %ebx doesn't contain ScreenPrimary */ + movl U_SYSTEM_GO32_INFO_BLOCK+4,%ebx + movl %ebx,_ScreenPrimary + /* core selector in %fs */ + /* keep original fs for debuggers !!!!! (PM) */ + movw %fs,%ax + movw %ax,___v2prt0_start_fs + + movw _core_selector,%ax + movw %ax,%fs + +// Top of frame + movl $0x0,%ebp + movl %esp,%ebx + movl 12(%ebx),%eax + movl %eax,U_SYSTEM_ENVP + movl %eax,_environ + movl 8(%ebx),%eax + movl %eax,_args + movl 4(%ebx),%eax + movl %eax,_argc + + call PASCALMAIN + movl $0,%eax + /* no error if passing here */ +/* movl $0x4c00,%eax + int $0x21 */ + + ret + + .data + +/* .comm U_SYSTEM_ENVP,4 */ + .globl _ScreenPrimary +_ScreenPrimary: + .long 0 + .globl _argc +_argc: + .long 0 + .globl _args +_args: + .long 0 + .globl _run_mode +_run_mode: + .word 4 + .globl _core_selector +_core_selector: + .word 0 + .globl ___v2prt0_start_fs +___v2prt0_start_fs: + .word 0 + .globl _environ +_environ: + .long 0 + +/* Here Pierre Muller added all what was in crt1.c */ +/* in assembler */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* adapted to assembler for FPC by Pierre Muller */ + +/* Global variables */ + + +/* This gets incremented each time the program is started. + Programs (such as Emacs) which dump their code to create + a new executable, cause this to be larger than 2. Library + functions that cache info in static variables should check + the value of `__bss_count' if they need to reinitialize + the static storage. */ + .data + .globl ___bss_count +___bs_count: + .long 1 + + .globl __crt0_startup_flags +__crt0_startup_flags: + .long 0 + + .globl __dos_ds +__dos_ds: + .long 0 + + .globl ___PROXY +___PROXY: + .ascii " !proxy" + .byte 0 + + .globl ___PROXY_LEN +___PROXY_LEN: + .long 7 + +/* + Revision 1.8 2000/02/22 14:26:28 jonas +/* + $Id$ +*/ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/*****************************************************************************\ + * Interface to 32-bit executable (from stub.asm) + * + * cs:eip according to COFF header + * ds 32-bit data segment for COFF program + * fs selector for our data segment (fs:0 is stubinfo) + * ss:sp our stack (ss to be freed) + * All unspecified registers have unspecified values in them. +\*****************************************************************************/ +/* modified by Pierre Muller to become the prt0.s for FPC Pascal */ + + .file "v2prt0.as" + +/* #include "stubinfo.h" */ + STUBINFO = 0 + STUBINFO_MAGIC = 0 + STUBINFO_SIZE = 0x10 + STUBINFO_MINSTACK = 0x14 + STUBINFO_MEMORY_HANDLE = 0x18 + STUBINFO_INITIAL_SIZE = 0x1c + STUBINFO_MINKEEP = 0x20 + STUBINFO_DS_SELECTOR = 0x22 + STUBINFO_DS_SEGMENT = 0x24 + STUBINFO_PSP_SELECTOR = 0x26 + STUBINFO_CS_SELECTOR = 0x28 + STUBINFO_ENV_SIZE = 0x2a + STUBINFO_BASENAME = 0x2c + STUBINFO_ARGV0 = 0x34 + STUBINFO_DPMI_SERVER = 0x44 + STUBINFO_END = 0x54 + + +/* .comm __stklen, 4 + this is added to the compiler so that we can specify + the stack size */ + .comm __stkbottom,4 + .comm __stubinfo, 4 + .comm ___djgpp_base_address, 4 + .comm ___djgpp_selector_limit, 4 + .comm ___djgpp_stack_limit, 4 + .lcomm sel_buf, 8 + +/* ___djgpp_ds_alias defined in go32/exceptn.s */ +/* inserted at the end of this file */ +/* we use a local copy that will be copied to exceptn.s */ + .globl ___v2prt0_ds_alias +___v2prt0_ds_alias: + .long 0 +/* allocate 32*4 bytes for RMCB under the $ffff limit for Windows NT */ + .globl ___v2prt0_rmcb_regs +___v2prt0_rmcb_regs: + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.data + +___djgpp_memory_handle_pointer: + .long ___djgpp_memory_handle_list+8 /* Next free, first for stub */ + .comm ___djgpp_memory_handle_list, 2048 /* Enough for 256 handles */ + + /* simply get current state */ +___sbrk_interrupt_state: + .long 0x902 + +sbrk16_first_byte: +.include "sbrk16.ah" +sbrk16_last_byte: + +sbrk16_api_ofs: + .long 0 +sbrk16_api_seg: + .word 0 +zero: + .long 0 + +exit16_first_byte: +.include "exit16.ah" +exit16_last_byte: + +/* hook_387_emulator: + .long ___emu387_load_hook */ + +/* this is for when main comes from a library */ + .long _main + + +.text + .globl start +start: + pushl %ds /* set %es same as %ds */ + popl %es /* push/pop 4 bytes shorter than ax */ + +/* Enable NULL pointer protection if DPMI supports it */ + testb $0x1, __crt0_startup_flags+1 /* include/crt0.h */ + jnz 1f + movl $start, %eax + cmpl $0x1000, %eax + jl 1f + movw $0x507, %ax + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %esi + xorl %ebx, %ebx /* Offset 0 in mem block */ + movl $1, %ecx /* Set one page */ + movl $zero, %edx + int $0x31 /* Make null page uncommitted */ + jnc 1f + call v2prt0_windows +1: +/* Create an alias for DS to be used by real-mode callbacks (exception handler messes with DS itself) */ + + movw %ds, %bx + movw $0x000a, %ax + int $0x31 + jnc ds_alias_ok + movb $0x4c, %ah + int $0x21 + +ds_alias_ok: + movw %ax, ___v2prt0_ds_alias + movl %eax, %ebx + movw $0x0009, %ax + movw %cs, %cx /* get CPL from %cs */ + andl $3, %ecx + shll $5, %ecx /* move it into place */ + orw $0xc093, %cx + int $0x31 /* set access rights for alias */ + +/* Maybe set our DS limit to 4Gb in size if flag set */ + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jz 2f + movw $0xffff, %cx + movl %ecx, %edx + movw $0x0008, %ax /* reset alias limit to -1 */ + int $0x31 + movw %cs, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + movw %ds, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + lsl %ebx, %ebx /* Should be -1 */ + incl %ebx + jz 2f + andb $0x7f, __crt0_startup_flags /* clear it if failure */ +2: +/* Allocate some DOS memory and copy our sbrk helper into it. */ + movl $sbrk16_first_byte, %esi + movzwl 8(%esi), %ebx + shrl $4, %ebx + movw $0x0100, %ax + int $0x31 + jnc dos_alloc_ok + movb $0x4c, %ah + int $0x21 + +dos_alloc_ok: + movw %cs, 2(%esi) +/* store API information */ + movw %ds, 4(%esi) + movw %dx, 6(%esi) +/* selector for allocated block */ + + movzwl (%esi), %eax /* calculate API address */ + movl %eax, sbrk16_api_ofs + + pushl %es /* move the data */ + movw %dx, %es + movl $(sbrk16_last_byte - sbrk16_first_byte), %ecx + shrl $2,%ecx + xorl %edi, %edi + cld + rep + movsl + popl %es + + movl %edx, %ebx /* dos memory selector */ + movw $0x000b, %ax /* get descriptor */ + movl $sel_buf, %edi + int $0x31 + + andb $0xbf, sel_buf+6 /* make 16-bit */ + andb $0xf0, sel_buf+5 /* remove old type */ + orb $0x0a, sel_buf+5 /* set new type to code/read */ + + xorl %eax, %eax /* allocate new selector */ + movw $0x0001, %cx + int $0x31 + movw %ax, sbrk16_api_seg + + movl %eax, %ebx + movw $0x000c, %ax /* set descriptor */ + movl $sel_buf, %edi + int $0x31 + +/* Initialize the brk/sbrk variables */ + +/* movl $end, __what_size_app_thinks_it_is */ + .byte 0x64 /* fs: */ + movl STUBINFO_INITIAL_SIZE, %eax + movl %eax, __what_size_dpmi_thinks_we_are + +/* Maybe lock the initial block, expects BX:CX */ + movl %ecx,%ebx + movl %edx,%ecx + addw $4096,%cx /* Skip null page */ + adcl $0,%ebx + subl $4096,%eax + pushl %eax + call lock_memory + + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %eax + movl %eax, ___djgpp_memory_handle_list + + .byte 0x64 /* fs: */ /* copy stubinfo into local memory */ + movl STUBINFO_SIZE, %eax + pushl %eax + call ___sbrk + movl %eax, __stubinfo + movl %eax,U_SYSTEM_STUB_INFO + movl %eax, %edi + .byte 0x64 /* fs: */ + movl STUBINFO_SIZE, %ecx + shrl $2, %ecx + xorl %esi, %esi /* Zero */ + pushl %ds + pushl %fs + popl %ds + cld + rep + movsl + popl %ds + movl __stklen, %eax /* get program-requested stack size */ + .byte 0x64 /* fs: */ + movl STUBINFO_MINSTACK, %ecx /* get stub-requested stack size */ + cmpl %ecx, %eax + jge use_stubinfo_stack_size /* use the larger of the two */ + movl %ecx, %eax + movl %eax, __stklen /* store the actual stack length */ +use_stubinfo_stack_size: + pushl %eax + call ___sbrk /* allocate the memory */ + cmpl $-1, %eax + je no_memory + movl %eax, ___djgpp_stack_limit /* Bottom of stack */ + addl $256,%eax + movl %eax,__stkbottom /* for stack checks */ + movl %eax,U_SYSTEM_STACKBOTTOM + + movl ___djgpp_stack_limit,%eax /* Bottom of stack */ + addl __stklen, %eax + movw %ds, %dx /* set stack */ + movw %dx, %ss + andl $0xfffffffc,%eax + movl %eax, %esp + + xorl %ebp, %ebp + call ___prt1_startup /* run program */ + jmp exit + +no_memory: + movb $0xff, %al + jmp exit + +/*-----------------------------------------------------------------------------*/ + +/* #define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31 */ + .macro FREESEL x + movw \x,%bx + movw $0x0001,%ax + int $0x31 + .endm + + .global ___exit + .align 2 +___exit: +/* special exit from dpmiexcp.c */ + .global __exit +__exit: + movl 4(%esp),%eax +exit: + movl %eax,%ecx + xorl %eax,%eax + movw %ax,%fs + movw %ax,%gs + cmpl $0,_exception_exit + jz no_exception + pushl %ecx + call *_exception_exit + popl %ecx +no_exception: + cli /* Just in case they didn't unhook ints */ + FREESEL U_SYSTEM_GO32_INFO_BLOCK+26 /* selector for linear memory */ + FREESEL ___v2prt0_ds_alias /* DS alias for rmcb exceptions */ + FREESEL sbrk16_api_seg /* sbrk cs */ + movw sbrk16_first_byte+6,%dx /* selector for allocated DOS mem */ + movw $0x101, %ax + int $0x31 /* Free block and selector */ +9: + movl __stubinfo, %edx + movl STUBINFO_CS_SELECTOR(%edx), %eax + movw %ax, sbrk16_api_seg + xorl %edi, %edi + movl %edi, sbrk16_api_ofs /* Offset is zero */ + + movw STUBINFO_DS_SELECTOR(%edx), %es + movb %cl, %dl /* Exit status */ + movl $exit16_first_byte, %esi + movl $(exit16_last_byte - exit16_first_byte), %ecx + cld + rep + movsb + + movw %es,%ax /* We will free stack! */ + movw %ax,%ss + movl $0x400,%esp /* Transfer buffer >= 1024 bytes */ + + xorl %ebp, %ebp /* V1.10 bug fix */ + movl ___djgpp_memory_handle_list, %edi + movl ___djgpp_memory_handle_list+2, %esi /* Skip word prefixes */ + + FREESEL %ds + movw %cs, %bx +/* Call exit procedure with BX=32-bit CS; SI+DI=32-bit handle; DL=exit status */ + .byte 0x2e + ljmp sbrk16_api_ofs + +/*-----------------------------------------------------------------------------*/ + +/* .lcomm __what_size_app_thinks_it_is, 4 */ +__what_size_app_thinks_it_is: + .long end + .lcomm __what_we_return_to_app_as_old_size, 4 + .lcomm __what_size_dpmi_thinks_we_are, 4 + +lock_memory: + /* BX:CX should be linear address; size is pushed on stack */ + testb $0x10, __crt0_startup_flags+1 /* include/crt0.h */ + jz 13f + pushl %esi + pushl %edi + pushl %eax + movl 16(%esp),%edi + movw 18(%esp),%si + movw $0x600,%ax + int $0x31 + popl %eax + popl %edi + popl %esi +13: ret $4 /* Pop the argument */ + + + .global ___sbrk + .align 2 +___sbrk: + movl __what_size_app_thinks_it_is, %eax + movl 4(%esp), %ecx /* Increment size */ + addl %ecx, %eax + jnc brk_common + /* Carry is only set if a negative increment or wrap happens. Negative + increment is semi-OK, wrap (only for multiple zone sbrk) isn't. */ + test $0x80000000, %ecx /* Clears carry */ + jnz brk_common + stc /* Put carry back */ + jmp brk_common + + .globl ___brk + .align 2 +___brk: + movl 4(%esp), %eax + clc + +brk_common: + pushl %esi + pushl %edi + pushl %ebx + + movl __what_size_app_thinks_it_is, %edx /* save info */ + movl %edx, __what_we_return_to_app_as_old_size + movl %eax, __what_size_app_thinks_it_is + + jc 10f /* Wrap for multi-zone */ + cmpl __what_size_dpmi_thinks_we_are, %eax /* don't bother shrinking */ + jbe brk_nochange + + addl $0x0000ffff, %eax /* round up to 64K block */ + andl $0xffff0000, %eax + push %eax /* size - save for later */ + + movl ___djgpp_memory_handle_list, %edi /* request new size */ + movw ___djgpp_memory_handle_list+2, %si + movl %eax, %ecx /* size not limit */ + movl %eax, %ebx /* size not limit */ + shrl $16, %ebx /* BX:CX size */ + + movw $0x0902, %ax /* disable interrupts */ + int $0x31 + movl %eax,___sbrk_interrupt_state + testb %al,%al + jz interrupts_already_disabled + movw $0x0900,%eax + int $0x31 +interrupts_already_disabled: + + lcall sbrk16_api_ofs + setc %dl /* Save carry */ + + /* popl %eax restore interrupts + int $0x31 postponed after ds alias is set correctly */ + + test %dl,%dl + popl %edx + jne brk_error + + movl %edi, ___djgpp_memory_handle_list /* store new handle */ + movw %si, ___djgpp_memory_handle_list+2 + movl %ecx, ___djgpp_base_address /* store new base address */ + movw %bx, ___djgpp_base_address+2 + + movl %edx, %eax + movl __what_size_dpmi_thinks_we_are, %ecx + subl %ecx, %eax + + addl ___djgpp_base_address, %ecx + movl %ecx, %ebx + shrl $16, %ebx /* BX:CX addr */ + pushl %eax /* Size */ + call lock_memory + + decl %edx /* limit now, not size */ +5: movl %edx, ___djgpp_selector_limit + orw $0x0fff, %dx /* low bits set */ + movw $0x0008, %ax /* reset CS limit */ + movw %cs, %bx + movl %edx, %ecx + shrl $16, %ecx + int $0x31 /* CX:DX is limit */ + + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jnz 3f + movw $0x0008, %ax /* reset DS limit */ + movw %ds, %bx + int $0x31 + + movw $0x0008, %ax /* reset DS alias limit */ + movl ___v2prt0_ds_alias, %ebx + int $0x31 +3: + movw $0x0007, %ax /* reset DS alias base */ + movl ___v2prt0_ds_alias, %ebx + movl ___djgpp_base_address, %edx + movw ___djgpp_base_address+2, %cx + int $0x31 + + movl %eax,___sbrk_interrupt_state /* restore interrupts */ + testb %al,%al + je do_not_enable + movw $0x0901,%eax + int $0x31 +do_not_enable: + movl ___djgpp_selector_limit, %edx +12: incl %edx /* Size not limit */ + testb $0x60, __crt0_startup_flags /* include/crt0.h */ + jz no_fill_sbrk_memory + pushl %ds + popl %es + + movl __what_size_dpmi_thinks_we_are, %edi /* set all newly resized bytes zero */ + movl %edx, %ecx /* Limit */ + subl %edi, %ecx /* Adjust count for base */ + xorl %eax, %eax + testb $0x40, __crt0_startup_flags + jz no_deadbeef + movl $0xdeadbeef, %eax /* something really easy to spot */ +no_deadbeef: + shrl $2, %ecx /* div 4 Longwords not bytes */ + cld + rep + stosl +no_fill_sbrk_memory: + movl %edx, __what_size_dpmi_thinks_we_are + +brk_nochange: /* successful return */ + movl __what_we_return_to_app_as_old_size, %eax + jmp brk_return + +brk_error: /* error return */ + movl __what_we_return_to_app_as_old_size, %eax + movl %eax, __what_size_app_thinks_it_is + movl $-1, %eax + +brk_return: + popl %ebx + popl %edi + popl %esi + ret + +/* From here on this are parts of crt1.c converted to assembler +and without any call to libc, so that it works without anything else +additions made by Pierre Muller*/ +/* from dpmidefs.h * / +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* from include */ +/* all macros removed here */ +/* #define FUNC(x) .globl x; x: */ + +/* #define ENTER pushl %ebp; movl %esp,%ebp */ + +/* #define LEAVE(x) movl %ebp,%esp; popl %ebp; ret $(x) */ +/* #define ARG1 8(%ebp) +#define ARG1h 10(%ebp) +#define ARG2 12(%ebp) +#define ARG2h 14(%ebp) +#define ARG3 16(%ebp) +#define ARG4 20(%ebp) +#define ARG5 24(%ebp) +#define ARG6 28(%ebp) +#define ARG7 32(%ebp) +#define ARG8 36(%ebp) */ + + .comm ___dpmi_error,2 + +/* from dpmi0000.s */ +/* .globl ___dpmi_allocate_ldt_descriptors */ +/* using pascal convention => not usabel by C code */ +___dpmi_allocate_ldt_descriptors: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ecx + movl $0x0000, %eax + int $0x31 + jnc .L_noerror0000 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0000 +.L_noerror0000: + movzwl %ax,%eax +.L_leave0000: + movl %ebp,%esp + popl %ebp + ret $4 + +/* from file dpmi0008.s */ +/* .globl ___dpmi_set_segment_limit */ +___dpmi_set_segment_limit: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movzwl 12(%ebp), %edx + movzwl 14(%ebp),%ecx + + movl $0x0008,%eax + int $0x31 + jnc .L_noerror0008 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0008 +.L_noerror0008: + xorl %eax,%eax +.L_leave0008: + movl %ebp,%esp + popl %ebp + ret $8 + +/* .globl ___dpmi_get_version */ +___dpmi_get_version: + pushl %ebp; movl %esp,%ebp + + movl $0x0400,%eax + int $0x31 + jnc .L_noerror0400 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0400 +.L_noerror0400: + movl 8(%ebp), %esi + movb %ah, (%esi) + movb %al, 1(%esi) + movw %bx, 2(%esi) + movb %cl, 4(%esi) + movb %dh, 5(%esi) + movb %dl, 6(%esi) + + xorl %eax,%eax +.L_leave0400: + + movl %ebp,%esp + popl %ebp + ret $4 + +/* .globl ___dpmi_get_segment_base_address*/ +___dpmi_get_segment_base_address: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movl $0x0006,%eax + int $0x31 + jnc .L_noerror0006 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0006 +.L_noerror0006: + + movl 12(%ebp), %ebx + movl %edx, (%ebx) + movw %cx, 2(%ebx) + + xorl %eax,%eax +.L_leave0006: + movl %ebp,%esp + popl %ebp + ret $8 + +.globl ___bss_count +.data + .align 2 +___bss_count: + .long 1 +.text + .align 2 + .globl _setup_core_selector +_setup_core_selector: + pushl %ebp + movl %esp,%ebp + pushl $1 + call ___dpmi_allocate_ldt_descriptors + /* addl $4,%esp */ + cmpl $-1,%eax + jne .L24 + movw $0,U_SYSTEM_GO32_INFO_BLOCK+26 + leave + ret + .align 2,0x90 +.L24: + movw %ax,U_SYSTEM_GO32_INFO_BLOCK+26 + movw %ax,_core_selector + pushl $0x10ffff + andl $0xffff,%eax + pushl %eax + call ___dpmi_set_segment_limit + leave + ret + .align 2 + .globl _setup_screens +_setup_screens: + pushl %ebp + movl %esp,%ebp + movw U_SYSTEM_GO32_INFO_BLOCK+26,%dx + movl $1048563,%ecx +/APP + movw %dx, %gs + .byte 0x65 + movw (%ecx),%ax +/NO_APP + cmpw $64896,%ax + jne .L26 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+8 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+4 + leave + ret + .align 2,0x90 +.L26: + movl $1097,%ecx +/APP + movw %dx,%gs + .byte 0x65 + movb (%ecx),%al +/NO_APP + cmpb $7,%al + jne .L29 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + .align 2,0x90 +.L29: + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + + .align 2 + .globl _setup_go32_info_block +_setup_go32_info_block: + pushl %ebp + movl %esp,%ebp + subl $8,%esp + leal -8(%ebp),%eax + pushl %eax + call ___dpmi_get_version + movl $40,U_SYSTEM_GO32_INFO_BLOCK + movl __stubinfo,%edx + movzwl 36(%edx),%eax + sall $4,%eax + movl %eax,U_SYSTEM_GO32_INFO_BLOCK+12 + movzwl 32(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+16 + movzwl 38(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+20 + movb -3(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+24 + movb -2(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+25 + movl $-1,U_SYSTEM_GO32_INFO_BLOCK+28 + pushl $U_SYSTEM_GO32_INFO_BLOCK+32 + movzwl 38(%edx),%eax + pushl %eax + call ___dpmi_get_segment_base_address + movw $4,U_SYSTEM_GO32_INFO_BLOCK+36 + movb -8(%ebp),%dl + salw $8,%dx + movzbw -7(%ebp),%ax + orw %ax,%dx + movw %dx,U_SYSTEM_GO32_INFO_BLOCK+38 + call copy_to_c_go32_info_block + leave + ret + +copy_to_c_go32_info_block: + leal U_SYSTEM_GO32_INFO_BLOCK,%esi + leal __go32_info_block,%edi + movl $10,%ecx + rep + movsl + ret + +.data + /* fpu codeword */ +___fpucw: + .long 0x1332 + /* __go32_info_block for C programs */ + .align 2 + .globl __go32_info_block +.comm __go32_info_block,40 + +/* + -- prt1_startup -- +*/ +.text + .align 2 + .globl ___prt1_startup +___prt1_startup: + pushl %ebp + movl %esp,%ebp + pushl %ebx + incl ___bss_count + movl $0,___crt0_argv + call _setup_core_selector + call _setup_screens + call _setup_go32_info_block + incl ___environ_changed + + fninit /* initialize fpu */ + /* fwait maybe this one is responsible of exceptions */ + fldcw ___fpucw + + pushl U_SYSTEM_ENVP + pushl ___crt0_argv + pushl ___crt0_argc + call _pascal_start + pushl %eax +/* call _exit changed to */ + call exit + .align 2,0x90 +/* .comm U_SYSTEM_DOS_ARGV0,4 */ + .comm ___dos_argv0,4 + .comm ___crt0_argc,4 + .comm ___crt0_argv,4 + .comm ___environ_changed,4 +/* ___environ_changed: not in data because it is defined in putenv.c */ +/* .long 0 */ + .globl _exception_exit +_exception_exit: + .long 0 + .globl _swap_in +_swap_in: + .long 0 + .globl _swap_out +_swap_out: + .long 0 + .global _v2prt0_exceptions_on +_v2prt0_exceptions_on: + .long 0 + +// Fill null page with NOPs +// and a jmp windows_error at the end + .globl v2prt0_windows +v2prt0_windows: + movl $0x90909090,%eax + xorl %edi,%edi + movl $0x400,%ecx + cld + rep + stosl + movl $0xffB,%edi + movb $0xe9,%al + stosb + movl $_fpc_windows_error-4,%eax + subl %edi,%eax + stosl + ret + +// Raise SIGILL with UD2 opcode + + .globl _fpc_windows_error +_fpc_windows_error: + cmpl $0,_exception_exit + je .L_error_216 + .byte 0x0f,0x0b +.L_error_216: + pushl $216 + call __exit + jmp exit +#enif + +/* this was the prt0.s from the go32v1 version */ +// +// call as start(argc, argv, envp) (C-calling convention) +// + .globl _pascal_start +_pascal_start: + /* %ebx doesn't contain ScreenPrimary */ + movl U_SYSTEM_GO32_INFO_BLOCK+4,%ebx + movl %ebx,_ScreenPrimary + /* core selector in %fs */ + /* keep original fs for debuggers !!!!! (PM) */ + movw %fs,%ax + movw %ax,___v2prt0_start_fs + + movw _core_selector,%ax + movw %ax,%fs + +// Top of frame + movl $0x0,%ebp + movl %esp,%ebx + movl 12(%ebx),%eax + movl %eax,U_SYSTEM_ENVP + movl %eax,_environ + movl 8(%ebx),%eax + movl %eax,_args + movl 4(%ebx),%eax + movl %eax,_argc + + call PASCALMAIN + movl $0,%eax + /* no error if passing here */ +/* movl $0x4c00,%eax + int $0x21 */ + + ret + + .data + +/* .comm U_SYSTEM_ENVP,4 */ + .globl _ScreenPrimary +_ScreenPrimary: + .long 0 + .globl _argc +_argc: + .long 0 + .globl _args +_args: + .long 0 + .globl _run_mode +_run_mode: + .word 4 + .globl _core_selector +_core_selector: + .word 0 + .globl ___v2prt0_start_fs +___v2prt0_start_fs: + .word 0 + .globl _environ +_environ: + .long 0 + +/* Here Pierre Muller added all what was in crt1.c */ +/* in assembler */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* adapted to assembler for FPC by Pierre Muller */ + +/* Global variables */ + + +/* This gets incremented each time the program is started. + Programs (such as Emacs) which dump their code to create + a new executable, cause this to be larger than 2. Library + functions that cache info in static variables should check + the value of `__bss_count' if they need to reinitialize + the static storage. */ + .data + .globl ___bss_count +___bs_count: + .long 1 + + .globl __crt0_startup_flags +__crt0_startup_flags: + .long 0 + + .globl __dos_ds +__dos_ds: + .long 0 + + .globl ___PROXY +___PROXY: + .ascii " !proxy" + .byte 0 + + .globl ___PROXY_LEN +___PROXY_LEN: + .long 7 + +/* + * fixed crash to to wrong code for disabling/enabling interrupts +/* + $Id$ +*/ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/*****************************************************************************\ + * Interface to 32-bit executable (from stub.asm) + * + * cs:eip according to COFF header + * ds 32-bit data segment for COFF program + * fs selector for our data segment (fs:0 is stubinfo) + * ss:sp our stack (ss to be freed) + * All unspecified registers have unspecified values in them. +\*****************************************************************************/ +/* modified by Pierre Muller to become the prt0.s for FPC Pascal */ + + .file "v2prt0.as" + +/* #include "stubinfo.h" */ + STUBINFO = 0 + STUBINFO_MAGIC = 0 + STUBINFO_SIZE = 0x10 + STUBINFO_MINSTACK = 0x14 + STUBINFO_MEMORY_HANDLE = 0x18 + STUBINFO_INITIAL_SIZE = 0x1c + STUBINFO_MINKEEP = 0x20 + STUBINFO_DS_SELECTOR = 0x22 + STUBINFO_DS_SEGMENT = 0x24 + STUBINFO_PSP_SELECTOR = 0x26 + STUBINFO_CS_SELECTOR = 0x28 + STUBINFO_ENV_SIZE = 0x2a + STUBINFO_BASENAME = 0x2c + STUBINFO_ARGV0 = 0x34 + STUBINFO_DPMI_SERVER = 0x44 + STUBINFO_END = 0x54 + + +/* .comm __stklen, 4 + this is added to the compiler so that we can specify + the stack size */ + .comm __stkbottom,4 + .comm __stubinfo, 4 + .comm ___djgpp_base_address, 4 + .comm ___djgpp_selector_limit, 4 + .comm ___djgpp_stack_limit, 4 + .lcomm sel_buf, 8 + +/* ___djgpp_ds_alias defined in go32/exceptn.s */ +/* inserted at the end of this file */ +/* we use a local copy that will be copied to exceptn.s */ + .globl ___v2prt0_ds_alias +___v2prt0_ds_alias: + .long 0 +/* allocate 32*4 bytes for RMCB under the $ffff limit for Windows NT */ + .globl ___v2prt0_rmcb_regs +___v2prt0_rmcb_regs: + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.data + +___djgpp_memory_handle_pointer: + .long ___djgpp_memory_handle_list+8 /* Next free, first for stub */ + .comm ___djgpp_memory_handle_list, 2048 /* Enough for 256 handles */ + + /* simply get current state */ +___sbrk_interrupt_state: + .long 0x902 + +sbrk16_first_byte: +.include "sbrk16.ah" +sbrk16_last_byte: + +sbrk16_api_ofs: + .long 0 +sbrk16_api_seg: + .word 0 +zero: + .long 0 + +exit16_first_byte: +.include "exit16.ah" +exit16_last_byte: + +/* hook_387_emulator: + .long ___emu387_load_hook */ + +/* this is for when main comes from a library */ + .long _main + + +.text + .globl start +start: + pushl %ds /* set %es same as %ds */ + popl %es /* push/pop 4 bytes shorter than ax */ + +/* Enable NULL pointer protection if DPMI supports it */ + testb $0x1, __crt0_startup_flags+1 /* include/crt0.h */ + jnz 1f + movl $start, %eax + cmpl $0x1000, %eax + jl 1f + movw $0x507, %ax + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %esi + xorl %ebx, %ebx /* Offset 0 in mem block */ + movl $1, %ecx /* Set one page */ + movl $zero, %edx + int $0x31 /* Make null page uncommitted */ + jnc 1f + call v2prt0_windows +1: +/* Create an alias for DS to be used by real-mode callbacks (exception handler messes with DS itself) */ + + movw %ds, %bx + movw $0x000a, %ax + int $0x31 + jnc ds_alias_ok + movb $0x4c, %ah + int $0x21 + +ds_alias_ok: + movw %ax, ___v2prt0_ds_alias + movl %eax, %ebx + movw $0x0009, %ax + movw %cs, %cx /* get CPL from %cs */ + andl $3, %ecx + shll $5, %ecx /* move it into place */ + orw $0xc093, %cx + int $0x31 /* set access rights for alias */ + +/* Maybe set our DS limit to 4Gb in size if flag set */ + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jz 2f + movw $0xffff, %cx + movl %ecx, %edx + movw $0x0008, %ax /* reset alias limit to -1 */ + int $0x31 + movw %cs, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + movw %ds, %bx + movw $0x0008, %ax /* reset DS limit to -1 */ + int $0x31 + lsl %ebx, %ebx /* Should be -1 */ + incl %ebx + jz 2f + andb $0x7f, __crt0_startup_flags /* clear it if failure */ +2: +/* Allocate some DOS memory and copy our sbrk helper into it. */ + movl $sbrk16_first_byte, %esi + movzwl 8(%esi), %ebx + shrl $4, %ebx + movw $0x0100, %ax + int $0x31 + jnc dos_alloc_ok + movb $0x4c, %ah + int $0x21 + +dos_alloc_ok: + movw %cs, 2(%esi) +/* store API information */ + movw %ds, 4(%esi) + movw %dx, 6(%esi) +/* selector for allocated block */ + + movzwl (%esi), %eax /* calculate API address */ + movl %eax, sbrk16_api_ofs + + pushl %es /* move the data */ + movw %dx, %es + movl $(sbrk16_last_byte - sbrk16_first_byte), %ecx + shrl $2,%ecx + xorl %edi, %edi + cld + rep + movsl + popl %es + + movl %edx, %ebx /* dos memory selector */ + movw $0x000b, %ax /* get descriptor */ + movl $sel_buf, %edi + int $0x31 + + andb $0xbf, sel_buf+6 /* make 16-bit */ + andb $0xf0, sel_buf+5 /* remove old type */ + orb $0x0a, sel_buf+5 /* set new type to code/read */ + + xorl %eax, %eax /* allocate new selector */ + movw $0x0001, %cx + int $0x31 + movw %ax, sbrk16_api_seg + + movl %eax, %ebx + movw $0x000c, %ax /* set descriptor */ + movl $sel_buf, %edi + int $0x31 + +/* Initialize the brk/sbrk variables */ + +/* movl $end, __what_size_app_thinks_it_is */ + .byte 0x64 /* fs: */ + movl STUBINFO_INITIAL_SIZE, %eax + movl %eax, __what_size_dpmi_thinks_we_are + +/* Maybe lock the initial block, expects BX:CX */ + movl %ecx,%ebx + movl %edx,%ecx + addw $4096,%cx /* Skip null page */ + adcl $0,%ebx + subl $4096,%eax + pushl %eax + call lock_memory + + .byte 0x64 /* fs: */ + movl STUBINFO_MEMORY_HANDLE, %eax + movl %eax, ___djgpp_memory_handle_list + + .byte 0x64 /* fs: */ /* copy stubinfo into local memory */ + movl STUBINFO_SIZE, %eax + pushl %eax + call ___sbrk + movl %eax, __stubinfo + movl %eax,U_SYSTEM_STUB_INFO + movl %eax, %edi + .byte 0x64 /* fs: */ + movl STUBINFO_SIZE, %ecx + shrl $2, %ecx + xorl %esi, %esi /* Zero */ + pushl %ds + pushl %fs + popl %ds + cld + rep + movsl + popl %ds + movl __stklen, %eax /* get program-requested stack size */ + .byte 0x64 /* fs: */ + movl STUBINFO_MINSTACK, %ecx /* get stub-requested stack size */ + cmpl %ecx, %eax + jge use_stubinfo_stack_size /* use the larger of the two */ + movl %ecx, %eax + movl %eax, __stklen /* store the actual stack length */ +use_stubinfo_stack_size: + pushl %eax + call ___sbrk /* allocate the memory */ + cmpl $-1, %eax + je no_memory + movl %eax, ___djgpp_stack_limit /* Bottom of stack */ + addl $256,%eax + movl %eax,__stkbottom /* for stack checks */ + movl %eax,U_SYSTEM_STACKBOTTOM + + movl ___djgpp_stack_limit,%eax /* Bottom of stack */ + addl __stklen, %eax + movw %ds, %dx /* set stack */ + movw %dx, %ss + andl $0xfffffffc,%eax + movl %eax, %esp + + xorl %ebp, %ebp + call ___prt1_startup /* run program */ + jmp exit + +no_memory: + movb $0xff, %al + jmp exit + +/*-----------------------------------------------------------------------------*/ + +/* #define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31 */ + .macro FREESEL x + movw \x,%bx + movw $0x0001,%ax + int $0x31 + .endm + + .global ___exit + .align 2 +___exit: +/* special exit from dpmiexcp.c */ + .global __exit +__exit: + movl 4(%esp),%eax +exit: + movl %eax,%ecx + xorl %eax,%eax + movw %ax,%fs + movw %ax,%gs + cmpl $0,_exception_exit + jz no_exception + pushl %ecx + call *_exception_exit + popl %ecx +no_exception: + cli /* Just in case they didn't unhook ints */ + FREESEL U_SYSTEM_GO32_INFO_BLOCK+26 /* selector for linear memory */ + FREESEL ___v2prt0_ds_alias /* DS alias for rmcb exceptions */ + FREESEL sbrk16_api_seg /* sbrk cs */ + movw sbrk16_first_byte+6,%dx /* selector for allocated DOS mem */ + movw $0x101, %ax + int $0x31 /* Free block and selector */ +9: + movl __stubinfo, %edx + movl STUBINFO_CS_SELECTOR(%edx), %eax + movw %ax, sbrk16_api_seg + xorl %edi, %edi + movl %edi, sbrk16_api_ofs /* Offset is zero */ + + movw STUBINFO_DS_SELECTOR(%edx), %es + movb %cl, %dl /* Exit status */ + movl $exit16_first_byte, %esi + movl $(exit16_last_byte - exit16_first_byte), %ecx + cld + rep + movsb + + movw %es,%ax /* We will free stack! */ + movw %ax,%ss + movl $0x400,%esp /* Transfer buffer >= 1024 bytes */ + + xorl %ebp, %ebp /* V1.10 bug fix */ + movl ___djgpp_memory_handle_list, %edi + movl ___djgpp_memory_handle_list+2, %esi /* Skip word prefixes */ + + FREESEL %ds + movw %cs, %bx +/* Call exit procedure with BX=32-bit CS; SI+DI=32-bit handle; DL=exit status */ + .byte 0x2e + ljmp sbrk16_api_ofs + +/*-----------------------------------------------------------------------------*/ + +/* .lcomm __what_size_app_thinks_it_is, 4 */ +__what_size_app_thinks_it_is: + .long end + .lcomm __what_we_return_to_app_as_old_size, 4 + .lcomm __what_size_dpmi_thinks_we_are, 4 + +lock_memory: + /* BX:CX should be linear address; size is pushed on stack */ + testb $0x10, __crt0_startup_flags+1 /* include/crt0.h */ + jz 13f + pushl %esi + pushl %edi + pushl %eax + movl 16(%esp),%edi + movw 18(%esp),%si + movw $0x600,%ax + int $0x31 + popl %eax + popl %edi + popl %esi +13: ret $4 /* Pop the argument */ + + + .global ___sbrk + .align 2 +___sbrk: + movl __what_size_app_thinks_it_is, %eax + movl 4(%esp), %ecx /* Increment size */ + addl %ecx, %eax + jnc brk_common + /* Carry is only set if a negative increment or wrap happens. Negative + increment is semi-OK, wrap (only for multiple zone sbrk) isn't. */ + test $0x80000000, %ecx /* Clears carry */ + jnz brk_common + stc /* Put carry back */ + jmp brk_common + + .globl ___brk + .align 2 +___brk: + movl 4(%esp), %eax + clc + +brk_common: + pushl %esi + pushl %edi + pushl %ebx + + movl __what_size_app_thinks_it_is, %edx /* save info */ + movl %edx, __what_we_return_to_app_as_old_size + movl %eax, __what_size_app_thinks_it_is + + jc 10f /* Wrap for multi-zone */ + cmpl __what_size_dpmi_thinks_we_are, %eax /* don't bother shrinking */ + jbe brk_nochange + + addl $0x0000ffff, %eax /* round up to 64K block */ + andl $0xffff0000, %eax + push %eax /* size - save for later */ + + movl ___djgpp_memory_handle_list, %edi /* request new size */ + movw ___djgpp_memory_handle_list+2, %si + movl %eax, %ecx /* size not limit */ + movl %eax, %ebx /* size not limit */ + shrl $16, %ebx /* BX:CX size */ + + movw $0x0902, %ax /* disable interrupts */ + int $0x31 + movl %eax,___sbrk_interrupt_state + testb %al,%al + jz interrupts_already_disabled + movw $0x0900,%eax + int $0x31 +interrupts_already_disabled: + + lcall sbrk16_api_ofs + setc %dl /* Save carry */ + + /* popl %eax restore interrupts + int $0x31 postponed after ds alias is set correctly */ + + test %dl,%dl + popl %edx + jne brk_error + + movl %edi, ___djgpp_memory_handle_list /* store new handle */ + movw %si, ___djgpp_memory_handle_list+2 + movl %ecx, ___djgpp_base_address /* store new base address */ + movw %bx, ___djgpp_base_address+2 + + movl %edx, %eax + movl __what_size_dpmi_thinks_we_are, %ecx + subl %ecx, %eax + + addl ___djgpp_base_address, %ecx + movl %ecx, %ebx + shrl $16, %ebx /* BX:CX addr */ + pushl %eax /* Size */ + call lock_memory + + decl %edx /* limit now, not size */ +5: movl %edx, ___djgpp_selector_limit + orw $0x0fff, %dx /* low bits set */ + movw $0x0008, %ax /* reset CS limit */ + movw %cs, %bx + movl %edx, %ecx + shrl $16, %ecx + int $0x31 /* CX:DX is limit */ + + testb $0x80, __crt0_startup_flags /* include/crt0.h */ + jnz 3f + movw $0x0008, %ax /* reset DS limit */ + movw %ds, %bx + int $0x31 + + movw $0x0008, %ax /* reset DS alias limit */ + movl ___v2prt0_ds_alias, %ebx + int $0x31 +3: + movw $0x0007, %ax /* reset DS alias base */ + movl ___v2prt0_ds_alias, %ebx + movl ___djgpp_base_address, %edx + movw ___djgpp_base_address+2, %cx + int $0x31 + + movl %eax,___sbrk_interrupt_state /* restore interrupts */ + testb %al,%al + je do_not_enable + movw $0x0901,%eax + int $0x31 +do_not_enable: + movl ___djgpp_selector_limit, %edx +12: incl %edx /* Size not limit */ + testb $0x60, __crt0_startup_flags /* include/crt0.h */ + jz no_fill_sbrk_memory + pushl %ds + popl %es + + movl __what_size_dpmi_thinks_we_are, %edi /* set all newly resized bytes zero */ + movl %edx, %ecx /* Limit */ + subl %edi, %ecx /* Adjust count for base */ + xorl %eax, %eax + testb $0x40, __crt0_startup_flags + jz no_deadbeef + movl $0xdeadbeef, %eax /* something really easy to spot */ +no_deadbeef: + shrl $2, %ecx /* div 4 Longwords not bytes */ + cld + rep + stosl +no_fill_sbrk_memory: + movl %edx, __what_size_dpmi_thinks_we_are + +brk_nochange: /* successful return */ + movl __what_we_return_to_app_as_old_size, %eax + jmp brk_return + +brk_error: /* error return */ + movl __what_we_return_to_app_as_old_size, %eax + movl %eax, __what_size_app_thinks_it_is + movl $-1, %eax + +brk_return: + popl %ebx + popl %edi + popl %esi + ret + +/* From here on this are parts of crt1.c converted to assembler +and without any call to libc, so that it works without anything else +additions made by Pierre Muller*/ +/* from dpmidefs.h * / +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* from include */ +/* all macros removed here */ +/* #define FUNC(x) .globl x; x: */ + +/* #define ENTER pushl %ebp; movl %esp,%ebp */ + +/* #define LEAVE(x) movl %ebp,%esp; popl %ebp; ret $(x) */ +/* #define ARG1 8(%ebp) +#define ARG1h 10(%ebp) +#define ARG2 12(%ebp) +#define ARG2h 14(%ebp) +#define ARG3 16(%ebp) +#define ARG4 20(%ebp) +#define ARG5 24(%ebp) +#define ARG6 28(%ebp) +#define ARG7 32(%ebp) +#define ARG8 36(%ebp) */ + + .comm ___dpmi_error,2 + +/* from dpmi0000.s */ +/* .globl ___dpmi_allocate_ldt_descriptors */ +/* using pascal convention => not usabel by C code */ +___dpmi_allocate_ldt_descriptors: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ecx + movl $0x0000, %eax + int $0x31 + jnc .L_noerror0000 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0000 +.L_noerror0000: + movzwl %ax,%eax +.L_leave0000: + movl %ebp,%esp + popl %ebp + ret $4 + +/* from file dpmi0008.s */ +/* .globl ___dpmi_set_segment_limit */ +___dpmi_set_segment_limit: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movzwl 12(%ebp), %edx + movzwl 14(%ebp),%ecx + + movl $0x0008,%eax + int $0x31 + jnc .L_noerror0008 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0008 +.L_noerror0008: + xorl %eax,%eax +.L_leave0008: + movl %ebp,%esp + popl %ebp + ret $8 + +/* .globl ___dpmi_get_version */ +___dpmi_get_version: + pushl %ebp; movl %esp,%ebp + + movl $0x0400,%eax + int $0x31 + jnc .L_noerror0400 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0400 +.L_noerror0400: + movl 8(%ebp), %esi + movb %ah, (%esi) + movb %al, 1(%esi) + movw %bx, 2(%esi) + movb %cl, 4(%esi) + movb %dh, 5(%esi) + movb %dl, 6(%esi) + + xorl %eax,%eax +.L_leave0400: + + movl %ebp,%esp + popl %ebp + ret $4 + +/* .globl ___dpmi_get_segment_base_address*/ +___dpmi_get_segment_base_address: + pushl %ebp; movl %esp,%ebp + + movl 8(%ebp), %ebx + movl $0x0006,%eax + int $0x31 + jnc .L_noerror0006 + movw %ax,___dpmi_error + movl $-1,%eax + jmp .L_leave0006 +.L_noerror0006: + + movl 12(%ebp), %ebx + movl %edx, (%ebx) + movw %cx, 2(%ebx) + + xorl %eax,%eax +.L_leave0006: + movl %ebp,%esp + popl %ebp + ret $8 + +.globl ___bss_count +.data + .align 2 +___bss_count: + .long 1 +.text + .align 2 + .globl _setup_core_selector +_setup_core_selector: + pushl %ebp + movl %esp,%ebp + pushl $1 + call ___dpmi_allocate_ldt_descriptors + /* addl $4,%esp */ + cmpl $-1,%eax + jne .L24 + movw $0,U_SYSTEM_GO32_INFO_BLOCK+26 + leave + ret + .align 2,0x90 +.L24: + movw %ax,U_SYSTEM_GO32_INFO_BLOCK+26 + movw %ax,_core_selector + pushl $0x10ffff + andl $0xffff,%eax + pushl %eax + call ___dpmi_set_segment_limit + leave + ret + .align 2 + .globl _setup_screens +_setup_screens: + pushl %ebp + movl %esp,%ebp + movw U_SYSTEM_GO32_INFO_BLOCK+26,%dx + movl $1048563,%ecx +/APP + movw %dx, %gs + .byte 0x65 + movw (%ecx),%ax +/NO_APP + cmpw $64896,%ax + jne .L26 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+8 + movl $655360,U_SYSTEM_GO32_INFO_BLOCK+4 + leave + ret + .align 2,0x90 +.L26: + movl $1097,%ecx +/APP + movw %dx,%gs + .byte 0x65 + movb (%ecx),%al +/NO_APP + cmpb $7,%al + jne .L29 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + .align 2,0x90 +.L29: + movl $753664,U_SYSTEM_GO32_INFO_BLOCK+4 + movl $720896,U_SYSTEM_GO32_INFO_BLOCK+8 + leave + ret + + .align 2 + .globl _setup_go32_info_block +_setup_go32_info_block: + pushl %ebp + movl %esp,%ebp + subl $8,%esp + leal -8(%ebp),%eax + pushl %eax + call ___dpmi_get_version + movl $40,U_SYSTEM_GO32_INFO_BLOCK + movl __stubinfo,%edx + movzwl 36(%edx),%eax + sall $4,%eax + movl %eax,U_SYSTEM_GO32_INFO_BLOCK+12 + movzwl 32(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+16 + movzwl 38(%edx),%ecx + movl %ecx,U_SYSTEM_GO32_INFO_BLOCK+20 + movb -3(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+24 + movb -2(%ebp),%al + movb %al,U_SYSTEM_GO32_INFO_BLOCK+25 + movl $-1,U_SYSTEM_GO32_INFO_BLOCK+28 + pushl $U_SYSTEM_GO32_INFO_BLOCK+32 + movzwl 38(%edx),%eax + pushl %eax + call ___dpmi_get_segment_base_address + movw $4,U_SYSTEM_GO32_INFO_BLOCK+36 + movb -8(%ebp),%dl + salw $8,%dx + movzbw -7(%ebp),%ax + orw %ax,%dx + movw %dx,U_SYSTEM_GO32_INFO_BLOCK+38 + call copy_to_c_go32_info_block + leave + ret + +copy_to_c_go32_info_block: + leal U_SYSTEM_GO32_INFO_BLOCK,%esi + leal __go32_info_block,%edi + movl $10,%ecx + rep + movsl + ret + +.data + /* fpu codeword */ +___fpucw: + .long 0x1332 + /* __go32_info_block for C programs */ + .align 2 + .globl __go32_info_block +.comm __go32_info_block,40 + +/* + -- prt1_startup -- +*/ +.text + .align 2 + .globl ___prt1_startup +___prt1_startup: + pushl %ebp + movl %esp,%ebp + pushl %ebx + incl ___bss_count + movl $0,___crt0_argv + call _setup_core_selector + call _setup_screens + call _setup_go32_info_block + incl ___environ_changed + + fninit /* initialize fpu */ + /* fwait maybe this one is responsible of exceptions */ + fldcw ___fpucw + + pushl U_SYSTEM_ENVP + pushl ___crt0_argv + pushl ___crt0_argc + call _pascal_start + pushl %eax +/* call _exit changed to */ + call exit + .align 2,0x90 +/* .comm U_SYSTEM_DOS_ARGV0,4 */ + .comm ___dos_argv0,4 + .comm ___crt0_argc,4 + .comm ___crt0_argv,4 + .comm ___environ_changed,4 +/* ___environ_changed: not in data because it is defined in putenv.c */ +/* .long 0 */ + .globl _exception_exit +_exception_exit: + .long 0 + .globl _swap_in +_swap_in: + .long 0 + .globl _swap_out +_swap_out: + .long 0 + .global _v2prt0_exceptions_on +_v2prt0_exceptions_on: + .long 0 + +// Fill null page with NOPs +// and a jmp windows_error at the end + .globl v2prt0_windows +v2prt0_windows: + movl $0x90909090,%eax + xorl %edi,%edi + movl $0x400,%ecx + cld + rep + stosl + movl $0xffB,%edi + movb $0xe9,%al + stosb + movl $_fpc_windows_error-4,%eax + subl %edi,%eax + stosl + ret + +// Raise SIGILL with UD2 opcode + + .globl _fpc_windows_error +_fpc_windows_error: + cmpl $0,_exception_exit + je .L_error_216 + .byte 0x0f,0x0b +.L_error_216: + pushl $216 + call __exit + jmp exit +#enif + +/* this was the prt0.s from the go32v1 version */ +// +// call as start(argc, argv, envp) (C-calling convention) +// + .globl _pascal_start +_pascal_start: + /* %ebx doesn't contain ScreenPrimary */ + movl U_SYSTEM_GO32_INFO_BLOCK+4,%ebx + movl %ebx,_ScreenPrimary + /* core selector in %fs */ + /* keep original fs for debuggers !!!!! (PM) */ + movw %fs,%ax + movw %ax,___v2prt0_start_fs + + movw _core_selector,%ax + movw %ax,%fs + +// Top of frame + movl $0x0,%ebp + movl %esp,%ebx + movl 12(%ebx),%eax + movl %eax,U_SYSTEM_ENVP + movl %eax,_environ + movl 8(%ebx),%eax + movl %eax,_args + movl 4(%ebx),%eax + movl %eax,_argc + + call PASCALMAIN + movl $0,%eax + /* no error if passing here */ +/* movl $0x4c00,%eax + int $0x21 */ + + ret + + .data + +/* .comm U_SYSTEM_ENVP,4 */ + .globl _ScreenPrimary +_ScreenPrimary: + .long 0 + .globl _argc +_argc: + .long 0 + .globl _args +_args: + .long 0 + .globl _run_mode +_run_mode: + .word 4 + .globl _core_selector +_core_selector: + .word 0 + .globl ___v2prt0_start_fs +___v2prt0_start_fs: + .word 0 + .globl _environ +_environ: + .long 0 + +/* Here Pierre Muller added all what was in crt1.c */ +/* in assembler */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* adapted to assembler for FPC by Pierre Muller */ + +/* Global variables */ + + +/* This gets incremented each time the program is started. + Programs (such as Emacs) which dump their code to create + a new executable, cause this to be larger than 2. Library + functions that cache info in static variables should check + the value of `__bss_count' if they need to reinitialize + the static storage. */ + .data + .globl ___bss_count +___bs_count: + .long 1 + + .globl __crt0_startup_flags +__crt0_startup_flags: + .long 0 + + .globl __dos_ds +__dos_ds: + .long 0 + + .globl ___PROXY +___PROXY: + .ascii " !proxy" + .byte 0 + + .globl ___PROXY_LEN +___PROXY_LEN: + .long 7 + +/* + + Revision 1.7 2000/02/16 13:24:55 pierre + * Mouse crash bug fixed !!! + + Revision 1.6 1999/07/10 23:17:15 pierre + merged from fixes branch + + Revision 1.5.2.1 1999/07/10 23:15:02 pierre + * fixes problem with putenv.c + + Revision 1.5 1999/03/01 15:40:53 peter + * use external names + * removed all direct assembler modes + + Revision 1.4 1999/02/19 12:25:37 pierre + + ___v2prt0_rmcb_regs in text section for Windows NT + + catch of calls into zero page for Windows 95 + (creates Run Time error 216 or SIGILL exception + if dpmiexcp is loaded !) + + Revision 1.3 1999/01/05 10:44:59 pierre + * suppressed fwaits to avoid FPU not present exceptions + + Revision 1.2 1998/12/21 14:14:21 pierre + added some c vars needed to avoid loading od crt1.o + + Revision 1.1 1998/12/21 13:07:03 peter + * use -FE + + Revision 1.4 1998/10/14 21:28:45 peter + * initialize fpu so sigfpe is finally generated for fpu errors + + Revision 1.3 1998/08/19 10:56:35 pierre + + added some special code for C interface + to avoid loading of crt1.o or dpmiexcp.o from the libc.a + + Revision 1.2 1998/05/22 00:39:38 peter + * go32v1, go32v2 recompiles with the new objects + * remake3 works again with go32v2 + - removed some "optimizes" from daniel which were wrong +*/