Subversion Repositories Kolibri OS

Rev

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