Subversion Repositories Kolibri OS

Rev

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

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