Subversion Repositories Kolibri OS

Rev

Rev 363 | Rev 378 | Go to most recent revision | Blame | Compare with Previous | 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+0x600], 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 [current_pgdir+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.            cmp dword [LFBAddress], -1
  380.            jne @f
  381.            mov [0x2f0000+0x901c],byte 2
  382.            stdcall kernel_alloc, 0x280000
  383.            mov [LFBAddress], eax
  384.            ret
  385. @@:
  386.            test [SCR_MODE],word 0100000000000000b
  387.            jnz @f
  388.            mov [0x2f0000+0x901c],byte 2
  389.            ret
  390. @@:
  391.            call map_LFB
  392.            ret
  393. endp
  394.  
  395. align 4
  396. proc map_LFB
  397.            locals
  398.              pg_count dd ?
  399.            endl
  400.  
  401.            mov edi, [LFBSize]
  402.            mov esi, [LFBAddress]
  403.            mov dword [exp_lfb+4], esi
  404.  
  405.            shr edi, 12
  406.            mov [pg_count], edi
  407.            shr edi, 10
  408.  
  409.            bt [cpu_caps], CAPS_PSE
  410.            jnc .map_page_tables
  411.            mov ebx, esi
  412.            or esi, PG_LARGE+PG_UW
  413.            shr ebx, 20
  414.            mov ecx, ebx
  415. @@:
  416.            mov [sys_pgdir+ebx], esi
  417.            add ebx, 4
  418.            add esi, 0x00400000
  419.            dec edi
  420.            jnz @B
  421.  
  422.            bt [cpu_caps], CAPS_PGE
  423.            jnc @F
  424.            or dword [sys_pgdir+ecx], PG_GLOBAL
  425. @@:
  426.            mov eax, cr3       ;flush TLB
  427.            mov cr3, eax
  428.            ret
  429.  
  430. .map_page_tables:
  431.  
  432. @@:
  433.            call alloc_page
  434.            stdcall map_page_table, esi, eax
  435.            add esi, 0x00400000
  436.            dec edi
  437.            jnz @B
  438.  
  439.            mov eax, [LFBAddress]
  440.            mov esi, eax
  441.            shr esi, 10
  442.            add esi, page_tabs
  443.            or eax, PG_UW
  444.            mov ecx, [pg_count]
  445.            shr ecx, 2
  446. .map:
  447.            mov [esi], eax
  448.            add eax, 0x1000
  449.            mov [esi+4], eax
  450.            add eax, 0x1000
  451.            mov [esi+8], eax
  452.            add eax, 0x1000
  453.            mov [esi+12], eax
  454.            add eax, 0x1000
  455.            add esi, 16
  456.            sub ecx, 1
  457.            jnz .map
  458.  
  459.            mov eax, cr3       ;flush TLB
  460.            mov cr3, eax
  461.  
  462.            ret
  463. endp
  464.  
  465. align 4
  466. proc new_mem_resize stdcall, new_size:dword
  467.  
  468.            mov ebx, pg_data.pg_mutex
  469.            call wait_mutex    ;ebx
  470.  
  471.            mov edi, [new_size]
  472.            add edi,4095
  473.            and edi,not 4095
  474.            mov [new_size], edi
  475.  
  476.            mov edx,[CURRENT_TASK]
  477.            shl edx,8
  478.            cmp [PROC_BASE+APPDATA.heap_base+edx],0
  479.            jne .exit
  480.  
  481.            mov esi, [PROC_BASE+APPDATA.mem_size+edx]
  482.            add esi, 4095
  483.            and esi, not 4095
  484.  
  485.            cmp edi, esi
  486.            jae .expand
  487.  
  488.            shr edi, 12
  489.            shr esi, 12
  490. @@:
  491.            mov eax, [page_tabs+0x00181000+edi*4]
  492.            test eax, 1
  493.            jz .next
  494.            mov dword [page_tabs+0x00181000+edi*4], 2
  495.            mov ebx, edi
  496.            shl ebx, 12
  497.            invlpg [ebx+std_application_base_address]
  498.            call free_page
  499.  
  500. .next:     add edi, 1
  501.            cmp edi, esi
  502.            jb @B
  503.  
  504. .update_size:
  505.         mov     ebx, [new_size]
  506.         call    update_mem_size
  507.  
  508.            xor eax, eax
  509.            dec [pg_data.pg_mutex]
  510.            ret
  511.  
  512. .expand:
  513.            add edi, new_app_base
  514.            add esi, new_app_base
  515.  
  516.            push esi
  517.            push edi
  518.  
  519.            add edi, 0x3FFFFF
  520.            and edi, not(0x3FFFFF)
  521.            add esi, 0x3FFFFF
  522.            and esi, not(0x3FFFFF)
  523.  
  524.            cmp esi, edi
  525.            jae .grow
  526.  
  527.            xchg esi, edi
  528.  
  529. @@:
  530.            call alloc_page
  531.            test eax, eax
  532.            jz .exit
  533.  
  534.            stdcall map_page_table, edi, eax
  535.  
  536.            push edi
  537.            shr edi, 10
  538.            add edi, page_tabs
  539.            mov ecx, 1024
  540.            xor eax, eax
  541.            cld
  542.            rep stosd
  543.            pop edi
  544.  
  545.            add edi, 0x00400000
  546.            cmp edi, esi
  547.            jb @B
  548. .grow:
  549.            pop edi
  550.            pop esi
  551. @@:
  552.            call alloc_page
  553.            test eax, eax
  554.            jz .exit
  555.            stdcall map_page,esi,eax,dword PG_UW
  556.  
  557.            push edi
  558.            mov edi, esi
  559.            xor eax, eax
  560.            mov ecx, 1024
  561.            cld
  562.            rep stosd
  563.            pop edi
  564.  
  565.            add esi, 0x1000
  566.            cmp esi, edi
  567.            jb  @B
  568.  
  569.            jmp .update_size
  570. .exit:
  571.            xor eax, eax
  572.            inc eax
  573.            dec [pg_data.pg_mutex]
  574.            ret
  575. endp
  576.  
  577. update_mem_size:
  578. ; in: edx = slot shl 8
  579. ;     ebx = new memory size
  580. ; destroys eax,ecx,edx
  581.  
  582.            mov    [PROC_BASE+APPDATA.mem_size+edx],ebx
  583. ;search threads and update
  584. ;application memory size infomation
  585.            mov    ecx,[PROC_BASE+APPDATA.dir_table+edx]
  586.            mov    eax,2
  587.  
  588. .search_threads:
  589. ;eax = current slot
  590. ;ebx = new memory size
  591. ;ecx = page directory
  592.            cmp    eax,[TASK_COUNT]
  593.            jg     .search_threads_end
  594.            mov    edx,eax
  595.            shl    edx,5
  596.            cmp    word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty?
  597.            jz     .search_threads_next
  598.            shl    edx,3
  599.            cmp    [PROC_BASE+edx+APPDATA.dir_table],ecx     ;if it is our thread?
  600.            jnz    .search_threads_next
  601.            mov    [PROC_BASE+edx+APPDATA.mem_size],ebx     ;update memory size
  602. .search_threads_next:
  603.            inc    eax
  604.            jmp    .search_threads
  605. .search_threads_end:
  606.            ret
  607.  
  608. ; param
  609. ;  eax= linear address
  610. ;
  611. ; retval
  612. ;  eax= phisical page address
  613.  
  614. align 4
  615. get_pg_addr:
  616.            shr eax, 12
  617.            mov eax, [page_tabs+eax*4]
  618.            and eax, 0xFFFFF000
  619.            ret
  620.  
  621. align 4
  622. proc page_fault_handler
  623.            pushad
  624.  
  625.            mov ebp, esp
  626.            mov eax, cr2
  627.            push eax
  628.            push ds
  629.            push es
  630.  
  631.            mov ax, 0x10
  632.            mov ds, ax
  633.            mov es, ax
  634.  
  635.            inc [pg_data.pages_faults]
  636.  
  637.            mov ebx, [ebp-4]
  638.  
  639.            cmp ebx, 0xe0000000
  640.            jae .lfb_addr
  641.  
  642.            cmp ebx, 0x60400000
  643.            jae .user_space
  644.  
  645.            cmp ebx, master_tab+0x1000
  646.            jae .alloc
  647.  
  648.            cmp ebx, 0x60000000
  649.            jae .tab_space
  650.  
  651.            jmp .kernel_space
  652.  
  653. .user_space:
  654.            shr ebx, 12
  655.            mov ecx, ebx
  656.            shr ecx, 10
  657.            mov edx, [master_tab+ecx*4]
  658.            test edx, 1
  659.            jz .fail
  660.  
  661.            mov eax, [page_tabs+ebx*4]
  662.            test eax, 2
  663.            jz .fail
  664. .alloc:
  665.            call alloc_page
  666.            and eax, eax
  667.            jz .exit
  668.  
  669.            stdcall map_page,[ebp-4],eax,dword PG_UW
  670.  
  671.            mov edi, [ebp-4]
  672.            and edi, 0xFFFFF000
  673.            mov ecx, 1024
  674.            xor eax, eax
  675.            cld
  676.            rep stosd
  677. .exit:
  678.            pop es
  679.            pop ds
  680.            mov esp, ebp
  681.            popad
  682.            add esp, 4
  683.            iretd
  684. .fail:
  685.            pop es
  686.            pop ds
  687.            mov esp, ebp
  688.            popad
  689.            add esp, 4
  690.  
  691.            save_ring3_context     ;debugger support
  692.  
  693.            mov bl, 14
  694.            jmp exc_c
  695.            iretd
  696.  
  697. .kernel_space:
  698. ;           shr ebx, 12
  699. ;           mov eax, [page_tabs+ebx*4]
  700. ;           shr ebx, 10
  701. ;           mov eax, [master_tab+ebx*4]
  702.            jmp .exit
  703. .old_addr:
  704. ;           shr ebx, 12
  705. ;           mov eax, [page_tabs+ebx*4]
  706. ;           shr ebx, 10
  707. ;           mov eax, [master_tab+ebx*4]
  708.            jmp .exit
  709. .lfb_addr:
  710. ;           shr ebx, 22
  711. ;           ;mov ecx, [sys_page_dir]
  712. ;           mov eax, [master_tab+ebx*4]
  713.            jmp .exit
  714. .tab_space:
  715. ;           shr ebx, 12
  716. ;           mov eax, [page_tabs+ebx*4]
  717. ;           shr ebx, 10
  718. ;           ;mov ecx, [sys_page_dir]
  719. ;           mov eax, [master_tab+ebx*4]
  720.            jmp .exit
  721. endp
  722.  
  723. align 4
  724. proc map_mem stdcall, lin_addr:dword,pdir:dword,\
  725.                       ofs:dword,buf_size:dword
  726.            mov eax, [buf_size]
  727.            test eax, eax
  728.            jz .exit
  729.  
  730.            mov eax, [pdir]
  731.            and eax, 0xFFFFF000
  732.  
  733.            stdcall map_page,[ipc_pdir],eax,dword PG_UW
  734.            mov ebx, [ofs]
  735.            shr ebx, 22
  736.            mov esi, [ipc_pdir]
  737.            mov edi, [ipc_ptab]
  738.            mov eax, [esi+ebx*4]
  739.            and eax, 0xFFFFF000
  740.            test eax, eax
  741.            jz .exit
  742.            stdcall map_page,edi,eax,dword PG_UW
  743. ;           inc ebx
  744. ;           add edi, 0x1000
  745. ;           mov eax, [esi+ebx*4]
  746. ;           test eax, eax
  747. ;           jz @f
  748. ;          and eax, 0xFFFFF000
  749. ;           stdcall map_page, edi, eax
  750.  
  751. @@:        mov edi, [lin_addr]
  752.            and edi, 0xFFFFF000
  753.            mov ecx, [buf_size]
  754.            add ecx, 4095
  755.            shr ecx, 12
  756.            inc ecx
  757.  
  758.            mov edx, [ofs]
  759.            shr edx, 12
  760.            and edx, 0x3FF
  761.            mov esi, [ipc_ptab]
  762.  
  763. .map:      mov eax, [esi+edx*4]
  764.            and eax, 0xFFFFF000
  765.            test eax, eax
  766.            jz .exit
  767.            stdcall map_page,edi,eax,dword PG_UW
  768.            add edi, 0x1000
  769.            inc edx
  770.            dec ecx
  771.            jnz .map
  772.  
  773. .exit:
  774.            ret
  775. endp
  776.  
  777. align 4
  778. proc map_memEx stdcall, lin_addr:dword,pdir:dword,\
  779.                         ofs:dword,buf_size:dword
  780.            mov eax, [buf_size]
  781.            test eax, eax
  782.            jz .exit
  783.  
  784.            mov eax, [pdir]
  785.            and eax, 0xFFFFF000
  786.  
  787.            stdcall map_page,[proc_mem_pdir],eax,dword PG_UW
  788.            mov ebx, [ofs]
  789.            shr ebx, 22
  790.            mov esi, [proc_mem_pdir]
  791.            mov edi, [proc_mem_tab]
  792.            mov eax, [esi+ebx*4]
  793.            and eax, 0xFFFFF000
  794.            test eax, eax
  795.            jz .exit
  796.            stdcall map_page,edi,eax,dword PG_UW
  797.  
  798. @@:        mov edi, [lin_addr]
  799.            and edi, 0xFFFFF000
  800.            mov ecx, [buf_size]
  801.            add ecx, 4095
  802.            shr ecx, 12
  803.            inc ecx
  804.  
  805.            mov edx, [ofs]
  806.            shr edx, 12
  807.            and edx, 0x3FF
  808.            mov esi, [proc_mem_tab]
  809.  
  810. .map:      mov eax, [esi+edx*4]
  811. ;           and eax, 0xFFFFF000
  812. ;           test eax, eax
  813. ;           jz .exit
  814.            stdcall map_page,edi,eax,dword PG_UW
  815.            add edi, 0x1000
  816.            inc edx
  817.            dec ecx
  818.            jnz .map
  819. .exit:
  820.            ret
  821. endp
  822.  
  823.  
  824.  
  825.  
  826. sys_IPC:
  827. ;input:
  828. ;  eax=1 - set ipc buffer area
  829. ;    ebx=address of buffer
  830. ;    ecx=size of buffer
  831. ;  eax=2 - send message
  832. ;    ebx=PID
  833. ;    ecx=address of message
  834. ;    edx=size of message
  835.  
  836.            cmp  eax,1
  837.            jne @f
  838.            call set_ipc_buff
  839.            mov [esp+36], eax
  840.            ret
  841. @@:
  842.            cmp eax, 2
  843.            jne @f
  844.            stdcall sys_ipc_send, ebx, ecx, edx
  845.            mov [esp+36], eax
  846.            ret
  847. @@:
  848.            xor eax, eax
  849.            not eax
  850.            mov [esp+36], eax
  851.            ret
  852.  
  853. align 4
  854. proc set_ipc_buff
  855.  
  856.            mov  eax,[CURRENT_TASK]
  857.            shl  eax,8
  858.            add  eax, PROC_BASE
  859.            pushf
  860.            cli
  861.            mov  [eax+0xA0],ebx     ;set fields in extended information area
  862.            mov  [eax+0xA4],ecx
  863.  
  864.            add ebx,  new_app_base
  865.            add ecx, ebx
  866.            add ecx, 4095
  867.            and ecx, not 4095
  868.  
  869. .touch:    mov eax, [ebx]
  870.            add ebx, 0x1000
  871.            cmp ebx, ecx
  872.            jna .touch
  873.  
  874.            popf
  875.            xor eax, eax
  876.            ret
  877. endp
  878.  
  879. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  880.            locals
  881.              dst_slot   dd ?
  882.              dst_offset dd ?
  883.              buf_size   dd ?
  884.            endl
  885.  
  886.            pushf
  887.            cli
  888.  
  889.            mov  eax, [PID]
  890.            call pid_to_slot
  891.            test eax,eax
  892.            jz   .no_pid
  893.  
  894.            mov [dst_slot], eax
  895.            shl  eax,8
  896.            mov  edi,[eax+PROC_BASE+0xa0]  ;is ipc area defined?
  897.            test edi,edi
  898.            jz   .no_ipc_area
  899.  
  900.            mov ebx, edi
  901.            add edi, new_app_base
  902.            and ebx, 0xFFF
  903.            mov [dst_offset], ebx
  904.  
  905.            mov esi, [eax+PROC_BASE+0xa4]
  906.            mov [buf_size], esi
  907.  
  908.            stdcall map_mem, [ipc_tmp], [PROC_BASE+eax+0xB8],\
  909.                              edi, esi
  910.  
  911.            mov edi, [dst_offset]
  912.            add edi, [ipc_tmp]
  913.            cmp dword [edi], 0
  914.            jnz  .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  915.  
  916.            mov ebx, dword [edi+4]
  917.            mov edx, ebx
  918.            add ebx, 8
  919.            add ebx, [msg_size]
  920.            cmp ebx, [buf_size]
  921.            ja .buffer_overflow         ;esi<0 - not enough memory in buffer
  922.  
  923.            mov dword [edi+4], ebx
  924.            mov eax,[TASK_BASE]
  925.            mov eax, [eax+0x04]         ;eax - our PID
  926.            mov edi, [dst_offset]
  927.            add edi, [ipc_tmp]
  928.            add edi, edx
  929.            mov [edi], eax
  930.            mov ecx, [msg_size]
  931.  
  932.            mov [edi+4], ecx
  933.            add edi, 8
  934.            mov esi, [msg_addr]
  935.            add esi, new_app_base
  936.            cld
  937.            rep movsb
  938.  
  939.            mov ebx, [ipc_tmp]
  940.            mov edx, ebx
  941.            shr ebx, 12
  942.            xor eax, eax
  943.            mov [page_tabs+ebx*4], eax
  944.            invlpg [edx]
  945.  
  946.            mov ebx, [ipc_pdir]
  947.            mov edx, ebx
  948.            shr ebx, 12
  949.            xor eax, eax
  950.            mov [page_tabs+ebx*4], eax
  951.            invlpg [edx]
  952.  
  953.            mov ebx, [ipc_ptab]
  954.            mov edx, ebx
  955.            shr ebx, 12
  956.            xor eax, eax
  957.            mov [page_tabs+ebx*4], eax
  958.            invlpg [edx]
  959.  
  960.            mov  eax, [dst_slot]
  961.            shl eax, 8
  962.            or   [eax+PROC_BASE+0xA8],dword 0x40
  963.            cmp  dword [check_idle_semaphore],20
  964.            jge  .ipc_no_cis
  965.  
  966.            mov  dword [check_idle_semaphore],5
  967. .ipc_no_cis:
  968.            popf
  969.            xor eax, eax
  970.            ret
  971. .no_pid:
  972.            popf
  973.            mov  eax, 4
  974.            ret
  975. .no_ipc_area:
  976.            popf
  977.            xor eax, eax
  978.            inc eax
  979.            ret
  980. .ipc_blocked:
  981.            popf
  982.            mov  eax, 2
  983.            ret
  984. .buffer_overflow:
  985.            popf
  986.            mov  eax, 3
  987.            ret
  988. endp
  989.  
  990. align 4
  991. sysfn_meminfo:
  992.  
  993.            add ebx, new_app_base
  994.            cmp ebx, new_app_base
  995.            jb .fail
  996.  
  997.            mov eax, [pg_data.pages_count]
  998.            mov [ebx], eax
  999.            shl eax, 12
  1000.            mov [esp+36], eax
  1001.            mov ecx, [pg_data.pages_free]
  1002.            mov [ebx+4], ecx
  1003.            mov edx, [pg_data.pages_faults]
  1004.            mov [ebx+8], edx
  1005.            mov esi, [heap_size]
  1006.            mov [ebx+12], esi
  1007.            mov edi, [heap_free]
  1008.            mov [ebx+16], edi
  1009.            mov eax, [heap_blocks]
  1010.            mov [ebx+20], eax
  1011.            mov ecx, [free_blocks]
  1012.            mov [ebx+24], ecx
  1013.            ret
  1014. .fail:
  1015.            mov dword [esp+36], -1
  1016.            ret
  1017.  
  1018. align 4
  1019. new_services:
  1020.  
  1021.            cmp  eax,4
  1022.            jle  sys_sheduler
  1023.  
  1024.            cmp eax, 11
  1025.            jb .fail
  1026.            ja @f
  1027.  
  1028.            call init_heap
  1029.            mov [esp+36], eax
  1030.            ret
  1031. @@:
  1032.            cmp eax, 12
  1033.            ja @f
  1034.  
  1035.            stdcall user_alloc, ebx
  1036.            mov [esp+36], eax
  1037.            ret
  1038. @@:
  1039.            cmp eax, 13
  1040.            ja @f
  1041.            add ebx, new_app_base
  1042.            stdcall user_free, ebx
  1043.            mov [esp+36], eax
  1044.            ret
  1045. @@:
  1046.            cmp eax, 14
  1047.            ja @f
  1048.            add ebx, new_app_base
  1049.            cmp ebx, new_app_base
  1050.            jb .fail
  1051.            stdcall get_event_ex, ebx, ecx
  1052.            mov [esp+36], eax
  1053.            ret
  1054. @@:
  1055.            cmp eax, 15
  1056.            ja @f
  1057.            mov ecx, [CURRENT_TASK]
  1058.            shl ecx, 8
  1059.            mov eax, [ecx+PROC_BASE+APPDATA.fpu_handler]
  1060.            mov [ecx+PROC_BASE+APPDATA.fpu_handler], ebx
  1061.            mov [esp+36], eax
  1062.            ret
  1063. @@:
  1064.            cmp eax, 16
  1065.            ja @f
  1066.  
  1067.            test ebx, ebx
  1068.            jz .fail
  1069.            add ebx, new_app_base
  1070.            cmp ebx, new_app_base
  1071.            jb .fail
  1072.            stdcall get_service, ebx
  1073.            mov [esp+36], eax
  1074.            ret
  1075. @@:
  1076.            cmp eax, 17
  1077.            ja @f
  1078.            stdcall srv_handlerEx, ebx
  1079.            mov [esp+36], eax
  1080.            ret
  1081. @@:
  1082.            cmp eax, 18
  1083.            ja @f
  1084.            mov ecx, [CURRENT_TASK]
  1085.            shl ecx, 8
  1086.            mov eax, [ecx+PROC_BASE+APPDATA.sse_handler]
  1087.            mov [ecx+PROC_BASE+APPDATA.sse_handler], ebx
  1088.            mov [esp+36], eax
  1089.            ret
  1090. @@:
  1091.            cmp eax, 19
  1092.            ja .fail
  1093.            add ebx, new_app_base
  1094.            cmp ebx, new_app_base
  1095.            jb .fail
  1096.            stdcall load_library, ebx
  1097.            mov [esp+36], eax
  1098.            ret
  1099.  
  1100. .fail:
  1101.            xor eax, eax
  1102.            mov [esp+36], eax
  1103.            ret
  1104.  
  1105. align 4
  1106. proc strncmp stdcall, str1:dword, str2:dword, count:dword
  1107.  
  1108.           mov ecx,[count]
  1109.           jecxz .end
  1110.  
  1111.           mov ebx,ecx
  1112.  
  1113.           mov edi,[str1]
  1114.           mov esi,edi
  1115.           xor eax,eax
  1116.           repne scasb
  1117.           neg ecx             ; cx = count - strlen
  1118.           add ecx,ebx         ; strlen + count - strlen
  1119.  
  1120. .okay:
  1121.           mov edi,esi
  1122.           mov esi,[str2]
  1123.           repe cmpsb
  1124.           mov al,[esi-1]
  1125.           xor ecx,ecx
  1126.  
  1127.           cmp al,[edi-1]
  1128.           ja .str2_big
  1129.           je .end
  1130.  
  1131. .str1_big:
  1132.           sub ecx,2
  1133.  
  1134. .str2_big:
  1135.           not ecx
  1136. .end:
  1137.           mov eax,ecx
  1138.           ret
  1139. endp
  1140.  
  1141. align 4
  1142. proc test_cpu
  1143.            locals
  1144.               cpu_type   dd ?
  1145.               cpu_id     dd ?
  1146.               cpu_Intel  dd ?
  1147.               cpu_AMD    dd ?
  1148.            endl
  1149.  
  1150.            mov [cpu_type], 0
  1151.            xor eax, eax
  1152.            mov [cpu_caps], eax
  1153.            mov [cpu_caps+4], eax
  1154.  
  1155.            pushfd
  1156.            pop eax
  1157.            mov ecx, eax
  1158.            xor eax, 0x40000
  1159.            push eax
  1160.            popfd
  1161.            pushfd
  1162.            pop eax
  1163.            xor eax, ecx
  1164.            mov [cpu_type], CPU_386
  1165.            jz .end_cpuid
  1166.            push ecx
  1167.            popfd
  1168.  
  1169.            mov [cpu_type], CPU_486
  1170.            mov eax, ecx
  1171.            xor eax, 0x200000
  1172.            push eax
  1173.            popfd
  1174.            pushfd
  1175.            pop eax
  1176.            xor eax, ecx
  1177.            je .end_cpuid
  1178.            mov [cpu_id], 1
  1179.  
  1180.            xor eax, eax
  1181.            cpuid
  1182.            mov [cpu_vendor], ebx
  1183.            mov [cpu_vendor+4], edx
  1184.            mov [cpu_vendor+8], ecx
  1185.            cmp ebx, dword [intel_str]
  1186.            jne .check_AMD
  1187.            cmp edx, dword [intel_str+4]
  1188.            jne .check_AMD
  1189.            cmp ecx, dword [intel_str+8]
  1190.            jne .check_AMD
  1191.            mov [cpu_Intel], 1
  1192.            cmp eax, 1
  1193.            jl .end_cpuid
  1194.            mov eax, 1
  1195.            cpuid
  1196.            mov [cpu_sign], eax
  1197.            mov [cpu_info],  ebx
  1198.            mov [cpu_caps],  edx
  1199.            mov [cpu_caps+4],ecx
  1200.  
  1201.            shr eax, 8
  1202.            and eax, 0x0f
  1203.            ret
  1204. .end_cpuid:
  1205.            mov eax, [cpu_type]
  1206.            ret
  1207.  
  1208. .check_AMD:
  1209.            cmp ebx, dword [AMD_str]
  1210.            jne .unknown
  1211.            cmp edx, dword [AMD_str+4]
  1212.            jne .unknown
  1213.            cmp ecx, dword [AMD_str+8]
  1214.            jne .unknown
  1215.            mov [cpu_AMD], 1
  1216.            cmp eax, 1
  1217.            jl .unknown
  1218.            mov eax, 1
  1219.            cpuid
  1220.            mov [cpu_sign], eax
  1221.            mov [cpu_info],  ebx
  1222.            mov [cpu_caps],  edx
  1223.            mov [cpu_caps+4],ecx
  1224.            shr eax, 8
  1225.            and eax, 0x0f
  1226.            ret
  1227. .unknown:
  1228.            mov eax, 1
  1229.            cpuid
  1230.            mov [cpu_sign], eax
  1231.            mov [cpu_info],  ebx
  1232.            mov [cpu_caps],  edx
  1233.            mov [cpu_caps+4],ecx
  1234.            shr eax, 8
  1235.            and eax, 0x0f
  1236.            ret
  1237. endp
  1238.  
  1239. MEM_WB     equ 6               ;write-back memory
  1240. MEM_WC     equ 1               ;write combined memory
  1241. MEM_UC     equ 0               ;uncached memory
  1242.  
  1243. align 4
  1244. proc init_mtrr
  1245.  
  1246.            cmp [0x2f0000+0x901c],byte 2
  1247.            je  .exit
  1248.  
  1249.            bt [cpu_caps], CAPS_MTRR
  1250.            jnc .exit
  1251.  
  1252.            mov eax, cr0
  1253.            or eax, 0x60000000   ;disable caching
  1254.            mov cr0, eax
  1255.            wbinvd               ;invalidate cache
  1256.  
  1257.            mov ecx, 0x2FF
  1258.            rdmsr                ;
  1259.            push eax
  1260.  
  1261.            xor edx, edx
  1262.            xor eax, eax
  1263.            mov ecx, 0x2FF
  1264.            wrmsr                ;disable all MTRR
  1265.  
  1266.            stdcall set_mtrr, dword 0,dword 0,[MEM_AMOUNT],MEM_WB
  1267.            stdcall set_mtrr, dword 1,[LFBAddress],[LFBSize],MEM_WC
  1268.            xor edx, edx
  1269.            xor eax, eax
  1270.            mov ecx, 0x204
  1271.            mov ebx, 6
  1272. @@:
  1273.            wrmsr                ;disable unused MTRR
  1274.            inc ecx
  1275.            wrmsr
  1276.            inc ecx
  1277.            dec ebx
  1278.            jnz @b
  1279.  
  1280.            wbinvd               ;again invalidate
  1281.  
  1282.            pop eax
  1283.            or eax, 0x800        ;set default memtype to UC
  1284.            and al, 0xF0
  1285.            mov ecx, 0x2FF
  1286.            wrmsr                ;and enable MTRR
  1287.  
  1288.            mov eax, cr0
  1289.            and eax, not 0x60000000
  1290.            mov cr0, eax         ; enable caching
  1291. .exit:
  1292.            ret
  1293. endp
  1294.  
  1295. align 4
  1296. proc set_mtrr stdcall, reg:dword,base:dword,size:dword,mem_type:dword
  1297.  
  1298.            xor edx, edx
  1299.            mov eax, [base]
  1300.            or eax, [mem_type]
  1301.            mov ecx, [reg]
  1302.            lea ecx, [0x200+ecx*2]
  1303.            wrmsr
  1304.  
  1305.            mov ebx, [size]
  1306.            dec ebx
  1307.            mov eax, 0xFFFFFFFF
  1308.            mov edx, 0x0000000F
  1309.            sub eax, ebx
  1310.            sbb edx, 0
  1311.            or eax, 0x800
  1312.            inc ecx
  1313.            wrmsr
  1314.            ret
  1315. endp
  1316.  
  1317. align 4
  1318. proc stall stdcall, delay:dword
  1319.            push ecx
  1320.            push edx
  1321.            push ebx
  1322.            push eax
  1323.  
  1324.            mov eax, [delay]
  1325.            mul [stall_mcs]
  1326.            mov ebx, eax       ;low
  1327.            mov ecx, edx       ;high
  1328.            rdtsc
  1329.            add ebx, eax
  1330.            adc ecx,edx
  1331. @@:
  1332.            rdtsc
  1333.            sub eax, ebx
  1334.            sbb edx, ecx
  1335.            jb @B
  1336.  
  1337.            pop eax
  1338.            pop ebx
  1339.            pop edx
  1340.            pop ecx
  1341.            ret
  1342. endp
  1343.  
  1344. iglobal
  1345. align 4
  1346.   intel_str    db "GenuineIntel",0
  1347.   AMD_str      db "AuthenticAMD",0
  1348. endg
  1349.  
  1350. uglobal
  1351. align 16
  1352.   irq_tab           rd 16
  1353.  
  1354.   MEM_FreeSpace     rd 1
  1355.  
  1356.   ipc_tmp           rd 1
  1357.   ipc_pdir          rd 1
  1358.   ipc_ptab          rd 1
  1359.  
  1360.   proc_mem_map      rd 1
  1361.   proc_mem_pdir     rd 1
  1362.   proc_mem_tab      rd 1
  1363.  
  1364.   tmp_task_pdir     rd 1
  1365.   tmp_task_ptab     rd 1
  1366.  
  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.    fpu_data:
  1399.                    rb 512
  1400.  
  1401.    mst MEM_STATE
  1402.  
  1403.    mem_block_map   rb 512
  1404.    event_map       rb 64
  1405.    mem_block_list  rd 64
  1406.    mem_block_mask  rd 2
  1407.  
  1408.    srv.fd          rd 1
  1409.    srv.bk          rd 1
  1410.  
  1411.    mem_used.fd     rd 1
  1412.    mem_used.bk     rd 1
  1413.  
  1414.    mem_block_arr   rd 1
  1415.    mem_block_start rd 1
  1416.    mem_block_end   rd 1
  1417.  
  1418.    heap_mutex      rd 1
  1419.    heap_size       rd 1
  1420.    heap_free       rd 1
  1421.    heap_blocks     rd 1
  1422.    free_blocks     rd 1
  1423.  
  1424.    page_start      rd 1
  1425.    page_end        rd 1
  1426.    events          rd 1
  1427.    event_start     rd 1
  1428.    event_end       rd 1
  1429.    event_uid       rd 1
  1430.    sys_page_map    rd 1
  1431.    os_stack        rd 1
  1432. endg
  1433.  
  1434. if 0
  1435.      push eax
  1436.      push edx
  1437.      mov edx, 0x400   ;bocsh
  1438.      mov al,0xff      ;bocsh
  1439.      out dx, al       ;bocsh
  1440.      pop edx
  1441.      pop eax
  1442. end if
  1443.  
  1444. align 4
  1445. k_strrchr:
  1446.         push eax
  1447.         xor eax,eax
  1448.         or  ecx,-1
  1449.         repne scasb
  1450.         add ecx,1
  1451.         neg ecx
  1452.         sub edi,1
  1453.         pop eax
  1454.         std
  1455.         repne scasb
  1456.         cld
  1457.         add edi,1
  1458.  
  1459.         cmp [edi],al
  1460.         jne @F
  1461.         mov eax,edi
  1462.         ret
  1463. @@:
  1464.         xor eax,eax
  1465.         ret
  1466.  
  1467. align 4
  1468. proc k_strncpy stdcall, dest:dword, src:dword, maxlen:dword
  1469.         mov eax, [dest]
  1470.         mov esi, [src]
  1471.         mov ecx, [maxlen]
  1472.         test eax, eax
  1473.         jz .L9
  1474.         test esi, esi
  1475.         jz .L9
  1476.         test ecx, ecx
  1477.         jz .L9
  1478.  
  1479.         sub  esi, eax
  1480.         jmp .L1
  1481.  
  1482. align 4
  1483. .L2:
  1484.         mov edx, [esi+eax]
  1485.         mov [eax], dl
  1486.         test dl, dl
  1487.         jz .L7
  1488.  
  1489.         mov [eax+1], dh
  1490.         test dh, dh
  1491.         jz .L6
  1492.  
  1493.         shr edx, 16
  1494.         mov [eax+2],dl
  1495.         test dl, dl
  1496.         jz .L5
  1497.  
  1498.         mov [eax+3], dh
  1499.         test dh, dh
  1500.         jz .L4
  1501.         add eax, 4
  1502. .L1:
  1503.         sub ecx, 4
  1504.         jae .L2
  1505.  
  1506.         add ecx, 4
  1507.         jz .L9
  1508.  
  1509.         mov dl, [eax+esi]
  1510.         mov [eax], dl
  1511.         test dl, dl
  1512.         jz .L3
  1513.  
  1514.         inc eax
  1515.         dec ecx
  1516.         jz .L9
  1517.  
  1518.         mov dl, [eax+esi]
  1519.         mov [eax], dl
  1520.         test dl, dl
  1521.         jz .L3
  1522.  
  1523.         inc eax
  1524.         dec ecx
  1525.         jz .L9
  1526.  
  1527.         mov dl, [eax+esi]
  1528.         mov [eax], dl
  1529.         test dl, dl
  1530.         jz .L3
  1531.  
  1532.         inc eax
  1533.         jmp .L9
  1534.  
  1535. .L4:    dec ecx
  1536.         inc eax
  1537.  
  1538. .L5:    dec ecx
  1539.         inc eax
  1540.  
  1541. .L6:    dec ecx
  1542.         inc eax
  1543. .L7:
  1544.         add ecx,3
  1545.         jz .L9
  1546. .L8:
  1547.         mov byte [ecx+eax], 0
  1548. .L3:
  1549.         dec ecx
  1550.         jnz .L8
  1551. .L9:
  1552.         ret
  1553. endp
  1554.  
  1555. if 0
  1556.  
  1557. magic equ 0xfefefeff
  1558.  
  1559. k_strlen:
  1560.         mov eax,[esp+4]
  1561.         mov edx, 3
  1562.  
  1563.         and edx, eax
  1564.         jz .L1
  1565.         jp .L0
  1566.  
  1567.         cmp dh, byte [eax]
  1568.         je .L2
  1569.  
  1570.         inc eax
  1571.         cmp dh, byte [eax]
  1572.  
  1573.         je .L2
  1574.  
  1575.         inc eax
  1576.         xor edx, 2
  1577.  
  1578.         jz .L1
  1579. .L0:
  1580.         cmp dh, [eax]
  1581.         je .L2
  1582.  
  1583.         inc eax
  1584.         xor edx, edx
  1585.  
  1586. .L1:
  1587.         mov ecx, [eax]
  1588.         add eax, 4
  1589.  
  1590.         sub edx, ecx
  1591.         add ecx, magic
  1592.  
  1593.         dec edx
  1594.         jnc .L3
  1595.  
  1596.         xor edx, ecx
  1597.         and edx, not magic
  1598.         jne .L3
  1599.  
  1600.         mov ecx, [eax]
  1601.         add eax, 4
  1602.  
  1603.         sub edx, ecx
  1604.         add ecx, magic
  1605.         dec edx
  1606.         jnc .L3
  1607.  
  1608.         xor edx, ecx
  1609.         and edx, not magic
  1610.         jne .L3
  1611.  
  1612.         mov ecx, [eax]
  1613.         add eax, 4
  1614.  
  1615.         sub edx, ecx
  1616.         add ecx, magic
  1617.  
  1618.         dec edx
  1619.         jnc .L3
  1620.  
  1621.         xor edx, ecx
  1622.  
  1623.         and edx, not magic
  1624.         jne .L3
  1625.  
  1626.         mov ecx, [eax]
  1627.         add eax, 4
  1628.  
  1629.         sub edx, ecx
  1630.         add ecx, magic
  1631.  
  1632.         dec edx
  1633.         jnc .L3
  1634.  
  1635.         xor edx, ecx
  1636.  
  1637.         and edx, not magic
  1638.         je .L1
  1639.  
  1640. .L3:    sub eax ,4
  1641.         sub ecx, magic
  1642.  
  1643.         cmp cl, 0
  1644.         jz .L2
  1645.  
  1646.         inc eax
  1647.         test ch, ch
  1648.         jz .L2
  1649.  
  1650.         shr ecx, 16
  1651.         inc eax
  1652.  
  1653.         cmp cl,0
  1654.         jz .L2
  1655.  
  1656.         inc eax
  1657.  
  1658. .L2:
  1659.         sub eax, [esp+4]
  1660.         ret
  1661.  
  1662. end if
  1663.