Subversion Repositories Kolibri OS

Rev

Rev 412 | Rev 431 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. $Revision: 425 $
  2.  
  3. tmp_page_tab      equ HEAP_BASE
  4.  
  5. align 4
  6. proc mem_test
  7.  
  8.            mov eax, cr0
  9.            and eax, not (CR0_CD+CR0_NW)
  10.            or eax, CR0_CD         ;disable caching
  11.            mov cr0, eax
  12.            wbinvd                 ;invalidate cache
  13.  
  14.            xor edi, edi
  15.            mov ebx, 'TEST'
  16. @@:
  17.            add edi, 0x400000
  18.            xchg ebx, dword [edi]
  19.            cmp dword [edi], 'TEST'
  20.            xchg ebx, dword [edi]
  21.            je @b
  22.            mov [MEM_AMOUNT], edi
  23.  
  24.            and eax, not (CR0_CD+CR0_NW)  ;enable caching
  25.            mov cr0, eax
  26.            mov eax, edi
  27.            mov [LFBSize], 0x00800000
  28.            ret
  29. endp
  30.  
  31. align 4
  32. proc init_mem
  33.  
  34.            mov eax, [MEM_AMOUNT]
  35.  
  36.            mov [pg_data.mem_amount], eax
  37.            mov [pg_data.kernel_max], eax
  38.  
  39.            shr eax, 12
  40.            mov edx, eax
  41.            mov [pg_data.pages_count], eax
  42.            mov [pg_data.kernel_pages], eax
  43.  
  44.            shr eax, 3
  45.            mov [pg_data.pagemap_size], eax
  46.  
  47.            shr edx, 10
  48.            cmp edx, 3
  49.            ja @f
  50.            inc edx       ;at least 4Mb for kernel heap
  51. @@:
  52.            mov [pg_data.kernel_tables], edx
  53.  
  54.            xor eax, eax
  55.            mov edi, sys_pgdir
  56.            mov ecx, 2048
  57.            cld
  58.            rep stosd
  59.  
  60.            mov edx, sys_pgdir
  61.            bt [cpu_caps], CAPS_PSE
  62.            jnc .no_PSE
  63.  
  64.            mov ebx, cr4
  65.            or ebx, CR4_PSE
  66.            mov eax, PG_LARGE+PG_SW
  67.            bt [cpu_caps], CAPS_PGE
  68.            jnc @F
  69.            or eax, PG_GLOBAL
  70.            or ebx, CR4_PGE
  71. @@:
  72.            mov cr4, ebx
  73.            sub [pg_data.kernel_tables], 2
  74.  
  75.            mov [edx], eax
  76.            add eax, 0x00400000
  77.            mov [edx+4], eax
  78.            add edx, 8
  79.  
  80.            mov eax, 0x800000+PG_SW
  81.            mov ecx, (HEAP_BASE-0x800000)/4096
  82.            jmp .map_low
  83. .no_PSE:
  84.            mov eax, PG_SW
  85.            mov ecx, HEAP_BASE/4096
  86. .map_low:
  87.            mov edi, tmp_page_tab
  88. @@:                                   ;
  89.            stosd
  90.            add eax, 0x1000
  91.            dec ecx
  92.            jnz @B
  93.  
  94.            mov ecx, [pg_data.kernel_tables]
  95.            shl ecx, 10
  96.            xor eax, eax
  97.            rep stosd
  98.  
  99.            mov ecx, [pg_data.kernel_tables]
  100.            mov eax, tmp_page_tab+PG_SW
  101.            mov edi, edx
  102.  
  103. .map_kernel_tabs:
  104.  
  105.            stosd
  106.            add eax, 0x1000
  107.            dec ecx
  108.            jnz .map_kernel_tabs
  109.  
  110.            mov dword [sys_pgdir+(page_tabs shr 20)], sys_pgdir+PG_SW
  111.            ret
  112. endp
  113.  
  114. align 4
  115. proc init_page_map
  116.  
  117.            mov edi, sys_pgmap
  118.            mov ecx, (HEAP_BASE/4096)/32      ;384/4
  119.            mov ebx, ecx
  120.            xor eax,eax
  121.            cld
  122.            rep stosd
  123.  
  124.            not eax
  125.            mov ecx, [pg_data.pagemap_size]
  126.            sub ecx, ebx
  127.            shr ecx, 2
  128.            rep stosd
  129.  
  130.            lea edi, [sys_pgmap+ebx*4]         ;+384
  131.            mov edx, [pg_data.pages_count]
  132.            mov ecx, [pg_data.kernel_tables]
  133.            add ecx, (HEAP_BASE/4096) and 31
  134.            sub edx, HEAP_BASE/4096
  135.            sub edx, ecx
  136.            mov [pg_data.pages_free], edx
  137.  
  138.            xor eax, eax
  139.            mov ebx, ecx
  140.            shr ecx, 5
  141.            rep stosd
  142.  
  143.            not eax
  144.            mov ecx, ebx
  145.            and ecx, 31
  146.            shl eax, cl
  147.            mov [page_start], edi;           sys_pgmap+384
  148.            stosd
  149.  
  150.            mov ebx, sys_pgmap
  151.            add ebx, [pg_data.pagemap_size]
  152.            mov [page_end], ebx
  153.  
  154.            mov [pg_data.pg_mutex], 0
  155.  
  156.            ret
  157. endp
  158.  
  159. align 4
  160. proc alloc_page
  161.  
  162.            pushfd
  163.            cli
  164.            mov ebx, [page_start]
  165.            mov ecx, [page_end]
  166. .l1:
  167.            bsf eax,[ebx];
  168.            jnz .found
  169.            add ebx,4
  170.            cmp ebx, ecx
  171.            jb .l1
  172.            popfd
  173.            xor eax,eax
  174.            ret
  175. .found:
  176.            btr [ebx], eax
  177.            mov [page_start],ebx
  178.            sub ebx, sys_pgmap
  179.            lea eax, [eax+ebx*8]
  180.            shl eax, 12
  181.            dec [pg_data.pages_free]
  182.            popfd
  183.            ret
  184. endp
  185.  
  186. align 4
  187. proc alloc_pages stdcall, count:dword
  188.            pushfd
  189.            cli
  190.            mov eax, [count]
  191.            add eax, 7
  192.            shr eax, 3
  193.            mov [count], eax
  194.            cmp eax, [pg_data.pages_free]
  195.            ja .fail
  196.  
  197.            mov ecx, [page_start]
  198.            mov ebx, [page_end]
  199. .find:
  200.            mov edx, [count]
  201.            mov edi, ecx
  202. .match:
  203.            cmp byte [ecx], 0xFF
  204.            jne .next
  205.            dec edx
  206.            jz .ok
  207.            inc ecx
  208.            cmp ecx,ebx
  209.            jb .match
  210. .fail:     xor eax, eax
  211.            popfd
  212.            ret
  213. .next:
  214.            inc ecx
  215.            cmp ecx, ebx
  216.            jb .find
  217.            popfd
  218.            xor eax, eax
  219.            ret
  220. .ok:
  221.            sub ecx, edi
  222.            inc ecx
  223.            mov esi, edi
  224.            xor eax, eax
  225.            rep stosb
  226.            sub esi, sys_pgmap
  227.            shl esi, 3+12
  228.            mov eax, esi
  229.            mov ebx, [count]
  230.            shl ebx, 3
  231.            sub [pg_data.pages_free], ebx
  232.            popfd
  233.            ret
  234. endp
  235.  
  236. align 4
  237. proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
  238.            push ebx
  239.            mov eax, [phis_addr]
  240.            and eax, not 0xFFF
  241.            or eax, [flags]
  242.            mov ebx, [lin_addr]
  243.            shr ebx, 12
  244.            mov [page_tabs+ebx*4], eax
  245.            mov eax, [lin_addr]
  246.            invlpg [eax]
  247.            pop ebx
  248.            ret
  249. endp
  250.  
  251. align 4
  252. map_space:    ;not implemented
  253.  
  254.  
  255.            ret
  256.  
  257.  
  258. align 4
  259. proc free_page
  260. ;arg:  eax  page address
  261.            pushfd
  262.            cli
  263.            shr eax, 12              ;page index
  264.            mov ebx, sys_pgmap
  265.            bts [ebx], eax           ;that's all!
  266.            cmc
  267.            adc [pg_data.pages_free], 0
  268.            shr eax, 3
  269.            and eax, not 3           ;dword offset from page_map
  270.            add eax, ebx
  271.            cmp [page_start], eax
  272.            ja @f
  273.            popfd
  274.            ret
  275. @@:
  276.            mov [page_start], eax
  277.            popfd
  278.            ret
  279. endp
  280.  
  281. ; param
  282. ;  eax= page base + page flags
  283. ;  ebx= liear address
  284. ;  ecx= count
  285.  
  286. align 4
  287. commit_pages:
  288.  
  289.            test ecx, ecx
  290.            jz .fail
  291.  
  292.            mov edi, ebx
  293.            mov ebx, pg_data.pg_mutex
  294.            call wait_mutex      ;ebx
  295.  
  296.            mov edx, 0x1000
  297.            mov ebx, edi
  298.            shr ebx, 12
  299. @@:
  300.            mov [page_tabs+ebx*4], eax
  301.            invlpg [edi]
  302.            add edi, edx
  303.            add eax, edx
  304.            inc ebx
  305.            dec ecx
  306.            jnz @B
  307.            mov [pg_data.pg_mutex],ecx
  308. .fail:
  309.            ret
  310.  
  311.  
  312. ; param
  313. ;  eax= base
  314. ;  ecx= count
  315.  
  316. align 4
  317. release_pages:
  318.  
  319.            pushad
  320.            mov ebx, pg_data.pg_mutex
  321.            call wait_mutex      ;ebx
  322.  
  323.            mov esi, eax
  324.            mov edi, eax
  325.  
  326.            shr esi, 10
  327.            add esi, page_tabs
  328.  
  329.            mov ebp, [pg_data.pages_free]
  330.            mov ebx, [page_start]
  331.            mov edx, sys_pgmap
  332. @@:
  333.            xor eax, eax
  334.            xchg eax, [esi]
  335.            invlpg [edi]
  336.  
  337.            test eax, 1
  338.            jz .next
  339.  
  340.            shr eax, 12
  341.            bts [edx], eax
  342.            cmc
  343.            adc ebp, 0
  344.            shr eax, 3
  345.            and eax, -4
  346.            add eax, edx
  347.            cmp eax, ebx
  348.            jae .next
  349.  
  350.            mov ebx, eax
  351. .next:
  352.            add edi, 0x1000
  353.            add esi, 4
  354.            dec ecx
  355.            jnz @B
  356.            mov [pg_data.pages_free], ebp
  357.            and [pg_data.pg_mutex],0
  358.            popad
  359.            ret
  360.  
  361. align 4
  362. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  363.            push ebx
  364.            mov ebx, [lin_addr]
  365.            shr ebx, 22
  366.            mov eax, [phis_addr]
  367.            and eax, not 0xFFF
  368.            or eax, PG_UW          ;+PG_NOCACHE
  369.            mov dword [master_tab+ebx*4], eax
  370.            mov eax, [lin_addr]
  371.            shr eax, 10
  372.            add eax, page_tabs
  373.            invlpg [eax]
  374.            pop ebx
  375.            ret
  376. endp
  377.  
  378. align 4
  379. proc init_LFB
  380.            locals
  381.              pg_count dd ?
  382.            endl
  383.  
  384.            cmp dword [LFBAddress], -1
  385.            jne @f
  386.            mov [BOOT_VAR+0x901c],byte 2
  387.            stdcall kernel_alloc, 0x280000
  388.            mov [LFBAddress], eax
  389.            ret
  390. @@:
  391.            test [SCR_MODE],word 0100000000000000b
  392.            jnz @f
  393.            mov [BOOT_VAR+0x901c],byte 2
  394.            ret
  395. @@:
  396.            mov edx, LFB_BASE
  397.            mov esi, [LFBAddress]
  398.            mov edi, [LFBSize]
  399.            mov dword [exp_lfb+4], edx
  400.  
  401.            shr edi, 12
  402.            mov [pg_count], edi
  403.            shr edi, 10
  404.  
  405.            bt [cpu_caps], CAPS_PSE
  406.            jnc .map_page_tables
  407.            or esi, PG_LARGE+PG_UW
  408.            shr edx, 20
  409.            mov ecx, edx
  410. @@:
  411.            mov [sys_pgdir+edx], esi
  412.            add edx, 4
  413.            add esi, 0x00400000
  414.            dec edi
  415.            jnz @B
  416.  
  417.            bt [cpu_caps], CAPS_PGE
  418.            jnc @F
  419.            or dword [sys_pgdir+ecx], PG_GLOBAL
  420. @@:
  421.            mov dword [LFBAddress], LFB_BASE
  422.            mov eax, cr3       ;flush TLB
  423.            mov cr3, eax
  424.            ret
  425.  
  426. .map_page_tables:
  427.  
  428.            call alloc_page
  429.            stdcall map_page_table, edx, eax
  430.            add edx, 0x00400000
  431.            dec edi
  432.            jnz .map_page_tables
  433.  
  434.            mov eax, [LFBAddress]
  435.            mov edi, page_tabs + (LFB_BASE shr 10)
  436.            or eax, PG_UW
  437.            mov ecx, [pg_count]
  438.            cld
  439. @@:
  440.            stosd
  441.            add eax, 0x1000
  442.            dec ecx
  443.            jnz @B
  444.  
  445.            mov dword [LFBAddress], LFB_BASE
  446.            mov eax, cr3       ;flush TLB
  447.            mov cr3, eax
  448.  
  449.            ret
  450. endp
  451.  
  452. align 4
  453. proc new_mem_resize stdcall, new_size:dword
  454.  
  455.            mov ebx, pg_data.pg_mutex
  456.            call wait_mutex    ;ebx
  457.  
  458.            mov edi, [new_size]
  459.            add edi,4095
  460.            and edi,not 4095
  461.            mov [new_size], edi
  462.  
  463.            mov edx,[CURRENT_TASK]
  464.            shl edx,8
  465.            cmp [SLOT_BASE+APPDATA.heap_base+edx],0
  466.            jne .exit
  467.  
  468.            mov esi, [SLOT_BASE+APPDATA.mem_size+edx]
  469.            add esi, 4095
  470.            and esi, not 4095
  471.  
  472.            cmp edi, esi
  473.            jae .expand
  474.  
  475.            shr edi, 12
  476.            shr esi, 12
  477. @@:
  478.            mov eax, [app_page_tabs+edi*4]
  479.            test eax, 1
  480.            jz .next
  481.            mov dword [app_page_tabs+edi*4], 2
  482.            mov ebx, edi
  483.            shl ebx, 12
  484.            invlpg [ebx+std_application_base_address]
  485.            call free_page
  486.  
  487. .next:     add edi, 1
  488.            cmp edi, esi
  489.            jb @B
  490.  
  491. .update_size:
  492.         mov     ebx, [new_size]
  493.         call    update_mem_size
  494.  
  495.            xor eax, eax
  496.            dec [pg_data.pg_mutex]
  497.            ret
  498.  
  499. .expand:
  500.            add edi, new_app_base
  501.            add esi, new_app_base
  502.  
  503.            push esi
  504.            push edi
  505.  
  506.            add edi, 0x3FFFFF
  507.            and edi, not(0x3FFFFF)
  508.            add esi, 0x3FFFFF
  509.            and esi, not(0x3FFFFF)
  510.  
  511.            cmp esi, edi
  512.            jae .grow
  513.  
  514.            xchg esi, edi
  515.  
  516. @@:
  517.            call alloc_page
  518.            test eax, eax
  519.            jz .exit
  520.  
  521.            stdcall map_page_table, edi, eax
  522.  
  523.            push edi
  524.            shr edi, 10
  525.            add edi, page_tabs
  526.            mov ecx, 1024
  527.            xor eax, eax
  528.            cld
  529.            rep stosd
  530.            pop edi
  531.  
  532.            add edi, 0x00400000
  533.            cmp edi, esi
  534.            jb @B
  535. .grow:
  536.            pop edi
  537.            pop esi
  538. @@:
  539.            call alloc_page
  540.            test eax, eax
  541.            jz .exit
  542.            stdcall map_page,esi,eax,dword PG_UW
  543.  
  544.            push edi
  545.            mov edi, esi
  546.            xor eax, eax
  547.            mov ecx, 1024
  548.            cld
  549.            rep stosd
  550.            pop edi
  551.  
  552.            add esi, 0x1000
  553.            cmp esi, edi
  554.            jb  @B
  555.  
  556.            jmp .update_size
  557. .exit:
  558.            xor eax, eax
  559.            inc eax
  560.            dec [pg_data.pg_mutex]
  561.            ret
  562. endp
  563.  
  564. update_mem_size:
  565. ; in: edx = slot shl 8
  566. ;     ebx = new memory size
  567. ; destroys eax,ecx,edx
  568.  
  569.            mov    [SLOT_BASE+APPDATA.mem_size+edx],ebx
  570. ;search threads and update
  571. ;application memory size infomation
  572.            mov    ecx,[SLOT_BASE+APPDATA.dir_table+edx]
  573.            mov    eax,2
  574.  
  575. .search_threads:
  576. ;eax = current slot
  577. ;ebx = new memory size
  578. ;ecx = page directory
  579.            cmp    eax,[TASK_COUNT]
  580.            jg     .search_threads_end
  581.            mov    edx,eax
  582.            shl    edx,5
  583.            cmp    word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty?
  584.            jz     .search_threads_next
  585.            shl    edx,3
  586.            cmp    [SLOT_BASE+edx+APPDATA.dir_table],ecx     ;if it is our thread?
  587.            jnz    .search_threads_next
  588.            mov    [SLOT_BASE+edx+APPDATA.mem_size],ebx     ;update memory size
  589. .search_threads_next:
  590.            inc    eax
  591.            jmp    .search_threads
  592. .search_threads_end:
  593.            ret
  594.  
  595. ; param
  596. ;  eax= linear address
  597. ;
  598. ; retval
  599. ;  eax= phisical page address
  600.  
  601. align 4
  602. get_pg_addr:
  603.            shr eax, 12
  604.            mov eax, [page_tabs+eax*4]
  605.            and eax, 0xFFFFF000
  606.            ret
  607.  
  608. align 4
  609. proc page_fault_handler
  610.            pushad
  611.  
  612.            mov ebp, esp
  613.            mov eax, cr2
  614.            push eax
  615.            push ds
  616.            push es
  617.  
  618.            mov ax, 0x10
  619.            mov ds, ax
  620.            mov es, ax
  621.  
  622.            inc [pg_data.pages_faults]
  623.  
  624.            mov ebx, [ebp-4]
  625.  
  626.            cmp ebx, 0x80000000
  627.            jae .user_space
  628.  
  629.            cmp ebx, app_page_tabs
  630.            jae .alloc
  631.  
  632.            cmp ebx, page_tabs
  633.            jae .tab_space
  634.  
  635.            cmp ebx, 0x7DC00000
  636.            jae .lfb_addr
  637.  
  638.            jmp .kernel_space
  639.  
  640. .user_space:
  641.            shr ebx, 12
  642.            mov ecx, ebx
  643.            shr ecx, 10
  644.            mov edx, [master_tab+ecx*4]
  645.            test edx, 1
  646.            jz .fail
  647.  
  648.            mov eax, [page_tabs+ebx*4]
  649.            test eax, 2
  650.            jz .fail
  651. .alloc:
  652.            call alloc_page
  653.            and eax, eax
  654.            jz .exit
  655.  
  656.            stdcall map_page,[ebp-4],eax,dword PG_UW
  657.  
  658.            mov edi, [ebp-4]
  659.            and edi, 0xFFFFF000
  660.            mov ecx, 1024
  661.            xor eax, eax
  662.            cld
  663.            rep stosd
  664. .exit:
  665.            pop es
  666.            pop ds
  667.            mov esp, ebp
  668.            popad
  669.            add esp, 4
  670.            iretd
  671. .fail:
  672.            pop es
  673.            pop ds
  674.            mov esp, ebp
  675.            popad
  676.            add esp, 4
  677.  
  678.            save_ring3_context     ;debugger support
  679.  
  680.            mov bl, 14
  681.            jmp exc_c
  682.            iretd
  683.  
  684. .kernel_space:
  685. ;           shr ebx, 12
  686. ;           mov eax, [page_tabs+ebx*4]
  687. ;           shr ebx, 10
  688. ;           mov eax, [master_tab+ebx*4]
  689.            jmp .exit
  690. .old_addr:
  691. ;           shr ebx, 12
  692. ;           mov eax, [page_tabs+ebx*4]
  693. ;           shr ebx, 10
  694. ;           mov eax, [master_tab+ebx*4]
  695.            jmp .exit
  696. .lfb_addr:
  697. ;           shr ebx, 22
  698. ;           ;mov ecx, [sys_page_dir]
  699. ;           mov eax, [master_tab+ebx*4]
  700.            jmp .exit
  701. .tab_space:
  702. ;           shr ebx, 12
  703. ;           mov eax, [page_tabs+ebx*4]
  704. ;           shr ebx, 10
  705. ;           ;mov ecx, [sys_page_dir]
  706. ;           mov eax, [master_tab+ebx*4]
  707.            jmp .exit
  708. endp
  709.  
  710. align 4
  711. proc map_mem stdcall, lin_addr:dword,pdir:dword,\
  712.                       ofs:dword,buf_size:dword
  713.            mov eax, [buf_size]
  714.            test eax, eax
  715.            jz .exit
  716.  
  717.            mov eax, [pdir]
  718.            and eax, 0xFFFFF000
  719.  
  720.            stdcall map_page,[ipc_pdir],eax,dword PG_UW
  721.            mov ebx, [ofs]
  722.            shr ebx, 22
  723.            mov esi, [ipc_pdir]
  724.            mov edi, [ipc_ptab]
  725.            mov eax, [esi+ebx*4]
  726.            and eax, 0xFFFFF000
  727.            test eax, eax
  728.            jz .exit
  729.            stdcall map_page,edi,eax,dword PG_UW
  730. ;           inc ebx
  731. ;           add edi, 0x1000
  732. ;           mov eax, [esi+ebx*4]
  733. ;           test eax, eax
  734. ;           jz @f
  735. ;          and eax, 0xFFFFF000
  736. ;           stdcall map_page, edi, eax
  737.  
  738. @@:        mov edi, [lin_addr]
  739.            and edi, 0xFFFFF000
  740.            mov ecx, [buf_size]
  741.            add ecx, 4095
  742.            shr ecx, 12
  743.            inc ecx
  744.  
  745.            mov edx, [ofs]
  746.            shr edx, 12
  747.            and edx, 0x3FF
  748.            mov esi, [ipc_ptab]
  749.  
  750. .map:      mov eax, [esi+edx*4]
  751.            and eax, 0xFFFFF000
  752.            test eax, eax
  753.            jz .exit
  754.            stdcall map_page,edi,eax,dword PG_UW
  755.            add edi, 0x1000
  756.            inc edx
  757.            dec ecx
  758.            jnz .map
  759.  
  760. .exit:
  761.            ret
  762. endp
  763.  
  764. align 4
  765. proc map_memEx stdcall, lin_addr:dword,pdir:dword,\
  766.                         ofs:dword,buf_size:dword
  767.            mov eax, [buf_size]
  768.            test eax, eax
  769.            jz .exit
  770.  
  771.            mov eax, [pdir]
  772.            and eax, 0xFFFFF000
  773.  
  774.            stdcall map_page,[proc_mem_pdir],eax,dword PG_UW
  775.            mov ebx, [ofs]
  776.            shr ebx, 22
  777.            mov esi, [proc_mem_pdir]
  778.            mov edi, [proc_mem_tab]
  779.            mov eax, [esi+ebx*4]
  780.            and eax, 0xFFFFF000
  781.            test eax, eax
  782.            jz .exit
  783.            stdcall map_page,edi,eax,dword PG_UW
  784.  
  785. @@:        mov edi, [lin_addr]
  786.            and edi, 0xFFFFF000
  787.            mov ecx, [buf_size]
  788.            add ecx, 4095
  789.            shr ecx, 12
  790.            inc ecx
  791.  
  792.            mov edx, [ofs]
  793.            shr edx, 12
  794.            and edx, 0x3FF
  795.            mov esi, [proc_mem_tab]
  796.  
  797. .map:      mov eax, [esi+edx*4]
  798. ;           and eax, 0xFFFFF000
  799. ;           test eax, eax
  800. ;           jz .exit
  801.            stdcall map_page,edi,eax,dword PG_UW
  802.            add edi, 0x1000
  803.            inc edx
  804.            dec ecx
  805.            jnz .map
  806. .exit:
  807.            ret
  808. endp
  809.  
  810.  
  811.  
  812.  
  813. sys_IPC:
  814. ;input:
  815. ;  eax=1 - set ipc buffer area
  816. ;    ebx=address of buffer
  817. ;    ecx=size of buffer
  818. ;  eax=2 - send message
  819. ;    ebx=PID
  820. ;    ecx=address of message
  821. ;    edx=size of message
  822.  
  823.            cmp  eax,1
  824.            jne @f
  825.            call set_ipc_buff
  826.            mov [esp+36], eax
  827.            ret
  828. @@:
  829.            cmp eax, 2
  830.            jne @f
  831.            stdcall sys_ipc_send, ebx, ecx, edx
  832.            mov [esp+36], eax
  833.            ret
  834. @@:
  835.            xor eax, eax
  836.            not eax
  837.            mov [esp+36], eax
  838.            ret
  839.  
  840. align 4
  841. proc set_ipc_buff
  842.  
  843.            mov  eax,[CURRENT_TASK]
  844.            shl  eax,8
  845.            add  eax, SLOT_BASE
  846.            pushf
  847.            cli
  848.            mov  [eax+0xA0],ebx     ;set fields in extended information area
  849.            mov  [eax+0xA4],ecx
  850.  
  851.            add ebx,  new_app_base
  852.            add ecx, ebx
  853.            add ecx, 4095
  854.            and ecx, not 4095
  855.  
  856. .touch:    mov eax, [ebx]
  857.            add ebx, 0x1000
  858.            cmp ebx, ecx
  859.            jna .touch
  860.  
  861.            popf
  862.            xor eax, eax
  863.            ret
  864. endp
  865.  
  866. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  867.            locals
  868.              dst_slot   dd ?
  869.              dst_offset dd ?
  870.              buf_size   dd ?
  871.            endl
  872.  
  873.            pushf
  874.            cli
  875.  
  876.            mov  eax, [PID]
  877.            call pid_to_slot
  878.            test eax,eax
  879.            jz   .no_pid
  880.  
  881.            mov [dst_slot], eax
  882.            shl  eax,8
  883.            mov  edi,[eax+SLOT_BASE+0xa0]  ;is ipc area defined?
  884.            test edi,edi
  885.            jz   .no_ipc_area
  886.  
  887.            mov ebx, edi
  888.            add edi, new_app_base
  889.            and ebx, 0xFFF
  890.            mov [dst_offset], ebx
  891.  
  892.            mov esi, [eax+SLOT_BASE+0xa4]
  893.            mov [buf_size], esi
  894.  
  895.            stdcall map_mem, [ipc_tmp], [SLOT_BASE+eax+0xB8],\
  896.                              edi, esi
  897.  
  898.            mov edi, [dst_offset]
  899.            add edi, [ipc_tmp]
  900.            cmp dword [edi], 0
  901.            jnz  .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  902.  
  903.            mov ebx, dword [edi+4]
  904.            mov edx, ebx
  905.            add ebx, 8
  906.            add ebx, [msg_size]
  907.            cmp ebx, [buf_size]
  908.            ja .buffer_overflow         ;esi<0 - not enough memory in buffer
  909.  
  910.            mov dword [edi+4], ebx
  911.            mov eax,[TASK_BASE]
  912.            mov eax, [eax+0x04]         ;eax - our PID
  913.            mov edi, [dst_offset]
  914.            add edi, [ipc_tmp]
  915.            add edi, edx
  916.            mov [edi], eax
  917.            mov ecx, [msg_size]
  918.  
  919.            mov [edi+4], ecx
  920.            add edi, 8
  921.            mov esi, [msg_addr]
  922.            add esi, new_app_base
  923.            cld
  924.            rep movsb
  925.  
  926.            mov ebx, [ipc_tmp]
  927.            mov edx, ebx
  928.            shr ebx, 12
  929.            xor eax, eax
  930.            mov [page_tabs+ebx*4], eax
  931.            invlpg [edx]
  932.  
  933.            mov ebx, [ipc_pdir]
  934.            mov edx, ebx
  935.            shr ebx, 12
  936.            xor eax, eax
  937.            mov [page_tabs+ebx*4], eax
  938.            invlpg [edx]
  939.  
  940.            mov ebx, [ipc_ptab]
  941.            mov edx, ebx
  942.            shr ebx, 12
  943.            xor eax, eax
  944.            mov [page_tabs+ebx*4], eax
  945.            invlpg [edx]
  946.  
  947.            mov  eax, [dst_slot]
  948.            shl eax, 8
  949.            or   [eax+SLOT_BASE+0xA8],dword 0x40
  950.            cmp  dword [check_idle_semaphore],20
  951.            jge  .ipc_no_cis
  952.  
  953.            mov  dword [check_idle_semaphore],5
  954. .ipc_no_cis:
  955.            popf
  956.            xor eax, eax
  957.            ret
  958. .no_pid:
  959.            popf
  960.            mov  eax, 4
  961.            ret
  962. .no_ipc_area:
  963.            popf
  964.            xor eax, eax
  965.            inc eax
  966.            ret
  967. .ipc_blocked:
  968.            popf
  969.            mov  eax, 2
  970.            ret
  971. .buffer_overflow:
  972.            popf
  973.            mov  eax, 3
  974.            ret
  975. endp
  976.  
  977. align 4
  978. sysfn_meminfo:
  979.  
  980.            add ebx, new_app_base
  981.            cmp ebx, new_app_base
  982.            jb .fail
  983.  
  984.            mov eax, [pg_data.pages_count]
  985.            mov [ebx], eax
  986.            shl eax, 12
  987.            mov [esp+36], eax
  988.            mov ecx, [pg_data.pages_free]
  989.            mov [ebx+4], ecx
  990.            mov edx, [pg_data.pages_faults]
  991.            mov [ebx+8], edx
  992.            mov esi, [heap_size]
  993.            mov [ebx+12], esi
  994.            mov edi, [heap_free]
  995.            mov [ebx+16], edi
  996.            mov eax, [heap_blocks]
  997.            mov [ebx+20], eax
  998.            mov ecx, [free_blocks]
  999.            mov [ebx+24], ecx
  1000.            ret
  1001. .fail:
  1002.            mov dword [esp+36], -1
  1003.            ret
  1004.  
  1005. align 4
  1006. new_services:
  1007.  
  1008.            cmp  eax,4
  1009.            jle  sys_sheduler
  1010.  
  1011.            cmp eax, 11
  1012.            jb .fail
  1013.            ja @f
  1014.  
  1015.            call init_heap
  1016.            mov [esp+36], eax
  1017.            ret
  1018. @@:
  1019.            cmp eax, 12
  1020.            ja @f
  1021.  
  1022.            stdcall user_alloc, ebx
  1023.            mov [esp+36], eax
  1024.            ret
  1025. @@:
  1026.            cmp eax, 13
  1027.            ja @f
  1028.            add ebx, new_app_base
  1029.            stdcall user_free, ebx
  1030.            mov [esp+36], eax
  1031.            ret
  1032. @@:
  1033.            cmp eax, 14
  1034.            ja @f
  1035.            add ebx, new_app_base
  1036.            cmp ebx, new_app_base
  1037.            jb .fail
  1038.            stdcall get_event_ex, ebx, ecx
  1039.            mov [esp+36], eax
  1040.            ret
  1041. @@:
  1042.            cmp eax, 15
  1043.            ja @f
  1044.            mov ecx, [CURRENT_TASK]
  1045.            shl ecx, 8
  1046.            mov eax, [ecx+SLOT_BASE+APPDATA.fpu_handler]
  1047.            mov [ecx+SLOT_BASE+APPDATA.fpu_handler], ebx
  1048.            mov [esp+36], eax
  1049.            ret
  1050. @@:
  1051.            cmp eax, 16
  1052.            ja @f
  1053.  
  1054.            test ebx, ebx
  1055.            jz .fail
  1056.            add ebx, new_app_base
  1057.            cmp ebx, new_app_base
  1058.            jb .fail
  1059.            stdcall get_service, ebx
  1060.            mov [esp+36], eax
  1061.            ret
  1062. @@:
  1063.            cmp eax, 17
  1064.            ja @f
  1065.            call srv_handlerEx   ;ebx
  1066.            mov [esp+36], eax
  1067.            ret
  1068. @@:
  1069.            cmp eax, 18
  1070.            ja @f
  1071.            mov ecx, [CURRENT_TASK]
  1072.            shl ecx, 8
  1073.            mov eax, [ecx+SLOT_BASE+APPDATA.sse_handler]
  1074.            mov [ecx+SLOT_BASE+APPDATA.sse_handler], ebx
  1075.            mov [esp+36], eax
  1076.            ret
  1077. @@:
  1078.            cmp eax, 19
  1079.            ja .fail
  1080.            add ebx, new_app_base
  1081.            cmp ebx, new_app_base
  1082.            jb .fail
  1083.            stdcall load_library, ebx
  1084.            mov [esp+36], eax
  1085.            ret
  1086.  
  1087. .fail:
  1088.            xor eax, eax
  1089.            mov [esp+36], eax
  1090.            ret
  1091.  
  1092. align 4
  1093. proc strncmp stdcall, str1:dword, str2:dword, count:dword
  1094.  
  1095.           mov ecx,[count]
  1096.           jecxz .end
  1097.  
  1098.           mov ebx,ecx
  1099.  
  1100.           mov edi,[str1]
  1101.           mov esi,edi
  1102.           xor eax,eax
  1103.           repne scasb
  1104.           neg ecx             ; cx = count - strlen
  1105.           add ecx,ebx         ; strlen + count - strlen
  1106.  
  1107. .okay:
  1108.           mov edi,esi
  1109.           mov esi,[str2]
  1110.           repe cmpsb
  1111.           mov al,[esi-1]
  1112.           xor ecx,ecx
  1113.  
  1114.           cmp al,[edi-1]
  1115.           ja .str2_big
  1116.           je .end
  1117.  
  1118. .str1_big:
  1119.           sub ecx,2
  1120.  
  1121. .str2_big:
  1122.           not ecx
  1123. .end:
  1124.           mov eax,ecx
  1125.           ret
  1126. endp
  1127.  
  1128. align 4
  1129. proc test_cpu
  1130.            locals
  1131.               cpu_type   dd ?
  1132.               cpu_id     dd ?
  1133.               cpu_Intel  dd ?
  1134.               cpu_AMD    dd ?
  1135.            endl
  1136.  
  1137.            mov [cpu_type], 0
  1138.            xor eax, eax
  1139.            mov [cpu_caps], eax
  1140.            mov [cpu_caps+4], eax
  1141.  
  1142.            pushfd
  1143.            pop eax
  1144.            mov ecx, eax
  1145.            xor eax, 0x40000
  1146.            push eax
  1147.            popfd
  1148.            pushfd
  1149.            pop eax
  1150.            xor eax, ecx
  1151.            mov [cpu_type], CPU_386
  1152.            jz .end_cpuid
  1153.            push ecx
  1154.            popfd
  1155.  
  1156.            mov [cpu_type], CPU_486
  1157.            mov eax, ecx
  1158.            xor eax, 0x200000
  1159.            push eax
  1160.            popfd
  1161.            pushfd
  1162.            pop eax
  1163.            xor eax, ecx
  1164.            je .end_cpuid
  1165.            mov [cpu_id], 1
  1166.  
  1167.            xor eax, eax
  1168.            cpuid
  1169.            mov [cpu_vendor], ebx
  1170.            mov [cpu_vendor+4], edx
  1171.            mov [cpu_vendor+8], ecx
  1172.            cmp ebx, dword [intel_str]
  1173.            jne .check_AMD
  1174.            cmp edx, dword [intel_str+4]
  1175.            jne .check_AMD
  1176.            cmp ecx, dword [intel_str+8]
  1177.            jne .check_AMD
  1178.            mov [cpu_Intel], 1
  1179.            cmp eax, 1
  1180.            jl .end_cpuid
  1181.            mov eax, 1
  1182.            cpuid
  1183.            mov [cpu_sign], eax
  1184.            mov [cpu_info],  ebx
  1185.            mov [cpu_caps],  edx
  1186.            mov [cpu_caps+4],ecx
  1187.  
  1188.            shr eax, 8
  1189.            and eax, 0x0f
  1190.            ret
  1191. .end_cpuid:
  1192.            mov eax, [cpu_type]
  1193.            ret
  1194.  
  1195. .check_AMD:
  1196.            cmp ebx, dword [AMD_str]
  1197.            jne .unknown
  1198.            cmp edx, dword [AMD_str+4]
  1199.            jne .unknown
  1200.            cmp ecx, dword [AMD_str+8]
  1201.            jne .unknown
  1202.            mov [cpu_AMD], 1
  1203.            cmp eax, 1
  1204.            jl .unknown
  1205.            mov eax, 1
  1206.            cpuid
  1207.            mov [cpu_sign], eax
  1208.            mov [cpu_info],  ebx
  1209.            mov [cpu_caps],  edx
  1210.            mov [cpu_caps+4],ecx
  1211.            shr eax, 8
  1212.            and eax, 0x0f
  1213.            ret
  1214. .unknown:
  1215.            mov eax, 1
  1216.            cpuid
  1217.            mov [cpu_sign], eax
  1218.            mov [cpu_info],  ebx
  1219.            mov [cpu_caps],  edx
  1220.            mov [cpu_caps+4],ecx
  1221.            shr eax, 8
  1222.            and eax, 0x0f
  1223.            ret
  1224. endp
  1225.  
  1226. MEM_WB     equ 6               ;write-back memory
  1227. MEM_WC     equ 1               ;write combined memory
  1228. MEM_UC     equ 0               ;uncached memory
  1229.  
  1230. align 4
  1231. proc init_mtrr
  1232.  
  1233.            cmp [BOOT_VAR+0x901c],byte 2
  1234.            je  .exit
  1235.  
  1236.            bt [cpu_caps], CAPS_MTRR
  1237.            jnc .exit
  1238.  
  1239.            mov eax, cr0
  1240.            or eax, 0x60000000   ;disable caching
  1241.            mov cr0, eax
  1242.            wbinvd               ;invalidate cache
  1243.  
  1244.            mov ecx, 0x2FF
  1245.            rdmsr                ;
  1246.            push eax
  1247.  
  1248.            xor edx, edx
  1249.            xor eax, eax
  1250.            mov ecx, 0x2FF
  1251.            wrmsr                ;disable all MTRR
  1252.  
  1253.            stdcall set_mtrr, dword 0,dword 0,[MEM_AMOUNT],MEM_WB
  1254.            stdcall set_mtrr, dword 1,[LFBAddress],[LFBSize],MEM_WC
  1255.            xor edx, edx
  1256.            xor eax, eax
  1257.            mov ecx, 0x204
  1258.            mov ebx, 6
  1259. @@:
  1260.            wrmsr                ;disable unused MTRR
  1261.            inc ecx
  1262.            wrmsr
  1263.            inc ecx
  1264.            dec ebx
  1265.            jnz @b
  1266.  
  1267.            wbinvd               ;again invalidate
  1268.  
  1269.            pop eax
  1270.            or eax, 0x800        ;set default memtype to UC
  1271.            and al, 0xF0
  1272.            mov ecx, 0x2FF
  1273.            wrmsr                ;and enable MTRR
  1274.  
  1275.            mov eax, cr0
  1276.            and eax, not 0x60000000
  1277.            mov cr0, eax         ; enable caching
  1278. .exit:
  1279.            ret
  1280. endp
  1281.  
  1282. align 4
  1283. proc set_mtrr stdcall, reg:dword,base:dword,size:dword,mem_type:dword
  1284.  
  1285.            xor edx, edx
  1286.            mov eax, [base]
  1287.            or eax, [mem_type]
  1288.            mov ecx, [reg]
  1289.            lea ecx, [0x200+ecx*2]
  1290.            wrmsr
  1291.  
  1292.            mov ebx, [size]
  1293.            dec ebx
  1294.            mov eax, 0xFFFFFFFF
  1295.            mov edx, 0x0000000F
  1296.            sub eax, ebx
  1297.            sbb edx, 0
  1298.            or eax, 0x800
  1299.            inc ecx
  1300.            wrmsr
  1301.            ret
  1302. endp
  1303.  
  1304. align 4
  1305. proc stall stdcall, delay:dword
  1306.            push ecx
  1307.            push edx
  1308.            push ebx
  1309.            push eax
  1310.  
  1311.            mov eax, [delay]
  1312.            mul [stall_mcs]
  1313.            mov ebx, eax       ;low
  1314.            mov ecx, edx       ;high
  1315.            rdtsc
  1316.            add ebx, eax
  1317.            adc ecx,edx
  1318. @@:
  1319.            rdtsc
  1320.            sub eax, ebx
  1321.            sbb edx, ecx
  1322.            jb @B
  1323.  
  1324.            pop eax
  1325.            pop ebx
  1326.            pop edx
  1327.            pop ecx
  1328.            ret
  1329. endp
  1330.  
  1331. iglobal
  1332. align 4
  1333.   intel_str    db "GenuineIntel",0
  1334.   AMD_str      db "AuthenticAMD",0
  1335. endg
  1336.  
  1337. uglobal
  1338. align 16
  1339.   irq_tab           rd 16
  1340.  
  1341.   MEM_FreeSpace     rd 1
  1342.  
  1343.   ipc_tmp           rd 1
  1344.   ipc_pdir          rd 1
  1345.   ipc_ptab          rd 1
  1346.  
  1347.   proc_mem_map      rd 1
  1348.   proc_mem_pdir     rd 1
  1349.   proc_mem_tab      rd 1
  1350.  
  1351.   tmp_task_pdir     rd 1
  1352.   tmp_task_ptab     rd 1
  1353.  
  1354.   fdd_buff          rd 1
  1355.   LFBSize           rd 1
  1356.  
  1357.   stall_mcs         rd 1
  1358. ;;CPUID information
  1359.  
  1360.   cpu_vendor        rd 3
  1361.   cpu_sign          rd 1
  1362.   cpu_info          rd 1
  1363.  
  1364. ;;;;;   cursors data
  1365.  
  1366. align 16
  1367. cur_saved_data   rb 4096
  1368.  
  1369. def_cursor       rd 1
  1370. hw_cursor        rd 1
  1371.  
  1372. scr_width        rd 1
  1373. scr_height       rd 1
  1374.  
  1375. cur_def_interl   rd 1
  1376. cur_saved_base   rd 1
  1377. cur_saved_interl rd 1
  1378. cur_saved_w      rd 1
  1379. cur_saved_h      rd 1
  1380.  
  1381. endg
  1382.  
  1383. uglobal
  1384. align 16
  1385.    fpu_data:
  1386.                    rb 512
  1387.  
  1388.    mst MEM_STATE
  1389.  
  1390.    mem_block_map   rb 512
  1391.    event_map       rb 64
  1392.    mem_block_list  rd 64
  1393.    mem_block_mask  rd 2
  1394.  
  1395.    srv.fd          rd 1
  1396.    srv.bk          rd 1
  1397.  
  1398.    mem_used.fd     rd 1
  1399.    mem_used.bk     rd 1
  1400.  
  1401.    mem_block_arr   rd 1
  1402.    mem_block_start rd 1
  1403.    mem_block_end   rd 1
  1404.  
  1405.    heap_mutex      rd 1
  1406.    heap_size       rd 1
  1407.    heap_free       rd 1
  1408.    heap_blocks     rd 1
  1409.    free_blocks     rd 1
  1410.  
  1411.    page_start      rd 1
  1412.    page_end        rd 1
  1413.    events          rd 1
  1414.    event_start     rd 1
  1415.    event_end       rd 1
  1416.    event_uid       rd 1
  1417.    sys_page_map    rd 1
  1418.    os_stack        rd 1
  1419. endg
  1420.  
  1421. if 0
  1422.      push eax
  1423.      push edx
  1424.      mov edx, 0x400   ;bocsh
  1425.      mov al,0xff      ;bocsh
  1426.      out dx, al       ;bocsh
  1427.      pop edx
  1428.      pop eax
  1429. end if
  1430.  
  1431. align 4
  1432. k_strrchr:
  1433.         push eax
  1434.         xor eax,eax
  1435.         or  ecx,-1
  1436.         repne scasb
  1437.         add ecx,1
  1438.         neg ecx
  1439.         sub edi,1
  1440.         pop eax
  1441.         std
  1442.         repne scasb
  1443.         cld
  1444.         add edi,1
  1445.  
  1446.         cmp [edi],al
  1447.         jne @F
  1448.         mov eax,edi
  1449.         ret
  1450. @@:
  1451.         xor eax,eax
  1452.         ret
  1453.  
  1454. align 4
  1455. proc k_strncpy stdcall, dest:dword, src:dword, maxlen:dword
  1456.         mov eax, [dest]
  1457.         mov esi, [src]
  1458.         mov ecx, [maxlen]
  1459.         test eax, eax
  1460.         jz .L9
  1461.         test esi, esi
  1462.         jz .L9
  1463.         test ecx, ecx
  1464.         jz .L9
  1465.  
  1466.         sub  esi, eax
  1467.         jmp .L1
  1468.  
  1469. align 4
  1470. .L2:
  1471.         mov edx, [esi+eax]
  1472.         mov [eax], dl
  1473.         test dl, dl
  1474.         jz .L7
  1475.  
  1476.         mov [eax+1], dh
  1477.         test dh, dh
  1478.         jz .L6
  1479.  
  1480.         shr edx, 16
  1481.         mov [eax+2],dl
  1482.         test dl, dl
  1483.         jz .L5
  1484.  
  1485.         mov [eax+3], dh
  1486.         test dh, dh
  1487.         jz .L4
  1488.         add eax, 4
  1489. .L1:
  1490.         sub ecx, 4
  1491.         jae .L2
  1492.  
  1493.         add ecx, 4
  1494.         jz .L9
  1495.  
  1496.         mov dl, [eax+esi]
  1497.         mov [eax], dl
  1498.         test dl, dl
  1499.         jz .L3
  1500.  
  1501.         inc eax
  1502.         dec ecx
  1503.         jz .L9
  1504.  
  1505.         mov dl, [eax+esi]
  1506.         mov [eax], dl
  1507.         test dl, dl
  1508.         jz .L3
  1509.  
  1510.         inc eax
  1511.         dec ecx
  1512.         jz .L9
  1513.  
  1514.         mov dl, [eax+esi]
  1515.         mov [eax], dl
  1516.         test dl, dl
  1517.         jz .L3
  1518.  
  1519.         inc eax
  1520.         jmp .L9
  1521.  
  1522. .L4:    dec ecx
  1523.         inc eax
  1524.  
  1525. .L5:    dec ecx
  1526.         inc eax
  1527.  
  1528. .L6:    dec ecx
  1529.         inc eax
  1530. .L7:
  1531.         add ecx,3
  1532.         jz .L9
  1533. .L8:
  1534.         mov byte [ecx+eax], 0
  1535. .L3:
  1536.         dec ecx
  1537.         jnz .L8
  1538. .L9:
  1539.         ret
  1540. endp
  1541.  
  1542. if 0
  1543.  
  1544. magic equ 0xfefefeff
  1545.  
  1546. k_strlen:
  1547.         mov eax,[esp+4]
  1548.         mov edx, 3
  1549.  
  1550.         and edx, eax
  1551.         jz .L1
  1552.         jp .L0
  1553.  
  1554.         cmp dh, byte [eax]
  1555.         je .L2
  1556.  
  1557.         inc eax
  1558.         cmp dh, byte [eax]
  1559.  
  1560.         je .L2
  1561.  
  1562.         inc eax
  1563.         xor edx, 2
  1564.  
  1565.         jz .L1
  1566. .L0:
  1567.         cmp dh, [eax]
  1568.         je .L2
  1569.  
  1570.         inc eax
  1571.         xor edx, edx
  1572.  
  1573. .L1:
  1574.         mov ecx, [eax]
  1575.         add eax, 4
  1576.  
  1577.         sub edx, ecx
  1578.         add ecx, magic
  1579.  
  1580.         dec edx
  1581.         jnc .L3
  1582.  
  1583.         xor edx, ecx
  1584.         and edx, not magic
  1585.         jne .L3
  1586.  
  1587.         mov ecx, [eax]
  1588.         add eax, 4
  1589.  
  1590.         sub edx, ecx
  1591.         add ecx, magic
  1592.         dec edx
  1593.         jnc .L3
  1594.  
  1595.         xor edx, ecx
  1596.         and edx, not magic
  1597.         jne .L3
  1598.  
  1599.         mov ecx, [eax]
  1600.         add eax, 4
  1601.  
  1602.         sub edx, ecx
  1603.         add ecx, magic
  1604.  
  1605.         dec edx
  1606.         jnc .L3
  1607.  
  1608.         xor edx, ecx
  1609.  
  1610.         and edx, not magic
  1611.         jne .L3
  1612.  
  1613.         mov ecx, [eax]
  1614.         add eax, 4
  1615.  
  1616.         sub edx, ecx
  1617.         add ecx, magic
  1618.  
  1619.         dec edx
  1620.         jnc .L3
  1621.  
  1622.         xor edx, ecx
  1623.  
  1624.         and edx, not magic
  1625.         je .L1
  1626.  
  1627. .L3:    sub eax ,4
  1628.         sub ecx, magic
  1629.  
  1630.         cmp cl, 0
  1631.         jz .L2
  1632.  
  1633.         inc eax
  1634.         test ch, ch
  1635.         jz .L2
  1636.  
  1637.         shr ecx, 16
  1638.         inc eax
  1639.  
  1640.         cmp cl,0
  1641.         jz .L2
  1642.  
  1643.         inc eax
  1644.  
  1645. .L2:
  1646.         sub eax, [esp+4]
  1647.         ret
  1648.  
  1649. end if
  1650.