1;Mupen64plus - linkage_x86.asm 2;Copyright (C) 2009-2011 Ari64 3; 4;This program is free software; you can redistribute it and/or modify 5;it under the terms of the GNU General Public License as published by 6;the Free Software Foundation; either version 2 of the License, or 7;(at your option) any later version. 8; 9;This program is distributed in the hope that it will be useful, 10;but WITHOUT ANY WARRANTY; without even the implied warranty of 11;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12;GNU General Public License for more details. 13; 14;You should have received a copy of the GNU General Public License 15;along with this program; if not, write to the 16;Free Software Foundation, Inc., 17;51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 19%ifdef ELF_TYPE 20 %macro cglobal 1 21 global %1 22 %endmacro 23 24 %macro cextern 1 25 extern %1 26 %endmacro 27%else 28 %macro cglobal 1 29 global _%1 30 %define %1 _%1 31 %endmacro 32 33 %macro cextern 1 34 extern _%1 35 %define %1 _%1 36 %endmacro 37%endif 38 39cglobal dyna_linker 40cglobal dyna_linker_ds 41cglobal jump_vaddr_eax 42cglobal jump_vaddr_ecx 43cglobal jump_vaddr_edx 44cglobal jump_vaddr_ebx 45cglobal jump_vaddr_ebp 46cglobal jump_vaddr_edi 47cglobal verify_code_ds 48cglobal verify_code_vm 49cglobal verify_code 50cglobal cc_interrupt 51cglobal do_interrupt 52cglobal fp_exception 53cglobal fp_exception_ds 54cglobal jump_syscall 55cglobal jump_eret 56cglobal new_dyna_start 57cglobal invalidate_block_eax 58cglobal invalidate_block_ecx 59cglobal invalidate_block_edx 60cglobal invalidate_block_ebx 61cglobal invalidate_block_ebp 62cglobal invalidate_block_esi 63cglobal invalidate_block_edi 64cglobal write_rdram_new 65cglobal write_rdramb_new 66cglobal write_rdramh_new 67cglobal write_rdramd_new 68cglobal read_nomem_new 69cglobal read_nomemb_new 70cglobal read_nomemh_new 71cglobal read_nomemd_new 72cglobal write_nomem_new 73cglobal write_nomemb_new 74cglobal write_nomemh_new 75cglobal write_nomemd_new 76cglobal write_mi_new 77cglobal write_mib_new 78cglobal write_mih_new 79cglobal write_mid_new 80cglobal breakpoint 81 82cextern base_addr 83cextern tlb_LUT_r 84cextern jump_in 85cextern add_link 86cextern hash_table 87cextern jump_dirty 88cextern new_recompile_block 89cextern g_cp0_regs 90cextern get_addr_ht 91cextern cycle_count 92cextern get_addr 93cextern branch_target 94cextern memory_map 95cextern pending_exception 96cextern restore_candidate 97cextern gen_interrupt 98cextern next_interrupt 99cextern stop 100cextern last_count 101cextern pcaddr 102cextern clean_blocks 103cextern reg 104cextern hi 105cextern lo 106cextern invalidate_block 107cextern address 108cextern g_rdram 109cextern cpu_byte 110cextern cpu_hword 111cextern cpu_word 112cextern cpu_dword 113cextern invalid_code 114cextern readmem_dword 115cextern check_interrupt 116cextern get_addr_32 117cextern write_mi 118cextern write_mib 119cextern write_mih 120cextern write_mid 121cextern TLB_refill_exception_new 122 123section .bss 124align 4 125 126section .rodata 127section .text 128 129dyna_linker: 130 ;eax = virtual target address 131 ;ebx = instruction to patch 132 mov edi, eax 133 mov ecx, eax 134 shr edi, 12 135 cmp eax, 0C0000000h 136 cmovge ecx, [tlb_LUT_r+edi*4] 137 test ecx, ecx 138 cmovz ecx, eax 139 xor ecx, 080000000h 140 mov edx, 2047 141 shr ecx, 12 142 and edx, ecx 143 or edx, 2048 144 cmp ecx, edx 145 cmova ecx, edx 146 ;jump_in lookup 147 mov edx, [jump_in+ecx*4] 148_A1: 149 test edx, edx 150 je _A3 151 mov edi, [edx] 152 xor edi, eax 153 or edi, [4+edx] 154 je _A2 155 mov edx, DWORD [12+edx] 156 jmp _A1 157_A2: 158 mov edi, [ebx] 159 mov ebp, esi 160 lea esi, [4+ebx+edi*1] 161 mov edi, eax 162 pusha 163 call add_link 164 popa 165 mov edi, [8+edx] 166 mov esi, ebp 167 lea edx, [-4+edi] 168 sub edx, ebx 169 mov DWORD [ebx], edx 170 jmp edi 171_A3: 172 ;hash_table lookup 173 mov edi, eax 174 mov edx, eax 175 shr edi, 16 176 shr edx, 12 177 xor edi, eax 178 and edx, 2047 179 movzx edi, di 180 shl edi, 4 181 cmp ecx, 2048 182 cmovc ecx, edx 183 cmp eax, [hash_table+edi] 184 jne _A5 185_A4: 186 mov edx, [hash_table+4+edi] 187 jmp edx 188_A5: 189 cmp eax, [hash_table+8+edi] 190 lea edi, [8+edi] 191 je _A4 192 ;jump_dirty lookup 193 mov edx, [jump_dirty+ecx*4] 194_A6: 195 test edx, edx 196 je _A8 197 mov ecx, [edx] 198 xor ecx, eax 199 or ecx, [4+edx] 200 je _A7 201 mov edx, DWORD [12+edx] 202 jmp _A6 203_A7: 204 mov edx, [8+edx] 205 ;hash_table insert 206 mov ebx, [hash_table-8+edi] 207 mov ecx, [hash_table-4+edi] 208 mov [hash_table-8+edi], eax 209 mov [hash_table-4+edi], edx 210 mov [hash_table+edi], ebx 211 mov [hash_table+4+edi], ecx 212 jmp edx 213_A8: 214 mov edi, eax 215 pusha 216 call new_recompile_block 217 test eax, eax 218 popa 219 je dyna_linker 220 ;pagefault 221 mov ebx, eax 222 mov ecx, 008h 223 224exec_pagefault: 225 ;eax = instruction pointer 226 ;ebx = fault address 227 ;ecx = cause 228 mov edx, [g_cp0_regs+48] 229 add esp, -12 230 mov edi, [g_cp0_regs+16] 231 or edx, 2 232 mov [g_cp0_regs+32], ebx ;BadVAddr 233 and edi, 0FF80000Fh 234 mov [g_cp0_regs+48], edx ;Status 235 mov [g_cp0_regs+52], ecx ;Cause 236 mov [g_cp0_regs+56], eax ;EPC 237 mov ecx, ebx 238 shr ebx, 9 239 and ecx, 0FFFFE000h 240 and ebx, 0007FFFF0h 241 mov [g_cp0_regs+40], ecx ;EntryHI 242 or edi, ebx 243 mov [g_cp0_regs+16], edi ;Context 244 push 080000000h 245 call get_addr_ht 246 add esp, 16 247 jmp eax 248 249;Special dynamic linker for the case where a page fault 250;may occur in a branch delay slot 251dyna_linker_ds: 252 mov edi, eax 253 mov ecx, eax 254 shr edi, 12 255 cmp eax, 0C0000000h 256 cmovge ecx, [tlb_LUT_r+edi*4] 257 test ecx, ecx 258 cmovz ecx, eax 259 xor ecx, 080000000h 260 mov edx, 2047 261 shr ecx, 12 262 and edx, ecx 263 or edx, 2048 264 cmp ecx, edx 265 cmova ecx, edx 266 ;jump_in lookup 267 mov edx, [jump_in+ecx*4] 268_B1: 269 test edx, edx 270 je _B3 271 mov edi, [edx] 272 xor edi, eax 273 or edi, [4+edx] 274 je _B2 275 mov edx, DWORD [12+edx] 276 jmp _B1 277_B2: 278 mov edi, [ebx] 279 mov ecx, esi 280 lea esi, [4+ebx+edi*1] 281 mov edi, eax 282 pusha 283 call add_link 284 popa 285 mov edi, [8+edx] 286 mov esi, ecx 287 lea edx, [-4+edi] 288 sub edx, ebx 289 mov DWORD [ebx], edx 290 jmp edi 291_B3: 292 ;hash_table lookup 293 mov edi, eax 294 mov edx, eax 295 shr edi, 16 296 shr edx, 12 297 xor edi, eax 298 and edx, 2047 299 movzx edi, di 300 shl edi, 4 301 cmp ecx, 2048 302 cmovc ecx, edx 303 cmp eax, [hash_table+edi] 304 jne _B5 305_B4: 306 mov edx, [hash_table+4+edi] 307 jmp edx 308_B5: 309 cmp eax, [hash_table+8+edi] 310 lea edi, [8+edi] 311 je _B4 312 ;jump_dirty lookup 313 mov edx, [jump_dirty+ecx*4] 314_B6: 315 test edx, edx 316 je _B8 317 mov ecx, [edx] 318 xor ecx, eax 319 or ecx, [4+edx] 320 je _B7 321 mov edx, DWORD [12+edx] 322 jmp _B6 323_B7: 324 mov edx, [8+edx] 325 ;hash_table insert 326 mov ebx, [hash_table-8+edi] 327 mov ecx, [hash_table-4+edi] 328 mov [hash_table-8+edi], eax 329 mov [hash_table-4+edi], edx 330 mov [hash_table+edi], ebx 331 mov [hash_table+4+edi], ecx 332 jmp edx 333_B8: 334 mov edi, eax 335 and edi, 0FFFFFFF8h 336 inc edi 337 pusha 338 call new_recompile_block 339 test eax, eax 340 popa 341 je dyna_linker_ds 342 ;pagefault 343 and eax, 0FFFFFFF8h 344 mov ecx, 080000008h ;High bit set indicates pagefault in delay slot 345 mov ebx, eax 346 sub eax, 4 347 jmp exec_pagefault 348 349jump_vaddr_eax: 350 mov edi, eax 351 jmp jump_vaddr_edi 352 353jump_vaddr_ecx: 354 mov edi, ecx 355 jmp jump_vaddr_edi 356 357jump_vaddr_edx: 358 mov edi, edx 359 jmp jump_vaddr_edi 360 361jump_vaddr_ebx: 362 mov edi, ebx 363 jmp jump_vaddr_edi 364 365jump_vaddr_ebp: 366 mov edi, ebp 367 368jump_vaddr_edi: 369 mov eax, edi 370 371jump_vaddr: 372 ;Check hash table 373 shr eax, 16 374 xor eax, edi 375 movzx eax, ax 376 shl eax, 4 377 cmp edi, [hash_table+eax] 378 jne _C2 379_C1: 380 mov edi, [hash_table+4+eax] 381 jmp edi 382_C2: 383 cmp edi, [hash_table+8+eax] 384 lea eax, [8+eax] 385 je _C1 386 ;No hit on hash table, call compiler 387 add esp, -12 388 push edi 389 mov [cycle_count], esi ;CCREG 390 call get_addr 391 mov esi, [cycle_count] 392 add esp, 16 393 jmp eax 394 395verify_code_ds: 396 mov [branch_target], ebp 397 398verify_code_vm: 399 ;eax = source (virtual address) 400 ;ebx = target 401 ;ecx = length 402 cmp eax, 0C0000000h 403 jl verify_code 404 mov edx, eax 405 lea ebp, [-1+eax+ecx*1] 406 shr edx, 12 407 shr ebp, 12 408 mov edi, [memory_map+edx*4] 409 test edi, edi 410 js _D5 411 lea eax, [eax+edi*4] 412_D1: 413 xor edi, [memory_map+edx*4] 414 shl edi, 2 415 jne _D5 416 mov edi, [memory_map+edx*4] 417 inc edx 418 cmp edx, ebp 419 jbe _D1 420 421verify_code: 422 ;eax = source 423 ;ebx = target 424 ;ecx = length 425 mov edi, [-4+eax+ecx*1] 426 xor edi, [-4+ebx+ecx*1] 427 jne _D5 428 mov edx, ecx 429 add ecx, -4 430 je _D3 431 test edx, 4 432 cmove ecx, edx 433 mov [cycle_count], esi 434_D2: 435 mov edx, [-4+eax+ecx*1] 436 mov ebp, [-4+ebx+ecx*1] 437 mov esi, [-8+eax+ecx*1] 438 xor ebp, edx 439 mov edi, [-8+ebx+ecx*1] 440 jne _D4 441 xor edi, esi 442 jne _D4 443 add ecx, -8 444 jne _D2 445 mov esi, [cycle_count] 446 mov ebp, [branch_target] 447_D3: 448 ret 449_D4: 450 mov esi, [cycle_count] 451_D5: 452 mov ebp, [branch_target] 453 push esi ;for stack alignment, unused 454 push DWORD [8+esp] 455 call get_addr 456 add esp, 16 ;pop stack 457 jmp eax 458 459cc_interrupt: 460 add esi, [last_count] 461 add esp, -28 ;Align stack 462 mov [g_cp0_regs+36], esi ;Count 463 shr esi, 19 464 mov DWORD [pending_exception], 0 465 and esi, 01fch 466 cmp DWORD [restore_candidate+esi], 0 467 jne _E4 468_E1: 469 call gen_interrupt 470 mov esi, [g_cp0_regs+36] 471 mov eax, [next_interrupt] 472 mov ebx, [pending_exception] 473 mov ecx, [stop] 474 add esp, 28 475 mov [last_count], eax 476 sub esi, eax 477 test ecx, ecx 478 jne _E3 479 test ebx, ebx 480 jne _E2 481 ret 482_E2: 483 add esp, -8 484 mov edi, [pcaddr] 485 mov [cycle_count], esi ;CCREG 486 push edi 487 call get_addr_ht 488 mov esi, [cycle_count] 489 add esp, 16 490 jmp eax 491_E3: 492 add esp, 16 ;pop stack 493 pop edi ;restore edi 494 pop esi ;restore esi 495 pop ebx ;restore ebx 496 pop ebp ;restore ebp 497 ret ;exit dynarec 498_E4: 499 ;Move 'dirty' blocks to the 'clean' list 500 mov ebx, DWORD [restore_candidate+esi] 501 mov DWORD [restore_candidate+esi], 0 502 shl esi, 3 503 mov ebp, 0 504_E5: 505 shr ebx, 1 506 jnc _E6 507 mov ecx, esi 508 add ecx, ebp 509 push ecx 510 call clean_blocks 511 pop ecx 512_E6: 513 inc ebp 514 test ebp, 31 515 jne _E5 516 jmp _E1 517 518do_interrupt: 519 mov edi, [pcaddr] 520 add esp, -12 521 push edi 522 call get_addr_ht 523 add esp, 16 524 mov esi, [g_cp0_regs+36] 525 mov ebx, [next_interrupt] 526 mov [last_count], ebx 527 sub esi, ebx 528 add esi, 2 529 jmp eax 530 531fp_exception: 532 mov edx, 01000002ch 533_E7: 534 mov ebx, [g_cp0_regs+48] 535 add esp, -12 536 or ebx, 2 537 mov [g_cp0_regs+48], ebx ;Status 538 mov [g_cp0_regs+52], edx ;Cause 539 mov [g_cp0_regs+56], eax ;EPC 540 push 080000180h 541 call get_addr_ht 542 add esp, 16 543 jmp eax 544 545fp_exception_ds: 546 mov edx, 09000002ch ;Set high bit if delay slot 547 jmp _E7 548 549jump_syscall: 550 mov edx, 020h 551 mov ebx, [g_cp0_regs+48] 552 add esp, -12 553 or ebx, 2 554 mov [g_cp0_regs+48], ebx ;Status 555 mov [g_cp0_regs+52], edx ;Cause 556 mov [g_cp0_regs+56], eax ;EPC 557 push 080000180h 558 call get_addr_ht 559 add esp, 16 560 jmp eax 561 562jump_eret: 563 mov ebx, [g_cp0_regs+48] ;Status 564 add esi, [last_count] 565 and ebx, 0FFFFFFFDh 566 mov [g_cp0_regs+36], esi ;Count 567 mov [g_cp0_regs+48], ebx ;Status 568 call check_interrupt 569 mov eax, [next_interrupt] 570 mov esi, [g_cp0_regs+36] 571 mov [last_count], eax 572 sub esi, eax 573 mov eax, [g_cp0_regs+56] ;EPC 574 jns _E11 575_E8: 576 mov ebx, 248 577 xor edi, edi 578_E9: 579 mov ecx, [reg+ebx] 580 mov edx, [reg+4+ebx] 581 sar ecx, 31 582 xor edx, ecx 583 neg edx 584 adc edi, edi 585 sub ebx, 8 586 jne _E9 587 mov ecx, [hi+ebx] 588 mov edx, [hi+4+ebx] 589 sar ecx, 31 590 xor edx, ecx 591 jne _E10 592 mov ecx, [lo+ebx] 593 mov edx, [lo+4+ebx] 594 sar ecx, 31 595 xor edx, ecx 596_E10: 597 neg edx 598 adc edi, edi 599 add esp, -8 600 push edi 601 push eax 602 mov [cycle_count], esi 603 call get_addr_32 604 mov esi, [cycle_count] 605 add esp, 16 606 jmp eax 607_E11: 608 mov [pcaddr], eax 609 call cc_interrupt 610 mov eax, [pcaddr] 611 jmp _E8 612 613new_dyna_start: 614 push ebp 615 push ebx 616 push esi 617 push edi 618 add esp, -8 ;align stack 619 push 0a4000040h 620 call new_recompile_block 621 mov edi, DWORD [next_interrupt] 622 mov esi, DWORD [g_cp0_regs+36] 623 mov DWORD [last_count], edi 624 sub esi, edi 625 jmp DWORD [base_addr] 626 627invalidate_block_eax: 628 push eax 629 push ecx 630 push edx 631 push eax 632 jmp invalidate_block_call 633 634invalidate_block_ecx: 635 push eax 636 push ecx 637 push edx 638 push ecx 639 jmp invalidate_block_call 640 641invalidate_block_edx: 642 push eax 643 push ecx 644 push edx 645 push edx 646 jmp invalidate_block_call 647 648invalidate_block_ebx: 649 push eax 650 push ecx 651 push edx 652 push ebx 653 jmp invalidate_block_call 654 655invalidate_block_ebp: 656 push eax 657 push ecx 658 push edx 659 push ebp 660 jmp invalidate_block_call 661 662invalidate_block_esi: 663 push eax 664 push ecx 665 push edx 666 push esi 667 jmp invalidate_block_call 668 669invalidate_block_edi: 670 push eax 671 push ecx 672 push edx 673 push edi 674 675invalidate_block_call: 676 call invalidate_block 677 pop eax ;Throw away 678 pop edx 679 pop ecx 680 pop eax 681 ret 682 683write_rdram_new: 684 mov edi, [address] 685 mov ecx, [cpu_word] 686 mov [g_rdram-0x80000000+edi], ecx 687 jmp _E12 688 689write_rdramb_new: 690 mov edi, [address] 691 xor edi, 3 692 mov cl, BYTE [cpu_byte] 693 mov BYTE [g_rdram-0x80000000+edi], cl 694 jmp _E12 695 696write_rdramh_new: 697 mov edi, [address] 698 xor edi, 2 699 mov cx, WORD [cpu_hword] 700 mov WORD [g_rdram-0x80000000+edi], cx 701 jmp _E12 702 703write_rdramd_new: 704 mov edi, [address] 705 mov ecx, [cpu_dword+4] 706 mov edx, [cpu_dword+0] 707 mov [g_rdram-0x80000000+edi], ecx 708 mov [g_rdram-0x80000000+4+edi], edx 709 jmp _E12 710 711 712do_invalidate: 713 mov edi, [address] 714 mov ebx, edi ;Return ebx to caller 715_E12: 716 shr edi, 12 717 cmp BYTE [invalid_code+edi], 1 718 je _E13 719 push edi 720 call invalidate_block 721 pop edi 722_E13: 723 ret 724 725read_nomem_new: 726 mov edi, [address] 727 mov ebx, edi 728 shr edi, 12 729 mov edi, [memory_map+edi*4] 730 mov eax, 00h 731 test edi, edi 732 js tlb_exception 733 mov ecx, [ebx+edi*4] 734 mov [readmem_dword], ecx 735 ret 736 737read_nomemb_new: 738 mov edi, [address] 739 mov ebx, edi 740 shr edi, 12 741 mov edi, [memory_map+edi*4] 742 mov eax, 00h 743 test edi, edi 744 js tlb_exception 745 xor ebx, 3 746 movzx ecx, BYTE [ebx+edi*4] 747 mov [readmem_dword], ecx 748 ret 749 750read_nomemh_new: 751 mov edi, [address] 752 mov ebx, edi 753 shr edi, 12 754 mov edi, [memory_map+edi*4] 755 mov eax, 00h 756 test edi, edi 757 js tlb_exception 758 xor ebx, 2 759 movzx ecx, WORD [ebx+edi*4] 760 mov [readmem_dword], ecx 761 ret 762 763read_nomemd_new: 764 mov edi, [address] 765 mov ebx, edi 766 shr edi, 12 767 mov edi, [memory_map+edi*4] 768 mov eax, 00h 769 test edi, edi 770 js tlb_exception 771 mov ecx, [4+ebx+edi*4] 772 mov edx, [ebx+edi*4] 773 mov [readmem_dword], ecx 774 mov [readmem_dword+4], edx 775 ret 776 777write_nomem_new: 778 call do_invalidate 779 mov edi, [memory_map+edi*4] 780 mov ecx, [cpu_word] 781 mov eax, 01h 782 shl edi, 2 783 jc tlb_exception 784 mov [ebx+edi], ecx 785 ret 786 787write_nomemb_new: 788 call do_invalidate 789 mov edi, [memory_map+edi*4] 790 mov cl, BYTE [cpu_byte] 791 mov eax, 01h 792 shl edi, 2 793 jc tlb_exception 794 xor ebx, 3 795 mov BYTE [ebx+edi], cl 796 ret 797 798write_nomemh_new: 799 call do_invalidate 800 mov edi, [memory_map+edi*4] 801 mov cx, WORD [cpu_hword] 802 mov eax, 01h 803 shl edi, 2 804 jc tlb_exception 805 xor ebx, 2 806 mov WORD [ebx+edi], cx 807 ret 808 809write_nomemd_new: 810 call do_invalidate 811 mov edi, [memory_map+edi*4] 812 mov edx, [cpu_dword+4] 813 mov ecx, [cpu_dword+0] 814 mov eax, 01h 815 shl edi, 2 816 jc tlb_exception 817 mov [ebx+edi], edx 818 mov [4+ebx+edi], ecx 819 ret 820 821write_mi_new: 822 mov ebx, [024h+esp] 823 add ebx, 4 824 mov [pcaddr], ebx 825 mov DWORD [pending_exception], 0 826 call write_mi 827 mov ebx, [pending_exception] 828 test ebx, ebx 829 jne mi_exception 830 ret 831 832write_mib_new: 833 mov ebx, [024h+esp] 834 add ebx, 4 835 mov [pcaddr], ebx 836 mov DWORD [pending_exception], 0 837 call write_mib 838 mov ebx, [pending_exception] 839 test ebx, ebx 840 jne mi_exception 841 ret 842 843write_mih_new: 844 mov ebx, [024h+esp] 845 add ebx, 4 846 mov [pcaddr], ebx 847 mov DWORD [pending_exception], 0 848 call write_mih 849 mov ebx, [pending_exception] 850 test ebx, ebx 851 jne mi_exception 852 ret 853 854write_mid_new: 855 mov ebx, [024h+esp] 856 add ebx, 4 857 mov [pcaddr], ebx 858 mov DWORD [pending_exception], 0 859 call write_mid 860 mov ebx, [pending_exception] 861 test ebx, ebx 862 jne mi_exception 863 ret 864 865mi_exception: 866 ;ebx = mem addr 867 ;ebp = instr addr + flags 868 mov ebp, [024h+esp] 869 mov ebx, [address] 870 add esp, 024h 871 call wb_base_reg 872 jmp do_interrupt 873 874tlb_exception: 875 ;eax = r/w 876 ;ebx = mem addr 877 ;ebp = instr addr + flags 878 mov ebp, [024h+esp] 879 add esp, 024h 880 call wb_base_reg 881 add esp, -4 882 push eax 883 push ebx 884 push ebp 885 call TLB_refill_exception_new 886 add esp, 16 887 mov edi, DWORD [next_interrupt] 888 mov esi, DWORD [g_cp0_regs+36] ;Count 889 mov DWORD [last_count], edi 890 sub esi, edi 891 jmp eax 892 893wb_base_reg: 894 ;ebx = address 895 ;ebp = instr addr + flags 896 mov ecx, ebp 897 mov edx, ebp 898 shr ecx, 12 899 and edx, 0FFFFFFFCh 900 mov ecx, [memory_map+ecx*4] 901 mov ecx, [edx+ecx*4] 902 mov edx, 06000022h 903 mov edi, ecx 904 movsx esi, cx 905 shr ecx, 26 906 shr edi, 21 907 sub ebx, esi 908 add esi, ebx 909 and edi, 01fh 910 rcr edx, cl 911 cmovc ebx, [reg+edi*8] 912 mov [reg+edi*8], ebx 913 sar ebx, 31 914 test ebp, 2 915 cmove ebx, [reg+4+edi*8] 916 mov [reg+4+edi*8], ebx 917 mov ebx, esi 918 ret 919 920breakpoint: 921 int 3 922 ret 923