Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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