2134 Commits
Author SHA1 Message Date
ptitSeb f7630dec30 Bumped to v0.1.2 2020-08-14 10:04:55 +02:00
ptitSeb 031f41a333 Added build info (time and date) and git hash tag, rebuilt at each build 2020-08-14 10:03:32 +02:00
ptitSeb d18eb1c9c5 Added version and help options to box86 2020-08-14 09:13:12 +02:00
ptitSeb a666619de7 Added 0F BA /7 BTC opcode 2020-08-13 19:31:21 +02:00
ptitSeb a6d55175ac Added 0E PUSH CS opcode 2020-08-13 19:17:31 +02:00
ptitSeb b33d952b47 [DYNAREC] Some minor changes to emit_cmp16 2020-08-13 18:13:44 +02:00
ptitSeb 65fc0f36e7 [DYNAREC] Added 0F E8 PSUBSB and 0F E9 PSUBSW opcodes 2020-08-13 16:31:09 +02:00
ptitSeb 4bb743bde0 [DYNAREC] Fixed emit_sub16c (fixed sound in DeusEx) 2020-08-13 16:20:33 +02:00
ptitSeb 1b8f92249d [DYNAREC] Minor changes, to avoid potential BUSERROR mainly 2020-08-13 16:18:46 +02:00
ptitSeb 42838834f6 [DYNAREC] More log info on Unimplemented opcode 2020-08-13 16:18:13 +02:00
ptitSeb 83508fa322 Added F1 INT1 dummy opcode 2020-08-12 18:05:28 +02:00
ptitSeb 044d667b9e Added GL_EXT_multisampled_render_to_texture wrapped functions to libGL 2020-08-12 16:58:11 +02:00
ptitSeb 97274871c8 Protect memory only if Dynarec is used 2020-08-12 16:29:31 +02:00
ptitSeb e5fabc828c [DYNAREC] Added utility function to get dynarecblock from arm native dynarec address (and used it in SegFault handler) 2020-08-12 14:01:52 +02:00
ptitSeb e5601cb09c [DYNAREC] Made 81 /7 CMP Ed, Id opcode resiliant to SMC (fixes DeusEx, maybe other too) 2020-08-12 13:58:05 +02:00
ptitSeb 6f87bd8570 Added 67 E8 xx opcode (should help #179 too) 2020-08-11 17:41:04 +02:00
ptitSeb b393923c6e Added 65 2B SUB Gd, GS:Ed and 65 03 ADD Gd, GS:Ed opcode ([DYNAREC] too) (should help #179) 2020-08-11 16:54:00 +02:00
ptitSeb 37ab148df6 Simplified a bit ResolveFile utility function 2020-08-11 13:58:37 +02:00
ptitSeb 2f977f200b Added libcurl-gnutls.so.4 as a synonym a libcurl.so.4 2020-08-11 11:18:15 +02:00
ptitSeb e674f1a528 Changed PltResolver, to be inject in PLT.GOT instead of GOT.PLT before GOT (fixes Don't Starve) 2020-08-11 11:17:28 +02:00
ptitSeb fc93d47b14 Removed some useless code in wrapped glib2 lib 2020-08-10 18:55:50 +02:00
ptitSeb 3028d096b9 Merge pull request #178 from rajdakin/makefix
x86 build fix
2020-08-10 16:52:19 +02:00
rajdakin e7313a4df4 [BOX86] Fixed multiple non-extern definitions (x86 build) 2020-08-10 16:49:24 +02:00
rajdakin 31af5ec181 [LIBTOOLS] Fixed x86 builds (__i386 is defined, not __x86__) 2020-08-10 16:48:13 +02:00
ptitSeb 98222c75c2 Merge pull request #177 from rajdakin/VMOVinsn_fix
[DYNAREC] Fixed the four VMOV VFPU instructions printer
2020-08-10 16:35:51 +02:00
rajdakin d0380eccf7 [DYNAREC] Fixed the four VMOV VFPU instructions printer 2020-08-10 16:28:03 +02:00
ptitSeb f570ee0ea2 Fixed nanoslepp that was broken with last commit 2020-08-09 15:38:43 +02:00
ptitSeb 6ac716b8ba Update README.md 2020-08-09 10:10:22 +02:00
ptitSeb e8a080f5c0 Added COLOR_PAIRS to ncurses* (help Dwarf Fortress in text mode) 2020-08-08 17:45:53 +02:00
ptitSeb 67237e54f9 Added some workaround for nanosleep with null parameter 2020-08-08 17:20:29 +02:00
ptitSeb 4acf0f080e refactored CPUID opcode, and added a few more SubCommand (80000001..80000005) 2020-08-08 11:23:09 +02:00
ptitSeb 8e576f3f7d Merge pull request #176 from spacepilotAV/patch-1
Fix spelling of surprisingly in README.md
2020-08-07 19:32:10 +02:00
ra1n 037859b007 Fix spelling of surprisingly in README.md
speeling is important guys ;)
2020-08-07 13:14:39 -04:00
ptitSeb e81e7c7ebd Allow the use of #ifndef in wrapper _private headers 2020-08-07 15:45:17 +02:00
ptitSeb a50079b920 Better wrapping of g_variant_new_va (should help #167) 2020-08-07 15:43:48 +02:00
ptitSeb 4a38d8199f Merge pull request #175 from truboxl/patch-1
Make test10 more robust
2020-08-06 12:38:27 +02:00
Jia Yuan Lo 4dd9337528 Make test10 more robust
Test10 currently only passes after "make install" (no regard to x86lib directory needed) or we build directly inside box86 folder.
This change make sure x86lib folder is properly located so that we can also "ctest" inside build folder after compile without "make install".

Signed-off-by: Jia Yuan Lo <[email protected]>
2020-08-06 18:22:01 +08:00
ptitSeb c6db07039f Merge pull request #174 from Icenowy/fld-double-sigbus
[DYNAREC] Avoid SIGBUS on FLD double
2020-08-06 09:57:43 +02:00
Icenowy Zheng 9294b59aae [DYNAREC] Avoid SIGBUS on FLD double
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-06 05:53:11 +08:00
ptitSeb 490f595d6d [DYNAREC] Avoid BUSERROR on 0F 7F MOVQ (should help #167) 2020-08-05 18:52:12 +02:00
ptitSeb 67af7a0baf [DYNAREC] Fixed freeze issue introduce with previous commit 2020-08-05 15:10:00 +02:00
ptitSeb 7da89748bb [DYNAREC] Small change on nolinker block handling (when son is outside the range of the parent) 2020-08-05 12:02:15 +02:00
ptitSeb 72a82ebece [DYNAREC] Reordered the cleaning of dynablocks / dynablocks list to avoid segfault 2020-08-05 11:17:21 +02:00
ptitSeb 12e44a3e62 Merge pull request #173 from Icenowy/blocks_hashmap_check
check whether blocks hashmap exists when removing block from it
2020-08-05 10:01:30 +02:00
Icenowy Zheng 5dd94df9dd check whether blocks hashmap exists when removing block from it
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-05 15:57:23 +08:00
ptitSeb 79051e04b4 Merge pull request #172 from Icenowy/dynablock_mark_foreach_fix
dynablock: do not access value when foreach on marks
2020-08-05 09:46:40 +02:00
ptitSeb 02a0a77bda Merge pull request #170 from Icenowy/sdl_tolowerupper
wrap SDL_to{lower,upper}
2020-08-05 09:39:33 +02:00
Icenowy Zheng b3c5115707 dynablock: do not access value when foreach on marks
Accessing the value of a kh_set (which has no values set) is an
undefined behavior, which may make monsters to appear.

Add a kh_foreach_key macro that do not touch values at all, and use it
when ennuerating marks in dynablock, to prevent SIGSEGV of accessing
non-existent values.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-05 15:26:55 +08:00
Icenowy Zheng e069681cfd wrap SDL_to{lower,upper}
These are very simple function that accepts an int and returns an int.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-05 15:00:30 +08:00
ptitSeb c93356fb1a Deactivated Segment optim for GS (should help #167) 2020-08-04 16:19:56 +02:00
ptitSeb c398c938e1 Added F2/F2 18..1D opcode (F2/F3 ignored) 2020-08-04 15:43:20 +02:00
ptitSeb f3c6dc31ac Added 66 36 prefix (and fixed 66 2E and 66 26 prefixes) 2020-08-04 15:28:44 +02:00
ptitSeb 06403425f9 Merge pull request #166 from Icenowy/ld_library_path_prepend
prepending LD_LIBRARY_PATH
2020-08-04 10:25:30 +02:00
ptitSeb a9fa9095d5 Merge pull request #165 from Icenowy/g_utf8_skip
wrap g_utf8_skip in glib, which is a pointer to an array of char
2020-08-04 09:40:17 +02:00
Icenowy Zheng 617eacfcd3 prepending LD_LIBRARY_PATH
LD_LIBRARY_PATH should be able to override system libraries, this is the
behavior of ld-linux.so.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-04 04:34:54 +08:00
Icenowy Zheng 7ba89639da wrap g_utf8_skip in glib, which is a pointer to an array of char
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-04 02:14:05 +08:00
ptitSeb 2914ed358e [DYNAREC] Don't allocate Direct Dynablock on mmap 2020-08-03 00:10:17 +02:00
ptitSeb 72041b6873 Make bridges allocate larger chunk 2020-08-03 00:09:41 +02:00
ptitSeb bf8da23a76 Added SS_ONSTACK fake handling to sigaltstack, so Unity game don't assert at start 2020-08-02 20:06:34 +02:00
ptitSeb f3f3d9cdfe Some small fixes to Segment offset cache mecanism 2020-08-02 19:57:43 +02:00
ptitSeb 05c7d8fec9 Use a Cache (per thread) of Segment Offset, to sppedup GS: and FS: access 2020-08-02 16:04:27 +02:00
ptitSeb 5201aeffa6 [DYNAREC] Small optim in GetDynablocksFromAddress, starting with fast getDBFromAddress before looking içnto elf memory 2020-08-02 16:03:55 +02:00
ptitSeb 2fba190d8b [DYNAREC] Improved son creation for large dynablock (or block near end of dynablocklist) by allow the use of a different dynablocklist parent 2020-08-02 14:17:54 +02:00
ptitSeb 9e669ad06b [DYNAREC] Added 66 F2/F3 A7 REP(N)Z CMPSW and 66 F2/F3 AF REP(N)Z SCASW 2020-08-02 14:16:36 +02:00
ptitSeb 7f66be599c [DYNAREC] Added D9 /4 FLDENV Ed opcode 2020-08-02 13:55:36 +02:00
ptitSeb 7d1f429ead [DYNAREC] Added 66 91..97 XCHG AX, reg opcode 2020-08-02 13:55:07 +02:00
ptitSeb 4e602abfcb Try to improve (and fix) obstack wrapping (should help #160) 2020-08-02 10:08:05 +02:00
ptitSeb aad016d418 Merge pull request #163 from Icenowy/obstack_free
Add an automatic wrapper for {,_}obstack_free
2020-08-01 22:12:25 +02:00
Icenowy Zheng 3544428e18 Add an automatic wrapper for {,_}obstack_free
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-02 04:07:29 +08:00
ptitSeb 459c3ef530 Various small x87 adjustments 2020-08-01 17:58:09 +02:00
ptitSeb a01f5b1f3f [DYNAREC] Added a warning when a son have no code 2020-08-01 17:57:52 +02:00
ptitSeb 9183391ab0 Forgot the EXPORT for my__obstack_begin (should help #160) 2020-08-01 17:56:51 +02:00
ptitSeb c22ca077ba [DYNAREC] Added CF IRET opcode 2020-08-01 15:11:17 +02:00
ptitSeb 63c224b073 Ajusted D9 F5 FPREM1 opcode 2020-08-01 14:07:48 +02:00
ptitSeb f36567593a Added _obstack_begin wrapped function to libc (for #160) 2020-07-31 18:11:10 +02:00
ptitSeb b2efee99fa Merge pull request #159 from Icenowy/main-fix
Fix compliation of non-dynarec build
2020-07-30 20:39:27 +02:00
Icenowy Zheng 6510dc9e45 Fix compliation of non-dynarec build
sysconf() is part of unistd.h, and src/main.c uses it. However, this
source code file only includes <unistd.h> when DYNAREC, makes
non-dynarec build fail for missing _SC_PAGESIZE macro.

Move the inclusion of <unistd.h> out of #ifdef DYNAREC.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-07-31 01:55:06 +08:00
ptitSeb 213beed360 Merge branch 'master' of https://github.com/ptitSeb/box86 2020-07-29 17:24:13 +02:00
ptitSeb 801f374a66 Added a workaround to get wine run under interpretor only 2020-07-29 17:23:51 +02:00
ptitSeb 7f3eecec4c Merge pull request #157 from icecream95/cmsg
Add a wrapped function for __cmsg_nxthdr
2020-07-29 13:16:40 +02:00
Icecream95 bd92f64df9 Add a wrapped function for __cmsg_nxthdr 2020-07-29 22:55:02 +12:00
ptitSeb ab2617c20f [DYNAREC] This +1 was not needed, end is alread aligned and all 2020-07-29 08:00:39 +02:00
ptitSeb cd958240df [DYNAREC] More small change on memory protection scheme 2020-07-28 17:34:06 +02:00
ptitSeb 4254a2a2f7 Small change to vfprintf wrapped function 2020-07-28 16:57:38 +02:00
ptitSeb 9735f21f65 [DYNAREC] Some more small fixes on memory protection scheme 2020-07-28 13:25:59 +02:00
ptitSeb 62343cbb77 Made bridge structure slightly bigger so it align 2020-07-28 13:24:46 +02:00
ptitSeb 23eca257f4 Merge pull request #156 from Newbytee/patch-1
Language fixup in README
2020-07-27 15:41:02 +02:00
Newbyte 5a3c17e831 Language fixup in README
I did some language fixes in README. During this I took some liberties to improve consistently, like always writing Box86 with a capital B. I am not sure whether you have a preferred way to stylise it, but as it is prior to this PR the README mixes box86 and Box86 heavily, and I decided to go with the latter. If you prefer it to always be written box86 with a lowercase b I can change it to be so.
2020-07-27 15:11:05 +02:00
ptitSeb de1bb7e438 Improved internal path resolution (should help #154) 2020-07-27 10:03:56 +02:00
ptitSeb 6216d06d0e [DYNAREC] Fine-tuned, again, how cleanDBFromAddressRange worked 2020-07-27 09:03:13 +02:00
ptitSeb cb03a51d40 [DYNAREC] Fixed a crash in later dynarec log level 2020-07-27 09:01:41 +02:00
ptitSeb 09a65a622a [DYNAREC] Small change in protection of dynarec volatile block, with a better detection of start address to scan 2020-07-26 20:42:25 +02:00
ptitSeb 95f6ce1f3e Fixed a potentiel read isse with execv method 2020-07-25 16:48:38 +02:00
ptitSeb 7ede988cb1 Added 64 67 A3 xx xx MOV FS:[Ov], EAX 2020-07-24 15:32:52 +02:00
ptitSeb a06e05dc9e Added 64 67 89 MOV FS:ED16,GD opcode 2020-07-23 10:13:27 +02:00
ptitSeb 2a3c6dc55c Added 6E/6F OUTSB/OUTSD (faked) opcode 2020-07-23 10:12:13 +02:00
ptitSeb 814701324c Added F2/F3 66 A7 REP(N)Z CMPSW 2020-07-22 15:41:43 +02:00
ptitSeb 01fea9ce3f Checked all wrapped function used by ntdlls.so, fixing some of them 2020-07-21 08:06:39 +02:00
ptitSeb da5e795858 [DYNAREC] Disable the use of SWP arm opcode for XCHG x86 opcode, while the 8bit verison seems ok, the 32bits is not 2020-07-20 08:30:52 +02:00
ptitSeb b491241307 Added 64 67 FF /6 PUSH FS:[Ed16] opcode 2020-07-20 08:29:40 +02:00
ptitSeb 81f6e87416 Fixed glXCreatePbuffer wrapped function signature 2020-07-19 23:20:06 +02:00
ptitSeb 20a680561a Added wrapped libncurses.so.6 and libtsinfo.so.6 (based on .5 version) 2020-07-19 18:21:45 +02:00
ptitSeb a4f2a19505 Added EC INSB AL, DX 2020-07-18 12:47:32 +02:00
ptitSeb a263283c93 Added 16 PUSH SS and 17 POP SS opcodes 2020-07-17 20:36:41 +02:00
ptitSeb ac2cdc65a8 Added a few off opcodes 2020-07-17 16:08:37 +02:00
ptitSeb c1b7740ac4 Added 66 91..97 XCHG AX, Reg opcodes 2020-07-17 08:21:57 +02:00
ptitSeb a1c8868159 Added 66 60 and 66 61 PUSHA POPA opcodes 2020-07-16 21:38:05 +02:00
ptitSeb a157acd185 Added 64 67 A1 xx xx opcode 2020-07-16 20:19:32 +02:00
ptitSeb 12ec1309bb Added option to disable the hack to force X11 GLX Extension beeing detected (help wine stuff while gl4es is not uet compatible) 2020-07-16 09:22:37 +02:00
ptitSeb 042d55f734 Added 66 F3 A4 (alt) MOV SB ([DYNAREC] too) 2020-07-16 08:17:21 +02:00
ptitSeb 67f8c6df42 Added F2/F3 40..4F (alt)INC/DEC reg opcode 2020-07-15 20:38:15 +02:00
ptitSeb c9d6c72fe0 Added 0F F7 MASKMOVQ opcode 2020-07-15 15:41:08 +02:00
ptitSeb e5fcadae30 Fixed signature for XGetAtomNames wrapped function 2020-07-15 13:42:00 +02:00
ptitSeb cb0ee7990a Added a workaround to ignore failed test of GLX extension in X11 2020-07-15 13:33:14 +02:00
ptitSeb 0eea4c5913 Added 0F E7 MOVNTQ opcode ([DYNAREC] too) 2020-07-15 09:14:36 +02:00
ptitSeb 5a8466b0d7 Fix compilation for non-dynarec build 2020-07-15 08:36:46 +02:00
ptitSeb 372d811f66 Added 65 8A MOV Gb, GS:Eb 2020-07-14 23:48:13 +02:00
ptitSeb ff2027846b [DYNAREC] Fixed issue when dlclose then dlopen a library 2020-07-14 20:26:37 +02:00
ptitSeb 8318eb1a0d Added 0F BA /5 BTS Ed, Ib opcode 2020-07-14 19:20:31 +02:00
ptitSeb 57c0751793 Added 66 FF /6 PUSH Ed opcode 2020-07-14 19:19:58 +02:00
ptitSeb 86b00ef7fe Added 66 9D POPF opcode 2020-07-14 18:59:56 +02:00
ptitSeb 6e12a556ec Fixed a warning 2020-07-14 18:06:01 +02:00
ptitSeb fba165d121 Added 64 67 8B opcode 2020-07-14 18:05:40 +02:00
ptitSeb 68d77636b0 Changed again a bit the destruction sequence for box86context 2020-07-14 14:37:11 +02:00
ptitSeb 394d46f731 Added 66 0F BA BTR opcode 2020-07-14 14:36:44 +02:00
ptitSeb 702a9f6aa5 Added dummy 0F 00 VERR/VERW and 0F EA PMAXSW opcode 2020-07-14 13:48:41 +02:00
ptitSeb 7ae3813ac5 Set my_context to NULL when context is beeing destroyed 2020-07-14 12:13:55 +02:00
ptitSeb 34a933af0b Try to get more info on segfault (not sure it's a good idea) 2020-07-14 12:13:22 +02:00
ptitSeb 4ac5d6df7f Added 36 SS: (ignored) prefix ([DYNAREC] too) 2020-07-14 11:29:52 +02:00
ptitSeb 0260548d9c Fixed a few glX wrapped functions 2020-07-14 11:29:22 +02:00
ptitSeb 5b64623f50 [DYNAREC] Fix a potential crash when a volite dynablock is 0 len 2020-07-14 10:18:29 +02:00
ptitSeb 233e472503 Added 0F EA PMINSW Gm, Em opcode 2020-07-14 09:58:36 +02:00
ptitSeb 335512e96a Added fake 62 BOUND GD, Ed opcode ([DYNAREC] too) 2020-07-14 09:47:13 +02:00
ptitSeb d451a3fdd7 Added 64 3B CMP Gd,FS:Ed ([DYNAREC] too) 2020-07-14 09:13:50 +02:00
ptitSeb 499de4fd60 Oops, forgot to remove some debug code 2020-07-13 21:05:18 +02:00
ptitSeb caf9abc16f Added also F2/F3 E9 opcode ([DYNAREC] too) 2020-07-13 19:12:35 +02:00
ptitSeb 5dfce69c37 Added F2/F3 E8 opcode ([DYNAREC] too) 2020-07-13 19:04:03 +02:00
ptitSeb 8f12829e95 Added some more wrapper to opengl 2020-07-13 18:23:13 +02:00
ptitSeb 15a42f5407 Added some wine prereserve mecanism 2020-07-13 17:38:45 +02:00
ptitSeb c8cdd3f432 [DYNAREC] Added F2/F3 66 AF REP(N)Z SCASW opcode 2020-07-13 17:38:19 +02:00
ptitSeb ac7c72396d Added F2/F3 66 AF REP(N)Z SCASW opcode 2020-07-13 17:37:43 +02:00
ptitSeb ce3271f095 Fixed some case of bad error with mmap / mmap64, plus improve trace of it 2020-07-13 17:36:32 +02:00
ptitSeb 3ff4b04e52 [DYNAREC] More alignment fixes 2020-07-13 17:35:05 +02:00
ptitSeb ecd90a41d5 [DYNAREC] Try to avoid some SIGBUS on DC xx opcodes 2020-07-13 14:50:58 +02:00
ptitSeb 87695cf84b [DYNAREC] Try to avoid potention SIGBUS on some F2 0F xx opcodes 2020-07-13 14:32:12 +02:00
ptitSeb 3bb93e1fd9 Added F2 0F 7C HADDPS opcode ([DYNAREC] too) 2020-07-13 11:30:24 +02:00
ptitSeb 69279b2233 Added D9 F6 FDECSTP and D9 F7 FINCSTP opcodes 2020-07-13 10:54:46 +02:00
ptitSeb 7c811666fe Added 0F A0/A1/A8/A9 PUSH/POP FS/GS opcodes ([DYNAREC] too) 2020-07-13 10:43:49 +02:00
ptitSeb 9a18dd3718 Added 0F D7 PMOVMSKB opcode ([DYNAREC] too) 2020-07-12 15:03:06 +02:00
ptitSeb 3338d26aaa Add 2 more wrapped function to libpulse 2020-07-12 12:38:58 +02:00
ptitSeb 167ea1587e Chnaged a bit signals debug 2020-07-12 12:38:31 +02:00
ptitSeb 7ad6399940 Added workaround for _finite function not always present in libm, using regular function as fallback (should help #138) 2020-07-12 10:39:03 +02:00
ptitSeb 71db6b3275 Some changes to the interpretor to ensure R_EIP is always correct 2020-07-11 18:12:03 +02:00
ptitSeb 00626b9f3e Fixed an issue with FS: access (or any other custom selector) 2020-07-11 16:11:48 +02:00
ptitSeb d0fa79c9ca [DYNAREC] Fixed PUSH FS:Ed opcode 2020-07-11 15:54:10 +02:00
ptitSeb fc1f75c3f6 [DYNAREC] Added 2 segment related opcodes 2020-07-11 15:17:15 +02:00
ptitSeb 21b9676093 Added some wrapped function to libusb-1.0 2020-07-11 14:38:36 +02:00
ptitSeb ea2a7204df Forgot that fix for libpng12 2020-07-11 14:38:10 +02:00
ptitSeb bcdd09a2e6 Removed dup'd function in wrapped libpng16 2020-07-11 14:28:37 +02:00
ptitSeb 7c394ddeee Show args for emulated program on BOX86_LOG=1 at start 2020-07-11 13:57:23 +02:00
ptitSeb 50d7e2d1d7 Some fixes to wrapped libpng16 and libpng12 2020-07-11 13:55:10 +02:00
ptitSeb 395cecb082 More change on signal handler. Still not complete enough 2020-07-10 20:46:20 +02:00
ptitSeb c8888915d7 [DYNAREC] Very small optim on CALL Ed opcode 2020-07-09 22:13:00 +02:00
ptitSeb 38740ce1c9 [DYNAREC] Try to avoid a segfault, bad mix with PltResolver that can hapens (should help #145) 2020-07-08 22:46:43 +02:00
ptitSeb 73b893215e [DYNAREC] Added FSAVE and FRSTOR opcode 2020-07-08 22:45:58 +02:00
ptitSeb e93c3f0028 Added option to have different trace per pid (to avoid overwritting when multiple process are spawning) 2020-07-08 18:21:49 +02:00
ptitSeb be2e35381e Removed a dupe in wrapped lib xrender 2020-07-08 16:46:57 +02:00
ptitSeb c79f59c86f Added one more wrapped function to libxi 2020-07-08 16:30:10 +02:00
ptitSeb 6f02d5f2c4 Added more gnutls wrapped functions 2020-07-08 16:23:40 +02:00
ptitSeb 969bd84f1d Added more FreeType wrapped functions 2020-07-08 15:36:20 +02:00
ptitSeb 8865b7bfec Added wrapped libgnutls (with some wrapped functions) 2020-07-08 15:15:11 +02:00
ptitSeb f60ecc3626 Added more wrapped function to libpng16 2020-07-08 14:10:36 +02:00
ptitSeb 824b230bd0 Added some support for modify_ldt syscall, but pretty useless whle 16bits is not supported 2020-07-08 13:38:13 +02:00
ptitSeb 71a208334d [DYNAREC] Changed a bit what PUSH/POP DS/ES emit (more in line with PUSH/POP reg) 2020-07-08 13:37:08 +02:00
ptitSeb 1d75d23772 Added wrapped libmpg123 lib (partial) 2020-07-07 09:40:16 +02:00
ptitSeb 6dd848eac5 Added F2/F3 70..7F (BND) Jxx and 64 8F PUSH FS:Ed opcodes 2020-07-07 07:50:17 +02:00
ptitSeb 0c0684bfb7 Added support for set_thread_area and handling of FS: 2020-07-06 21:57:46 +02:00
ptitSeb b56337df19 [DYNAREC] Fix potential crash when deleting a dynoblock without map 2020-07-06 21:57:46 +02:00
ptitSeb 0f0512c67c Merge pull request #144 from Mashintime/master
Update CMakeLissts.txt to copy libstdc++.so.5
2020-07-06 21:35:46 +02:00
Mashintime b677261976 Update CMakeLissts.txt to copy libstdc++.so.5
Included in x86libs but not copied to /usr/lib when 'make installing'
2020-07-06 15:25:24 -04:00
ptitSeb 0d0a75319c Fixed an old typo on impacting thread_attr_setstacksize 2020-07-06 21:24:53 +02:00
ptitSeb 0d283757d5 Update README.md 2020-07-06 07:48:19 +02:00
ptitSeb c09f477251 Improvement to the trace of called wrapped functions 2020-07-05 18:48:13 +02:00
ptitSeb 1d2bf3cb48 Try to make the O_XXXX convert function more portable 2020-07-05 14:28:25 +02:00
ptitSeb 7057160b3e Improved handling of pthread get/set affinit (old and new version) 2020-07-04 18:53:26 +02:00
ptitSeb 4244f41c41 Added helper function to get function name based on address 2020-07-04 15:41:28 +02:00
ptitSeb 70f587e305 Fixed potential issue with cmake 2020-07-04 14:20:51 +02:00
ptitSeb 97c5119807 Update README.md 2020-07-03 21:04:08 +02:00
ptitSeb 77a74d64bf [DYNAREC] Try to avoid a crash caused by a bad mix of dynarec and unresolved plt 2020-07-02 09:53:55 +02:00
ptitSeb 0547cec24d More SDL2 wrapped function with dummy fallback (plus some refactor and a fix probably) 2020-06-30 19:51:20 +02:00
ptitSeb 6837f58a0e Added 1 unofficial wrapped function (with dummy fallback) to SDL2 2020-06-30 18:28:32 +02:00
ptitSeb 2518377f83 Some fix to SDL2 wrapped lib 2020-06-30 14:14:24 +02:00
ptitSeb d38e67f539 Improved libx11 callback handling 2020-06-30 13:55:09 +02:00
ptitSeb a3d16d3c71 [DYNAREC] Fixed a warning 2020-06-30 12:48:41 +02:00
ptitSeb 14e1363930 Changed how FXSAVE/FXRSTOR works (in [DYNAREC] too) 2020-06-30 12:45:54 +02:00
ptitSeb 86eba0aaeb [DYNAREC] Actually use 64 FS: prefix 2020-06-30 12:06:39 +02:00
ptitSeb 10d7e28de3 Added some wrapped functions to a few libs 2020-06-30 09:49:02 +02:00
ptitSeb 082d08755e Stop ignoring tgsysall for now 2020-06-30 09:41:38 +02:00
ptitSeb 195bbddd6f This should avoid the 'wall of segfault' that happens sometimes 2020-06-30 09:06:43 +02:00
ptitSeb d68cbfd837 Added CF IRET opcode (not sure if correct) 2020-06-30 00:42:21 +02:00
ptitSeb 851d487015 [DYNAREC] Fixed FXSAVE / FXRSTOR (partial) opcode 2020-06-30 00:16:18 +02:00
ptitSeb 0a3ae03043 Added libncurses.so.5 wrapped function (bases libncursesw) and added 1 wrapped function to lbtsinfo.so.5 2020-06-30 00:09:59 +02:00
ptitSeb d56fea52f3 Added preliminary dlinfo wrapped function 2020-06-29 23:25:08 +02:00
ptitSeb 1de0f14194 [DYNAREC] Fix hang when call address 0 2020-06-29 23:24:48 +02:00
ptitSeb d3addae744 Fixed a warning in x86tls.c 2020-06-29 21:30:22 +02:00
ptitSeb ee0e831efe [DYNAREC] Added some FS: opcode (copy of GS: ones) 2020-06-29 20:41:44 +02:00
ptitSeb 59559efbb5 Handling default value for FS when creating new x86emu_t structure 2020-06-29 19:52:56 +02:00
ptitSeb 05e2a9c824 Fixed pwrite64 wrapped function signature 2020-06-29 19:39:41 +02:00
ptitSeb 9038d94184 Added a few wrapped function to libm 2020-06-29 18:25:51 +02:00
ptitSeb 08a93fc5ae Added memccpy wrapped function to libc 2020-06-29 18:09:04 +02:00
ptitSeb 6b6075ca48 Fixed dladdr wrapped function 2020-06-29 17:43:54 +02:00
ptitSeb 51135b9222 Added support for DT_RUNPATH (handed the same way as DT_RPATH) 2020-06-29 16:49:39 +02:00
ptitSeb 922c1770a0 [DYNAREC] Fix PUSH/POP DS/ES that should handle 32bits value on the stack (even if segment is 16bits) 2020-06-29 14:24:11 +02:00
ptitSeb b9dc8d79e0 Added 1 wrapped function to libX11 2020-06-29 13:03:11 +02:00
ptitSeb 7b823e4185 Changed execv wrapped function to automaticaly call box86(t) for x86 binary (help valgrind with --trace-children=yes) 2020-06-29 12:27:53 +02:00
ptitSeb fbdb4aa619 Changed how actual box86 fullpath is found 2020-06-29 12:24:55 +02:00
ptitSeb 7716936f77 [DYNAREC] Better way to free dynablocks (when a son would be free because his parent is freed, but still accessed to check if it can be freed) 2020-06-29 12:02:25 +02:00
ptitSeb 9636fec9da Free elfs first thing in FreeBox86Context 2020-06-29 12:01:15 +02:00
ptitSeb e15676e946 Changed how argv strings are handled 2020-06-29 11:41:07 +02:00
ptitSeb 28fb4ed090 [DYNAREC] Fixed a small potential memory overwritting 2020-06-29 11:19:55 +02:00
ptitSeb 8b5474d0a8 Added a few libX11 wrapped functions 2020-06-29 10:02:17 +02:00
ptitSeb 35e5a48e63 Added some FreeType wrapped functions 2020-06-29 08:56:47 +02:00
ptitSeb 470446a104 Removed some debug leftover 2020-06-29 08:56:26 +02:00
ptitSeb c0cc48d129 Added preliminary support for FS: and set_thread_area 2020-06-29 08:44:13 +02:00
ptitSeb 1134294037 [DYNAREC] Fix (66) 8E MOV Seg,Ew opcodes 2020-06-29 07:45:25 +02:00
ptitSeb f0f49d4f8f [DYNAREC] Fixed 66 8C MOV Ew, Seg and 66 8E MOV Seg, Ew opcodes 2020-06-28 19:22:19 +02:00
ptitSeb 5f361cbd2d Added exception for win-preloader in main (to not preload but load directly) 2020-06-28 18:01:54 +02:00
ptitSeb 20d65d3685 Wrapped lib now have path set to actual name 2020-06-28 17:16:50 +02:00
ptitSeb 51f0780c66 [DYNAREC] Added 0F 63 PACKSSWB opcode 2020-06-28 16:22:02 +02:00
ptitSeb b3db9aece7 [DYNAREC] Fixed PUSH ES / POP ES 2020-06-28 15:58:29 +02:00
ptitSeb 4e22fd1a69 Enabled SYS_RECVMMSG and SYS_SENDMMSG on syscall 102 even if those 2 macro are not defined 2020-06-28 11:23:42 +02:00
ptitSeb d290ccee7f [DYNAREC] Added 0F 51 SQRTPS and 0F 52 RSQRTPS opcodes 2020-06-27 20:13:42 +02:00
ptitSeb 4d227ef882 [DYNAREC] Added MINPD and MAXPD 66 0F 5D and 66 0F 5F opcodes 2020-06-27 18:28:40 +02:00
ptitSeb 6f842cea8b Changed the way NEEDED lib and GLOBAL symbol are fetched (again, for good this time hopefully, at least is seems to fix #136) 2020-06-27 14:02:56 +02:00
ptitSeb 36da25e08e Added 1 wrapped function to x11 lib 2020-06-27 08:57:45 +02:00
ptitSeb f586bb2617 Added syscall 196 sys_lstat64 2020-06-26 23:10:31 +02:00
ptitSeb f3a81ac635 Added syscall 66 sys_setsid 2020-06-26 19:37:31 +02:00
ptitSeb 266fc0961b Added syscall 271: sys_utimes 2020-06-26 19:09:11 +02:00
ptitSeb 824ae55d77 Added DS: prefix (ignored), can be used as hint, along with CS: in conditionnal jump (also ignored) 2020-06-26 18:22:41 +02:00
ptitSeb 656bfdc569 Fixed a small warning in gio2 wrapped lib 2020-06-26 09:01:53 +02:00
ptitSeb 0f45dd5fee Added libc syscall 174 (rt_sigaction) 2020-06-25 08:53:28 +02:00
ptitSeb 82e7faf83d Added more slot for pthread_once_callback 2020-06-24 18:24:20 +02:00
ptitSeb 0c7310b18d Really fixed epoll_create1 2020-06-24 16:00:28 +02:00
ptitSeb 2cedd0d2c6 Do not convert argument for epoll_create1 2020-06-24 15:15:44 +02:00
ptitSeb b63d087d5c Improved trace on semop wrapped function 2020-06-24 15:15:16 +02:00
ptitSeb bccdb36bd3 Added 2 x11 related wrapped functions 2020-06-23 07:47:24 +02:00
ptitSeb 298ef551ce Merge pull request #132 from rajdakin/explicitELF64
Explicit error message when having 64-bits ELFs
2020-06-21 20:46:39 +02:00
rajdakin 9b23a0a7ab [ELF] Explicit error message when having 64-bits ELFs 2020-06-21 20:44:54 +02:00
ptitSeb 5e2546dd0c Try to stop at double-segfault 2020-06-21 17:44:57 +02:00
ptitSeb 4e9bef301d Reworks INIT/FINI process, and fixed epoll syscall (now Half-Life quit properly) 2020-06-21 15:45:31 +02:00
ptitSeb be5d718280 [DYNAREC] Fixed a warning 2020-06-21 10:45:21 +02:00
ptitSeb 3bc1d6d0a1 Added alternative name for libopenal.so as openal.so 2020-06-21 09:25:34 +02:00
ptitSeb 2d23169ea5 [DYNAREC] Fixed many F3 0F xxxxSS opcodes 2020-06-20 19:48:59 +02:00
ptitSeb b486c60d5e Merge pull request #130 from rajdakin/printer
Dynarec printer fix
2020-06-20 18:22:25 +02:00
rajdakin 3246d2bbb6 [SIGNAL] Fixed unknown architecture build 2020-06-20 18:13:09 +02:00
rajdakin 7d7765ce14 [DYNAREC] Fixed one more time the printer (VMOV.F32 S, imm) 2020-06-20 18:12:46 +02:00
ptitSeb c1f2750b05 [DYNAREC] Fixed some printer issue with VFPU registers 2020-06-20 17:39:12 +02:00
ptitSeb bb4d44499c [DYNAREC] Added 66 0F C2 CMPPD opcode 2020-06-20 15:32:37 +02:00
ptitSeb 195ac3e5b6 [DYNAREC] Added 0F 2D CVTPS2PI opcode 2020-06-20 15:22:14 +02:00
ptitSeb bc9679cad9 [DYNAREC] Added 66 0F E6 CVTTPD2DQ opcode 2020-06-20 14:55:08 +02:00
ptitSeb a603b58970 [DYNAREC] Fixed 66 0F 5E DIVPD opcode 2020-06-20 14:39:06 +02:00
ptitSeb a740dbf871 [DYNAREC] Added 66 0F 5E DIVPD and 66 0F 15 UNPCKHPD opcode 2020-06-20 14:32:26 +02:00
ptitSeb b10e462e03 [DYNAREC] Added (naive) 0F 50 MOVMSKPS opcode 2020-06-20 14:19:37 +02:00
ptitSeb 6f28eb16c6 [DYNAREC] Fixed another potential BUSERROR 2020-06-20 12:53:22 +02:00
ptitSeb 140a41141c Fixed a potential BUSERROR 2020-06-20 12:03:46 +02:00
ptitSeb 6f00b50c6e Added Faked libtcmalloc_minimal (empty wrapped, use regular malloc/new functions) 2020-06-20 11:45:16 +02:00
ptitSeb a9cb19933a Change order of Global and Weak symbol fetching. Should be good this time 2020-06-20 10:50:03 +02:00
ptitSeb cbd8ce408e Enabled Trace in LOCAL function works now 2020-06-20 09:51:44 +02:00
ptitSeb 9837888e50 Allow Trace on LOCAL symbol loaded at start (was ok on dlopenned libs) 2020-06-20 09:28:28 +02:00
ptitSeb 42176b6593 Added a few dbus and gtk wrapped functions 2020-06-19 21:05:10 +02:00
ptitSeb a320528e64 Added some workaround for g_threads_got_initialized 2020-06-19 20:13:26 +02:00
ptitSeb 69a9175c67 Small changes to atfork handling 2020-06-19 18:55:01 +02:00
ptitSeb 9fdc3196d9 Fixed loaing of dependant libs of a local lib 2020-06-19 17:12:36 +02:00
ptitSeb 0b271fc44f Added PltResolver, so JmpSlot symbols are resolved at runtime now 2020-06-19 16:26:21 +02:00
ptitSeb 0fa2f7b8f1 Added one wrapped function to FontConfig 2020-06-18 22:30:44 +02:00
ptitSeb 41c775fb44 Fixed a warning 2020-06-18 22:10:31 +02:00
ptitSeb 28b06f45fe Fixed R_386_TLS_TPOFF relocation (fixed libtcmalloc_minimal.so.4 loading) 2020-06-18 22:06:28 +02:00
ptitSeb 083b3d2a1c Improved vfprintf trace 2020-06-18 22:05:51 +02:00
ptitSeb 61866f6dae [DYNAREC] Made the printing of a segfault a permanent printf for now 2020-06-18 22:05:34 +02:00
ptitSeb 39d7274359 Changed BOX86 load address to a low address 2020-06-18 22:04:46 +02:00
ptitSeb a9b4d994eb [DYNAREC] Added F3 0F 1E and F3 0F 1F multibte NOP, also used a ENDBR opcode 2020-06-18 08:46:55 +02:00
ptitSeb 3701dcd0b4 Added F3 0F 1E and F3 0F 1F multibte NOP, also used a ENDBR opcode 2020-06-18 08:46:18 +02:00
ptitSeb efe2588fd9 Added__libc_dlXXX wrapped function 2020-06-18 08:45:10 +02:00
ptitSeb 3c17d886cc Added many libcrypto and libSSL wrapped functions (and now Minit runs) 2020-06-17 18:51:21 +02:00
ptitSeb 83fe3605f6 Merge pull request #129 from rajdakin/fixes
Fixed ARMS (ARM shifted) instruction category
2020-06-17 12:08:52 +02:00
rajdakin dec474953b [DYNAREC] Ran the printer generator 2020-06-17 11:50:08 +02:00
rajdakin f80964d8d7 [DYNAREC] Fixed ARMS (ARM shifted) instruction category 2020-06-17 11:41:09 +02:00
ptitSeb a43687ee30 Change how symbol are fetched in Elf Relocate mecanism (hacky and probably wrong, but seems to work pretty well) 2020-06-17 00:07:26 +02:00
ptitSeb e04233a897 Some debugging helper 2020-06-16 18:22:21 +02:00
ptitSeb 93cd9b00bd [DYNAREC] Made x86emu_t structure up-to-date when calling arm_linker 2020-06-16 18:21:59 +02:00
ptitSeb 3a592ca9c4 [DYNAREC] Added a special case on 'read' wrapped function when reading on a write protected block (because it's an executable one) 2020-06-16 18:18:48 +02:00
ptitSeb 555d0d51b0 CPUID detection actualy need this bit to be changeable, not fixed 2020-06-16 18:10:53 +02:00
ptitSeb a70f29a8c9 Merge pull request #128 from rajdakin/fixesARMs
Fixed the ARMs and ARM$ instructions type for the printer
2020-06-16 11:36:37 +02:00
ptitSeb dad53a84c8 Merge pull request #127 from rajdakin/fixes
Fixed the U/SXT* opcodes print (and probably others too)
2020-06-16 11:35:56 +02:00
rajdakin d03b21ee19 [DYNAREC] Fixed the ARMs and ARM$ instructions type for the printer 2020-06-16 11:34:50 +02:00
rajdakin 1a1bf5f76a [DYNAREC] Oops, fixed the fix that removes rbrackets of reglists 2020-06-16 11:28:27 +02:00
rajdakin 0ebc0f19b8 [DYNAREC] Fixed the U/SXT* opcodes print (and probably others too) 2020-06-16 11:23:25 +02:00
ptitSeb d4cfa94aaa Merge pull request #126 from M-HT/old_glibc
Allow compilation with older version of glibc
2020-06-16 07:58:20 +02:00
M-HT 383d4c8f9a Allow compilation with older version of glibc 2020-06-16 07:35:33 +02:00
ptitSeb 48b187edd1 [DYNAREC] Don't create a son at the 1st instruction 2020-06-15 18:15:48 +02:00
ptitSeb 316e18f8c5 The syscall 254 sys_epoll_create use a flags parameter that need transform... 2020-06-15 17:59:07 +02:00
ptitSeb 657595d363 Rollback: don't ignore unsupported Int 2020-06-15 17:59:07 +02:00
ptitSeb 9cd9ad16b2 Some fixes t DBUS wrapped lib 2020-06-15 16:50:33 +02:00
ptitSeb 7d49d0fc8a Complete handling of LOCAL/GLOBAL on glopen wrapped function 2020-06-15 16:25:38 +02:00
ptitSeb fa9bdbfd64 Added a few more syscall 2020-06-15 16:23:45 +02:00
ptitSeb 558dc58a52 Don't stop on unknown interrupt, just skip it 2020-06-15 16:23:15 +02:00
ptitSeb 383b1afe0b Try to handle LOCAL/GLOBAL on dlopen wrapped function 2020-06-14 22:32:11 +02:00
ptitSeb 3d757a2af6 Merge pull request #124 from M-HT/fix_64bit_inodes
Fix 64bit inodes in readdir and readdir_r functions
2020-06-14 13:49:31 +02:00
M-HT 2cb20b665d Fix 64bit inodes in readdir and readdir_r functions 2020-06-14 13:16:57 +02:00
ptitSeb eadb36bcdd Merge pull request #123 from M-HT/fix_64bit_inodes
Add option to fix 64bit inodes
2020-06-13 23:27:23 +02:00
M-HT a3bbaeb11b Add option to fix 64bit inodes 2020-06-13 23:03:30 +02:00
ptitSeb 816ee7e23b Fixed last commit 2020-06-10 21:54:45 +02:00
ptitSeb 2a10da129e [TRACE] Allow tracing function in the Init part of a dlopen lib 2020-06-10 18:58:10 +02:00
ptitSeb 9784c3bf2d Compensate for bad lib dependacie in libmss.so.6 (fixes #121 Neverwinter Night Diamond Edition) 2020-06-07 22:40:18 +02:00
ptitSeb f64a7e2c5b Added some png12 and libc wrapped functions 2020-06-07 18:17:54 +02:00
ptitSeb f01359a62e Added some pango wrapped functions 2020-06-07 17:26:57 +02:00
ptitSeb 729f392148 Added a large batch of cairo wrapped functions 2020-06-07 17:20:11 +02:00
ptitSeb e48802c898 Added a dbus wrapped function 2020-06-07 16:42:32 +02:00
ptitSeb 34ed9f03e1 Added cairo_pango wrapped functions 2020-06-07 15:54:25 +02:00
ptitSeb 4990b6db94 Added some FreeType wrapped functions 2020-06-07 15:54:25 +02:00
ptitSeb ecf50c8181 Added 2 wrapped functions to libfontconfig 2020-06-07 15:54:25 +02:00
ptitSeb 927159011c Some small fixes to cpuinfo file creation 2020-06-07 13:46:31 +02:00
ptitSeb 640db5e667 Added some cairo wrapped functions 2020-06-07 13:18:05 +02:00
ptitSeb 509f09dfbc Refined gdk_display hack 2020-06-07 13:07:40 +02:00
ptitSeb 4f42ae0d81 Added a few libm wrapped functions 2020-06-07 12:44:18 +02:00
ptitSeb 1b4391ac23 Added some DBus wrapped functions 2020-06-07 12:39:39 +02:00
ptitSeb 5cb6894657 Added a workaround, again, for gdk_display symbol 2020-06-07 12:14:39 +02:00
ptitSeb be66c8bffa Create a fake /proc/cpuinfo instead of opening the real one 2020-06-07 11:48:37 +02:00
ptitSeb 5f71bcfe9a Slight change in elfloader 2020-06-06 11:10:53 +02:00
ptitSeb 95d786e9a8 Added a special case for libSgGL to load libGL as needed (fixes Hotline Miami) 2020-06-06 11:08:52 +02:00
ptitSeb 8b5e977868 Improved wrapping of curl (and now UrbanTerror download maps) 2020-06-05 17:20:51 +02:00
ptitSeb 49a631b475 Forgot a debug printf in mmap 2020-06-05 16:26:53 +02:00
ptitSeb 8b98a68d1a Update README with latest improvments 2020-06-05 11:42:31 +02:00
ptitSeb c03e46814b [BOX86LIB] Some slight adjustments for box86 as a lib 2020-06-05 11:41:58 +02:00
ptitSeb 7efac81f8b Force RelWithDebInfo build type if none was specified 2020-06-05 08:28:34 +02:00
ptitSeb 58e98e9580 [DYNAREC] Change a message log level, so it's less alarming 2020-06-04 17:58:53 +02:00
ptitSeb 56c211fbeb Added a few libpng12 wrapped function (fixed old FTL 1.5.13) 2020-06-04 17:23:18 +02:00
ptitSeb 2aa2e53fef [DYNAREC] Use a mecanism with Memory Protection to handle JIT'd code (good improvment in speed for Unity games at least) 2020-06-04 16:56:00 +02:00
ptitSeb 3993c88fbb Simplified Lib/Elf loading process (hopefully fixing some bugs in the process) 2020-06-03 19:53:17 +02:00
ptitSeb f706e7eecc Added a few __libc_XXXX wrapped function 2020-06-03 18:54:36 +02:00
ptitSeb 549de25a49 Improved trace a bit (lib name added in front of function name) 2020-06-03 18:54:14 +02:00
ptitSeb 217b05fb80 Small change to Interpretor in non-trace build 2020-06-03 18:53:14 +02:00
ptitSeb e1b9d40ca6 Fixed TRACE build 2020-06-03 17:50:41 +02:00
ptitSeb 0eeba809f2 Added one GS:ADD and one GS:ADC opcode (fixes Arma3 DS, #120, but it crashes after loading everything) 2020-06-03 16:29:59 +02:00
ptitSeb 4a0df1042d Fixed 'Unimplemented Opcode' message that would crash without showing in certain cases on no trace build (mainly with Dynarec) 2020-06-03 16:18:00 +02:00
ptitSeb e7a4274511 [DYNAREC] Try to avoid to keep a reference of a block that will potentially get removed 2020-06-02 16:36:36 +02:00
ptitSeb b3def68a4f Added Logo and Icon from @grayduck 2020-06-01 21:50:16 +02:00
ptitSeb 3c67de08a3 [DYNAREC] Create a temp variable there, that seems more safe 2020-06-01 21:49:27 +02:00
ptitSeb cec67ef3e3 Fixed the TRACE that was broken since last refactor 2020-06-01 17:37:04 +02:00
ptitSeb 881501b278 Fixed issue with glDebugMessageCallbackARB (now 140 run with mesa) 2020-06-01 12:12:18 +02:00
ptitSeb d09a949755 Fixed PREFETCH opcode (especially for the Interpretor) 2020-06-01 11:42:27 +02:00
ptitSeb bf6fa0f335 Added sbrk and brk functions to wrapped libc 2020-05-31 09:28:40 +02:00
ptitSeb 9dcfa322a5 Added SDL_Sem function to wrapped SDL2 2020-05-30 18:15:46 +02:00
ptitSeb a1c21ce05f [DYNAREC] More improvements to FreeDynablock 2020-05-30 09:59:28 +02:00
ptitSeb 22be56179d [DYNAREC] Improved FreeDynablock function 2020-05-29 20:16:58 +02:00
ptitSeb 24da6fcb3b [DYNAREC] Add dest reference in table only when dest as a mark set 2020-05-28 21:48:15 +02:00
ptitSeb 8078b27172 [DYNAREC] Chnage DBGetBlock to forget current block if it gets removed 2020-05-27 21:21:22 +02:00
ptitSeb 89d1254106 [DYNAREC] Added 66 F3 variant for REP MOVSW and REP STOSW 2020-05-27 14:16:32 +02:00
ptitSeb 497f66f5dc Fix for previous fix, for some (not so?) rare cases 2020-05-26 19:37:30 +02:00
ptitSeb a321d54142 Fix a small issue when detecting owner of some memory 2020-05-26 18:49:45 +02:00
ptitSeb 8495b461b8 [DYNAREC] Added protect/unprotect of an address range (will be used later) 2020-05-24 18:35:21 +02:00
ptitSeb 35d6354898 [DYNAREC] Detect PageSize (will be used later) 2020-05-24 17:57:30 +02:00
ptitSeb a2b4af137c Update README.md 2020-05-23 21:03:09 +02:00
ptitSeb 756d1c12fd Update README.md 2020-05-23 21:01:46 +02:00
ptitSeb 63f2e52edb Merge branch 'master' of https://github.com/ptitSeb/box86 2020-05-21 13:54:37 +02:00
ptitSeb fd704eca00 Remove the creation of x86emu_t structure from the stack when using RunFunction, use the thread local onee now 2020-05-20 20:42:38 +02:00
ptitSeb 8c233f1861 Removed emu from context structure, and made a per thread one 2020-05-20 19:01:22 +02:00
ptitSeb 669bb00590 Added libudev.so.1 wrapped lib (straight copy of libudev.so.0 for now) 2020-05-18 10:54:01 +02:00
ptitSeb 815fd918cb Fixed non-dynarec build (#116) 2020-05-15 13:09:47 +02:00
ptitSeb 4249adbe4e Update COMPILE.md 2020-05-14 08:49:00 +02:00
ptitSeb 1aec17da4d Update COMPILE.md 2020-05-14 08:45:59 +02:00
ptitSeb 3680a3092e [DYNAREC] Made FillBlock candidate for threading 2020-05-13 16:47:52 +02:00
ptitSeb b11a269867 [DYNAREC] Fixed TRACE build 2020-05-13 14:52:26 +02:00
ptitSeb cccbf75878 Simplified some function, removing the x86emu_t* argument 2020-05-13 13:17:03 +02:00
ptitSeb 5ce309e64b [DYNAREC] 66 0F D6 MOVQ can be unaligned... (should help #115) 2020-05-12 22:08:11 +02:00
ptitSeb 4b48a43413 Removed a small warning in new pthread_cond handling 2020-05-12 16:08:35 +02:00
ptitSeb a05df24c8b Changed, again, how phtread_conditions are handled 2020-05-12 16:06:59 +02:00
ptitSeb 4f599b521a Improved a bit the handling of thread conditions 2020-05-12 11:13:02 +02:00
ptitSeb 44cf2fc4fb [DYNAREC] Removed some warning 2020-05-12 11:12:30 +02:00
ptitSeb 0ca9f70796 [DYNAREC] Add father/son notion in dynablock, to allow branging in the middle of a dynablock (and avoid generating a new one) 2020-05-11 19:54:54 +02:00
ptitSeb 83cb2dbc4d [DYNAREC] Added mecanism to allow liner with volite code blocks 2020-05-11 08:54:39 +02:00
ptitSeb b09937ad3d [DYAREC] Added a few more NOP variant 2020-05-10 16:21:08 +02:00
ptitSeb c88d5d462c Use another method to handle errors in wrapped libjpeg 2020-05-10 13:12:18 +02:00
ptitSeb 78c971cb87 Added a few more SDL2 wrapped functions 2020-05-09 10:39:59 +02:00
ptitSeb 1bafddcfe2 Rewrapped some non-64 libc functions, to avoid mixing with 64 bits on some plateforms (fixes Saves of IcewindDale on Pi4) 2020-05-08 22:20:53 +02:00
ptitSeb 047b2071f5 [BOX86LIB] Added some libs to the linking of libbox86.so 2020-05-07 20:15:25 +02:00
ptitSeb 8aca039ca6 Added some old and rarely used opcode (helps ZeldaClassic) 2020-05-07 11:50:49 +02:00
ptitSeb db8c6b0c9e Fixed build with cmake less than 3.13.5 (fix for #112) 2020-05-06 20:49:32 +02:00
ptitSeb dbc6aa83f3 Merge pull request #111 from rajdakin/cmake-fix
Fix configuration on older CMake
2020-05-06 20:03:06 +02:00
rajdakin 08472aa68b [CMake] Fix configuration on older CMake 2020-05-06 19:59:57 +02:00
ptitSeb 3010068660 Try a fix on Python finding with old cmake (should fix #110) 2020-05-06 19:28:22 +02:00
ptitSeb 5e2faff01d [DYNAREC] Small changes 2020-05-06 19:12:49 +02:00
ptitSeb 598338809f Take LD_PRELOAD into account if BOX86_LD_PRELOAD is not present 2020-05-06 19:12:11 +02:00
ptitSeb 4778760622 [DYNAREC] Improved handling of JIT'd code by marking potentialy changed block as dirty instead of purging the whole block 2020-05-06 16:41:59 +02:00
ptitSeb 3a23cc42f6 Small cosmetic changes 2020-05-06 14:16:56 +02:00
ptitSeb e23283e794 [BOX86LIB] Improved the Build as a lib version, and introduced build as dynamic lib 2020-05-06 14:09:56 +02:00
ptitSeb 4d730a31c4 Merge pull request #109 from icecream95/posix_spawn
Wrap some posix_spawn functions
2020-05-06 07:37:02 +02:00
ptitSeb 216b6407f3 Merge pull request #108 from rajdakin/reprinter
Printer automation
2020-05-05 20:38:11 +02:00
rajdakin e95988f402 [DYNAREC] Forgot to increase the version number 2020-05-05 19:32:40 +02:00
rajdakin 1ce3731d7d [DYNAREC] Refactored the printer generator (8) 2020-05-05 19:27:32 +02:00
rajdakin 7420d3c8de [DYNAREC] Refactored the printer generator (7) 2020-05-05 19:27:32 +02:00
rajdakin f1edcc06d3 [DYNAREC] Refactored the printer generator (6) 2020-05-05 19:27:32 +02:00
rajdakin ce5c3db346 [DYNAREC] Refactored the printer generator (5) 2020-05-05 19:27:32 +02:00
rajdakin cc0b7b3719 [DYNAREC] Refactored the printer generator (4) + major bug fix 2020-05-05 19:27:32 +02:00
rajdakin 7854fa2e18 [DYNAREC] Removed WIP spacing 2020-05-05 19:27:32 +02:00
rajdakin 1b7bc825d5 [DYNAREC] Refactored the printer generator (3) 2020-05-05 19:27:32 +02:00
rajdakin e65f58acb2 [DYNAREC] Refactored the printer generator (2) 2020-05-05 19:27:32 +02:00
rajdakin 18fe17dc2d [DYNAREC] Refactored the printer generator (1) 2020-05-05 19:27:32 +02:00
rajdakin 8098461e0f [DYNAREC] Changed a little how the printer generator works 2020-05-05 19:27:32 +02:00
rajdakin bf8e9f9242 [DYNAREC] Added an ARM instructions printer generator 2020-05-05 19:27:32 +02:00
rajdakin 4838067440 [WRAPPERS] Rewrote the wrappers generator a bit 2020-05-05 19:27:32 +02:00
rajdakin 53a080e32e [CMake] Cleanup the CMakeLists.txt file a bit 2020-05-05 19:27:32 +02:00
rajdakin 3ac41770b8 [CMake] Force the use of Python3 2020-05-05 19:27:32 +02:00
ptitSeb 6fe51fd7f4 [DYNAREC] Finaly found why Unreal crashes when CPUID detection was enabled: linfmod use some SMC, that's bad. So found some workaround 2020-05-05 17:16:46 +02:00
ptitSeb a6cbe15b5e [DYNAREC] Some small optim on 32bits float access 2020-05-05 17:15:33 +02:00
ptitSeb 3313eba45c [DYNAREC] When using BOX86_DYNAREC_DUMP, use some mutexes to avoid mixing block in dump 2020-05-05 17:14:04 +02:00
Icecream95 b01150f707 Wrap some posix_spawn functions 2020-05-05 14:13:52 +12:00
ptitSeb 4502948f89 Changed a bit the thread creation / cancellation, and associted mutex 2020-05-04 22:47:37 +02:00
ptitSeb 8cb2ffbd2e Added some crude (maybe incorrect?) workaround for function with 0 size in elf header (fixed some libfmod function, somehow) 2020-05-04 15:45:34 +02:00
ptitSeb be80cb03d6 Changed how Trace ona Function works, so it can works on defered (dlopen'd) library 2020-05-04 15:44:43 +02:00
ptitSeb 13d6e96cdc Set trace begin/end as global 2020-05-04 14:04:18 +02:00
ptitSeb 9f280b1f9c Set CPU Family to 6 (instead of 1) in CPUID 2020-05-03 18:53:43 +02:00
ptitSeb 786dfa6700 [DYNAREC] Small optimization on x87 Stack sync 2020-05-03 18:52:36 +02:00
ptitSeb e260aee2e6 [DYNAREC] Use NOP instead of B to ext instruction 2020-05-03 18:51:59 +02:00
ptitSeb 504c27c934 [DYNAREC], Nope, that Unreal bug is still not fixed, not enable CPUID detection yet 2020-05-03 18:51:25 +02:00
ptitSeb c4ba481561 In trace, function name with 0 sized are like infinite size 2020-05-03 18:48:43 +02:00
ptitSeb 841770aed1 [DYNAREC] Small dump improvment 2020-05-03 18:48:01 +02:00
ptitSeb 1a4643f3a2 [DYNAREC] Small improvment on x87 cache access 2020-05-03 12:56:17 +02:00
ptitSeb e89702d99d [DYNAREC] Fixed printer for rotated immadiate 2020-05-03 12:55:46 +02:00
ptitSeb 250e3820df [DYNAREC] Small fixe to the printer to get more printed opcodes in dumps 2020-05-03 11:14:36 +02:00
ptitSeb 8b2a509a32 [DYNAREC] A bit more color in dump 2020-05-02 19:48:31 +02:00
ptitSeb 6db92c56b9 [DYNAREC] Some trace improvments 2020-05-02 19:17:44 +02:00
ptitSeb e4914a2139 Rollback CPUID detection code until I found why Unreal crashes with it 2020-05-01 21:42:18 +02:00
ptitSeb 704c4b36ab Added support for CPUID detection in PUSHF/POPF 2020-05-01 09:32:47 +02:00
ptitSeb b9d61108bf Added a few wrapped function (should help X3) 2020-05-01 09:01:56 +02:00
ptitSeb e92d2f737b Small thread improvment 2020-04-30 21:10:10 +02:00
ptitSeb 6ec36072c4 A bit more wrapped libz functions 2020-04-30 15:06:00 +02:00
ptitSeb ab18d4d23a [DYNAREC] Fix build for non-trace enabled build (fix #105) 2020-04-30 14:01:28 +02:00
ptitSeb 1e6893a9d9 [DYNAREC] Added a few more opcodes (Int3 and FXSAVE/FXRSTOR) 2020-04-30 11:08:34 +02:00
ptitSeb 01bcc957e8 Added PSUBB opcode (should help 'The Journey Down Chapter One') 2020-04-29 14:44:39 +02:00
ptitSeb 3c989cfa04 Removed that yield in cond_broadcast, useless, and probably harming the performances 2020-04-28 18:55:18 +02:00
ptitSeb bde29ef155 Fixed some libz wrapped functions (fixed AM2R) 2020-04-28 18:41:23 +02:00
ptitSeb cee4cd26e0 [DYNAREC] Don't use x1, x2 or x3 scratch before use READFLAGS, also fixed the the bordercase fix call/ret optim (all this fixed zsnes and starfox) 2020-04-28 17:42:57 +02:00
ptitSeb f774b88211 [DYNAREC] Fixed PUSHAD/POPAD opcode, also small fix on border case for Call/Ret optimisation 2020-04-28 17:42:57 +02:00
ptitSeb 251f9b7338 Update README.md 2020-04-27 10:24:17 +02:00
ptitSeb dd5fc10a95 [DYNAREC] Optimised CALL/RET by using a local stack in x6emu_t struct (large improvment in some game, but doesn't help ShovelKnight) 2020-04-26 22:39:40 +02:00
ptitSeb 5e84efc542 Remove test on x87 stack status 2020-04-26 15:15:25 +02:00
ptitSeb b29fd4abbd [DYNAREC] Added missing change from previous commit 2020-04-26 15:15:03 +02:00
ptitSeb 1c6f2254f3 [DYNAREC] Store current block in table linker, to help find next block 2020-04-25 15:14:23 +02:00
ptitSeb 73685273f4 Added wrapped libdrm (almost empty) 2020-04-24 19:26:59 +02:00
ptitSeb 76d070777f Added a few wrapped functions to xcb, fontconfig and freetype 2020-04-24 17:23:21 +02:00
ptitSeb 42d18f7302 Added libstdc++.so.5 (along with the .6) in x86libs (usefull in some older games) 2020-04-24 16:15:25 +02:00
ptitSeb 963a7a527a On system where getrandom syscall is not supported, read /dev/urandom and not /dev/random 2020-04-24 12:02:05 +02:00
ptitSeb df61ed3048 [DYNAREC] Fixed potential issue when an opcode is not handled by the dynarec (fixed TeamSpeak3, for good) 2020-04-24 12:01:16 +02:00
ptitSeb 2a8e6061a2 Added BOX86_NOSIGILL 2020-04-24 11:11:22 +02:00
ptitSeb 96c4fe7057 Some changes in signal hanbdling (not sure it's a good idea) 2020-04-24 10:51:11 +02:00
ptitSeb 124df9ae83 Also add my_getrandom fallback to wrapped libc syscall 2020-04-24 08:30:49 +02:00
ptitSeb 62b2eecf6e Some system (like the Pandora) don't have the getrandom syscall 2020-04-24 08:26:29 +02:00
ptitSeb 9fb6b7bbd9 Use align on come fctnl function (fixes TeamSpeak3 server) 2020-04-23 22:27:15 +02:00
ptitSeb 0ac7929230 Added syscall 355 2020-04-23 21:39:38 +02:00
ptitSeb d16e8f1c51 Added some aio_*64 wrapped function to librt 2020-04-23 21:30:39 +02:00
ptitSeb 4b59f04930 Small fixes to some gobject signals 2020-04-23 16:06:12 +02:00
ptitSeb 7a375136cc Cosmetics in myalign.c 2020-04-23 16:05:49 +02:00
ptitSeb 62a328af45 Go back to using SharedCallback for qsort and qsort_r (should be faster and more reliable) 2020-04-23 08:37:42 +02:00
ptitSeb aafe35dca7 Changed how MMAP memory is alloced/freed 2020-04-22 14:40:27 +02:00
ptitSeb c73b728255 More cosmetic changes 2020-04-22 14:40:01 +02:00
ptitSeb 1186072e48 Added a sched_yield before cond_brodcast, just in case Dynarec is building a block with a cond_wait inside (to be tested) 2020-04-22 14:38:42 +02:00
ptitSeb 141de19804 Misc cosmetic changes 2020-04-22 14:37:41 +02:00
ptitSeb 97d71dfe09 [DYNAREC] Fixed some printer issues 2020-04-22 14:32:30 +02:00
ptitSeb f05b4fa7ff Some small changes to pthread_register_cancel, again, to hopefully have something working 100% 2020-04-21 19:34:37 +02:00
ptitSeb 2f36ec82f9 Made my_context global, plus some warning hunting... 2020-04-21 15:12:29 +02:00
ptitSeb c386a0a356 [DYNAREC] Warning hunt... 2020-04-21 15:11:57 +02:00
ptitSeb 4ba1f972b5 [DYNAREC] Fixed some emiter (missing parenthesis) 2020-04-21 13:50:08 +02:00
ptitSeb 525eb10854 [DYNAREC] Ooops, fixed ROR Ed, Ib opcode 2020-04-20 18:36:16 +02:00
ptitSeb 7176b08882 Fixed some potentiel memory overwrite (should help #102) 2020-04-20 16:57:32 +02:00
ptitSeb a6f4248502 [DYNAREC] Added complete emiter for ror32c 2020-04-20 12:18:14 +02:00
ptitSeb f0da6dd64f [DYNAREC] Added complete emiter for rol32c 2020-04-20 11:31:03 +02:00
ptitSeb af3c9042c3 Disabling that pthread_cancel test, box86 is still too unstable on that it seems 2020-04-19 21:38:40 +02:00
ptitSeb d8aa65bc17 Update README.md 2020-04-19 19:40:27 +02:00
ptitSeb da6ab3f752 Update README.md 2020-04-19 19:39:33 +02:00
ptitSeb 3cdf7fe742 Update README.md 2020-04-19 19:38:38 +02:00
ptitSeb cb54d7e343 Update README.md 2020-04-19 19:38:02 +02:00
ptitSeb 60611e54f3 [RPI] Call sanitize_mojosetup_gtk_background also on uninstall, to avoid extreme sluginess of the GUI 2020-04-19 19:33:17 +02:00
ptitSeb a4a78681ef More improvement to pthread_register_cancel handling 2020-04-19 17:56:15 +02:00
ptitSeb 4d85147077 Fixed a mamory averwriting issue 2020-04-19 17:55:27 +02:00
ptitSeb 857048f47c Small change in the init phase 2020-04-19 17:19:15 +02:00
ptitSeb 6084102d20 More improvement to thread_cancel_register mecanism 2020-04-19 16:52:31 +02:00
ptitSeb 2dc1fcc875 Improved handling of __pthread_register_cancel (and add a unit test about that) 2020-04-19 15:58:54 +02:00
ptitSeb 584479c10d Move around a bit thread helper initialization 2020-04-19 15:39:35 +02:00
ptitSeb 3430550dac Some attempt to improve __pthread_cancel_(un)register wrapped functions 2020-04-19 13:33:19 +02:00
ptitSeb 81f5bc79aa Various improvement to thread handling (should solve some memory issue when a lot of thread are created) 2020-04-19 13:33:19 +02:00
ptitSeb e20ccb7991 More changes to exec (now steam can start some game directly) 2020-04-19 13:33:19 +02:00
ptitSeb 5cf4af83b0 Update README.md 2020-04-18 15:42:47 +02:00
ptitSeb e5cb34d1f8 Update FUNDING.yml 2020-04-18 15:41:55 +02:00
ptitSeb 91c46f99a0 Update FUNDING.yml 2020-04-18 15:38:50 +02:00
ptitSeb dbdcaf8962 Create FUNDING.yml 2020-04-18 15:38:08 +02:00
ptitSeb 230d6246c6 Fixed a warning from previous commit 2020-04-18 15:32:20 +02:00
ptitSeb 066e5f966a Simplified some phtread wrapped functions 2020-04-18 15:24:16 +02:00
ptitSeb ff615cba03 Added preliminary FS: support 2020-04-18 15:06:08 +02:00
ptitSeb 631fa0f536 Move box86 on top of user memory (help Witcher 2, but not enough, as it use FS:) 2020-04-18 14:35:50 +02:00
ptitSeb ce2eb76703 Small changes in sem_open and set priority on threads 2020-04-18 10:56:15 +02:00
ptitSeb 9422039e09 Added IMG_LoadTexture and friend wrapped funcito to sdl2image 2020-04-17 22:24:47 +02:00
ptitSeb 0f13eb8611 More log for exev* wrapped functions 2020-04-17 21:49:59 +02:00
ptitSeb 196394f666 Added dummy syscall 243 (need work for a proper implementation 2020-04-17 21:49:21 +02:00
ptitSeb 9b2f7029df Improved elfloader to support elf with 'fragmented' memory map 2020-04-17 15:48:35 +02:00
ptitSeb a2e6b57c35 Simplified handling of exevl* 2020-04-17 14:02:24 +02:00
ptitSeb e5fdb4ba85 [DYNAREC] Added complete emiter for sar32c 2020-04-17 14:02:03 +02:00
ptitSeb 0c83522296 [DYNAREC] Fixed needed_flags function 2020-04-16 19:23:54 +02:00
ptitSeb f59e30442a Proprer support for timer_create with notify to SIGEV_THREAD 2020-04-16 17:40:00 +02:00
ptitSeb b67b750009 [DYNAREC] Added shr32c complete emiter 2020-04-16 15:41:02 +02:00
ptitSeb 61f2a43628 [DYNAREC] Reduce the recursivity of needed_flags function 2020-04-16 12:09:08 +02:00
ptitSeb 769545ccd7 Add proper support for RPATH with 2020-04-16 11:15:46 +02:00
ptitSeb c0b9272b82 Fixed ODroid and GameShell profile help that were mixed up 2020-04-16 09:30:40 +02:00
ptitSeb d5e5cbb393 Added ODROID profile 2020-04-16 07:52:09 +02:00
ptitSeb d8251ec441 Fix link on non-dynarec build 2020-04-16 07:40:47 +02:00
ptitSeb 0a04ef44d4 [DYNAREC] Fix issue when code use lots of FPU code with a few jump (i.e. x87 with loops), on dynarec pass 1 (helps Hotline Miami, and probably others) 2020-04-15 22:25:50 +02:00
ptitSeb 79ada49fdc Added some workaround to get steam somehow running 2020-04-15 21:36:08 +02:00
ptitSeb 1bf134c3ef Fixed interpretor for PALIGNR SSSE3 opcode 2020-04-15 16:54:56 +02:00
ptitSeb 38098290b7 [DYNAREC] Fixed psrlw and psraw opcode 2020-04-15 15:49:46 +02:00
ptitSeb b66c95d920 [DYNAREC] Added neg8 complete emiter 2020-04-15 15:42:35 +02:00
ptitSeb 25ae0f9311 [DYNAREC] Added neg16 complete emiter 2020-04-15 13:04:08 +02:00
ptitSeb f63799ecbb [DYNAREC] Small fixes to NEG and XADD opcodes 2020-04-15 12:03:25 +02:00
ptitSeb f2de080c68 [DYNAREC] Added shl32c complete emiter 2020-04-15 11:28:22 +02:00
ptitSeb 4ceaa7bd4b More workround on fcntl F_SETFL 2020-04-15 11:20:02 +02:00
ptitSeb 5753983f41 Fixed fctnl and fcntl64 wrapped function that weren't converting some parameter (should help OSS game, among other things) 2020-04-15 08:40:16 +02:00
ptitSeb 58768ca886 Merge pull request #97 from PokeEngineer/master
Include sysmacros.h in elfloader.c
2020-04-15 07:38:40 +02:00
Jacob Mullins d3d740c38f Included sysmacros.h
Some compilers (like the one on the GameShell) need this to be included or you get undefined references to "major," "minor," and "makedev."
2020-04-15 00:43:57 -04:00
ptitSeb 27f99bd3c0 Added some basic /proc/self/maps emulation (missing heap, stack and loaded lib) 2020-04-14 20:18:22 +02:00
ptitSeb 230fa96d2b Added basic support for RPATH 2020-04-14 14:27:08 +02:00
ptitSeb 1e7f5692ce Added syscall 266 2020-04-13 10:41:40 +02:00
ptitSeb af884e427d [DYNAREC] Added PSRAW/PSRAD/PRSRLW/PSRLD opcodes 2020-04-12 10:53:58 +02:00
ptitSeb 00b2002855 Added PAVGB and PAVGW SSE2 opcodes (also in DYNAREC) 2020-04-12 10:10:47 +02:00
ptitSeb e5d20ea8ae [DYNAREC] Fixed isue with CLC and STC opcodes 2020-04-12 09:37:01 +02:00
ptitSeb 3b4ca235d5 [DYNAREC] Added neg32 complete emiter with flags 2020-04-11 18:37:40 +02:00
ptitSeb 8633aca6fa Fixes isNativeCall (help FTL) 2020-04-11 18:17:14 +02:00
ptitSeb 85dde4b9d0 [DYNAREC] Assorted bugfixes (but still an issue in zsnes somewhere) 2020-04-11 15:30:58 +02:00
ptitSeb 43e981579f [DYNAREC] Added sbb8 and sbb16 complete emiter with flags 2020-04-10 10:44:31 +02:00
ptitSeb f12706599e [DYNAREC] Added sbb32 complete emiter with flags 2020-04-10 09:57:58 +02:00
ptitSeb 650668eaf7 [DYNAREC] Added adc16 complete emiter with flags 2020-04-10 08:41:43 +02:00
ptitSeb 6093589e41 [DYNAREC] Added adc8 complete emiter with flags 2020-04-09 23:38:37 +02:00
ptitSeb ce777c9393 [DYNAREC] Added complete emiter with flags for adc32 2020-04-09 22:55:50 +02:00
ptitSeb 983523c2f6 [DYNAREC] Inc/Dec doesn't change CC, plus many fixes on emiter with flags... 2020-04-09 20:02:47 +02:00
ptitSeb 8f5843e0fe [DYNAREC] Added or16/xor16/and16 and use the emiters 2020-04-09 18:24:09 +02:00
ptitSeb 98b0602ae5 [DYNAREC] Added complete emiter for sub16, and converted SUB and INC/DEC 16 opcodes 2020-04-09 17:06:10 +02:00
ptitSeb 0286e8362e [DYNAREC] Use emit_add8/32 and emit_sub8/32 for inc/dec opcodes 2020-04-09 16:20:38 +02:00
ptitSeb bcfc464f24 [DYNAREC] Fixed add8/sub8 and added complete emiter with flags for add16 2020-04-09 14:51:42 +02:00
ptitSeb 7a9e9df3c0 [DYNAREC] Added complete emiter with flags for or8, xor8 and and8 2020-04-09 11:49:28 +02:00
ptitSeb 829bf941f4 [DYNAREC] Added complete emiter for sub8 opcodes 2020-04-09 10:48:26 +02:00
ptitSeb 3e42161c35 [DYNAREC] Also use emit_addXX on XADD opcodes 2020-04-09 10:47:54 +02:00
ptitSeb 9cdaa5e028 [DYNAREC] Fixed some logic complete emiter (with constant) 2020-04-09 08:02:35 +02:00
ptitSeb 34ef7b9b79 [DYNAREC] Added more complete emiter, plus some reorganisation of sources 2020-04-08 21:59:56 +02:00
ptitSeb 201677899b [DYNAREC] Created emiter (with flags) for add32 and sub32 2020-04-08 18:56:00 +02:00
ptitSeb fd563c5b4b [DYNAREC] Fun with flags: improved Carry flag handling 2020-04-07 17:50:15 +02:00
ptitSeb d5b5031f5c [DYNAREC] Fun with flags: added the X_PEND flags to calculate flags + setting defered 2020-04-07 17:40:32 +02:00
ptitSeb 08f2fcd1b9 [DYNAREC] Fun with flags: done all test emiter too. 2020-04-06 16:38:45 +02:00
ptitSeb f7da6bc070 [DYNAREC] Fun with flags: Continue adding all cmp emiter, plus some bug fixes 2020-04-06 16:02:31 +02:00
ptitSeb 1414fed3b2 [DYNAREC] Added optionnal Coloring to Dump 2020-04-06 16:01:36 +02:00
ptitSeb 13ff5c80be [DYNAREC] Fun with flags: Optimized cmp16_0 emiter 2020-04-05 21:17:29 +02:00
ptitSeb 782dd645c3 [DYNAREC] Fun with flags: Optimized cmp16 emiter 2020-04-05 21:13:47 +02:00
ptitSeb 020bcd46c2 [DYNAREC] Fun with flags: Optimized cmp32_0 emiter 2020-04-05 21:08:02 +02:00
ptitSeb fefb01f930 [DYNAREC] Func with flags: optimzed cmp32 emiter 2020-04-05 21:02:38 +02:00
ptitSeb 6489a2ca3b [DYNAREC] Fun with flags: fixed a typo 2020-04-05 21:02:16 +02:00
ptitSeb cbe4ec30d1 [DYNAREC] Fun with flags: optimize FCOMI emiter 2020-04-05 20:35:22 +02:00
ptitSeb 38a9b04ce0 [DYNAREC] Change the way X86 Flags are handled 2020-04-05 20:10:18 +02:00
ptitSeb 7de59621c4 Changed how ROR and ROL handle flags (less exact but faster, seems ok on all tests) 2020-04-04 11:11:46 +02:00
ptitSeb e9560dd916 [DYNAREC] Improved is_nops function 2020-04-02 18:19:50 +02:00
ptitSeb 91fec006ae [DYNAREC] Improved dynarec by allowing each block to be bigger 2020-04-02 08:26:18 +02:00
ptitSeb 82af74c459 [PANDORA] Fix for the use of tremor in SDL(1/2)_mixer 2020-04-01 15:35:47 +02:00
ptitSeb 32dc46efac [DYNAREC] Improve DUMP info a bit 2020-04-01 13:05:41 +02:00
ptitSeb 020b94794b [DYNAREC] Removed duplicate include 2020-03-31 21:52:27 +02:00
ptitSeb bb59ef692e Improved a bit a warning message 2020-03-31 21:51:58 +02:00
ptitSeb 8280d4628d Fixed a few wrapped functions prototypes 2020-03-30 16:39:46 +02:00
ptitSeb 91c6a71353 [DYNAREC] Fixed CMPXCHG opcode (helps Telsagrad, and probably others) 2020-03-30 16:21:10 +02:00
ptitSeb fa9e8223b9 [DYNAREC] Fixed memory allocated with mmap64 that was tracked (fix Unity/Mono JIT not beeing Dynarec'd correctly) 2020-03-30 15:11:08 +02:00
ptitSeb 7057ce7a2c Fixes to some libc wrapper functions with callback (fixed Teslagrad) 2020-03-30 14:16:04 +02:00
ptitSeb b98febce24 Added one more synonim for SDL2 2020-03-29 15:52:40 +02:00
ptitSeb 11758cfa90 Improvments to libc wrapped function with callback 2020-03-29 09:38:26 +02:00
ptitSeb a37928110d Some improvments to vorbisfile wrapped lib 2020-03-29 09:38:02 +02:00
ptitSeb a3c7674676 [DYNAREC] Added PMADDUBSW opcode 2020-03-28 20:43:07 +01:00
ptitSeb ed68b17bac [DYNAREC] Added PACKSSWB opcode, and changed a MOVD one to avoid some BusError 2020-03-28 17:40:24 +01:00
ptitSeb aa86b8ecf4 [DYNAREC] Added PADDSB opcode 2020-03-28 17:04:44 +01:00
ptitSeb e0c5630ed7 [DYNAREC] Added PSUBSB opcode 2020-03-28 17:01:39 +01:00
ptitSeb c4b4107f57 [DYNAREC] Added PCMPEQB opcode 2020-03-28 16:58:08 +01:00
ptitSeb d198f6c64a [DYNAREC] Added PADDUSB opcode 2020-03-28 16:52:05 +01:00
ptitSeb fd3812c27e [DYNAREC] Added PSADBW and PMAXUB 2020-03-28 16:46:08 +01:00
ptitSeb ddbffd874b [DYNAREC] Added PSHUFB SSE3 opcode 2020-03-28 15:02:08 +01:00
ptitSeb bc1b5bed0b Refactored (and simplified) libc functions with callbacks 2020-03-28 14:04:37 +01:00
ptitSeb f7019e0ff8 Added 2 SSE3 opcodes 2020-03-28 14:01:58 +01:00
ptitSeb e47f88f4f3 Changed (optimized?) a bit the idiv operations 2020-03-28 14:01:35 +01:00
ptitSeb baf750b89a Added one dummy libc wrapped function 2020-03-28 10:39:30 +01:00
ptitSeb bea256ddc6 Added wrapped lib Xmu (with 2 functions) 2020-03-28 10:25:28 +01:00
ptitSeb e7f841b71e Made looking for emulated libs more resiliant 2020-03-27 22:19:54 +01:00
ptitSeb 1df10d7a48 [DYNAREC] Added UD2 opcode 2020-03-27 21:50:54 +01:00
ptitSeb 53c4a0d418 More SDL2 wrapped functions 2020-03-26 20:48:19 +01:00
ptitSeb 883f1990c6 Added some more GS: opcodes 2020-03-25 23:02:22 +01:00
ptitSeb c2efed56e0 Added 1 libX11 wrapped function 2020-03-25 19:28:21 +01:00
ptitSeb 37814194ae [PANDORA] Try some workaround for Xxf86vm Gamma issues 2020-03-25 14:29:54 +01:00
ptitSeb 03cc86c6d1 Added a few libc wrapped functions 2020-03-25 11:58:42 +01:00
ptitSeb 206f5d3aa8 Added barely used 82 opcode (same as 80) [DYNAREC] too 2020-03-25 11:41:36 +01:00
ptitSeb d5c71f3dcc Added FPREM1 opcode 2020-03-25 11:14:55 +01:00
ptitSeb 1ed35d06c7 Add some fail safe on program that use _IO_2_1_st* symbols 2020-03-25 08:56:31 +01:00
ptitSeb 4456ab2ab5 Add a libc symbol 2020-03-25 08:55:55 +01:00
ptitSeb 645297de61 Added one new syscall 2020-03-24 18:02:25 +01:00
ptitSeb 71dbfda219 Added 2 X11 wrapped functions 2020-03-24 17:06:28 +01:00
ptitSeb c8977e68d0 Added a wrapped x11 function 2020-03-23 13:57:58 +01:00
ptitSeb 9b1bfb17b0 Expose SSE3 and SSSE3 2020-03-23 13:46:25 +01:00
ptitSeb 95858b46b0 [DYNAREC] Changed MOVQ 0f 7f opcode to avoid potential Bus Error (helps steam) 2020-03-23 13:31:48 +01:00
ptitSeb d7ca13e7f7 Added wrapped libnm (also as a replacement for libnm-glib and libnm-util, to help steam, but need network-manager-gnome package) 2020-03-22 19:05:33 +01:00
ptitSeb a17dfe8ed6 Added a few gtk wrapped functions 2020-03-22 17:10:45 +01:00
ptitSeb 1d9eb8fa17 Added some more gio2 wrapped functions 2020-03-22 16:58:16 +01:00
ptitSeb 6d8e64a213 Added gudev wrapped functions 2020-03-22 14:55:45 +01:00
ptitSeb c5859a0d92 Added a large bunch of glib2 / gobject2 / gio2 wrapped functions 2020-03-22 14:38:23 +01:00
ptitSeb 058b199606 Added a large bunch of dbus and dbus-glib1 wrapped functions 2020-03-22 08:45:29 +01:00
ptitSeb 5b58985fdf One more glib2 wrapped function 2020-03-21 20:42:44 +01:00
ptitSeb b9e1192d69 Added more slot to gobject2 callbacks 2020-03-21 19:31:42 +01:00
ptitSeb 1d0a575773 Try to define all gobject cclosur_marshaler as DATA and not wrapped functions 2020-03-21 19:22:29 +01:00
ptitSeb 72e3e36f1b Added wrapped dbusmenu-glib library 2020-03-21 18:54:35 +01:00
ptitSeb bd2271de86 Fixed a wrapped gobject2 function (and steam is almost starting) 2020-03-21 17:52:42 +01:00
ptitSeb ffa2aa6f1c Added a few more libc wrapped functions 2020-03-21 16:44:49 +01:00
ptitSeb c0d35aa6e7 Some (speed) improvement to wrapped pulse library 2020-03-21 15:58:07 +01:00
ptitSeb 11c1396d83 Small change in epool_ctl wrapped function 2020-03-21 15:57:43 +01:00
ptitSeb 41e6ba1030 Init new stacks to 0 (in line with x86 behavour?) 2020-03-21 15:57:13 +01:00
ptitSeb e92e9043fa Fixed some multi-threaded libpulse wrapped functions 2020-03-21 15:29:56 +01:00
ptitSeb c53ab30b2e Improved autodetect of binary, and added special case for steam 2020-03-21 12:34:53 +01:00
ptitSeb c763ca269a Smalls changes on libudev wrapped function 2020-03-21 11:59:16 +01:00
ptitSeb bf4c05c41c Added a few more gobject2 wrapped functions 2020-03-21 10:06:22 +01:00
ptitSeb 9b9130ed57 Added a few more dbug-glib2 wrapped functions 2020-03-20 19:51:18 +01:00
ptitSeb 5fde277748 Added a wrapped function to gobject2 2020-03-19 21:39:07 +01:00
ptitSeb 7757666a0b Added some more glib2 wrapped functions 2020-03-18 21:00:29 +01:00
ptitSeb 4bc52873f7 Added some glib2 wrapped functions 2020-03-17 22:16:53 +01:00
ptitSeb a5a38203ae Added some gio dbus wrapped functions 2020-03-16 17:57:23 +01:00
ptitSeb 1209862996 Fixed fprintf trace (in case it's in fact __fprintf_chk that is called) 2020-03-16 17:56:57 +01:00
ptitSeb 4f0bb1010d Fixed return value for dladdr wrapped function 2020-03-15 15:29:03 +01:00
ptitSeb 050b974051 [DYNAREC] Fixed a MOVQ mmx opcode 2020-03-15 12:41:13 +01:00
ptitSeb 88fb7efec3 Use fopen64 and fseeko64 on main binary so >4Gb file can be open (now psychonauts installer can be run) 2020-03-15 09:53:39 +01:00
ptitSeb a91c562dcf Removed old monounity wrapped lib attempt (not working well enough) 2020-03-14 12:52:27 +01:00
ptitSeb f1a136c9b4 Added libXdamage wrapped lib (complete) 2020-03-13 20:21:43 +01:00
ptitSeb 57583b39e7 Added libXcomposite wrapped library (complete) 2020-03-13 19:31:13 +01:00
ptitSeb 3467ea2476 Added some more libcrypto wrapped functions 2020-03-12 20:23:23 +01:00
ptitSeb 0e6daf412d Fixed execl wrapped functions 2020-03-12 20:23:11 +01:00
ptitSeb 8468c5318d Improve trace, especialy in BUILDLIB scenario 2020-03-11 20:29:49 +01:00
ptitSeb 853f4865ce [BUILDLIB] Add some failsafe fallback for getauxval 2020-03-10 20:57:21 +01:00
ptitSeb 0742c694b0 Added a few gtk wrapped functions 2020-03-09 20:13:13 +01:00
ptitSeb 247622a6db [DYNAREC] Small change in how JIT'd code in handled in the linker 2020-03-08 16:36:26 +01:00
ptitSeb cbd4b4f73a Fixed an issue with TLS data (and now hotline_launcher works) 2020-03-08 15:59:05 +01:00
ptitSeb 3782d7f4df [TRACE] Fixed start of symbol that was not printed in the trace 2020-03-08 12:08:20 +01:00
ptitSeb bc13894b31 Added lots of libxcb wrapped functions 2020-03-08 11:24:57 +01:00
ptitSeb d6ff293d7f [BUILD] Added dependancie on wrapped functions between .c and _private.h 2020-03-07 17:11:11 +01:00
ptitSeb 9e2ba671b8 Added some FontConfig wrapped functions 2020-03-07 16:19:44 +01:00
ptitSeb fb56c5f422 Added a few more X11 wrapped functions 2020-03-07 13:03:54 +01:00
ptitSeb a45d6bd79b Added some wrapped function used by gtk-1.2 2020-03-06 15:53:47 +01:00
ptitSeb 28a26db054 Added dontstarve autodetect to force use of emulated SDL2 2020-03-06 10:17:35 +01:00
ptitSeb 95782e7311 Remove import glob from wrapper generator, not used anymore 2020-03-06 09:51:17 +01:00
ptitSeb 5f6221de7f [DYNAREC] Added TZCNT opcode 2020-03-06 09:50:26 +01:00
ptitSeb b42ac3eb11 Revert stat / lstat change 2020-03-05 18:32:32 +01:00
ptitSeb 2964727959 Reworked py generator to avoid useless recompiles 2020-03-05 17:05:15 +01:00
ptitSeb fca7808b55 [DYNAREC] Added a few more opcodes 2020-03-05 14:21:15 +01:00
ptitSeb 07c98d30ad [DYNAREC] Add preliminary support for JIT'd code 2020-03-05 11:41:43 +01:00
ptitSeb a7c95a783e [DYNAREC] Added a few opcodes 2020-03-05 11:40:49 +01:00
ptitSeb e84ebce421 [DYNAREC] Dump of Dynarec blocks is now a seprated option 2020-03-05 11:39:56 +01:00
ptitSeb 0df765bbbd Fixed some type in USAGE 2020-03-04 13:19:02 +01:00
ptitSeb 2af2fbfe6d [DYNAREC] Preliminary work to support JIT'd code in Dynarec 2020-03-03 16:09:24 +01:00
ptitSeb 96f5f92b09 Fixed some typo is libgthread2 wrapped lib 2020-03-03 10:25:01 +01:00
ptitSeb dedd7f4827 Use lstat instead of stat on filexist function (alow use of symlink of libs) 2020-03-02 16:57:52 +01:00
ptitSeb 28a066a7c9 Added a few more pulse wrapped functions (should help Paper, Please) 2020-03-02 14:40:43 +01:00
ptitSeb 6377884c4a Improved emulation of dl_iterate_phdr (fixed Paper, Please) 2020-03-02 13:56:23 +01:00
ptitSeb 41cc61e4c7 Fixed an issue with a wrapped function in gtk 2020-03-01 14:40:04 +01:00
ptitSeb 73e13baa84 And more SDL2 wrapped functions 2020-03-01 13:03:23 +01:00
rajdakin 403707bb5b A few more SDL2 wrapped functions 2020-03-01 11:02:06 +01:00
ptitSeb 873bdd793a Some more SDL2 wrapped functions 2020-02-29 09:49:41 +01:00
ptitSeb edbd6cdfa5 A few more SDL2 wrapped functions 2020-02-28 18:37:50 +01:00
ptitSeb e7a9679a20 More SDL2 wrapped functions 2020-02-27 21:28:20 +01:00
ptitSeb b9d09acf92 Added a few SDL2 wrapped functons 2020-02-26 22:04:30 +01:00
ptitSeb 7a02b1720e Fixed glXProcAddress and alGetProcAddress when querying a my_ wrapped functions (fixed Isaac Aftyerbirth, and probably others games) 2020-02-15 21:26:53 +01:00
ptitSeb 3c88e8aac0 Added a few wrapped functions to wrandr and dbus 2020-02-15 20:11:29 +01:00
ptitSeb df4e93973b [DYNAREC] revert the use of TryLock, it fallback to interpretor too often 2020-02-15 19:48:59 +01:00
ptitSeb c3dbe47f3c [DYNAREC] Fixed x87 TAG issues (causing massive FPU under/over flow messages) 2020-02-15 19:48:25 +01:00
ptitSeb af91d80c94 Added some handling of TAG for x87 emulation (DYNAREC too) 2020-02-15 18:22:46 +01:00
ptitSeb a133621934 Use Trylock instead of Lock RWMutex in Dynarec block creation, to allow fallback to Interpreter instead of waiting 2020-02-15 16:00:48 +01:00
ptitSeb 329bddc4f6 Avoid Dynarec in signal handler, to avoid potentiel deadlocks 2020-02-15 15:59:57 +01:00
ptitSeb 31785d6fbe Added wrapped mkstemps64 function 2020-02-15 12:53:45 +01:00
ptitSeb c7bf006b49 Added better support for pthread_cleanup_push and pop macros (help Unity games) 2020-02-14 10:47:15 +01:00
ptitSeb 3fc1458cc2 Added a few more SDL2 wrapped functions 2020-02-13 20:21:29 +01:00
ptitSeb 53be7dad84 Added better handing of thread stack querying 2020-02-12 17:29:46 +01:00
ptitSeb 7507a0f20f Added a few SDL2 wrapped functions 2020-02-11 20:20:12 +01:00
ptitSeb 32a6711898 Small improvment on trace, to avoid potention deadlock or segfault 2020-02-10 20:19:42 +01:00
ptitSeb 223c6513ba Simplified pulsesimple, as it use full pulse now 2020-02-09 10:47:41 +01:00
ptitSeb d395df1f37 [DYNAREC] Prepare SDIV and UDIV emmiter (but no use yet) 2020-02-08 15:58:28 +01:00
ptitSeb f5a7d96a77 [DYNAREC] Added support for SWP opcode when handling XCHG x86 opcode 2020-02-08 12:34:38 +01:00
ptitSeb 81ae020273 [DYNAREC] Added detection of hardware cpu extensions 2020-02-08 10:57:24 +01:00
ptitSeb 57024db6e6 Improved getauxval handling 2020-02-07 08:18:25 +01:00
ptitSeb e507b964a1 Added actual getauxval wrapped function, and support for native getauxval 2020-02-06 22:48:12 +01:00
ptitSeb d2bff48e88 New developpement cycle 2020-02-06 22:01:12 +01:00
ptitSeb ba364f629f Bump version to v0.1.0 2020-02-05 18:46:10 +01:00
ptitSeb ae723c42fe Merge pull request #92 from madcock/patch-2
Clean up Gameshell section
2020-02-05 12:47:18 +01:00
Michael Adcock 8cf46bb5a8 Clean up Gameshell section
It's the same as RPI2, without the extra RPI definitions. ;-)
(We can use ASM flags too.)
2020-02-05 03:04:54 -08:00
ptitSeb ffadb9df59 Small improvment on auxiliary vector emulation 2020-02-04 11:39:15 +01:00
ptitSeb 87c55d434c Fix a warning 2020-02-03 17:23:09 +01:00
ptitSeb ae513fd908 Fix build on x86 platform 2020-02-03 17:22:14 +01:00
ptitSeb 4683f2194d Updated README and CHANGELOG 2020-02-02 18:01:15 +01:00
ptitSeb 823174af3e Improved support for XESetWireToEvent and XESetEventToWire (descent3 should be able to start a new game on every platform now) 2020-02-02 16:41:07 +01:00
ptitSeb 77c205cd78 Improved trace (print function name when possible) 2020-02-02 15:43:32 +01:00
ptitSeb ea047b1573 Fixed a typo in a function name 2020-02-02 14:46:20 +01:00
ptitSeb c4b9c107af Fixed wrapped alGetProcAddress and alcGetProcAddress 2020-02-02 14:04:42 +01:00
ptitSeb 5bb580a9e0 [DYNAREC] Use dynarec for elf inits (to speedup loading) 2020-02-02 12:09:50 +01:00
ptitSeb b82e0f124a [DYNAREC] Try to use rwlock instead of mutex for Dynarec blocks creations 2020-02-02 11:51:36 +01:00
ptitSeb 4e5512ecb3 Refined XCHG opcode in interpretor 2020-02-02 11:40:22 +01:00
ptitSeb 48dffd1d6e Use calloc instead of malloc, it seems x86 malloc mem is zero'd most of the time 2020-02-01 20:06:48 +01:00
ptitSeb a0820fcd2d Refined FTS handling 2020-02-01 20:06:18 +01:00
ptitSeb 0819240675 [TRACE] Add some padding to Formatter structure, because newer version are bigger 2020-02-01 16:41:10 +01:00
ptitSeb 1ae7e8f998 Fixed debug info for XCreateWindow 2020-02-01 15:57:43 +01:00
ptitSeb bfbf7c2d10 Added better debug for XCreateWindow 2020-02-01 15:52:55 +01:00
ptitSeb 8fb4d06858 Added fts_* wrapped functions support 2020-02-01 15:30:52 +01:00
ptitSeb 0bec217d1e Added one more wrapped function to libc 2020-02-01 10:28:01 +01:00
ptitSeb a0a7b8b758 Added a few wrapped function to libc 2020-01-31 12:18:32 +01:00
ptitSeb 5e344b7db6 Added a wrapped function to libjpeg 2020-01-31 11:49:52 +01:00
ptitSeb a954773ba6 Simplified libpng12 wrapped and add a few wrapped functions 2020-01-31 11:37:14 +01:00
ptitSeb ee27dfd927 [DYNAREC] Fix build issue 2020-01-30 11:38:27 +01:00
ptitSeb 44995a791f [DYNAREC] Added 3 GS: opcode (need testing) 2020-01-30 11:08:14 +01:00
ptitSeb df69100282 [DYNAREC] Added 66 0F F8 PSUBB OpCode (should help FTL 1.6.12) 2020-01-30 10:41:49 +01:00
ptitSeb c6b6247812 Fixed test02 2020-01-29 19:35:46 +01:00
ptitSeb 466b9e88b0 Syscall IPC doesn't exist everywhere. Fix build for now. Will need implementation 2020-01-29 17:32:53 +01:00
ptitSeb 1c51f99ed4 Added a couple of wrapped function (to be tested) 2020-01-29 17:30:02 +01:00
ptitSeb 2a68db14dc A bit more work in syscall (still to be validated) 2020-01-29 15:38:13 +01:00
ptitSeb b5bbd3e6d9 Some work on syscall, to try get old statically linked loki games working 2020-01-29 14:59:37 +01:00
ptitSeb 3ccdce5df4 Avoid a malloc when creating a new x86emu_t struct 2020-01-29 09:04:27 +01:00
ptitSeb 6c9195bae8 Improved wrapped SDL_RWops for SDL1, potentially fixing many games (at least fixes Robin Hood) 2020-01-28 21:42:43 +01:00
ptitSeb ed324369a0 Improved handling of FreeType, when using custom stream to load fonts (to be perfected, but that's a start) 2020-01-28 20:57:38 +01:00
ptitSeb 37efbe3f4b Improved, again, gtk signal handling (but more work is needed) 2020-01-28 18:18:08 +01:00
ptitSeb 0e2f4cd25a Improved debug a bit on wrapped gtk functions and callbacks 2020-01-27 23:02:43 +01:00
ptitSeb d773410d6b Some fixes / improvements to gtk and signal handling (again) 2020-01-27 17:47:10 +01:00
ptitSeb 1db72cb2fe Allow to run program with missing needed lib, with an env. var. 2020-01-27 17:22:02 +01:00
ptitSeb cd952734e5 Added a few SDL2 wrapped functions 2020-01-27 12:03:09 +01:00
ptitSeb 6b134cc102 Added a few wrapped function gobject2 2020-01-26 16:34:30 +01:00
ptitSeb 55c399bab6 Added some wrapped function in libgdk 2020-01-26 16:30:04 +01:00
ptitSeb 60a3214375 A few more wrapped function to libc, and one for libX11 2020-01-26 16:20:11 +01:00
ptitSeb f992b50444 Added empty wrapped libs gstreamer-0.10 and gstinterfaces-0.10 2020-01-26 15:29:45 +01:00
ptitSeb 65a62df0b1 Added a few wrapped functions to libc 2020-01-26 15:08:32 +01:00
ptitSeb a154752c1a Added dlsym as a fallback for dlvsym 2020-01-26 15:08:09 +01:00
ptitSeb 9ee6dcd27b Added 0F 2B MOVNTPS opcode (DYNAREC too) 2020-01-26 11:10:54 +01:00
ptitSeb fc5f512d24 Added a bunch of gtk wrapped functions 2020-01-26 10:36:53 +01:00
ptitSeb 089ed989f2 Try to improve handling of setjmp and libjpeg error handler (still something wrong somewhere) 2020-01-25 17:40:21 +01:00
ptitSeb b26c2253af Fixed an issue with pulseaudio (fixing ShovelKnight, again, on Pi4, and probably many other) 2020-01-25 16:24:26 +01:00
ptitSeb 647429d822 Fixed potential cPandora compilation issue (should fix #90) 2020-01-25 13:58:46 +01:00
ptitSeb 8c1368a79f Added MASKMOVDQU opcode (helps emulated libjpeg.so.8, for crimsonland) 2020-01-25 09:30:25 +01:00
ptitSeb cf37e29f96 Added MOVNTDQ opcode (in the dynarec too) 2020-01-24 22:47:29 +01:00
ptitSeb ce9a991a28 Small clean up in library_private structure 2020-01-23 22:52:15 +01:00
ptitSeb 4faf21a899 [BUILD_LIB] Fixed a few issues with initialization when built as lib 2020-01-22 23:33:53 +01:00
ptitSeb 8f2c02ec2a Added 2 more wrapped functions to libpng12 2020-01-22 21:11:15 +01:00
ptitSeb 872bd0042c Add a new function to run functions 2020-01-22 21:10:53 +01:00
ptitSeb c8c2d8de61 Fixed a few gtk wrapped functions 2020-01-21 16:05:15 +01:00
ptitSeb 30e8ebccb7 Added a few X11 wrapped functions 2020-01-20 08:18:57 +01:00
ptitSeb 7b0efb110f Added RCPPS opcode (and now AnomalyWarzoneEarth boots) 2020-01-19 19:01:15 +01:00
ptitSeb e553d93b17 Added a few wrapped functions (plus a faked MinorityMix_SetPosition for AntiChamber) 2020-01-18 21:30:40 +01:00
ptitSeb 41ba98dc84 Fixed some bus error in the Interpretor 2020-01-18 18:26:48 +01:00
ptitSeb 1dd53d4a03 Merge pull request #87 from PokeEngineer/master
Create an uninstall target
2020-01-18 17:10:57 +01:00
Jacob Mullins 00b1132fcf Created an uninstall target 2020-01-18 10:38:44 -05:00
ptitSeb 4d1fa73ac7 Removed some warning 2020-01-16 16:41:46 +01:00
ptitSeb 5493e5c35c Refined the initialization part for BOX86 as a Lib 2020-01-15 11:14:03 +01:00
ptitSeb e9c5272435 Box86 as Lib need -fPIC 2020-01-15 08:49:02 +01:00
ptitSeb 807ad56a39 Reworked a bit to have easier box86 as a lib 2020-01-14 22:36:05 +01:00
ptitSeb 472aa40b53 Removed the option to build without GTK wrapper (too much changed in the python generator for now) 2020-01-14 21:49:05 +01:00
ptitSeb 64e2b3e6db Added (hidden) option to build as a static lib 2020-01-14 21:40:43 +01:00
ptitSeb 5dc6f268c7 Refined NOGTK option 2020-01-14 20:37:23 +01:00
ptitSeb 931ef0c0c1 Added (hidden) option to not built GTK wrappers 2020-01-14 20:33:50 +01:00
ptitSeb 290adf2434 Merge pull request #86 from mittorn/master
Implement some FS opcodes used in windows dlls
2020-01-13 14:38:28 +01:00
mittorn 554c1c36bc Implement some FS opcodes used in windows dlls 2020-01-13 21:13:39 +07:00
ptitSeb 0e5994a0f9 And a bit more wrapped gtk functions 2020-01-12 19:15:08 +01:00
ptitSeb e3fb2b63c9 Some more wrapped gtk functions 2020-01-12 19:09:48 +01:00
ptitSeb 82c67783c1 Fixed libcairo that wasn't properly wrapped 2020-01-12 17:33:41 +01:00
ptitSeb 9799bbfedb Added more wrapped function to gtk (mainly around cairo) 2020-01-12 17:16:59 +01:00
ptitSeb e8a1196674 Added wrapped libXpm 2020-01-12 11:26:33 +01:00
ptitSeb 48a4e81214 Try to use gtk-2 for gtk-1.2 apps, but structs size are different, so disabling for now 2020-01-12 10:37:40 +01:00
ptitSeb bf441d6918 Added a few SDL 1 wrapped functions 2020-01-11 19:45:03 +01:00
ptitSeb aab4089986 Tried to improve signal handling (still not 100% ok) 2020-01-11 18:52:12 +01:00
ptitSeb c7cf40d55e Merge pull request #82 from madcock/patch-1
Update Gameshell params
2020-01-11 14:14:13 +01:00
Michael Adcock b977e3063f Update Gameshell params
Removed -march and added -mpcu to fix [cc: error: unrecognized argument in option ‘-march=armv7-a+fp’]
2020-01-11 03:28:24 -08:00
ptitSeb e5181e75be Added a few more wrapped function to freetype (and Arkos Traker 2 works again) 2020-01-11 11:47:02 +01:00
ptitSeb 58c903467e Fixed some warning 2020-01-11 11:02:17 +01:00
ptitSeb a615e0b627 Wrapped some new libc functions 2020-01-11 10:47:40 +01:00
ptitSeb b6c729f2d3 Added some wrapped function on x11 and friends 2020-01-10 22:39:09 +01:00
ptitSeb ff437ce8cf [DYNAREC] Some fixes for bordercase use of VSHR 2020-01-10 19:29:04 +01:00
ptitSeb 66a986c76f [DYNAREC] Fixed VLD1QALL_32 opcode (this fixes #81) 2020-01-10 19:28:33 +01:00
ptitSeb 410729e91a Merge pull request #80 from BlackHazel/patch-1
Update CMakeLists.txt (Typo)
2020-01-10 15:15:46 +01:00
BlackHazel 916f758e8c Update CMakeLists.txt (Typo) 2020-01-10 14:49:36 +01:00
ptitSeb 8affc5529e Rename FreeLibrary to Free1Library (not ideal, but that should solve #79) 2020-01-10 11:40:04 +01:00
ptitSeb efa07f3ad5 Added some libatk wrapped functions 2020-01-10 07:53:44 +01:00
ptitSeb 9a7daf4cd4 Added one data symbol to wrapped libc 2020-01-09 21:59:00 +01:00
ptitSeb c5068ea1d1 Added all wrapped function to libgmodule2 2020-01-09 21:36:06 +01:00
ptitSeb 0db1306563 Fixed some mystake in previous commit 2020-01-09 21:35:47 +01:00
ptitSeb 6b42fd6a24 Added a few wrapped function to libXtst 2020-01-09 20:57:12 +01:00
ptitSeb d418e67c77 Added a few wrapped functions to libm 2020-01-09 20:32:19 +01:00
ptitSeb 26bfef4161 Added 1 wrapped function to libasound 2020-01-09 20:32:04 +01:00
ptitSeb c64cffa352 Added deprecated SDL_mutexP and SDL_mutexV as alias 2020-01-09 16:41:41 +01:00
ptitSeb 863019f113 [DYNAREC]Added PUSH/POP ES and ES: prefix opcodes 2020-01-09 09:40:15 +01:00
ptitSeb c60581d7d3 Fixed BOX86_LIBGL, that was not always working correctly 2020-01-09 08:48:31 +01:00
ptitSeb a1abae4717 Fixed old issue aboug glXGetprocAddressARB (and a few other) not beeing visible in glXGetProcAddress 2020-01-08 22:14:47 +01:00
ptitSeb f970138c5f Added ES: prefix handling, along with push/pop es 2020-01-08 21:35:15 +01:00
ptitSeb 560e88f379 [DYNAREC] Changed most LDRD/STRD with dual LDR/STR to avoid bus erros 2020-01-08 11:43:30 +01:00
ptitSeb 18ff3c0b2c A few more wrapped function signature fixes for gtk stuffs 2020-01-08 08:19:28 +01:00
ptitSeb b92f20fa62 Some signature fixes for a few gtk wrapped functions 2020-01-07 16:31:21 +01:00
ptitSeb 2d22e18f5a Try to make Dynarec compile by default for Pandora/Pyra/Gameshell/RPix 2020-01-07 08:29:57 +01:00
ptitSeb 82fce8520c Added one wrapped function to freetype (and now WakingMars works) 2020-01-06 21:48:52 +01:00
ptitSeb 21ad3afce8 Now BOX86_EMULATED_LIBS allow to force libs to be emulated and not wrapped, and also added a detection on LittleInferno that needed that workaround for libvorbis 2020-01-05 15:47:10 +01:00
ptitSeb 5b680d4925 Added a few more wrapped functions for libogg 2020-01-05 15:46:24 +01:00
ptitSeb cabcf2cc39 Made loading of lib a bit more configurable (soon) 2020-01-05 14:15:23 +01:00
ptitSeb 9cc5f50f95 Added 2 more wrapped functions to libc 2020-01-04 18:40:49 +01:00
ptitSeb 2097af4172 [RPI] Added a workaround for GoG mojosetup (issue is with the background picture that is 5000x3000, so workaround is to delete it) 2020-01-04 17:09:56 +01:00
ptitSeb 141595e2d5 Fixed gtk_image_new function signature 2020-01-04 11:25:09 +01:00
ptitSeb 461f8d0e84 Make the stack bigger for RunFunction 2020-01-04 10:35:46 +01:00
ptitSeb 1775f4a47e Changed a bit of gobject2 signal connection is done 2020-01-04 09:53:17 +01:00
ptitSeb 48a271105d [DYNAREC] More MMX and SSE opcodes 2020-01-04 09:52:52 +01:00
ptitSeb 01bac8e3c4 Some more SSE opcodes 2020-01-04 09:52:32 +01:00
ptitSeb 9f6f94d504 [DYNAREC] More work on MMX opcodes 2020-01-03 21:33:21 +01:00
ptitSeb cd8ceda3ee [DYNAREC] Added a few more MMX opcodes 2020-01-02 19:35:42 +01:00
ptitSeb cd6cb90576 [DYNAREC] And a few more MMX opcodes 2020-01-02 08:37:15 +01:00
ptitSeb b69ed41ea6 [DYNAREC] Added a few more mmx opcode, and fixing an SSE one 2020-01-01 23:27:57 +01:00
ptitSeb 0d66d57806 [DYNAREC] Added 0f 67, 0f 68 and 0f 6a opcodes 2020-01-01 22:32:04 +01:00
ptitSeb 5762d865bb [DYNAREC] Added PMULLW and fix VQSUBxxx emitter 2020-01-01 20:42:45 +01:00
ptitSeb bac874ce38 [DYNAREC] Added PREFETCHh and PSHUFW mmx opcode, plus improvment to a few existing ones 2020-01-01 18:05:53 +01:00
ptitSeb fdf0aaacf1 Change some warning log level to LOG_INFO 2020-01-01 18:05:04 +01:00
ptitSeb f810e7a5f3 [DYNAREC] Added PUNPCKLBW, PUNPCKLWD and PUNPCKLDQ MMX opcode, plus improved a few other 0x0F MMX ones 2020-01-01 15:26:36 +01:00
ptitSeb 13fa2c74ef [DYNAREC] Added PSRLD, PSRAD, PSLLD, PMULHW and PMULHUW MMX opcodes (need testing) 2020-01-01 14:18:48 +01:00
ptitSeb f24bbd1e5f Added PSRLD, PSRAD, PSLLD and PMULHUW MMX opcodes 2020-01-01 14:17:40 +01:00
ptitSeb ab5f21c34d [DYNAREC] Added PSUBUSB and PSUBUSW opcode 2020-01-01 13:19:54 +01:00
ptitSeb ad6ee87e4f Added PSUBUSW opcode 2020-01-01 13:13:49 +01:00
ptitSeb b9478291bc Reworked gtk signal handling, to make it lighter (and now The Binding of Isaac boot, before finding unimplemented opcodes) 2020-01-01 12:44:34 +01:00
ptitSeb 59228657e5 Fixed signature for wrapped gdk_window_get_origin function 2019-12-31 19:37:43 +01:00
ptitSeb 3db1ab2b3e Added some wrapped function libudev-0 2019-12-31 18:42:46 +01:00
ptitSeb 8d75b56a2c Changed a bit how GTypeInfo and friends are wrapped 2019-12-31 18:07:23 +01:00
ptitSeb 1499ef31a9 Fix dl_iterate_phdr 1st iteration (name should be empty) 2019-12-31 17:35:00 +01:00
ptitSeb cdc1e4e18e Added a few SDL2 wrapped functions 2019-12-31 17:25:33 +01:00
ptitSeb 6f5102689f Added a last large btch of gtk wrapped functions 2019-12-31 16:15:20 +01:00
ptitSeb decc1af534 Added some more gtk wrapped functions (Hollyplayer is happy now, no more missing functions) 2019-12-31 13:08:02 +01:00
ptitSeb a912c34b9d Impoved libasound wrapper (and now there is sound in Hollywood Player) 2019-12-31 12:57:11 +01:00
ptitSeb 0fc22270b7 Fixed a mystake in gdk_window_get_root_origin wrapped function 2019-12-31 12:46:23 +01:00
ptitSeb 0ff9da5d4e Added a few more gtk-2 wrapped functions 2019-12-31 12:00:09 +01:00
ptitSeb 887ef22002 Fixed and issue with g_main_context_get_poll_func 2019-12-31 11:59:52 +01:00
ptitSeb c9adb6bf97 Added a few cURL wrapped functions 2019-12-31 11:18:29 +01:00
ptitSeb 33f2c63278 Added more gtk stuff, and improve Callbacks Arg handling 2019-12-31 11:12:27 +01:00
ptitSeb 950e6d99d3 Allow custom gtk class to be derived from GTKCaintainerClass now 2019-12-31 09:18:32 +01:00
ptitSeb d4ab117327 Added a large set of wrapped function to gtk-2 2019-12-30 23:08:17 +01:00
ptitSeb 419f2a5707 Added a global structure to libXt (but it may need some heavy wrapping...) 2019-12-30 19:40:13 +01:00
ptitSeb 0fac701577 Added more wrapped gtk-2 functions 2019-12-30 19:15:38 +01:00
ptitSeb c3ea1b17ac More function about pixbuff and image if gdk libs 2019-12-30 18:31:20 +01:00
ptitSeb 8ad4bd5178 Added a few fontconfig and freetype wrapped functions 2019-12-30 17:59:53 +01:00
ptitSeb c7896186b0 Add _XtInherit wrapped function to libXt 2019-12-30 17:59:37 +01:00
ptitSeb 43bd57cf4c Added 2 wrapped libX11 functions 2019-12-30 17:40:21 +01:00
ptitSeb 199d9503b3 Added 2 (untested, may need alignment) wrapped functions to libc 2019-12-30 17:38:15 +01:00
ptitSeb 1d2347f742 Add som libXt wrapped functions 2019-12-30 17:28:35 +01:00
ptitSeb f0c55d2e45 Added 2 functions to wrapped libc 2019-12-30 17:08:17 +01:00
ptitSeb 60a18f7e2d Add most menu wrapped functions to gtk-2 2019-12-30 17:02:47 +01:00
ptitSeb 369ffeb64a Added a new bunch of glib2 wrapped functions 2019-12-30 16:30:24 +01:00
ptitSeb 3f624ab813 Added some workaround for global gdk_display and g_threads_got_initialized 2019-12-30 13:08:07 +01:00
ptitSeb 590abc18f9 Added a few more gtk and co wrapped functions 2019-12-30 00:43:17 +01:00
ptitSeb 48f4ccce5d And added a large bunch of gdk wrapped functions 2019-12-29 23:28:07 +01:00
ptitSeb 28787055e0 Added tab wrapped functions to pango 2019-12-29 20:35:12 +01:00
ptitSeb ba42e0e3e4 Added a new large bunch of glib2 and gobject2 wrapped functions 2019-12-29 20:15:57 +01:00
ptitSeb 6aabb24b34 And a bit more gtk and gdk stuff (tests with scribble-xinput gtk tuto) 2019-12-29 18:31:28 +01:00
ptitSeb 5ab5e07775 Added more gtk and gdk wrapped functions (tested with scribble-simple gtk tuto) 2019-12-29 18:03:27 +01:00
ptitSeb f78ea33be6 Fix wrapped gtk libs, so custom widget can be created (tested with gtkdial tuto, only widget can be the parent class for now) 2019-12-29 17:46:02 +01:00
ptitSeb 5fbc9b637e Fixed some more gobject2 wrapped function (tested with gtk tictactoe tutorial) 2019-12-28 19:23:59 +01:00
ptitSeb a0e6a3edb9 Added wrapped g_print and g_printerr to glib2, plus some small fixes too (g_print tested) 2019-12-28 16:44:13 +01:00
ptitSeb 29c594ad6b And more wrapped gobject2 functions 2019-12-28 16:22:18 +01:00
ptitSeb ed52a461db Added a few more wrapped glib2 functions 2019-12-28 14:20:13 +01:00
ptitSeb 448313858e Added wrapped widget functions to gtk-2 2019-12-28 14:00:27 +01:00
ptitSeb 965cc02452 Added a buch of gobject wrapped functions 2019-12-28 13:18:30 +01:00
ptitSeb 2dc3a02623 Added g_source_new and friends to glib2 wrapped lib 2019-12-28 12:59:04 +01:00
ptitSeb 737df4b330 Added a bunch of gtk-2 wrapped functions 2019-12-28 12:20:17 +01:00
ptitSeb c8f66e72b9 Added most wrapped g_main_ functions to glib2 2019-12-28 12:04:14 +01:00
ptitSeb f9b121034f Added most wrapped list functions to glib2 2019-12-28 11:41:19 +01:00
ptitSeb 305002c295 Added most wrapped text_tag_table functions to gtk-2 2019-12-28 11:33:57 +01:00
ptitSeb 3ae728ddc2 Added wrapped gc function to gdk-2 2019-12-28 11:31:49 +01:00
ptitSeb f0b7b36aea Added wrapped colormap gdk-2 functions 2019-12-28 11:15:46 +01:00
ptitSeb dbeb70c08f Added wrapped option_menu functions to gtk-2 2019-12-28 11:01:10 +01:00
ptitSeb 7a8e911cf0 Added some wrapped pixbuff functions to gdk-x11-2 2019-12-28 10:59:01 +01:00
ptitSeb 9a560c2e95 Added wrapped tree_selection functions to gtk-2 2019-12-28 10:52:10 +01:00
ptitSeb befb826287 Added gtk_dialog_color_seelction wrapped functions to gtk-2 2019-12-28 10:45:27 +01:00
ptitSeb 9613686764 Added all wrapped _get_type functions to gtk-2 2019-12-28 10:42:47 +01:00
ptitSeb d4a2c50164 Added some tree_* wrapped function to gtk-2 2019-12-28 10:28:02 +01:00
ptitSeb e1b83d432a Added wrapped dialog functions to gtk-2 2019-12-28 10:13:13 +01:00
ptitSeb fc2ef2b5f1 Added adjustment_* wrapped functions to gtk-2 2019-12-28 10:05:30 +01:00
ptitSeb 24243ec0e4 Added most wrapped windows function to gdk-x11-2 2019-12-28 09:58:30 +01:00
ptitSeb 65ce48c2a1 Wrapped pango_context_* function in pango 2019-12-27 21:18:18 +01:00
ptitSeb 063968bd3a More wrapped tree view function in gtk-2 2019-12-27 21:13:01 +01:00
ptitSeb 0e9fea45fd Added wrapped text_iter function to gtk-2 2019-12-27 20:07:10 +01:00
ptitSeb ba10fdc2b7 Added x11 interaction wrapped function to gdk-x11-2 2019-12-27 19:45:15 +01:00
ptitSeb 4a9ced0854 Added wrapped pango function in gdk-x11-2 2019-12-27 19:24:26 +01:00
ptitSeb f1ef36a0e4 Added wrapped im_multicontext functions to gtk-2 2019-12-27 19:16:51 +01:00
ptitSeb 857b68a22c Added wrapped functions on layout to pango 2019-12-27 19:14:07 +01:00
ptitSeb acfd95c0e0 Added some more gtk wrapped functions (text_buffer stuff) 2019-12-27 18:51:03 +01:00
ptitSeb a57e4871a3 Added wrapped libgthread-2.0.so.0 (partial) 2019-12-27 18:26:31 +01:00
ptitSeb b5754732d9 Added a few more glib2 wrapped functions 2019-12-27 18:26:13 +01:00
ptitSeb d29f7d6ba8 Added some gtk wrapped list functions 2019-12-27 17:34:30 +01:00
ptitSeb bc928bb412 Removed duplicates from wrapped libncursesw (already in libtinfo) 2019-12-27 17:22:31 +01:00
ptitSeb 14de9efaff Added wrapped libtinfo, and moved symbols from libncursesw (mojosetup is happy now) 2019-12-27 17:01:45 +01:00
ptitSeb 2254ba15d3 Merge pull request #78 from rajdakin/master
Fixed the ncurses' ulong problem, added formw to the wrapped lib list
2019-12-27 16:32:03 +01:00
rajdakin 9318f7f596 Fixed the ncurses' ulong problem, added formw to the wrapped library list 2019-12-27 16:07:48 +01:00
ptitSeb 5d1fb26f15 Added 2 wrapped functions in libncursesw (still some issues) 2019-12-27 15:42:47 +01:00
ptitSeb e33df891a4 Merge pull request #77 from rajdakin/master
Added libncursesw to the wrapped libraries
2019-12-27 15:11:26 +01:00
rajdakin 243d185a44 Added libncursesw to the wrapped libraries 2019-12-27 15:08:10 +01:00
ptitSeb 7729dfa6c0 Added some pango wrapped functions 2019-12-27 14:51:21 +01:00
ptitSeb 120eb3271d Added a few more gtk wrapped functions 2019-12-27 14:35:57 +01:00
ptitSeb 7a9f4c2e50 Added most wrapped functions for libSM 2019-12-27 14:26:25 +01:00
ptitSeb eb2f60b8f6 More gtk wrapped functions 2019-12-27 13:41:27 +01:00
ptitSeb e63053ba48 Added some gtk window wrapped functions 2019-12-27 13:11:59 +01:00
ptitSeb bab12a3af3 Added some glib2 wrapped functions 2019-12-27 12:43:03 +01:00
ptitSeb 86f36deee7 Changed how GO2 define'd symbol resolved the alias name (searching all symbol if not found in current lib) 2019-12-27 12:42:43 +01:00
ptitSeb 15724a34f6 Added a few gdk wrapped functions 2019-12-27 11:26:19 +01:00
ptitSeb 33063f11b3 Added some more gtk wrapped functions 2019-12-26 23:10:18 +01:00
ptitSeb 415bcd544f Added a few wide char wrapped libc functions 2019-12-26 21:43:05 +01:00
ptitSeb 5409e8030b Added wrapped libXt (partial) 2019-12-26 21:30:06 +01:00
ptitSeb 16aba6c8bb Changed Test and install to use x86 libs 2019-12-25 11:54:17 +01:00
ptitSeb 026b2593bb Moved x86 libs to specific folder 2019-12-25 11:50:37 +01:00
ptitSeb 3e8e0ef0f3 Add libstdc++ and libgcc_s x86 binaries 2019-12-25 11:47:37 +01:00
ptitSeb a626c79b8b Update COMPILE.md 2019-12-24 11:48:57 +01:00
ptitSeb dc6dba42c4 Update COMPILE.md 2019-12-24 11:46:11 +01:00
ptitSeb b98f7a8459 Added a few more freetype wrapped functions 2019-12-23 15:14:10 +01:00
ptitSeb 4845ab0d40 Added some more wrapped function libpng12 (help BeatHazard) 2019-12-23 13:03:55 +01:00
ptitSeb 831fead5ed Added some freetype wrapped functions (should help Knytt Underground) 2019-12-23 12:04:03 +01:00
ptitSeb 658e2c4200 Added a few gobject wrapped functions 2019-12-23 11:44:16 +01:00
ptitSeb 83e4df1c79 Added a few libm and pthread wrapped functions 2019-12-23 11:06:20 +01:00
ptitSeb 125f204d58 Changed again (seriously, will it work perfectly one day) elf loader (fixing trine loading, checked with unreal, ut99, mohaa, worldofgoo, supermeatboy, superhexagon and limbo and it seems all is good) 2019-12-23 11:05:44 +01:00
ptitSeb 94a75a8e71 Added lib32 and x86 to implicit BOX86_LD_LIBRARY_PATH 2019-12-22 16:35:25 +01:00
ptitSeb 52412e8a23 Added barrier stuff in wrapped pthreads lib 2019-12-22 16:28:54 +01:00
ptitSeb f931db1c8d Added a few gio2 wrapped functions 2019-12-22 16:28:08 +01:00
ptitSeb 85363c677b Allow x8emu_t structure to be created on the stack 2019-12-22 16:16:28 +01:00
ptitSeb 7634447fda Even more wrapped functions from libpulse 2019-12-22 15:06:23 +01:00
ptitSeb 660d1e9ccd More wrapped function from libpulse 2019-12-22 14:06:14 +01:00
ptitSeb e73d0157df Refactored wrapped libpulse (seems better now) 2019-12-22 13:58:38 +01:00
ptitSeb 92ebb07369 Added many wrapped functions in glib2 around gvariant 2019-12-21 16:08:00 +01:00
ptitSeb ad19ca0f44 Added BOX86_X11THREADS env. var. 2019-12-21 15:13:15 +01:00
ptitSeb aacf835609 [DYNAREC] Added PEXTRW and improved PINSRW opcodes 2019-12-21 14:24:50 +01:00
ptitSeb 29690127d2 Added a few more emitter (and precised signed/unsigned) 2019-12-21 13:47:01 +01:00
ptitSeb 5da1de32f0 Added almost all libusb-1 wrapped functions 2019-12-21 13:15:20 +01:00
ptitSeb 98035453b8 Added a few more emitter 2019-12-21 13:15:02 +01:00
ptitSeb 2ef3c925db Added more wrapped gtk function 2019-12-21 11:27:59 +01:00
ptitSeb e671b8acfa More gtk wrapped functions 2019-12-21 11:10:54 +01:00
ptitSeb 58626e9c0b More gtk wrapped functions 2019-12-21 10:59:57 +01:00
ptitSeb 650ede22e0 More gtk wrapped function (and a few libc too) 2019-12-21 10:36:12 +01:00
ptitSeb a2648ce970 Merge branch 'master' of https://github.com/ptitSeb/box86 2019-12-21 10:18:00 +01:00
ptitSeb fdc587b964 Added more functions to wrapped libpulse 2019-12-21 10:16:22 +01:00
ptitSeb 537d447a28 Added empty wrapped libgudev-1.0 2019-12-21 00:07:13 +01:00
ptitSeb b8eb8d5b4e Added 2 more syscall (311 and 312) 2019-12-21 00:06:49 +01:00
ptitSeb 823dd8f6cc Added empty wrapped dbus-glib-1 2019-12-20 23:49:14 +01:00
ptitSeb 80ce6c091c Added empty wrapped libusb-1.0 2019-12-20 23:27:38 +01:00
ptitSeb ff740f4983 Fixed wrapped libfontconfig and FcAddPattern wrapped function 2019-12-20 23:18:14 +01:00
ptitSeb 5e16c59b72 Fixed wrapped libSM and libpulse 2019-12-20 23:17:51 +01:00
ptitSeb 4c0c6a4348 Lets just ignore int 3 instead of quit 2019-12-20 21:50:11 +01:00
ptitSeb 587f38be50 Wrapped a few libSM and libICE functions 2019-12-20 21:45:03 +01:00
ptitSeb 6e2f5b09f8 Added empty wrapped libSM.so and libICE.so 2019-12-20 21:09:20 +01:00
ptitSeb b238ab7c64 Added Profile for Pyra and RPI2/3/4. Also 'make install' is now possible 2019-12-20 19:42:12 +01:00
ptitSeb 6568138155 Changes wrapped libpulse to use hash map for callbacks 2019-12-20 11:32:47 +01:00
ptitSeb c167acd84c More functions wrapped in libpulse (but really, there are too many callback in this API) 2019-12-19 23:40:14 +01:00
ptitSeb cbd0d9b798 Added beggining of wrapped libpulse 2019-12-18 23:43:18 +01:00
ptitSeb 51902d0ec5 Fixed (again) wrapped libXtst lib 2019-12-18 23:07:54 +01:00
ptitSeb 1669f5d261 Fixed wrapped libXtst lib 2019-12-18 23:02:22 +01:00
ptitSeb 1b5500f7dd Added wrapped libXtst lib (almost complete, untested) 2019-12-18 22:55:26 +01:00
ptitSeb 3f273d4362 Added wrapped bz2 lib (complete but untested) 2019-12-18 22:32:02 +01:00
ptitSeb f540c20cde Added a few more gtk wrapped functions 2019-12-18 20:46:47 +01:00
ptitSeb 042c4f5935 Fixed 1 wrapped function in gdk-pixbuff (should help mojosetup) 2019-12-18 17:38:54 +01:00
ptitSeb 134f63ef59 Fixed psrad opcode with Interpretor 2019-12-18 15:14:54 +01:00
ptitSeb 731f12e114 Removed some harmless warnings 2019-12-18 15:07:28 +01:00
ptitSeb 2eea0b7f7d Added a few wrapped freetype functions 2019-12-18 09:08:39 +01:00
ptitSeb 1734916c7a [DYNAREC] Fixed 66 0F C4 PINSRW Gx,Ew,Ib Opcode (Fixing regression #76 on ShovelKight) 2019-12-17 22:26:50 +01:00
ptitSeb c83f1a2f3b Fixed 0F F2 PSLLD Gm, Em Opcode 2019-12-17 22:25:43 +01:00
ptitSeb 3497a9e081 [DYNAREC] Fixed (again, for good this time) 0F 6E MOVD Gm, Ed mmx opcode 2019-12-17 08:38:20 +01:00
ptitSeb cb133cef99 [DYNAREC] Fixed some ARM printer (VLD1_32/VST1_32) for logs 2019-12-17 08:37:38 +01:00
ptitSeb db2e6a23b8 [DYNAREC] Fixed another MMX instruction (and now Steam bootstrap does download its datas) 2019-12-17 00:02:45 +01:00
ptitSeb 469e8318ac Added more debug info to a gtk signal full wrapped function 2019-12-17 00:01:52 +01:00
ptitSeb 91bf052e7c Added a few xcb function (mostly unchecked) 2019-12-16 21:21:43 +01:00
ptitSeb f42c6ee7a3 Fixed (rarely used) PUSH/POP Segment (32bits with 0 padded segment value) 2019-12-16 21:21:04 +01:00
ptitSeb 395f734c46 Change box86.conf to point to /usr/local/bin/box86 2019-12-16 13:04:32 +01:00
ptitSeb a990273258 Added a bunch of gtk functions (not enough for Beathazard) 2019-12-15 22:37:56 +01:00
ptitSeb d05528ec5c Added a lot of wrapped libs, and now gtk2 mojosetup seems happy 2019-12-15 20:46:48 +01:00
ptitSeb 3770cc3a5f Remove a chance for bus error in dynarec, and added UD2 in interpretor 2019-12-15 19:51:31 +01:00
ptitSeb 143b5e8ec7 Added a few wrapped functions (libc and png12) and fixed XRRConfigSize (and now Knytt Underground works) 2019-12-15 14:17:08 +01:00
ptitSeb dfaa3d6e8a Some fixes to MMX and SSE opcodes 2019-12-15 13:42:10 +01:00
ptitSeb 9df95f96c2 Added 3 more wrapped functions (libc and sdl2) 2019-12-15 11:01:40 +01:00
ptitSeb 926f2f3dcd Fixed _IO_XXXX functions 2019-12-14 22:58:39 +01:00
ptitSeb d275fd3dba Try to wrap sf_open_virtual from sndfile lib 2019-12-14 21:50:05 +01:00
ptitSeb c986f8749d Also use LD_LIBRARY_PATH and PATH env. var. (the BOX86_ version have the priority) 2019-12-14 19:45:28 +01:00
ptitSeb 01f055ef31 Fixed some stupid typo in gtk-2 wrapped libs 2019-12-14 18:23:21 +01:00
ptitSeb 0b2ba32219 And some last work on gtk-2 wrapped lib (all function for mojo installer should be there now) 2019-12-14 18:03:41 +01:00
ptitSeb 79f2eb8f1e And a few more work on gtk-2 wrapped lib (almost there) 2019-12-14 17:44:33 +01:00
ptitSeb 5857eeb532 And even more work on gtk-2 wrapped lib 2019-12-14 17:16:05 +01:00
ptitSeb 714018b715 And more work on gtk-2 wrapped lib 2019-12-14 16:47:19 +01:00
ptitSeb bf2c2d4f3b More work with wrapped gtk-2 2019-12-14 16:05:34 +01:00
ptitSeb 80a4578bc3 Fixed CPUID leaf 7 2019-12-14 13:47:55 +01:00
ptitSeb 1e918f3226 Added and Fixed some MMX opcodes (including in Dynarec) 2019-12-14 12:32:02 +01:00
ptitSeb 51552f232e Added wrapped fontconfig library (partial) 2019-12-13 09:05:48 +01:00
ptitSeb 9ebc0463bf Added a few more SSE opcode (and Pier Solar boots now) 2019-12-13 08:31:11 +01:00
ptitSeb 8b6ce21884 Wrapped correctly XextAddDisplay 2019-12-13 00:12:31 +01:00
ptitSeb 3132398bae Fixed a crash when looking for a callback if it's NULL 2019-12-13 00:11:55 +01:00
ptitSeb ff8f50cbf8 Added crude version of FXSAVE and FXRSTOR 2019-12-13 00:08:52 +01:00
ptitSeb 15b0580133 Refactored a bit wrapped X11 lib 2019-12-12 23:04:28 +01:00
ptitSeb eced4f290a removed a warning in wrapped libdl 2019-12-12 23:04:10 +01:00
ptitSeb 8b6e6cfbe9 Added pshufb, another sse3 opcode 2019-12-12 20:29:07 +01:00
ptitSeb 3d46df6922 Fixed dependancies for wrapped dbusmenu-gtk library 2019-12-12 09:40:34 +01:00
ptitSeb 71604cf176 Added wrapped dbusmenu-gtk library 2019-12-12 09:35:53 +01:00
ptitSeb 1ad7a4f6ca Added PALIGNR opcode (in dynarec too) 2019-12-12 09:35:33 +01:00
ptitSeb 03be3e23d4 Added some dbus wrapped functions 2019-12-11 21:38:09 +01:00
ptitSeb 3d7ae93e6c Added wrapped libsndfile (but 1 function that contains callback needs better wrapping) 2019-12-10 23:59:21 +01:00
ptitSeb dc028adc56 Added a few more gtk function (and dwarf fortress runs now) 2019-12-10 23:19:37 +01:00
ptitSeb fc7740a4ce More wrapping around gtk (and some workaround for g_signal_connect_data signal callback) 2019-12-10 23:06:04 +01:00
ptitSeb 2b8b6ee5cc And more gtk-2 wrapped function. Still not enough to be somehow functionnal 2019-12-09 23:57:05 +01:00
ptitSeb 081388d4dc Added one more function to CPUID 2019-12-09 22:33:07 +01:00
ptitSeb 5259e8f122 Added more gtk wrapped functions 2019-12-09 22:17:15 +01:00
ptitSeb 39284057c8 Added wrapped fopencookie function 2019-12-09 21:54:43 +01:00
ptitSeb f9a072ada5 Added (mostly empty) wrapped gtk-2 2019-12-09 21:20:30 +01:00
ptitSeb bff5bdd5dc And a few more wrapped functions 2019-12-09 19:22:41 +01:00
ptitSeb 3f9d60238c Added 2 MMX opcodes, in DYNAREC too (because now, software seems to detect MMX and use it) 2019-12-09 07:38:48 +01:00
ptitSeb ae457d72c4 [DYNAREC] Small optimisation, to reduce time spent looking for next block 2019-12-08 22:57:36 +01:00
ptitSeb bd0e7b7f3f Fixed SDL2 Timer callback (and now Tales of Maj'Eyal boots) 2019-12-08 21:21:00 +01:00
ptitSeb a955c6ea7e Wrapped realpath so self point to emulated binary and not box86 (helps Tales of Maj'Eyal) 2019-12-08 21:08:36 +01:00
ptitSeb ce647c4f90 A few more libpng12 wrapped functions 2019-12-08 21:00:07 +01:00
ptitSeb 92ea53a218 Fixed CPU emulation of ID bit (now Lua Jit accept that emulated CPU) 2019-12-08 20:46:58 +01:00
ptitSeb b7a7dce80d And a new small batch of wrapped functions 2019-12-08 11:16:57 +01:00
ptitSeb b6b1667365 Added openal.so as synonym for openal.so.1 wrapped lib 2019-12-08 11:02:57 +01:00
ptitSeb def9166e43 Added __wprintf_chk wrapped function 2019-12-08 10:52:04 +01:00
ptitSeb 509fc59ede Added some wrapped functions (should help Star Ruler 2) 2019-12-08 09:57:15 +01:00
ptitSeb c5bfa7db40 Disable wrapped libmono for now, as wrapping is to incomplete 2019-12-08 09:18:46 +01:00
ptitSeb ca383864bb Improved a bit error callback handling in x11 (still some issues in Pier Solar) 2019-12-07 23:34:06 +01:00
ptitSeb 4d6ea9d8f9 Added 2 more wrapped function (and The Bard's Tale runs now) 2019-12-07 16:31:11 +01:00
ptitSeb 3859dcea09 Use syscall for file access in syscall instead of a mix of libc/syscall 2019-12-07 14:50:25 +01:00
ptitSeb 1c6f7071bf Better log on syscalls 2019-12-07 14:34:50 +01:00
ptitSeb bb0714b624 Made one emu context per signhandler 2019-12-07 13:51:20 +01:00
ptitSeb 992c530ed5 Also some Align work on SMPEG2 (still no sound in ATDeluxe intro) 2019-12-07 10:36:27 +01:00
ptitSeb 9376d776de Fixed some OggVorbis alignment functions, and fixed SMPEG that needed alignment too (fixed Loki Heroes 3) 2019-12-07 10:17:15 +01:00
ptitSeb 359e5a28c6 Don't reference _IO_2_1_stdXXX_ directly, that should fix build for some platform 2019-12-07 08:55:24 +01:00
ptitSeb 4262beb545 Made some change for software that use _IO_2_2_stdXXX_ (help Loki titles) 2019-12-06 22:32:00 +01:00
ptitSeb 20e3fb7d70 Improve wrapped SDL1 SDL_GetWMinfo function 2019-12-06 00:19:10 +01:00
ptitSeb cfc08dfea9 Added BOX86_LD_PRELOAD to load manualy some libraries 2019-12-05 23:36:40 +01:00
ptitSeb c288ac6514 Two new _IO_proc wrapped function to libc 2019-12-05 22:57:43 +01:00
ptitSeb 326c983bf1 Added wrapped msync function to libc 2019-12-05 22:34:43 +01:00
ptitSeb 073ebaadfc Small change in sys_select and sys_newselect syscalls 2019-12-05 21:52:07 +01:00
ptitSeb 250145530f Small Syscall improvements 2019-12-04 21:39:57 +01:00
ptitSeb 3eacb55dbc Added l and L in wrapper definition (to handle signed and unsigned long) 2019-12-04 14:45:20 +01:00
ptitSeb b1958a81a3 Changed Wrapper, to use K instead of L for faked long double (so L will be free to use for unsigned long) 2019-12-04 10:56:54 +01:00
ptitSeb e04324df79 Made SDL_VIDEO_GL_DRIVER a synonim of BOX86_LIBGL 2019-12-04 08:19:40 +01:00
ptitSeb d048d4964e Allow setting any OpenGL library (doesn't overload SDL_VIDEO_GL_DRIVER variable for SDL/SDL2 program) 2019-12-03 23:25:08 +01:00
ptitSeb 53b56ba123 Added some SDL2 and libc wrapped lib stuff (and now Torchlight2 boots) 2019-12-03 08:47:13 +01:00
ptitSeb 36dc893334 Added more _IO_XXXX wrapped function to libc 2019-12-02 22:01:03 +01:00
ptitSeb 470db114bd Added INSB and INSD (fake) opcodes 2019-12-02 21:56:15 +01:00
ptitSeb 8e02b0f75a Added a couple of syscall (nedded by smac) 2019-12-01 20:18:23 +01:00
ptitSeb 2950c0b8dc Added some old pthread stuff (and now sc3ku 2.0 works) 2019-12-01 19:55:32 +01:00
ptitSeb d03f420b92 Added a few more pulse symbols in pulse-simple wrapped lib 2019-12-01 19:08:12 +01:00
ptitSeb f005e269c9 Added a few more wrapped function for libc and pthread (helps MB: Warband) 2019-12-01 18:00:20 +01:00
ptitSeb d5cd2b009b Move, again, position where box86 load (should help big program) 2019-12-01 17:45:05 +01:00
ptitSeb dd8c5a3b81 Added a mecanism to unload/reload lib with dlclose/dlopen (and now, mohaa can change map) 2019-12-01 17:38:45 +01:00
ptitSeb 3f0a82503f Added a few libc wrapped functions 2019-12-01 17:38:14 +01:00
ptitSeb c82927f841 And rechanged a bit elf symbol resolution/relocation (mohaa still works, unreal works again, nothing seems broken now) 2019-12-01 12:27:42 +01:00
ptitSeb 213f5bf616 Changed loading address of box86, to be < 0x80000000 (this fixed mohaa loading crash) 2019-12-01 00:04:04 +01:00
ptitSeb 87f5f26ecb Changed (again...) a bit how symbol are loaded in elfloader (this fix mohaa loading hang) 2019-12-01 00:03:18 +01:00
ptitSeb ec49241cef Some fix to a few libc wrapped functions 2019-11-30 18:27:49 +01:00
ptitSeb 14f1a8f17b Added some libm,libc and pthread wrapped function, and fixed execvp 2019-11-30 12:22:30 +01:00
ptitSeb aee17dc28a Added a few pulse function in pulse-simple wrapper (may help Warband) 2019-11-30 11:46:05 +01:00
ptitSeb 5828e5a5a7 Added some vorbis/ogg function, and fixed align/unalign of OggVorbis_File struture (that fixes SuperHexxagon) 2019-11-30 11:36:52 +01:00
ptitSeb 6d13315fdb Corrected a typo in wrapped libx11 2019-11-29 11:29:21 +01:00
ptitSeb 75f224ccf8 [DYNAREC] Fixed xchg Reg, Reg on same register (helps steam) 2019-11-28 22:52:20 +01:00
ptitSeb 85646182e0 Fixed a small memory leak 2019-11-27 05:50:58 +01:00
ptitSeb 17654cfe24 Added more slot to NextWireToEvent and NectEventToWire X11 functions 2019-11-26 08:05:26 +01:00
ptitSeb 5286f42314 [DYNAREC] Added a few more 66 0F opcodes 2019-11-25 21:50:14 +01:00
ptitSeb ae9bb4e1c5 Merge branch 'master' of https://github.com/ptitSeb/box86 2019-11-25 20:57:33 +01:00
ptitSeb 77f041505b Fixed a bug in 66 0F opcodes that could have affected many SSE/SSE2 programs 2019-11-25 20:57:17 +01:00
ptitSeb 6d5487da24 Added syscall 164 2019-11-25 10:32:23 +01:00
ptitSeb e4738ab016 Fixed compilation issue on x86 platform 2019-11-25 10:29:44 +01:00
ptitSeb 10d830aba1 Added binfmt box86.conf template 2019-11-25 06:20:20 +01:00
ptitSeb 62e97c8a3e Added syscall 76 2019-11-24 23:57:30 +01:00
ptitSeb 83e9d4606a More changes on TLS data handling 2019-11-24 22:50:49 +01:00
ptitSeb d496fd8977 Fixed some issue when loading a lib after initial load that contains TLS data 2019-11-24 18:56:32 +01:00
ptitSeb f008a397d0 Changed a bit execv so calling x86 binary will use box86 automaticaly 2019-11-24 11:14:39 +01:00
ptitSeb d7c636cf23 [DYNAREC] Optimized (again) how geted works 2019-11-23 23:51:17 +01:00
ptitSeb 2094122541 [DYNAREC] Small optim wgen using cmp against #0 2019-11-23 14:51:03 +01:00
ptitSeb 5b0769fba3 [DYNAREC] Various small fixes and optims 2019-11-23 13:19:52 +01:00
ptitSeb 5323837c32 Changed how RDTSC instruction is done, using clock_gettime (old method with gettimeofday still available) 2019-11-23 12:50:52 +01:00
ptitSeb ade0289e63 FIx an potential issue with __vsprintf_chk wrapped function 2019-11-23 10:08:04 +01:00
ptitSeb 156e45d5a2 Some changes and improvments in some syscalls (mainly around signal handling, but still not enough to be able to run mugen) 2019-11-22 23:15:00 +01:00
ptitSeb 2d47c5502d Some improvements in syscalls (but not enough to run un-upx'd mugen) 2019-11-21 09:04:39 +01:00
ptitSeb 2c963e4e63 Added support for elf with no header section (load upx files, but it wont decompress them yet) 2019-11-20 08:20:47 +01:00
ptitSeb fd890a2eba Try to add pa_strerror function is wrapped pulse-simple 2019-11-19 22:56:54 +01:00
ptitSeb 04df667d0c Some more libc wrapped function (for ut99) 2019-11-19 08:11:00 +01:00
ptitSeb 1853a0f11c Some fixes to Data symbol from native that were not always found 2019-11-19 07:56:05 +01:00
ptitSeb f53f22f53b Made x11 lib access a bit faster 2019-11-19 07:55:19 +01:00
ptitSeb 08d3239129 Made default stack 8Mb 2019-11-19 00:18:32 +01:00
ptitSeb d4b9134bee Some more old functions wrapped (more are needed for Loki SimCity3000 Unlimited) 2019-11-18 08:20:44 +01:00
ptitSeb fce200380c Some syscall and dynarec changes to accomodate SC3k Loki install 2019-11-17 23:29:43 +01:00
ptitSeb a6c82cce5a [DYNAREC] Added DIVPS, SQRTSS and SQRTSD opcodes 2019-11-17 19:33:46 +01:00
ptitSeb 09a1fa0dac [DYNAREC] Added PACKSSDW, PACKUSWB, PCMPGTW and PCMPGTB (helps Desperado) 2019-11-17 18:42:12 +01:00
ptitSeb 7b2064fcd8 [DYNAREC] Added PSHUFLW and PSHUFHW opcodes 2019-11-17 18:06:30 +01:00
ptitSeb d0f19c9378 Added libGL.so in the list a wrapped lib (same as libGL.so.1) 2019-11-17 14:11:20 +01:00
ptitSeb 0c48bc2293 Added a fake IN EAX, Ib opcode 2019-11-17 14:10:41 +01:00
ptitSeb e1efc1682b Added some partial support for XESetWireToEvent and XESetEventToWire (should help descent3 loki demo) 2019-11-17 12:58:03 +01:00
ptitSeb fc1dac64d3 Added a slot for arg[0]... 2019-11-17 12:57:27 +01:00
ptitSeb b1c1558aa3 Added a buch of old syscall (used by some Loki installer) 2019-11-17 11:50:55 +01:00
ptitSeb caee60d13b Added alternate name for libSDL2-2.0.so.0 and libsdl2-2.0.so.0 2019-11-17 10:01:02 +01:00
ptitSeb 26405c2da6 Added a Video using the Dynarec on the readme (needs to do more of them) 2019-11-16 22:12:15 +01:00
ptitSeb 78cb58b146 Fixed a warning 2019-11-16 22:01:21 +01:00
ptitSeb 3a4c2e5b65 Merge pull request #73 from ptitSeb/dynarec
Dynarec
2019-11-16 21:39:11 +01:00
ptitSeb 0b08c51036 [DYNAREC] Add some MMX opcodes (used by fmodex) 2019-11-16 21:05:01 +01:00
ptitSeb 2837f63312 Added real implementation for dl_iterate_phdr (still partially implemented, but enough to run Unreal) 2019-11-16 17:51:46 +01:00
ptitSeb 2119fd8dd3 Added some stuff to ChangeLog 2019-11-16 17:51:00 +01:00
ptitSeb 6e2a7cd0ab [DYNAREC] Added RDTSC opcode 2019-11-16 15:04:43 +01:00
ptitSeb a1b997966e Fix building on non-dynarec 2019-11-16 14:38:59 +01:00
ptitSeb 11c374a4b3 Added a test for swapcontext and friends 2019-11-16 13:55:46 +01:00
ptitSeb 577c5ac45b Added real support for getcontext / setcontext / makecontext and swapcontext (and now DotT Remastered wboots) 2019-11-16 13:52:25 +01:00
ptitSeb 3110ed8df7 Added 2 wrapped functions needed by Eets 2 2019-11-16 11:04:15 +01:00
ptitSeb 421d33772b Added libpulse-simple wrapper (no libpulse for now) 2019-11-15 23:55:11 +01:00
ptitSeb c7366c2e5c [DYNAREC] Fixed SAR for 8 and 16bits (fixed some carts in ZSNES and, at last, The Profile Save bug in WorldOfGoo) 2019-11-15 21:43:11 +01:00
ptitSeb bb59140a06 More Thread hacking, needed by Guacamelee: this need to be uderstood and done a bit better, the hack is very crude for now 2019-11-14 00:06:58 +01:00
ptitSeb 0a89b2777a Removed wrapper.h dependancy also from bridge.h 2019-11-14 00:06:09 +01:00
ptitSeb 4ae0ef5f0d Hacked some Thread function to avoid thread creation failure on arm (fixed Guacamelee) 2019-11-13 23:17:15 +01:00
ptitSeb 475a3374d9 Change comment on Mix_RegisterEffect, but still no support for it 2019-11-13 23:02:43 +01:00
ptitSeb 13a0943ce8 Added a few more wrapped functions (will help Guacamelee later) 2019-11-12 22:52:38 +01:00
ptitSeb 11de135dbe Removed dependancy of wrappers.h from bridge_private.h 2019-11-12 22:51:46 +01:00
ptitSeb 55a4d96814 [DYNAREC] removed obsolete comment 2019-11-12 22:51:09 +01:00
ptitSeb f3fdd52c2a [DYNAREC] Fixed 2 issues with flags (that fixes zsnes, but still not the profile saving of WorldOfGoo) 2019-11-11 23:30:45 +01:00
ptitSeb 04fcdbb989 [DYNAREC] Small change on an unused functionality of get_ed 2019-11-11 23:26:37 +01:00
ptitSeb b6882e4c8b Added another form of MOV Seg, Ew 2019-11-11 23:25:39 +01:00
ptitSeb c18ae816e9 [DYNAREC] And a few more opcodes added 2019-11-10 12:44:07 +01:00
ptitSeb fefc0383b8 [DYNAREC] Added BSR/BSF 32 and 16 bits opcodes 2019-11-10 11:37:59 +01:00
ptitSeb 453c26d648 [DYNAREC] added a new batch of opcodes 2019-11-10 10:32:51 +01:00
ptitSeb eb32c93750 Added Mov Seg, Reg opcode (zsnes seems to run now) 2019-11-10 09:04:50 +01:00
ptitSeb d9907f1e88 [DYNAREC] Fixed LAHF opcode (that didn't fixed WorldOfGoo profiles issue) 2019-11-10 09:04:16 +01:00
ptitSeb 29706f815b Fixed SDL1 RWops that were partly broken since last refactor 2019-11-09 13:36:28 +01:00
ptitSeb 777d20651e [DYNAREC] Added a few more 66 0F opcode (this somefixes fixes #2 on the Pandora) 2019-11-09 12:34:30 +01:00
ptitSeb c62448e866 Merge pull request #72 from icecream95/png
Add some png functions for glmark2
2019-11-09 09:35:13 +01:00
Icecream95 eabe18ba6f Add some png functions for glmark2 2019-11-09 18:21:14 +13:00
ptitSeb 2bbc33bf0d Reworked TLS handling (and now Arkos Tracker 2 seems to load file) 2019-11-08 22:40:18 +01:00
ptitSeb 36f1c54dbf Merge pull request #70 from slock83/dynarec
Added required flags in CMakeLists for dynarec compilation
2019-11-07 18:23:53 +01:00
Anthony Rossi 0ce8b2321c Made a new gameshell target 2019-11-07 18:20:11 +01:00
ptitSeb f5668cce2c More libc wrapped function from @icecream95 2019-11-06 21:41:07 +01:00
ptitSeb c75d658238 change wrapped XInitImage to Bridge the callback function inside the XImage 2019-11-06 07:54:45 +01:00
ptitSeb 718ceacee6 Merge pull request #71 from icecream95/arkos
Add some wrapped functions for Arkos Tracker 2
2019-11-06 07:45:29 +01:00
Icecream95 1444cf979d Add some wrapped functions for Arkos Tracker 2 2019-11-06 18:21:30 +13:00
ptitSeb de4ae72ed7 Use similar code for SDL1.2 RWops than SDL2 RWops, and added smpeg 0.4 wrapped lib 2019-11-05 22:51:27 +01:00
ptitSeb 57fa84f9e7 Removed a warning on pthread_mutexattr_settype undefined 2019-11-05 19:53:14 +01:00
Anthony Rossi 7df5001472 Added required flags in CMakeLists for dynarec compilation 2019-11-05 19:03:26 +01:00
ptitSeb f1e049e8be New fix for the O_ flag convert (and thanks again @icecream95 for all the findings and testing on this) 2019-11-05 09:20:49 +01:00
ptitSeb f664797a36 Added a few more wrapped function (and now, Heretic 2 v1.06c works) 2019-11-05 09:15:33 +01:00
ptitSeb 7bb7c5747a Change previous commit, because it's not AT_ flags but O_ flags that needs convert 2019-11-05 08:50:54 +01:00
ptitSeb aad4c91e01 Try some workaround for AT_ constant not beeing indentical between x86 and ARM (solution is too ARM specific for now, a more generic one need to be done) 2019-11-05 08:23:51 +01:00
ptitSeb 9dc1f02d06 Some opcodes and functions (and now Heretic 2 starts, at least in software mode) 2019-11-05 00:39:46 +01:00
ptitSeb 59be622226 [DYNAREC] Added Compilation help in COMPILE.md 2019-11-05 00:00:47 +01:00
ptitSeb 30cecc7694 Added some check to avoid a crash when tracing __open with a NULL parameter 2019-11-04 23:57:04 +01:00
ptitSeb 18237cbfd9 Added some syscall (so Heretic 2 old text mode installer seems to works) 2019-11-04 23:36:08 +01:00
ptitSeb b4a98f67ee Added 2 libc wrapped functions 2019-11-04 10:41:53 +01:00
ptitSeb 2fef0f9652 [DYNAREC] Fixed FIST(T)(P) on 16bit value 2019-11-04 09:43:47 +01:00
ptitSeb 48c3f927eb [DYNAREC] Try to not mix NEON and VFPU VMOV opcodes 2019-11-03 23:32:04 +01:00
ptitSeb b6e9acc3c3 [WRAPPER] Improved generated dependancy handling again, so _private.h file also trigger a rebuild 2019-11-03 21:12:03 +01:00
ptitSeb 0b74e623d9 [DYNAREC] Fix build system to handle Wrapper dependancy correctly 2019-11-03 20:55:56 +01:00
ptitSeb 88b2d7933b Added a few more Wrapped function (Cook, Serve, Delicious is happy now) 2019-11-03 19:28:59 +01:00
ptitSeb 1b97a18d17 [DYNAREC] Fix rounding for FIST(P) to int32 opcode (Fix HollywoodPlayer) 2019-11-03 10:48:49 +01:00
ptitSeb 2279bc7187 [DYNAREC] Fixed FSCALE opcode (fixing sound and music in Broken Sword 1) 2019-11-02 22:54:35 +01:00
ptitSeb d1903570de [DYNAREC] Fixed emitter for STREXD (should fix Broken Sword 1, among other things) 2019-11-02 22:10:31 +01:00
ptitSeb 92c947e419 [DYNAREC] Added an hidden (for now) option to enable Dynarec on all address (not recomended) 2019-11-02 21:07:41 +01:00
ptitSeb 34061ad32c [DYNAREC] Added MOVHPD opcodes 2019-11-02 19:43:02 +01:00
ptitSeb a1e639dce5 [DYNAREC] Added CVTPD2PS opcode 2019-11-02 16:52:30 +01:00
ptitSeb a29da7ee6a [DYNAREC] Fixed one FISTP that was not restaoring rounding state correctly 2019-11-02 16:52:05 +01:00
ptitSeb 1e8291c3ed [DYNAREC] Added CMPPS and MOVDDUP opcodes 2019-11-02 16:28:55 +01:00
ptitSeb d7d3bcc868 [DYNAREC] Added FISTTP i64, ST0 opcode 2019-11-02 15:16:34 +01:00
ptitSeb a9c45098c7 [DYNAREC] Added push/pop DS/ES and 8bits value as 16bits 2019-11-02 15:01:26 +01:00
ptitSeb 10b1dbefd2 [DYNAREC] Small changes in Linker 2019-11-02 14:44:46 +01:00
ptitSeb 0df5881023 [DYNAREC] Improved cmp/test inlined version, and fixed imul16 opcode 2019-11-02 14:20:26 +01:00
ptitSeb 93c945b2c8 [DYNAREC] Fixed SAR Ed, 1 opcode (and NWN starts again) 2019-11-02 13:57:31 +01:00
ptitSeb 8782441b86 [DYNAREC] Added imul16 inlined version 2019-11-02 11:27:53 +01:00
ptitSeb ab8edf9bec [DYNAREC] Improved a bit D1 and D3 opcode by splitting the code 2019-11-02 11:27:30 +01:00
ptitSeb 2e5b11af1d [DYNAREC] Aligned start of block, to easy debugging a bit 2019-11-02 00:34:44 +01:00
ptitSeb 2e6ea6018e [DYNAREC] Fixed B_MARK macro 2019-11-02 00:33:59 +01:00
ptitSeb f84871cf01 [DYNAREC] Used LDREXD/STREXD to update table jump of linker, and avoid issue with concurent access 2019-11-01 22:02:44 +01:00
ptitSeb 9648517b15 [DYNAREC] And added test32 / test16 / test8 too 2019-11-01 18:51:32 +01:00
ptitSeb 008f612c08 [DYNAREC] Added a dynarec verison of cmp32, cmp16 (still unused) and cmp8 2019-11-01 17:30:56 +01:00
ptitSeb 9bd2a19901 [DYNAREC] Changed how x87 save S32 and S16, should be better 2019-11-01 13:38:11 +01:00
ptitSeb ce8c82042a [DYNAREC] Refactored x87 opcode that used CALL, to avoid purge of all FPU cache 2019-11-01 11:01:03 +01:00
ptitSeb 1310eba02c [DYNAREC] Refactor FPU reg allocation, that is now dynamic for x87 and sse 2019-11-01 09:12:31 +01:00
ptitSeb 2e2b4d4e08 [DYNAREC] Some changes to prepare next refactor on FPU reg, to have dynamic allocation for both x87 and SSE (and MMX when it will be added) 2019-10-31 20:38:55 +01:00
ptitSeb 41bbdca01d [DYNAREC] Fixed Direct Mapping of blocks, that was not always working correctly (espacially for libs) 2019-10-31 08:34:39 +01:00
ptitSeb 0acd350d7f [DYNAREC] Fixed an issue with MOVLPS Gx, Ex (Not a Hero start now) 2019-10-30 22:17:24 +01:00
ptitSeb e7216d42aa [DYNAREC] Added a few more instruction (Risk of Rain works, but a bit slow ingame. Not a Hero crash after selecting language) 2019-10-30 22:03:30 +01:00
ptitSeb 3b33059900 [DYNAREC] A new batch of fixes and improvments (and now FTL runs, and with good speed) 2019-10-30 21:08:18 +01:00
ptitSeb 4c671d9d85 [DYNAREC] This should fix / improved a few things (but FTL still have some issue, main menu is now missing backgound picture and music) 2019-10-30 19:00:06 +01:00
ptitSeb 5004a5f482 [DYNAREC] Fixed a bunch of issue (FTL doesn't crash anymore, but the text in loading screen is still missing) 2019-10-30 09:11:13 +01:00
ptitSeb daab23978b [DYNAREC] Changed the way Dynablocks are allocated and searched, reducing CPU (at the cost of memory footprint) used to search blocks 2019-10-30 07:48:04 +01:00
ptitSeb 6e0d8e000b Don't cleanup Callback for now 2019-10-29 18:47:21 +01:00
ptitSeb 5dc5aeabb8 Bump version, will be 0.1.0 when Dynarec will be mostly complete 2019-10-29 18:47:00 +01:00
ptitSeb faf52f39b5 Extract '.text' for latter use 2019-10-29 18:46:32 +01:00
ptitSeb 5f173bf10a [DYNAREC] Added a few more F2 0F SSE2 opcodes 2019-10-29 08:30:44 +01:00
ptitSeb 14b13b7074 [DYNAREC] Fixed PMULUDQ to used unsigned VMULL (fixing sound in Memoranda) 2019-10-29 08:06:59 +01:00
ptitSeb a84d4f4fa0 [DYNAREC] Fixed some limit usecase of PSRL(D/Q) opcode (but Memoranda sound is still partly broken) 2019-10-28 23:57:49 +01:00
ptitSeb f0b49dfce4 [DYNAREC] Added a new batch of SSE/SSE2 opcodes (UNDERTALE is happy now, at least until the title screen) 2019-10-28 22:46:03 +01:00
ptitSeb a199873854 [DYNAREC] Added more 66 0F SSE/SSE2 opcodes 2019-10-28 20:53:50 +01:00
ptitSeb 0257cbaa14 [DYNAREC] Added a few more 0F opcodes 2019-10-28 18:53:17 +01:00
ptitSeb 73cb0c9ee5 [DYNAREC] Some more SSE/SSE2 opcodes 2019-10-28 15:42:29 +01:00
ptitSeb f754b6269e [DYNAREC] Added UNPCKLPS and UNPCKHPS opcodes 2019-10-27 15:49:19 +01:00
ptitSeb 22c0ae5a49 [DYNAREC] Added a few more opcode, and fixed fpu scratch register helper 2019-10-27 15:14:30 +01:00
ptitSeb 1b23f36ecd [DYNAREC] And a few more SSE opcodes 2019-10-27 11:19:33 +01:00
ptitSeb 35c60d2a11 [DYNAREC] Added a bunch of SSE opcodes 2019-10-27 10:58:25 +01:00
ptitSeb 828fb05d52 [DYNAREC] Added some F3 0F opcodes 2019-10-27 09:51:53 +01:00
ptitSeb fb983c53bf [DYNAREC] Added MOVDQU and XORPS opcodes 2019-10-26 20:33:27 +02:00
ptitSeb 08ef7aa5a0 [DYNAREC] Added POR opcode 2019-10-26 18:56:37 +02:00
ptitSeb 9ac85482ca Added PANDN opcode 2019-10-26 18:52:38 +02:00
ptitSeb 189915f200 [DYNAREC] Added PSRLD and PSRAD opcodes 2019-10-26 18:43:09 +02:00
ptitSeb d68a9cd996 [DYNAREC] Added PCMPEQD opcode 2019-10-26 18:15:33 +02:00
ptitSeb 1a8fd4a979 [DYNAREC] Added PAND opcode 2019-10-26 18:02:49 +02:00
ptitSeb b45c92cf98 [DYNAREC] Fixed VADD(Q) emitte and printer 2019-10-26 17:36:15 +02:00
ptitSeb 11b3d62d16 [DYNAREC] Push/Pop SSE Cache when calling a C function 2019-10-26 17:04:03 +02:00
ptitSeb a46ad1e66e [DYNAREC] Added PADDD opcode 2019-10-26 16:46:08 +02:00
ptitSeb 970135e098 [DYNAREC] Added PSHUFLD opcode 2019-10-26 15:19:04 +02:00
ptitSeb ccec11c059 [DYNAREC] Added a MOVD opcode 2019-10-26 11:44:24 +02:00
ptitSeb 40412a5257 [DYNAREC] Added PXOR opcode 2019-10-25 16:31:29 +02:00
ptitSeb dc07f8666b [DYNAREC] Added MOVDQA opcode 2019-10-25 15:55:58 +02:00
ptitSeb d622dba733 [DYNAREC] Fixed BOX86_DYNAREC_LOG env var 2019-10-25 14:35:09 +02:00
ptitSeb 1dd9c2dddf [DYNAREC] Added DIVSD opcode 2019-10-25 11:46:04 +02:00
ptitSeb 979f49a8b9 [DYNAREC] Added a few more SSE opcodes 2019-10-25 11:40:49 +02:00
ptitSeb 9a11ee556c [DYNAREC] Added ADDSD and MULSD and fixed CVT SI to/from SD 2019-10-24 11:04:44 +02:00
ptitSeb 192b9b8f60 [DYNAREC] Added PUNPCKLQDQ and CMOVxx Gw, Ew 2019-10-24 10:28:25 +02:00
ptitSeb d6485f88fd [DYNAREC] Fixed LODSW and MOVAPS opcodes 2019-10-24 10:13:44 +02:00
ptitSeb bbce797c14 [DYNAREC] Added a 1st SSE opcode 2019-10-24 00:27:03 +02:00
ptitSeb e978d42834 [DYNAREC] Added some NEON infrastructure for SSE 2019-10-23 23:41:12 +02:00
ptitSeb 2d9b5d0f20 [DYNAREC] Some refactoring around VFPU/NEON register, paving to way to SSE/SSE2 2019-10-23 22:17:22 +02:00
ptitSeb 37d2c4ec22 [DYNAREC] fixed IP for CPUID opcode 2019-10-23 21:35:48 +02:00
ptitSeb 4b60120754 [DYNAREC] Added MOSW/STOSW/SCASW/CMPSW/LODSW opcodes 2019-10-23 21:33:57 +02:00
ptitSeb 02ff4614a2 [DYNAREC] Added CPUID, and refactored a bit to avoid useless re-compilaiton when adding a function to dynarec_arm_functions 2019-10-23 21:17:43 +02:00
ptitSeb a0b15aa6c2 Added one more test, not yet integrated in cmake 2019-10-23 20:25:08 +02:00
ptitSeb ca21c41bfc [DYNAREC] Added 2 x87 opcodes 2019-10-23 20:24:41 +02:00
ptitSeb 0591033231 [DYNAREC] Added 2 more adc/sbb 8bits opcodes 2019-10-23 08:19:54 +02:00
ptitSeb c984423c4d {DYNAREC] Fixed issue with LEA reg, [reg-0x80000000] Opcode 2019-10-23 01:08:09 +02:00
ptitSeb 805397b530 [DYNAREC] Added epilog for instructions, to help handling barriers 2019-10-21 22:03:41 +02:00
ptitSeb 394c1bd571 Added 2 more function to SDL2 so VVVVV runs now 2019-10-21 21:59:43 +02:00
ptitSeb c1a016baad [DYNAREC] Fixed opcode F3 C3 that also needs a Barrier (fixes Maldita Castilla) 2019-10-21 00:38:02 +02:00
ptitSeb c667bbcaa6 [DYNAREC] To avoid bus error on some games (like NWN) 2019-10-20 22:03:05 +02:00
ptitSeb 38e7165433 [DYNAREC] Fixed the Call 0 / pop reg hack (and now NeverWinterNight boots again) 2019-10-20 22:02:41 +02:00
ptitSeb e02a8a63e4 [DYNAREC] Fixed an issue with the Barrier optimization (that fix AsciiSector that was broken for some timme) 2019-10-20 19:27:05 +02:00
ptitSeb 420d6e6648 [DYNAREC] Assorted fixed and small improvements. SuperMeatBoy runs again, but WorldOfGoo still don't s't save it's persistant data correctly 2019-10-20 17:16:57 +02:00
ptitSeb a78380a3b4 [DYNAREC] Finished some leftover in local branch refactoring 2019-10-20 08:11:52 +02:00
ptitSeb fe7c2bd388 [DYNAREC] Added one more FLD wrapped function 2019-10-19 19:06:52 +02:00
ptitSeb 930f7ce973 [DYNAREC] Various small changes to try get the Hash for blocks more efficient 2019-10-19 18:17:28 +02:00
ptitSeb 9f0ad317ad [DYNAREC] For now, don't push/pop d8-d15, to save a bit of time 2019-10-19 16:49:17 +02:00
ptitSeb 1a95ca5065 [DYNAREC] Added a few more x87 opcodes 2019-10-19 16:39:17 +02:00
ptitSeb 5b912fd9b3 [DYNAREC] Created (and applied) a macro helper for local branch 2019-10-19 15:37:02 +02:00
ptitSeb ec1ddbd646 [DYNAREC] Added (LOCK) CMPXCHG8b opcode 2019-10-19 15:05:28 +02:00
ptitSeb 8e4fbe58b5 [DYNAREC] Added (LOCK) XADD 8b and 32b 2019-10-19 14:47:34 +02:00
ptitSeb 544e8fb582 [DYNAREC] Added (LOCK) CMPXCHG 8b and 32b opcodes 2019-10-19 14:34:26 +02:00
ptitSeb bd7c19520d [DYNAREC] Added some LOCK: opcodes 2019-10-19 14:03:40 +02:00
ptitSeb 74817f6959 [DYNAREC] Fixed a typo in last refactoring 2019-10-19 14:03:23 +02:00
ptitSeb 6d6d548284 [DYNAREC] Factorised LOCK/UNLOCK for later use in F0 prefix 2019-10-19 13:42:19 +02:00
ptitSeb 4104d6c128 [DYNAREC] Small refactoring on opcode generators 2019-10-19 13:08:12 +02:00
ptitSeb 312e9c7634 [DYNAREC] Added Int 32 bits x87 opeations opcodes 2019-10-19 12:10:30 +02:00
ptitSeb a427be2390 [DYNAREC] Added FCMOVxx opcodes 2019-10-19 12:00:07 +02:00
ptitSeb 33215027e6 [DYNAREC] Added FRNDINT opcode (not sure if perfect) 2019-10-19 10:44:08 +02:00
ptitSeb 9ed1be3632 [DYNAREC] Added FCHS/FABS/FSQRT opcode 2019-10-19 10:18:03 +02:00
ptitSeb 23d4759e16 [DYNAREC] Fixed FCOMI/FCOMIP that weren't setting flags properly (WorldOfGoo works again) 2019-10-19 10:05:49 +02:00
ptitSeb 239acd0733 [DYNAREC] Added FCOMI/FCOMIP and FNSTSW 2019-10-18 23:52:25 +02:00
ptitSeb cdd830c256 [DYNAREC] Improved VCMP printer 2019-10-18 23:51:53 +02:00
ptitSeb f5f5a7533f [DYNAREC] Added VCMP printer 2019-10-18 23:49:29 +02:00
ptitSeb a87c542d6b [DYNAREC] Added FCOM/FCOMP/FUCOM/FUCOMP 2019-10-18 22:57:03 +02:00
ptitSeb 2470905bf8 [DYNAREC] Try to implement a hot block detection to get them local dynablock hash 2019-10-18 21:28:37 +02:00
ptitSeb d1d67b4cf5 [DYNAREC] Added MOVZX/MOVSX Gw, Eb 2019-10-18 19:51:23 +02:00
ptitSeb c010c899b7 [DYNAREC] Added more x87 opcodes (DC series) 2019-10-18 19:45:27 +02:00
ptitSeb 57f1bb36ea [DYNAREC] Made callback to also use Dynarec 2019-10-18 18:44:34 +02:00
ptitSeb 8637c3a8cf [DYNAREC] Added FDIV/FDIVR opcodes 2019-10-18 18:43:59 +02:00
ptitSeb e431c5f4e1 [DYNAREC] Fixed FILD ST0, Ew (and now Castilla Maldita runs fine) 2019-10-18 18:43:22 +02:00
ptitSeb 84e175b265 [DYNAREC] Added some function to help debugging 2019-10-18 18:42:37 +02:00
ptitSeb 34facb1bd4 [DYNAREC] Samll improvements for debugging in-dynarec Native Call and linker effeciancy (Maldita Castila still have issues) 2019-10-18 17:12:44 +02:00
ptitSeb 710d8b311c [DYNAREC] Allow small NativeCall block to be created, even if not in Elf memory 2019-10-18 13:43:35 +02:00
ptitSeb efa5701654 [DYNAREC] So this is still needed (issue can be ssen on pico8 0.11 with disapearing menu in splore) 2019-10-18 13:42:21 +02:00
ptitSeb 2b3ececc3f [DYNAREC] A large bunch of x87 fixes. Now dynarec can run correctly on the (still incomplete) x87, making some speed boost in some cases (like the loading of FTL that is 10x faster now) 2019-10-18 13:11:44 +02:00
ptitSeb eec37508f4 [DYNAREC] Added some Float to Integer opcode (complicated, but seems ok). Still some odd behavour when switching from dynarec to interpretor 2019-10-17 23:46:41 +02:00
ptitSeb dd7f508a91 [DYNAREC] Added FSUB and FSUBR opcodes 2019-10-17 17:59:01 +02:00
ptitSeb d05db1c8d4 [DYNAREC] Some small optim in x87 Cache purge 2019-10-17 17:52:41 +02:00
ptitSeb ef534db878 [DYNAREC] Added some FLD and fixed stack not always updated correctly 2019-10-17 17:39:26 +02:00
ptitSeb 48b4b3d4ae [DYNAREC] Fixed some VCVT print 2019-10-17 17:38:51 +02:00
ptitSeb a15c4771c8 [DYNAREC] Added more FADD opcodes 2019-10-17 17:09:38 +02:00
ptitSeb fc929f622b [DYNAREC] Added an FADD opcode 2019-10-17 17:05:00 +02:00
ptitSeb 707be246e9 [DYNAREC] Optim on stack managment, plus a bunch of fixes and more FMUL opcodes 2019-10-17 16:56:22 +02:00
ptitSeb 3eee490042 [DYNAREC] added a FMULP opcode 2019-10-17 15:44:24 +02:00
ptitSeb 9d3d250545 [DYNAREC] Added FILD opcode 2019-10-17 15:04:36 +02:00
ptitSeb e912e0a98a [DYNAREC] More FPU conversion emitter/printer 2019-10-17 14:54:24 +02:00
ptitSeb 20ca0566be [DYNAREC] oops, fixed FST/FSTP with float conversion 2019-10-17 14:00:21 +02:00
ptitSeb d092d2e6e9 [DYNAREC] Added some FLD/FST/FSTP with float conversion 2019-10-17 13:58:03 +02:00
ptitSeb 180e49847b [DYNAREC] and more FST/FSTP opcodes 2019-10-17 13:33:01 +02:00
ptitSeb 62c055f7ac [DYNAREC] More FST/FSTP opcodes 2019-10-17 13:26:04 +02:00
ptitSeb 3a4753ef70 [DYNAREC] FSTP tbytes works now 2019-10-17 13:18:21 +02:00
ptitSeb 43d02c8f3e [DYNAREC] Fixed current batch of x87 opcodes 2019-10-17 12:52:43 +02:00
ptitSeb b7d6955b43 [DYNAREC] Added a few more x87 opcodes (but they all needs some debugging) 2019-10-17 11:52:37 +02:00
ptitSeb 2941140df6 [DYNAREC] Added a few more x87 opcodes 2019-10-17 11:27:10 +02:00
ptitSeb 47bd2db9c3 [DYNAREC] Added a few more instructions 2019-10-17 11:14:14 +02:00
ptitSeb e7460dc878 [DYNAREC] Added some first x87 opcodes 2019-10-17 10:45:57 +02:00
ptitSeb 89504ca289 [DYNAREC] More infrastructure for x87 opcodes 2019-10-17 10:40:52 +02:00
ptitSeb 652b2d9d86 [DYNAREC] More emitter / printer for x87 2019-10-17 09:37:48 +02:00
ptitSeb c46dff15dc Merge branch 'dynarec' of https://github.com/ptitSeb/box86 into dynarec 2019-10-16 22:57:42 +02:00
ptitSeb b121064454 [DYNAREC] Added one D9 x87 instruction 2019-10-16 22:57:20 +02:00
ptitSeb ce952b9ab9 [DYNAREC] Added some emitter and printer for future x87 emulation 2019-10-16 22:57:20 +02:00
ptitSeb 3567d9eccf [DYNAREC] Added some infrastructure for newt step in opcode implementation 2019-10-16 22:57:20 +02:00
ptitSeb 34e24f6fa4 [DYNAREC] Added ROL/ROR/RCL/RCR/SHL/SHR/SAR 8bits opcodes 2019-10-16 22:57:19 +02:00
ptitSeb 4084c5a448 [DYNAREC] added INC/DEC 16bits 2019-10-16 22:57:19 +02:00
ptitSeb e0e426fe53 [DYNAREC] Fixed DAA/DAS/AAA/AAS opcodes and improved POPF 2019-10-16 22:57:19 +02:00
ptitSeb cede4198fa [DYNAREC] Updated README and USAGE with DynaRec infos 2019-10-16 22:57:19 +02:00
ptitSeb 249d008272 [DYNAREC] Added DAA/DAS/AAA/AAS opcodes 2019-10-16 22:57:19 +02:00
ptitSeb 9ba8db83bd [DYNAREC] Small smart linker improvment 2019-10-16 22:57:19 +02:00
ptitSeb de3202630d [DYNAREC] Made the linker smarter, so it can handled changing jump address 2019-10-16 22:57:19 +02:00
ptitSeb db5a19ec82 [DYNAREC] Don't force linker when jumping to [0xCONSTANT], as it may change (fix pico8 parser) 2019-10-16 22:57:18 +02:00
ptitSeb 5a140abd05 [DYNAREC] Made the Out-of-block epilog to forece last opcode to caclulate flag 2019-10-16 22:57:18 +02:00
ptitSeb c6b6e9e78f [DYNAREC] Fixed some ADC/SBB and all RCL/RCR opcode that was missing USEFLAG macro (GeminiRue boots, but deadlock in menu, pico8 still broken) 2019-10-16 22:57:18 +02:00
ptitSeb f35975e748 [DYNAREC] A few more Fixes and some cosmetics changes (GeminiRue still have parsing issues) 2019-10-16 22:57:18 +02:00
ptitSeb 0056aaf687 [DYNAREC] Fixed regression introduced with last refactoring 2019-10-16 22:57:18 +02:00
ptitSeb bf6ccfbf1e [DYNAREC] Small refactoring 2019-10-16 22:57:18 +02:00
ptitSeb 1467c8f48f [DYNAREC] Fixedsome LDR(B)/STR(B) emitter (but not enough to fix gemini_rue or pico8) 2019-10-16 22:57:18 +02:00
ptitSeb c334e3b4da [DYNAREC] Fixed some 0F prefixed opcode (pico8 still not behave correctly) 2019-10-16 22:57:18 +02:00
ptitSeb c7b6dc0762 [DYNAREC] Fixed some 16bits opcode (now BrokenSword 1 starts, but pico8 still fail with a syntax error when loading some working cards) 2019-10-16 22:57:18 +02:00
ptitSeb 03045e2a78 [DYNAREC] Fixed GETEW/EWBACK and GETEB/EBBACK macro, and now things are working, and faster then without Dynarec 2019-10-16 22:57:18 +02:00
ptitSeb 628bbc5810 [DYNAREC] Fixed GWBACK macro, and added fixedaddress detection when resolving ED, to use Linker when address is fixed 2019-10-16 22:57:18 +02:00
ptitSeb e2ddaa67fa [DYNAREC] Numerous fixes and some refactoring, mostly around 8bits opcodes (stll WorldOfGoo 1.53 cannot boot properly, with libpng errors 2019-10-16 22:57:17 +02:00
ptitSeb dba3675688 [DYNAREC] Added option to disable Linker from command line 2019-10-16 22:57:17 +02:00
ptitSeb 54073bb12f Better wrapped fprintf log 2019-10-16 22:57:17 +02:00
ptitSeb d512a56bb9 [DYNAREC] Added more BT/BTR 32 opcodes 2019-10-16 22:57:17 +02:00
ptitSeb e2e63d3121 [DYNAREC] Fixed some 8bits add/sub opcode (now asciisector runs, faster then without dynarec, but the circle fadeout of the map just doesn't work, so still something wrong somewhere 2019-10-16 22:57:17 +02:00
ptitSeb e51a5682b5 Added some comment for easier debugging 2019-10-16 22:57:17 +02:00
ptitSeb 38991a4b2e [DYNAREC] Added BTC 16/32 opcode 2019-10-16 22:57:17 +02:00
ptitSeb bb368f910c [DYNAREC] Added BTS/BTR 32/16 2019-10-16 22:57:17 +02:00
ptitSeb a68c9f2f65 [DYNAREC] Fixed 66 81 and 66 83 opcodes (Undertale now boot, and is faster, but the splash screen is garbled there there is still something wrong somewhere) 2019-10-16 22:57:17 +02:00
ptitSeb f3535225ab [DYNAREC] Added 66 81 and 66 83 opcode 2019-10-16 22:57:17 +02:00
ptitSeb e20f7663f1 [DYNAREC] Messed up a bit with flags and falgs optim. Seems better but should be refactor 2019-10-16 22:57:16 +02:00
ptitSeb c222cb4e0d [DYNAREC] Fixed shrd/shrld 32/16 opcode (some bugs are still there, at least 1, shown in pico8 0.11 with splore menu going blank) 2019-10-16 22:57:16 +02:00
ptitSeb bcb03fc62f [DYNAREC] Added BT 16 opcode 2019-10-16 22:57:16 +02:00
ptitSeb 51c0afa1a1 [DYNAREC] Added shld/shrd 16 opcode 2019-10-16 22:57:16 +02:00
ptitSeb 6008798b99 [DYNAREC] Added shld/shrd opcodes 2019-10-16 22:57:16 +02:00
ptitSeb 9e1376657b [DYNAREC] Added rol/ror/rcl/rcr/shl/shr/sar 8 opcodes 2019-10-16 22:57:16 +02:00
ptitSeb 572ebc27fa [DYNAREC] rol/ror/rcl/rcr/shl/shr 16 opcodes 2019-10-16 22:57:16 +02:00
ptitSeb 363c851f2b [DYNAREC] Added 66 F7 opcode 2019-10-16 22:57:16 +02:00
ptitSeb 516b4bdbbd [DYNAREC] Added inc/dec reg16 2019-10-16 22:57:16 +02:00
ptitSeb 47f4ca2b3a [DYNAREC] fixed 1 cmp 16 opcode 2019-10-16 22:57:16 +02:00
ptitSeb 4808a19633 [DYNAREC] Added adc/sbc 16 opcodes 2019-10-16 22:57:16 +02:00
ptitSeb b2e61ea5f6 [DYNAREC] The check didn't find that typo in a sub 16 opcode 2019-10-16 22:57:16 +02:00
ptitSeb 5f698e971e [DYNAREC] Add/check sbb 8/32 and add/sub 16 2019-10-16 22:57:15 +02:00
ptitSeb 71ed1c374b [DYNAREC] Add/check/fix the (rep) stos/movs/scas/cmps/lods 8/32bits opcodes 2019-10-16 22:57:15 +02:00
ptitSeb 757ee37905 [DYNAREC] Changed TST emitter, and now valgrind is ok 2019-10-16 22:57:15 +02:00
ptitSeb eee9899cbe [DYNAREC] check/fix rol/ror/rcl/rcr/srl/shr 32 2019-10-16 22:57:15 +02:00
ptitSeb ab00993f21 [DYNAREC] Added pushf/pop and started checking opcode (add32/8, sub32/8, inc32/8, dec32/8, neg32/8, not32/8 and/or/xor/cmp/test32/8 are ok) 2019-10-16 22:57:15 +02:00
ptitSeb 29590f0327 [DYNAREC] Added a few more 8bits opcodes 2019-10-16 22:57:15 +02:00
ptitSeb 459f209a20 [DYNAREC] Some more 16bits instructions 2019-10-16 22:57:15 +02:00
ptitSeb 6f2e829e87 [DYNAREC] Fixed NativeCall hack when RETN is used, and added missing ADC opcode (UNDERTALE now boots, but get stuck after splash screen) 2019-10-16 22:57:14 +02:00
ptitSeb 1d5b98f564 [DYNAREC] Refactored sources, to try reduce compile time 2019-10-16 22:57:14 +02:00
ptitSeb f3837e2954 [DYNAREC] A few more 8bits opcodes 2019-10-16 22:57:14 +02:00
ptitSeb 99306352a3 [DYNAREC] Added a test to not call UpdateFlags if flags are clean 2019-10-16 22:57:14 +02:00
ptitSeb 5e95c04139 [DYNAREC] Fixed some copypasta bugs in 8bits mul/div opcode, and added CALL macro an option to save more regs 2019-10-16 22:57:14 +02:00
ptitSeb ae7f6de506 [DYNAREC] Small (mostly cosmetics) changes 2019-10-16 22:57:13 +02:00
ptitSeb 650ae663e4 [DYNAREC] More 8bits opcodes 2019-10-16 22:57:13 +02:00
ptitSeb 88cffdf4ec [DYNAREC] Added BSWAP opcode 2019-10-16 22:57:13 +02:00
ptitSeb 824547a96d [DYNAREC] Some more 16bits CMP opcode 2019-10-16 22:57:13 +02:00
ptitSeb ad9b6e570b [DYNAREC] Added some 32bits ROR, ROL, RCL and RCR opcodes 2019-10-16 22:57:13 +02:00
ptitSeb 9c9e1944f8 [DYNAREC] added 2 16bits opcodes 2019-10-16 22:57:13 +02:00
ptitSeb 043db28b00 [DYNAREC] Added some ADC and SBB opcode 2019-10-16 22:57:13 +02:00
ptitSeb e8c1af8822 [DYNAREC] Aving multiple mutex is a bad idea, that will lead to deadlock, so reverted to only 1 mutex for dynablocks 2019-10-16 22:57:13 +02:00
ptitSeb 18316aca9a [DYNAREC] Made dynablock per elfimage, and selection with address (that will avoid dynarec'ing a block of code that is not from an elf image, like a JIT'd code, because it may be not constant) 2019-10-16 22:57:13 +02:00
ptitSeb e86df52fbb [DYNAREC] Moved block mutex inside dynablocks structure 2019-10-16 22:57:12 +02:00
ptitSeb b66d0fe188 [DYNAREC] Some small changes in 8bits opcode, and disabled code for adc/sbb opcode (in wrapped C function) 2019-10-16 22:57:12 +02:00
ptitSeb 076fa22486 [DYNAREC] Added more 8bit opcodes 2019-10-16 22:57:12 +02:00
ptitSeb 5b433fd6d0 [DYNAREC] Added some TST opcode 2019-10-16 22:57:12 +02:00
ptitSeb 1aa37cec89 [DYNAREC] Fixed REPx CMPSx and REPx SCASx, and added REP LODSx (and pico8 intro sound is back) 2019-10-16 22:57:12 +02:00
ptitSeb 2c8cd5e4fa [DYNAREC] Added some REP XXX opcode (but it seems the intro sound of pico8 is broken now, at least silent) 2019-10-16 22:57:12 +02:00
ptitSeb 20bd4aed8f [DYNAREC] Added ADC and SBB opcode (wrapper to C implementation for now) 2019-10-16 22:57:12 +02:00
ptitSeb a01ba37d6c [DYNAREC] More 8bits opcodes 2019-10-16 22:57:12 +02:00
ptitSeb 79926534cb [DYNAREC] Added 1 version of 8bit OR and ADD opcode 2019-10-16 22:57:12 +02:00
ptitSeb 695adb718d [DYNAREC] Aded SETxx opcodes 2019-10-16 22:57:12 +02:00
ptitSeb 5284e9270a [DYNAREC] Revert a change that break printer in many opcode. Strange, this need to be analysed latter 2019-10-16 22:57:12 +02:00
ptitSeb e260019df8 [DYNAREC] Fixed a bug with 8bit reg access (still not enough to get undertale to run) 2019-10-16 22:57:12 +02:00
ptitSeb 6c8c4b3e45 [DYNAREC] More bug fixes, but Undertale still crashes 2019-10-16 22:57:11 +02:00
ptitSeb 295d5db77a [DYNAREC] More fixes and improvments, but still some issues with pico8 when using SPLORE 2019-10-16 22:57:11 +02:00
ptitSeb 3e556eae78 [DYNAREC] Fixed Native call when return address is not the expected one (like with set_jump functions). Fixes pixo8, at last 2019-10-16 22:57:11 +02:00
ptitSeb a97f278bb1 [DYNAREC] Fixed NEG opcode (plus a few other cosmetics changes). This fixes airstrike, but not pico8 unfortunatly. 2019-10-16 22:57:11 +02:00
ptitSeb 6cd864e64e [DYNAREC] Fixed a typo in previous refactoring 2019-10-16 22:57:11 +02:00
ptitSeb 1002a23b71 [DYNAREC] Made some macro for scratch register, to cleary see difference between Register and Litteral (also fixed a few things in the process) 2019-10-16 22:57:11 +02:00
ptitSeb 694a6052fe [DYNAREC] And a few more fixes, mainly SUB with flags opcode (still some more fixes to find) 2019-10-16 22:57:11 +02:00
ptitSeb 80bfdf62e9 [DYNAREC] Fixed BT opcode (not enough to fix Airstrike or Pico8) 2019-10-16 22:57:11 +02:00
ptitSeb 6f58c7200c [DYNAREC] Added some 8b opcodes 2019-10-16 22:57:11 +02:00
ptitSeb fce629c1f0 [DYNAREC] One more GS: opcode 2019-10-16 22:57:11 +02:00
ptitSeb 93dad28d0b [DYNAREC] More changes (simplifications), using some armv7 instructions 2019-10-16 22:57:10 +02:00
ptitSeb a7b2a140a9 [DYNAREC] Added a TODO comment 2019-10-16 22:57:10 +02:00
ptitSeb 08a4ba0614 [DYNAREC] Fixed NativeCall Hack 2019-10-16 22:57:10 +02:00
ptitSeb 6275d20fb1 [DYNAREC] Try to improve the geted part 2019-10-16 22:57:10 +02:00
ptitSeb 1318798124 [DYNAREC] Simplified some opcodes 2019-10-16 22:57:10 +02:00
ptitSeb 3f86366cfa [DYNAREC] Added and Fix a bunch of stuff, but there is still something broken somewhere (pico8 doesn't load carts, undertale segfault) 2019-10-16 22:57:10 +02:00
ptitSeb bf5485a268 [DYNAREC] Added XCHG with lock opcode 2019-10-16 22:57:10 +02:00
ptitSeb e34934fd92 [DYNAREC] Added a few more opcodes, including DIVs and MULs 2019-10-16 22:57:09 +02:00
ptitSeb a350f7f955 [DYNAREC] More logic and arithmetics opcodes 2019-10-16 22:57:09 +02:00
ptitSeb 25ddf08f88 [DYNAREC] Added another IMUL opcode 2019-10-16 22:57:09 +02:00
ptitSeb b131c5ee64 [DYNAREC] Added LEAVE opcode 2019-10-16 22:57:09 +02:00
ptitSeb 6b4b19f9da [DYNAREC] And more logic opcodes 2019-10-16 22:57:09 +02:00
ptitSeb 4d7a788598 [DYNAREC] Added BT opcode 2019-10-16 22:57:09 +02:00
ptitSeb 957b85d72e [DYNAREC] Fixed printer for some MOV LSR cases 2019-10-16 22:57:09 +02:00
ptitSeb beed90e6e9 [DYNAREC] Added Mov Eb, Gb opcode 2019-10-16 22:57:08 +02:00
ptitSeb 2c561b1e80 [DYNAREC] Added an OR opcode 2019-10-16 22:57:08 +02:00
ptitSeb e9622d7738 [DYNAREC] Fixed a bug with optimizations. (now FTL starts again) 2019-10-16 22:57:08 +02:00
ptitSeb d285951785 [DYNAREC] Added some hack for regular method to grab EIP 2019-10-16 22:57:08 +02:00
ptitSeb b3bf4a161d [DYNAREC] Added Mov Gw, Ew opcode 2019-10-16 22:57:08 +02:00
ptitSeb ed187e4513 [DYNAREC] Fixed Mov Ew, Gw opcode (Undertale works again correctly, still slower) 2019-10-16 22:57:08 +02:00
ptitSeb 79df27c12b [DYNAREC] Added support for GOT/PLT style Native Call (but there is still something wrong somewhere, Undertale doesn't wrk correctly anymore) 2019-10-16 22:57:08 +02:00
ptitSeb 1fb9a4297c [DYNAREC] Added a movzx opcode 2019-10-16 22:57:08 +02:00
ptitSeb 9b914a7791 [DYNAREC] Added a imul opcode 2019-10-16 22:57:08 +02:00
ptitSeb 8891cbee05 [DYNAREC] Added CMOVxx opcode 2019-10-16 22:57:08 +02:00
ptitSeb 3c36e8bfe6 [DYNAREC] More dynarec opcode 2019-10-16 22:57:08 +02:00
ptitSeb 3e55dd04f2 [DYNAREC] Added another 16bit opcode 2019-10-16 22:57:08 +02:00
ptitSeb 96f084d69e [DYNAREC] Added Syscall opcode 2019-10-16 22:57:08 +02:00
ptitSeb 4c69e02643 [DYNAREC] Fix and improvement to printer 2019-10-16 22:57:07 +02:00
ptitSeb 0b4015fa9f [DYNAREC] Added a 16bit opcode 2019-10-16 22:57:07 +02:00
ptitSeb 3f09f67fca [DYNAREC] Small refactoring of dynarec 2019-10-16 22:57:07 +02:00
ptitSeb b170e39523 [DYNAREC] Small fix on Exitx86emu opcode 2019-10-16 22:57:07 +02:00
ptitSeb 119a42d696 [DYNAREC] Added native call in dynarec, and fixed lastest change in trace that was consuming useless cpu 2019-10-16 22:57:07 +02:00
ptitSeb 613f46e8a7 [DYNAREC] More conditionnal jump 2019-10-16 22:57:07 +02:00
ptitSeb 2f32f36e47 [DYNAREC] Fixed Mov Reg, Id, fixing dynarec with undertale (still not faster) 2019-10-16 22:57:07 +02:00
ptitSeb 754844d4bd [DYNAREC] Generated code can now also emit trace (for easier debugging) 2019-10-16 22:57:07 +02:00
ptitSeb 91dfeba954 [DYNAREC] Implemented Barrier on optim propagation 2019-10-16 22:57:07 +02:00
ptitSeb af24315968 [DYNAREC] Added a small optimisation about flags handling 2019-10-16 22:57:07 +02:00
ptitSeb af7cb756cd [DYNAREC] Fixed a few stuff in opcode 2019-10-16 22:57:07 +02:00
ptitSeb de403a57e1 [DYNAREC] Added a few more opcode 2019-10-16 22:57:06 +02:00
ptitSeb 386e8e5383 [DYNAREC] Fixed LDR and STM print 2019-10-16 22:57:06 +02:00
ptitSeb 19cfbd07b5 [DYNAREC] More opcode 2019-10-16 22:57:06 +02:00
ptitSeb 69e2b511af [DYNAREC] Added a few more instructions 2019-10-16 22:57:06 +02:00
ptitSeb c7b1564a20 [DYNAREC] Fixed B(L) printer 2019-10-16 22:57:06 +02:00
ptitSeb b313e75ef6 [DYNAREC] A few simplification in the dynarec writing 2019-10-16 22:57:06 +02:00
ptitSeb d43072e902 [DYNAREC] Added a few more opcodes 2019-10-16 22:57:06 +02:00
ptitSeb 5d7c1e84bc [DYNAREC] Change handling of FLAGS, now using same mecanism than Interpretor 2019-10-16 22:57:06 +02:00
ptitSeb 9e57593a79 Fixed fork 2019-10-16 22:57:06 +02:00
ptitSeb 2a8fc16241 [DYNAREC] Fixed B(L) emitter 2019-10-16 22:57:06 +02:00
ptitSeb 7c1ca92fcb [DYNAREC] Fix arm_printer for BLX opcode 2019-10-16 22:57:06 +02:00
ptitSeb dd81e06d35 [DYNAREC] Added a few more opcode 2019-10-16 22:57:06 +02:00
ptitSeb 6f17e1e0e8 [DYNAREC] Fixed linker (was useless before), and added JZ opcode 2019-10-16 22:57:05 +02:00
ptitSeb 8c4a4c2999 [DYNAREC] Added a few more instructions 2019-10-16 22:57:05 +02:00
ptitSeb ed92cd0945 [DYNAREC] Fixed issue with flags, now all test are OK 2019-10-16 22:57:05 +02:00
ptitSeb eeeaa6d339 [DYNAREC] Another small improvment in dynarec dump 2019-10-16 22:57:05 +02:00
ptitSeb 8c8782d1e5 [DYNAREC] Better dynarec dump in some cases 2019-10-16 22:57:05 +02:00
ptitSeb 6b6b926347 [DYNAREC] Small optimization of get_ed 2019-10-16 22:57:05 +02:00
ptitSeb 2ef3b9689e [DYNAREC] Fixed an issue with arm_printer 2019-10-16 22:57:05 +02:00
ptitSeb 023b0723ea Refined .gitignore 2019-10-16 22:57:05 +02:00
ptitSeb 97d2e4bc30 [DYNAREC] Added a crude Arm opcode printer, to help debugging 2019-10-16 22:57:05 +02:00
ptitSeb c2b2a73329 [DYNAREC] Small improvement in dynarec logs 2019-10-16 22:57:05 +02:00
ptitSeb 4185a6a144 [DYNAREC] Fixed and add some opcode, still some bug to fix (test10 broken) 2019-10-16 22:57:05 +02:00
ptitSeb 3eb2ef6cfd [DYNAREC] Created and changed some macro to simplify opcode writing 2019-10-16 22:57:05 +02:00
ptitSeb 0b1fec3927 [DYNAREC] Fixed some opcode, all tests pass now 2019-10-16 22:57:04 +02:00
ptitSeb 25f8668b88 [DYNAREC] Enabled dynarec in more case than just thread, and clear cache for newly filled dynarec block (still test 10 and 12 broken) 2019-10-16 22:57:04 +02:00
ptitSeb 1b47bed603 [DYNAREC] Add runtime linker between blocks 2019-10-16 22:57:04 +02:00
ptitSeb bf418055a3 [DYNAREC] Small typo 2019-10-16 22:57:04 +02:00
ptitSeb 125224f976 [DYNAREC], Change the way mmap is called (batched now), and put many things behind mutex (still issues with threads 2019-10-16 22:57:04 +02:00
ptitSeb af34862b9c [DYNAREC] Fixed Flags mirroring 2019-10-16 22:57:04 +02:00
ptitSeb d6121c4d82 [DYNAREC] Added XOR Gd, Ed opcode 2019-10-16 22:57:04 +02:00
ptitSeb 11f03846ab [DYNAREC] Small geted optimization 2019-10-16 22:57:04 +02:00
ptitSeb d4ad0bf00a [DYNAREC] Added GS: Infrastructure 2019-10-16 22:57:04 +02:00
ptitSeb ed12f40b32 [DYNAREC] Added a global switch, plus some 0xFF opcodes 2019-10-16 22:57:04 +02:00
ptitSeb f018edcc5b [DYNAREC] Added Sub Ed, Ix and Mov Ed, Id opcode 2019-10-16 22:57:03 +02:00
ptitSeb 078742c054 [DYNAREC] Added Ret opcode 2019-10-16 22:57:03 +02:00
ptitSeb 3e05a60d38 [DYNAREC] Added Mov Gd, Ed 2019-10-16 22:57:03 +02:00
ptitSeb 6cacba1a67 [DYNAREC] Added Call relative opcode 2019-10-16 22:57:03 +02:00
ptitSeb 21bb5d5e2a [DYNAREC] Added simple Mov Ed, Gd opcode, and improved Push 2019-10-16 22:57:03 +02:00
ptitSeb 57c13b9a73 [DYNAREC] First working draft of the Dynarec. Only PUSH instruction for now, so not usefull yet 2019-10-16 22:57:03 +02:00
ptitSeb 5a41eaaa6f [DYNAREC] More infrastructure, no emiter yet 2019-10-16 22:57:03 +02:00
ptitSeb 71efacc050 [DYNAREC] Put some atomic to lock concurent access to dynablock list 2019-10-16 22:57:03 +02:00
ptitSeb e64b6cf64a [DYNAREC] Added some basic infrastructure 2019-10-16 22:57:03 +02:00
ptitSeb bff43a86e8 Update wrappedalut.c 2019-10-16 22:55:18 +02:00
ptitSeb 1de4494bc2 [DYNAREC] Added one D9 x87 instruction 2019-10-16 19:49:52 +02:00
ptitSeb 7edace78f7 [DYNAREC] Added some emitter and printer for future x87 emulation 2019-10-16 19:33:33 +02:00
ptitSeb 106ebc1abd [DYNAREC] Added some infrastructure for newt step in opcode implementation 2019-10-16 14:16:56 +02:00
ptitSeb 884aebab48 [DYNAREC] Added ROL/ROR/RCL/RCR/SHL/SHR/SAR 8bits opcodes 2019-10-15 23:06:48 +02:00
ptitSeb fec4803386 [DYNAREC] added INC/DEC 16bits 2019-10-15 22:56:48 +02:00
ptitSeb c39c8cceef [DYNAREC] Fixed DAA/DAS/AAA/AAS opcodes and improved POPF 2019-10-15 19:46:52 +02:00
ptitSeb 34f71cf75a [DYNAREC] Updated README and USAGE with DynaRec infos 2019-10-15 14:39:33 +02:00
ptitSeb c631ee1292 [DYNAREC] Added DAA/DAS/AAA/AAS opcodes 2019-10-15 14:13:59 +02:00
ptitSeb df9cbc04a8 [DYNAREC] Small smart linker improvment 2019-10-15 09:24:14 +02:00
ptitSeb bd2728399d [DYNAREC] Made the linker smarter, so it can handled changing jump address 2019-10-15 08:44:14 +02:00
ptitSeb 556465529b [DYNAREC] Don't force linker when jumping to [0xCONSTANT], as it may change (fix pico8 parser) 2019-10-15 08:20:40 +02:00
ptitSeb 4033c7aef0 [DYNAREC] Made the Out-of-block epilog to forece last opcode to caclulate flag 2019-10-15 08:19:49 +02:00
ptitSeb 09609997b3 [DYNAREC] Fixed some ADC/SBB and all RCL/RCR opcode that was missing USEFLAG macro (GeminiRue boots, but deadlock in menu, pico8 still broken) 2019-10-14 22:49:56 +02:00
ptitSeb dd510d9086 [DYNAREC] A few more Fixes and some cosmetics changes (GeminiRue still have parsing issues) 2019-10-14 21:37:49 +02:00
ptitSeb d65e14910b [DYNAREC] Fixed regression introduced with last refactoring 2019-10-14 19:58:53 +02:00
ptitSeb fe0809cef8 [DYNAREC] Small refactoring 2019-10-14 18:33:34 +02:00
ptitSeb 0532f5adc3 [DYNAREC] Fixedsome LDR(B)/STR(B) emitter (but not enough to fix gemini_rue or pico8) 2019-10-13 22:53:36 +02:00
ptitSeb fadee457ba [DYNAREC] Fixed some 0F prefixed opcode (pico8 still not behave correctly) 2019-10-13 21:12:06 +02:00
ptitSeb 10bda2b797 [DYNAREC] Fixed some 16bits opcode (now BrokenSword 1 starts, but pico8 still fail with a syntax error when loading some working cards) 2019-10-13 20:40:00 +02:00
ptitSeb 262e93a6b4 [DYNAREC] Fixed GETEW/EWBACK and GETEB/EBBACK macro, and now things are working, and faster then without Dynarec 2019-10-13 18:06:46 +02:00
ptitSeb 8c4b2bb777 [DYNAREC] Fixed GWBACK macro, and added fixedaddress detection when resolving ED, to use Linker when address is fixed 2019-10-13 17:23:57 +02:00
ptitSeb f7fff13094 [DYNAREC] Numerous fixes and some refactoring, mostly around 8bits opcodes (stll WorldOfGoo 1.53 cannot boot properly, with libpng errors 2019-10-13 17:01:43 +02:00
ptitSeb e0b2560ffa [DYNAREC] Added option to disable Linker from command line 2019-10-13 14:23:41 +02:00
ptitSeb dc5fc68387 Better wrapped fprintf log 2019-10-13 12:14:04 +02:00
ptitSeb b3027741f6 [DYNAREC] Added more BT/BTR 32 opcodes 2019-10-13 11:27:28 +02:00
ptitSeb ad8c74e0c3 [DYNAREC] Fixed some 8bits add/sub opcode (now asciisector runs, faster then without dynarec, but the circle fadeout of the map just doesn't work, so still something wrong somewhere 2019-10-13 11:26:49 +02:00
ptitSeb 7c569f5b80 Added some comment for easier debugging 2019-10-13 11:21:45 +02:00
ptitSeb 06d07b200e [DYNAREC] Added BTC 16/32 opcode 2019-10-13 10:51:36 +02:00
ptitSeb 19c6e4e79d [DYNAREC] Added BTS/BTR 32/16 2019-10-13 10:44:52 +02:00
ptitSeb f78ea4d279 [DYNAREC] Fixed 66 81 and 66 83 opcodes (Undertale now boot, and is faster, but the splash screen is garbled there there is still something wrong somewhere) 2019-10-12 23:24:52 +02:00
ptitSeb e95142fffc [DYNAREC] Added 66 81 and 66 83 opcode 2019-10-12 23:02:38 +02:00
ptitSeb 7f181e09da [DYNAREC] Messed up a bit with flags and falgs optim. Seems better but should be refactor 2019-10-12 22:38:13 +02:00
ptitSeb 5276449269 [DYNAREC] Fixed shrd/shrld 32/16 opcode (some bugs are still there, at least 1, shown in pico8 0.11 with splore menu going blank) 2019-10-12 20:37:39 +02:00
ptitSeb f63cc905d5 [DYNAREC] Added BT 16 opcode 2019-10-12 19:37:21 +02:00
ptitSeb fa51cb3ea1 [DYNAREC] Added shld/shrd 16 opcode 2019-10-12 19:18:14 +02:00
ptitSeb 1fb5dd39ed [DYNAREC] Added shld/shrd opcodes 2019-10-12 19:07:31 +02:00
ptitSeb 1d85be7bb2 [DYNAREC] Added rol/ror/rcl/rcr/shl/shr/sar 8 opcodes 2019-10-12 18:47:42 +02:00
ptitSeb e7ffc6d0d3 [DYNAREC] rol/ror/rcl/rcr/shl/shr 16 opcodes 2019-10-12 18:26:41 +02:00
ptitSeb dc9d6ff55a [DYNAREC] Added 66 F7 opcode 2019-10-12 18:05:36 +02:00
ptitSeb 335dbf233c [DYNAREC] Added inc/dec reg16 2019-10-12 17:52:02 +02:00
ptitSeb cb8cb43194 [DYNAREC] fixed 1 cmp 16 opcode 2019-10-12 17:45:23 +02:00
ptitSeb c234a4fefc [DYNAREC] Added adc/sbc 16 opcodes 2019-10-12 17:42:41 +02:00
ptitSeb 682ec6745c [DYNAREC] The check didn't find that typo in a sub 16 opcode 2019-10-12 17:26:15 +02:00
ptitSeb 5de4ec65e2 [DYNAREC] Add/check sbb 8/32 and add/sub 16 2019-10-12 17:24:25 +02:00
ptitSeb e15e8259a2 [DYNAREC] Add/check/fix the (rep) stos/movs/scas/cmps/lods 8/32bits opcodes 2019-10-12 16:41:20 +02:00
ptitSeb aac6571998 [DYNAREC] Changed TST emitter, and now valgrind is ok 2019-10-12 14:43:19 +02:00
ptitSeb 129730e73f [DYNAREC] check/fix rol/ror/rcl/rcr/srl/shr 32 2019-10-12 14:36:34 +02:00
ptitSeb f9ab62025d [DYNAREC] Added pushf/pop and started checking opcode (add32/8, sub32/8, inc32/8, dec32/8, neg32/8, not32/8 and/or/xor/cmp/test32/8 are ok) 2019-10-12 11:26:22 +02:00
ptitSeb 7a61fff0c8 [DYNAREC] Added a few more 8bits opcodes 2019-10-11 23:05:57 +02:00
ptitSeb 43f407559d [DYNAREC] Some more 16bits instructions 2019-10-11 22:23:38 +02:00
ptitSeb b2eefc00e8 [DYNAREC] Fixed NativeCall hack when RETN is used, and added missing ADC opcode (UNDERTALE now boots, but get stuck after splash screen) 2019-10-11 20:54:18 +02:00
ptitSeb 21ca9af789 [DYNAREC] Refactored sources, to try reduce compile time 2019-10-11 16:26:48 +02:00
ptitSeb 068b259777 [DYNAREC] A few more 8bits opcodes 2019-10-11 14:06:23 +02:00
ptitSeb 15225bed69 [DYNAREC] Added a test to not call UpdateFlags if flags are clean 2019-10-11 11:50:21 +02:00
ptitSeb 6dd402978f [DYNAREC] Fixed some copypasta bugs in 8bits mul/div opcode, and added CALL macro an option to save more regs 2019-10-11 11:22:09 +02:00
ptitSeb 717e6ac0f9 [DYNAREC] Small (mostly cosmetics) changes 2019-10-11 09:29:00 +02:00
ptitSeb ed3c1ccf49 [DYNAREC] More 8bits opcodes 2019-10-10 23:01:16 +02:00
ptitSeb b8f540474d [DYNAREC] Added BSWAP opcode 2019-10-10 22:13:58 +02:00
ptitSeb 32562b84bf [DYNAREC] Some more 16bits CMP opcode 2019-10-10 21:53:58 +02:00
ptitSeb 488932fa17 [DYNAREC] Added some 32bits ROR, ROL, RCL and RCR opcodes 2019-10-10 21:02:43 +02:00
ptitSeb 2e61a2a4db [DYNAREC] added 2 16bits opcodes 2019-10-10 20:22:48 +02:00
ptitSeb fd9f620bab [DYNAREC] Added some ADC and SBB opcode 2019-10-10 20:12:44 +02:00
ptitSeb ac72791a48 [DYNAREC] Aving multiple mutex is a bad idea, that will lead to deadlock, so reverted to only 1 mutex for dynablocks 2019-10-10 19:51:06 +02:00
ptitSeb 171f9b317c [DYNAREC] Made dynablock per elfimage, and selection with address (that will avoid dynarec'ing a block of code that is not from an elf image, like a JIT'd code, because it may be not constant) 2019-10-10 16:48:11 +02:00
ptitSeb f311a6f566 [DYNAREC] Moved block mutex inside dynablocks structure 2019-10-10 15:07:11 +02:00
ptitSeb df0084e037 [DYNAREC] Some small changes in 8bits opcode, and disabled code for adc/sbb opcode (in wrapped C function) 2019-10-10 09:35:47 +02:00
ptitSeb 4ec601b537 [DYNAREC] Added more 8bit opcodes 2019-10-10 08:31:32 +02:00
ptitSeb 29da3f9408 [DYNAREC] Added some TST opcode 2019-10-10 08:11:17 +02:00
ptitSeb aa014eaf14 [DYNAREC] Fixed REPx CMPSx and REPx SCASx, and added REP LODSx (and pico8 intro sound is back) 2019-10-10 07:54:27 +02:00
ptitSeb e2306956a5 [DYNAREC] Added some REP XXX opcode (but it seems the intro sound of pico8 is broken now, at least silent) 2019-10-10 00:13:37 +02:00
ptitSeb d604f0f746 [DYNAREC] Added ADC and SBB opcode (wrapper to C implementation for now) 2019-10-09 22:13:24 +02:00
ptitSeb 6fff9c1314 [DYNAREC] More 8bits opcodes 2019-10-09 22:02:51 +02:00
ptitSeb faec52284f [DYNAREC] Added 1 version of 8bit OR and ADD opcode 2019-10-09 21:49:26 +02:00
ptitSeb bf1c6ee242 [DYNAREC] Aded SETxx opcodes 2019-10-09 21:32:04 +02:00
ptitSeb 330da45dca [DYNAREC] Revert a change that break printer in many opcode. Strange, this need to be analysed latter 2019-10-09 15:56:32 +02:00
ptitSeb c79bd682e5 [DYNAREC] Fixed a bug with 8bit reg access (still not enough to get undertale to run) 2019-10-09 08:39:08 +02:00
ptitSeb e9f6992059 [DYNAREC] More bug fixes, but Undertale still crashes 2019-10-09 00:26:07 +02:00
ptitSeb 289d6beb17 Merge pull request #66 from kant/patch-2
Syntax issues fixed
2019-10-08 23:49:06 +02:00
ptitSeb e11e825c3a Merge pull request #65 from kant/patch-1
Syntax issue on line 17
2019-10-08 23:48:40 +02:00
ptitSeb 2916541885 [DYNAREC] More fixes and improvments, but still some issues with pico8 when using SPLORE 2019-10-08 22:47:48 +02:00
Darío Hereñú 3eac50321c Syntax issues fixed 2019-10-08 17:44:06 -03:00
Darío Hereñú 1f2442f384 Syntax issue on line 17 2019-10-08 17:39:17 -03:00
ptitSeb 0ea6c8e1e2 [DYNAREC] Fixed Native call when return address is not the expected one (like with set_jump functions). Fixes pixo8, at last 2019-10-08 21:44:18 +02:00
ptitSeb 0a6d6cee32 [DYNAREC] Fixed NEG opcode (plus a few other cosmetics changes). This fixes airstrike, but not pico8 unfortunatly. 2019-10-08 20:51:05 +02:00
ptitSeb c8debfd8ed [DYNAREC] Fixed a typo in previous refactoring 2019-10-08 17:50:17 +02:00
ptitSeb c6ef22a226 [DYNAREC] Made some macro for scratch register, to cleary see difference between Register and Litteral (also fixed a few things in the process) 2019-10-08 16:21:56 +02:00
ptitSeb 0d8a21e85b [DYNAREC] And a few more fixes, mainly SUB with flags opcode (still some more fixes to find) 2019-10-08 08:41:00 +02:00
ptitSeb 88f97ebaf3 [DYNAREC] Fixed BT opcode (not enough to fix Airstrike or Pico8) 2019-10-07 23:38:22 +02:00
ptitSeb b652e9959c [DYNAREC] Added some 8b opcodes 2019-10-07 21:59:34 +02:00
ptitSeb cadea596e1 [DYNAREC] One more GS: opcode 2019-10-07 21:26:57 +02:00
ptitSeb f7074bcce9 [DYNAREC] More changes (simplifications), using some armv7 instructions 2019-10-07 21:19:22 +02:00
ptitSeb 6ab8e78133 [DYNAREC] Added a TODO comment 2019-10-07 15:31:34 +02:00
ptitSeb a8c53255a8 [DYNAREC] Fixed NativeCall Hack 2019-10-07 15:17:14 +02:00
ptitSeb aaeb4677e1 [DYNAREC] Try to improve the geted part 2019-10-07 14:50:55 +02:00
ptitSeb 269535411b [DYNAREC] Simplified some opcodes 2019-10-07 09:28:15 +02:00
ptitSeb 33f179b78f [DYNAREC] Added and Fix a bunch of stuff, but there is still something broken somewhere (pico8 doesn't load carts, undertale segfault) 2019-10-07 00:01:08 +02:00
ptitSeb abe6d22870 [DYNAREC] Added XCHG with lock opcode 2019-10-06 14:36:24 +02:00
ptitSeb 2ac095fd04 [DYNAREC] Added a few more opcodes, including DIVs and MULs 2019-10-06 14:04:27 +02:00
ptitSeb a319b98daf [DYNAREC] More logic and arithmetics opcodes 2019-10-06 11:21:14 +02:00
ptitSeb 547ed02318 [DYNAREC] Added another IMUL opcode 2019-10-06 10:06:17 +02:00
ptitSeb 15faf7e061 [DYNAREC] Added LEAVE opcode 2019-10-05 22:46:34 +02:00
ptitSeb afc91dfc4d [DYNAREC] And more logic opcodes 2019-10-05 22:40:08 +02:00
ptitSeb 8a6ccf6ddf [DYNAREC] Added BT opcode 2019-10-05 22:03:04 +02:00
ptitSeb 7014b1a1c0 [DYNAREC] Fixed printer for some MOV LSR cases 2019-10-05 22:02:39 +02:00
ptitSeb 6b12ad18ef [DYNAREC] Added Mov Eb, Gb opcode 2019-10-05 21:11:26 +02:00
ptitSeb 8f6021657f [DYNAREC] Added an OR opcode 2019-10-05 20:18:32 +02:00
ptitSeb 185fe1f092 [DYNAREC] Fixed a bug with optimizations. (now FTL starts again) 2019-10-05 19:54:49 +02:00
ptitSeb ca0d56e33e [DYNAREC] Added some hack for regular method to grab EIP 2019-10-05 19:14:46 +02:00
ptitSeb fb1b84c12e [DYNAREC] Added Mov Gw, Ew opcode 2019-10-05 17:29:08 +02:00
ptitSeb bfcff3170e [DYNAREC] Fixed Mov Ew, Gw opcode (Undertale works again correctly, still slower) 2019-10-05 17:23:23 +02:00
ptitSeb e864759628 [DYNAREC] Added support for GOT/PLT style Native Call (but there is still something wrong somewhere, Undertale doesn't wrk correctly anymore) 2019-10-05 16:43:55 +02:00
ptitSeb 14ba777e85 [DYNAREC] Added a movzx opcode 2019-10-05 15:07:19 +02:00
ptitSeb 268d68927d [DYNAREC] Added a imul opcode 2019-10-05 14:44:05 +02:00
ptitSeb 70ac928a78 [DYNAREC] Added CMOVxx opcode 2019-10-05 13:41:15 +02:00
ptitSeb c16987c1b6 [DYNAREC] More dynarec opcode 2019-10-05 13:08:55 +02:00
ptitSeb 3f45496b70 [DYNAREC] Added another 16bit opcode 2019-10-05 12:54:58 +02:00
ptitSeb 58ebd0f1a3 [DYNAREC] Added Syscall opcode 2019-10-05 12:41:19 +02:00
ptitSeb 56ce86b08b [DYNAREC] Fix and improvement to printer 2019-10-05 12:41:04 +02:00
ptitSeb 4d6e6c43fd [DYNAREC] Added a 16bit opcode 2019-10-05 12:19:14 +02:00
ptitSeb 08d8f98742 [DYNAREC] Small refactoring of dynarec 2019-10-05 11:02:57 +02:00
ptitSeb d501c6f321 [DYNAREC] Small fix on Exitx86emu opcode 2019-10-05 10:56:33 +02:00
ptitSeb 6ff13a1c5d [DYNAREC] Added native call in dynarec, and fixed lastest change in trace that was consuming useless cpu 2019-10-05 10:46:42 +02:00
ptitSeb 35a3cf229a [DYNAREC] More conditionnal jump 2019-10-05 09:46:53 +02:00
ptitSeb 9619b023c7 [DYNAREC] Fixed Mov Reg, Id, fixing dynarec with undertale (still not faster) 2019-10-04 21:42:59 +02:00
ptitSeb c0251d78a2 [DYNAREC] Generated code can now also emit trace (for easier debugging) 2019-10-04 21:16:23 +02:00
ptitSeb 4877ea333d [DYNAREC] Implemented Barrier on optim propagation 2019-10-04 19:26:16 +02:00
ptitSeb e11da4bc5f [DYNAREC] Added a small optimisation about flags handling 2019-10-04 18:12:07 +02:00
ptitSeb 0d0ac4e7f5 [DYNAREC] Fixed a few stuff in opcode 2019-10-04 16:42:25 +02:00
ptitSeb 7b33635997 [DYNAREC] Added a few more opcode 2019-10-04 16:07:47 +02:00
ptitSeb 47fd5dc02f [DYNAREC] Fixed LDR and STM print 2019-10-04 16:07:32 +02:00
ptitSeb 37568985ac [DYNAREC] More opcode 2019-10-04 11:25:20 +02:00
ptitSeb 0dc1fcebc3 [DYNAREC] Added a few more instructions 2019-10-04 11:18:02 +02:00
ptitSeb ea6d20f154 [DYNAREC] Fixed B(L) printer 2019-10-04 10:35:55 +02:00
ptitSeb cb430ac2b1 [DYNAREC] A few simplification in the dynarec writing 2019-10-04 08:45:54 +02:00
ptitSeb fbf7e5b92b [DYNAREC] Added a few more opcodes 2019-10-04 00:11:46 +02:00
ptitSeb 04bae841bf [DYNAREC] Change handling of FLAGS, now using same mecanism than Interpretor 2019-10-03 23:54:42 +02:00
ptitSeb c2ae984b2c Fixed fork 2019-10-03 21:51:31 +02:00
ptitSeb c78a0c31b5 [DYNAREC] Fixed B(L) emitter 2019-10-03 21:49:57 +02:00
ptitSeb 64f519b094 [DYNAREC] Fix arm_printer for BLX opcode 2019-10-03 10:21:44 +02:00
ptitSeb 4fc50631c1 [DYNAREC] Added a few more opcode 2019-10-02 23:36:45 +02:00
ptitSeb 1e0411b303 [DYNAREC] Fixed linker (was useless before), and added JZ opcode 2019-10-02 23:12:50 +02:00
ptitSeb 16c77bedde [DYNAREC] Added a few more instructions 2019-10-02 20:21:15 +02:00
ptitSeb 5c143cf736 [DYNAREC] Fixed issue with flags, now all test are OK 2019-10-02 20:06:15 +02:00
ptitSeb ffe8831ff6 [DYNAREC] Another small improvment in dynarec dump 2019-10-02 18:20:16 +02:00
ptitSeb 9395c39d4f [DYNAREC] Better dynarec dump in some cases 2019-10-02 18:00:35 +02:00
ptitSeb 827c9169f9 [DYNAREC] Small optimization of get_ed 2019-10-02 16:55:21 +02:00
ptitSeb d3f17d0ced [DYNAREC] Fixed an issue with arm_printer 2019-10-02 16:54:59 +02:00
ptitSeb a8cfb46964 Refined .gitignore 2019-10-02 16:20:21 +02:00
ptitSeb 11dbb69635 [DYNAREC] Added a crude Arm opcode printer, to help debugging 2019-10-02 16:20:00 +02:00
ptitSeb 5a8f986748 [DYNAREC] Small improvement in dynarec logs 2019-10-02 10:40:31 +02:00
ptitSeb ce766cea74 [DYNAREC] Fixed and add some opcode, still some bug to fix (test10 broken) 2019-10-02 09:18:21 +02:00
ptitSeb 8f2da8fe37 [DYNAREC] Created and changed some macro to simplify opcode writing 2019-10-02 08:42:30 +02:00
ptitSeb 360ba93e4c [DYNAREC] Fixed some opcode, all tests pass now 2019-10-02 08:05:33 +02:00
ptitSeb f17b1f8e67 [DYNAREC] Enabled dynarec in more case than just thread, and clear cache for newly filled dynarec block (still test 10 and 12 broken) 2019-10-01 23:46:59 +02:00
ptitSeb e52681e3f1 [DYNAREC] Add runtime linker between blocks 2019-10-01 22:00:13 +02:00
ptitSeb 6b14acfb93 Merge branch 'master' into dynarec 2019-10-01 21:28:42 +02:00
ptitSeb d5c6847d1f [DYNAREC] Small typo 2019-10-01 21:21:03 +02:00
ptitSeb 2fc49d5d68 [DYNAREC], Change the way mmap is called (batched now), and put many things behind mutex (still issues with threads 2019-10-01 21:20:36 +02:00
ptitSeb 2c68b3933d Merge pull request #63 from rajdakin/master
Fixed the PSRAQ instruction
2019-10-01 21:17:59 +02:00
rajdakin cea91ec477 Fixed the PSRAQ instruction 2019-10-01 21:11:04 +02:00
ptitSeb 375717346b [DYNAREC] Fixed Flags mirroring 2019-09-30 21:33:41 +02:00
ptitSeb ef856ce1ce [DYNAREC] Added XOR Gd, Ed opcode 2019-09-29 22:38:11 +02:00
ptitSeb 2da87ea466 [DYNAREC] Small geted optimization 2019-09-29 22:24:45 +02:00
ptitSeb c1ee773c83 [DYNAREC] Added GS: Infrastructure 2019-09-29 22:16:27 +02:00
ptitSeb ca1f0e11ff [DYNAREC] Added a global switch, plus some 0xFF opcodes 2019-09-29 19:31:45 +02:00
ptitSeb 83cf1a8662 [DYNAREC] Added Sub Ed, Ix and Mov Ed, Id opcode 2019-09-29 18:35:14 +02:00
ptitSeb a68aef90f5 [DYNAREC] Added Ret opcode 2019-09-29 16:12:29 +02:00
ptitSeb 0b432e8139 [DYNAREC] Added Mov Gd, Ed 2019-09-29 15:54:28 +02:00
ptitSeb cb795b8089 [DYNAREC] Added Call relative opcode 2019-09-29 15:45:15 +02:00
ptitSeb 949e781e64 [DYNAREC] Added simple Mov Ed, Gd opcode, and improved Push 2019-09-29 15:32:31 +02:00
ptitSeb 8de42fc6d3 [DYNAREC] First working draft of the Dynarec. Only PUSH instruction for now, so not usefull yet 2019-09-29 13:05:13 +02:00
ptitSeb e9f07fa36a [DYNAREC] More infrastructure, no emiter yet 2019-09-29 10:23:23 +02:00
ptitSeb 5f91619de7 [DYNAREC] Put some atomic to lock concurent access to dynablock list 2019-09-28 16:20:52 +02:00
ptitSeb df7818bc87 [DYNAREC] Added some basic infrastructure 2019-09-28 16:11:14 +02:00
ptitSeb e381c79535 Merge pull request #61 from afonso360/mmx
Implement all MMX Instructions + Tests
2019-09-28 00:02:46 +02:00
ptitSeb 055dcb8cf5 Added some libc function needed by mohaa linux server 2019-09-27 21:01:24 +02:00
Afonso Bordado b679fade0b Add MMX test binary and reference output 2019-09-27 09:50:18 +00:00
Afonso Bordado b9d35c3327 Minor cleanups 2019-09-26 22:24:28 +00:00
Afonso Bordado f1a01e7563 Implement MMX Shifts 2019-09-26 22:15:05 +00:00
Afonso Bordado a2735296b7 Use intruction names in tests 2019-09-26 21:25:31 +00:00
Afonso Bordado a4b26be5e7 Add MMX Shift instructions 2019-09-26 21:22:31 +00:00
Afonso Bordado 0d4e4081c4 Add MMX compare ops 2019-09-26 16:56:19 +00:00
Afonso Bordado 2099b0866c Add MMX Unpack tests 2019-09-26 16:18:31 +00:00
Afonso Bordado 07cc1a7fc5 Add debug info when test fails 2019-09-26 16:08:41 +00:00
Afonso Bordado 8ceedc8c9e Fix error loading MMX registers 2019-09-26 16:08:05 +00:00
Afonso Bordado c8735a444e Add MMX paccksswb and tests 2019-09-26 15:44:09 +00:00
Afonso Bordado 352da49fdc Add MMX Multiply instructions 2019-09-26 14:37:56 +00:00
Afonso Bordado 0285cd1522 Add MMX Logical Ops 2019-09-26 13:06:12 +00:00
Afonso Bordado 8d4ff9076d Add MMX SUB Instructions + tests 2019-09-26 07:41:23 +00:00
Afonso Bordado 5053141678 MMX Test: Use instruction name intrinsic 2019-09-26 06:17:41 +00:00
Afonso Bordado 3075400211 Add MMX ADD instructions 2019-09-25 21:46:15 +00:00
Afonso Bordado b301237ac6 Add psrlq and paddb + tests 2019-09-25 20:43:46 +00:00
Afonso Bordado c6f071d37d Add MMX cpuid tests 2019-09-25 19:26:35 +00:00
ptitSeb 85011ebd1e Update README.md 2019-09-24 21:11:39 +02:00
ptitSeb bb783ca8eb Merge pull request #60 from afonso360/fix-o0-build
Fix undefined reference to inline functions when building with O0
2019-09-21 19:09:31 +02:00
Afonso Bordado 61fecbab28 Fix undefined reference to inline function when building with O0
Currently building with O0 causes these functions to fail linking.
2019-09-21 17:03:25 +00:00
ptitSeb fc5562e110 Added more video (not from me) on the Readme. 2019-09-16 10:23:23 +02:00
ptitSeb 82d3bc26ca Update README.md 2019-09-16 10:13:36 +02:00
ptitSeb e7d9ec3875 Fixed a small bug in BOX86_ default PATH and LD_LIBRARY_PATH 2019-09-15 21:34:26 +02:00
ptitSeb 6359841f34 Fixed SDL1 SDL_EventFilter handling 2019-09-15 18:24:38 +02:00
ptitSeb 7d2f002139 Fixed issue with the GOS wrapped macro (so SDL_JoystickGetGUID is found now) 2019-09-15 15:20:08 +02:00
ptitSeb 86fe4487d0 Added mktemp wrapped function 2019-09-15 14:47:23 +02:00
ptitSeb b9aebfbe50 Added a small batch of wrapped functions 2019-09-15 14:00:32 +02:00
ptitSeb 350f77397d Added 2 more wrapped GL 4.4 functions 2019-09-15 11:48:18 +02:00
ptitSeb 5d6a4fc068 Custom wrapper for SDL 1.2 version of SDL_LoadObject, SDL_LoadFunction and SDL_UnloadObject 2019-09-15 09:44:49 +02:00
ptitSeb 71ae77070e Use any Python interpretor that in found on the system to generate wrappers 2019-09-15 09:05:32 +02:00
ptitSeb 4867096bba Better error message when file is not a file or not executable 2019-09-15 08:33:05 +02:00
ptitSeb db495d3331 Small change in help, again 2019-09-15 08:15:19 +02:00
ptitSeb 33c34a9f2c Merge pull request #52 from voltagex/patch-1
Fix some spelling and grammar in the help text
2019-09-15 08:04:32 +02:00
Adam Baxter 9024d36bb0 Fix some spelling and grammar in the help text 2019-09-15 15:52:38 +10:00
ptitSeb 083d4d3ebb Merge pull request #51 from ctoth/master
README fixes
2019-09-15 07:43:54 +02:00
Christopher Toth 1fc0ac852f README fixes 2019-09-14 23:32:44 -06:00
ptitSeb 402f1af78d Removed a warning in x86 build 2019-09-13 09:55:00 +02:00
ptitSeb c1b9c43c08 Merge pull request #48 from M-HT/fixes
New instruction and minor fixes
2019-09-12 22:35:04 +02:00
M-HT 08680c30bc Fix compilation instructions 2019-09-12 22:24:18 +02:00
M-HT 9db394408c Fix function vsprintf in libc 2019-09-12 22:21:37 +02:00
M-HT 1575c15a2b Add instruction 'rep stosw' 2019-09-12 22:20:13 +02:00
ptitSeb a019198997 Merge pull request #47 from M-HT/fixes
Fix wrapper generator to work with python2 and python3
2019-09-09 21:04:43 +02:00
M-HT ada81a7129 Fix wrapper generator to work with python2 and python3 2019-09-09 20:41:26 +02:00
ptitSeb 4f833dbf60 Merge pull request #46 from rajdakin/fixes
Fixes
2019-09-08 20:14:44 +02:00
rajdakin 50fed3ee4b Fixed the *stsymbolmap type 2019-09-08 19:48:58 +02:00
rajdakin 429dbd78cc Fixed the x86emu_fork function 2019-09-08 19:48:17 +02:00
rajdakin 3c354dc67b Forced the use of Python2 with the wrappers 2019-09-08 19:47:34 +02:00
ptitSeb 79ecafe9a6 Added alternate names for libssl and libcrypto (should help running on some debian system) 2019-08-25 10:53:03 +02:00
ptitSeb 3a69598d93 Try a better way for the hack for open(64) of /proc/self/cmdline 2019-08-15 19:21:41 +02:00
ptitSeb 6f8f539c47 Fixed flock wrapped function (helps Steam and SteamCMD) 2019-08-15 19:13:44 +02:00
ptitSeb ee49cec5ae Fixed open64 trace 2019-08-15 19:08:10 +02:00
ptitSeb f231f70d7f [PANDORA] Add X11 32bits -> 16bits automatic conversion option 2019-08-15 15:08:14 +02:00
ptitSeb acedd159ad Better logging macro 2019-08-15 10:10:39 +02:00
ptitSeb 8cfdaeeac7 Added a bunch of SDL2 wrapped functions 2019-08-13 21:23:15 +02:00
ptitSeb 059ad7b0c2 Some additions to wrapped libm 2019-08-11 17:13:55 +02:00
ptitSeb a05cda5d72 The box86 binary that have trace enabled is named box86t now... 2019-08-11 17:13:35 +02:00
ptitSeb 82a5870e39 Better log for fmodf and fmod wrapped functions 2019-08-06 17:45:12 +02:00
ptitSeb 77fdb3ad1f Added a bunch of wrapped function (and fixed a few X11 function with callback) 2019-08-06 17:21:11 +02:00
ptitSeb b1c6cb605e Fixed some issue with dlsym 2019-08-04 19:38:35 +02:00
ptitSeb 13ecf84ae0 Fixed a potential issue with dlsym on RTLD_NEXT (thanks @rajdakin) 2019-08-04 14:38:06 +02:00
ptitSeb 69e3489ef8 Added new opcode (handling segment, hopfully it's ok) 2019-08-03 21:22:58 +02:00
ptitSeb f45e64dbb9 No need to clean stack for new thread 2019-08-03 21:22:34 +02:00
ptitSeb 390b2e0601 Added a few more wrapped functions in SDL2 mainly 2019-08-03 20:03:23 +02:00
ptitSeb f7b97e556d Added a few more asound wrapped functions 2019-08-03 19:32:37 +02:00
ptitSeb 02dd7f7554 Added snd_pcm_avail so wrapped libasound 2019-08-02 21:29:47 +02:00
ptitSeb eb817d4469 Added a few more X11 wrapped functions 2019-08-01 18:05:58 +02:00
ptitSeb 55e37b7605 Better dependancies on wrapped X11 extensions libs 2019-08-01 16:48:16 +02:00
ptitSeb 7cf51a387c Added mincore and setcontext (untested) wrapped functions 2019-08-01 15:39:57 +02:00
ptitSeb a93fb9c690 Added 1 SSE opcode 2019-08-01 15:39:37 +02:00
ptitSeb b7e963f005 Changed the way dlsym look for the symbol (search also in dependant libs) 2019-08-01 15:21:37 +02:00
ptitSeb 12f2d917d3 Added some wrapped function (including 2 functions with callback in png16) for Trine 2019-07-31 22:22:03 +02:00
ptitSeb eb4172c08d Added SDL_utf8strlcpy to wrapped function 2019-07-31 21:30:18 +02:00
ptitSeb 0bd6a97867 Fixed SDL2_snprintf and added 2 new wrapped function (for La-Mulana) 2019-07-31 14:58:27 +02:00
ptitSeb 52a78b7ac2 Even better fix when calling XSetErrorHandler with a NULL handler 2019-07-31 11:57:22 +02:00
ptitSeb f8d56351b9 Fixed an issue when calling XSetErrorHandler with a NULL handler 2019-07-31 11:56:34 +02:00
ptitSeb 5ac9477284 Added 1 MMX Opcode 2019-07-30 22:48:13 +02:00
ptitSeb 73b76d3fd7 Fixed 2 wrapped SDL2 function (they return a struct and should have some special care taken) 2019-07-30 22:15:46 +02:00
ptitSeb c835972b8b Fixed an issue with function that return structures 2019-07-30 22:15:00 +02:00
ptitSeb d6341fd2de Fixed issues with the new SDL2 RWops handling 2019-07-30 20:21:18 +02:00
ptitSeb e5140393de Try to change handling of SDL2 RWops, hopefully fixing 'size' use and other cases 2019-07-30 16:51:38 +02:00
ptitSeb a24946719c Added a hack for RWops static function stdio_size (used on RWFromFP and RWFromFile) 2019-07-29 19:04:49 +02:00
ptitSeb c7018d1dac Added wrapped toascii libc function 2019-07-29 15:48:21 +02:00
ptitSeb 015f1551aa Added wrapped libresolv (partial) 2019-07-29 15:06:49 +02:00
ptitSeb fe9417f217 Added more libGL wrapped function (4.4 and 4.5) 2019-07-29 12:26:25 +02:00
ptitSeb 80d28b50e0 Made the message if not finding a Weak symbol as a Warning instead of an Error 2019-07-29 10:29:51 +02:00
ptitSeb 9d60c8ef1a More SDL2 symbol, and fixed a few other 2019-07-29 10:26:54 +02:00
ptitSeb 6aea2acad0 Added STT_NOTYPE to Symbol referenced (helps libfodex.so) 2019-07-29 08:20:07 +02:00
ptitSeb 31f0efd7cd Added a few more symbols 2019-07-29 07:49:18 +02:00
ptitSeb 7bb7d8857d Organized the project, with folders... 2019-07-28 14:01:19 +02:00
ptitSeb 9f59d66ab7 Start support Unity games (WIP...) 2019-07-28 12:14:29 +02:00
ptitSeb 0b16044f1a Added a few wrapped functions 2019-07-27 09:31:14 +02:00
ptitSeb 6b45e4886a Small changes/fixes to wrapped openal and alut 2019-07-21 20:18:41 +02:00
ptitSeb b3472e35f1 Improved tracing of Native wrapped functions 2019-07-19 11:04:18 +02:00
ptitSeb c42574030d Changed the way phtread_cond_t are handled 2019-07-15 15:13:58 +02:00
ptitSeb 6040f1316f Fixed SDL2 ReadXX wrapped functions 2019-07-15 11:38:14 +02:00
ptitSeb 196a73d416 Fixed (hopefully) and completed openal wrapper 2019-07-15 09:05:27 +02:00
ptitSeb 20f3bb2fa0 Some more finetuning to libvorbis alignments 2019-07-15 00:00:51 +02:00
ptitSeb aac73a1476 Aligned some more libvorbis structure, and checked all functions (and added a few too) 2019-07-14 23:47:18 +02:00
ptitSeb 92ec9a8446 Added wrapped libXdmcp (complete) 2019-07-14 21:43:38 +02:00
ptitSeb 9c7e5ffc18 Added wrapped libXau (complete) 2019-07-14 21:23:16 +02:00
ptitSeb 98eeaebdae And another small batch of SDL2 wrapped functions 2019-07-14 17:46:15 +02:00
ptitSeb fafd015424 Added a few SDL2 wrapped functions (help pico8_dyn) 2019-07-14 17:17:38 +02:00
ptitSeb 7109034f4b Added 2 wrapped libc functions 2019-07-14 16:28:03 +02:00
ptitSeb df5f152ba8 One more png16 wrapped function 2019-07-14 15:18:17 +02:00
ptitSeb 5aa35b98bc Made LOCK function fallback to regular unlock on Ivalid Lock Opcode, plus added a variant of BTR opcode 2019-07-14 15:04:24 +02:00
ptitSeb e362963d2a Added wrapped libsdl1ttf (complete) 2019-07-14 14:29:19 +02:00
ptitSeb 34dc5355bc Added libGL as prerequisite for libGLU 2019-07-14 14:28:56 +02:00
ptitSeb 9812c5250d Changed the way Threads are created 2019-07-14 12:23:36 +02:00
ptitSeb 0432851f94 Added libjpeg.so.62 as an alias for libjpeg.so.8 2019-07-14 12:23:17 +02:00
ptitSeb a8721b637c Trace can be now >2GB 2019-07-13 18:00:49 +02:00
ptitSeb 26c2dafaf8 Small check on FindNearestSymbolName 2019-07-13 14:53:33 +02:00
ptitSeb e6f85c01bd Added a few openal wrapped functions 2019-07-13 14:39:15 +02:00
ptitSeb edcc388dd4 Some more opcode for GS: 2019-07-13 14:33:59 +02:00
ptitSeb 965bf6af4e Wrapped vswscanf 2019-07-13 13:40:50 +02:00
ptitSeb 834b3f7dfb A few more thread wrapped functions 2019-07-13 13:05:21 +02:00
ptitSeb 141d57f5b0 Added Wrapped libuuid (complete) 2019-07-13 12:56:53 +02:00
ptitSeb 8c285de23c uname now return i686 as machine 2019-07-13 10:48:34 +02:00
ptitSeb 034f290d9c Less traces in DEBUG mode for libc syscall 2019-07-13 10:48:12 +02:00
ptitSeb a38c98dccd Update README.md 2019-07-11 15:31:26 +02:00
ptitSeb 325582b295 Fixed implementation of sys_clone 2019-07-10 07:42:27 +02:00
ptitSeb f024818d2e Added partial implementation of getcontext 2019-07-10 07:41:56 +02:00
ptitSeb 6699449e9f Added some command in USAGE.md 2019-07-10 07:41:21 +02:00
ptitSeb 18860e2980 Log XLoadQueryFont 2019-07-09 07:56:14 +02:00
ptitSeb 7a1cc9925d [PANDORA] Add crude font substitution on XFontQueryLoad on Pandora for 9x15 => 6x13 2019-07-09 07:55:31 +02:00
ptitSeb de99a7af47 Also log success call to dlsym with BOX86_DLSYM_ERROR (maybe introduce =2 for more loggin?) 2019-07-09 07:54:40 +02:00
ptitSeb e15647ae1b Fix build with TRACE activated 2019-07-07 20:17:06 +02:00
ptitSeb d897087b3d Improved trace by creating a map of native symbol used instead of using dladdr 2019-07-06 12:24:27 +02:00
ptitSeb b4a788e03a Merge pull request #33 from M-HT/fixes
Fix function vsscanf in libc wrapper
2019-07-05 14:58:05 +02:00
M-HT fb0928c0f5 Fix function vscanf in libc wrapper 2019-07-05 13:28:55 +02:00
ptitSeb 1e449415b1 Added syscall 45 2019-07-03 18:06:30 +02:00
ptitSeb dc672db867 Add a few wrapped functions 2019-07-03 16:06:18 +02:00
ptitSeb 50a300ddd7 Remove some warning 2019-07-03 16:06:02 +02:00
ptitSeb 55224d6f4c BOX86_DLSYM_ERROR will also log dlopen errors 2019-07-03 15:12:15 +02:00
ptitSeb 80d9ce417c Added proprer bejavour for dlerror 2019-07-01 20:31:19 +02:00
ptitSeb d28a3b7c30 And a few more wrapped libc and pthread functions 2019-07-01 17:29:12 +02:00
ptitSeb f3b80cbb4b Allow lib to have no entry point 2019-07-01 15:54:41 +02:00
ptitSeb 5b0d212ba2 A few more wrapped functions 2019-07-01 15:47:12 +02:00
ptitSeb 5741d76b96 Add proprer handling of TLS -both main elf and libraries 2019-06-30 19:47:54 +02:00
ptitSeb 86d7f65026 Fixed __thread test (test11 was outputing it's location) 2019-06-30 17:34:21 +02:00
ptitSeb 9f0b1af6b7 Lets have thread_once acting thread local 2019-06-30 12:10:43 +02:00
ptitSeb e9b90ee58e Added one more instruction in GS: part of x86 interpretor (still partly wrong) 2019-06-30 11:28:33 +02:00
ptitSeb 8e1ab7d505 Added a new test on __thread local variable (not working yet) 2019-06-30 11:27:05 +02:00
ptitSeb 21a72bd2e5 Added R_386_TLS_TPOFF to the dump list 2019-06-27 23:00:17 +02:00
ptitSeb 245c4eaacb Added some utilities functions on elf and function name and finding 2019-06-27 19:31:19 +02:00
ptitSeb d08a85eeae More libcrypto wrapped functions 2019-06-27 19:30:48 +02:00
ptitSeb 92bb8906ca Fix an issue with wrapped sigaction when act is NULL 2019-06-27 12:41:11 +02:00
ptitSeb 1caf52e02a Get tid of process when calling a wrapped function only when logging function call 2019-06-27 12:18:07 +02:00
ptitSeb 9ac44be751 A few more c wrapped functions 2019-06-27 12:17:31 +02:00
ptitSeb 9ace74fee7 Added ability to open SELF to wrapped dlopen 2019-06-27 12:02:24 +02:00
ptitSeb a8f1d26ea9 Added a few wrapped libm functions 2019-06-27 11:34:15 +02:00
ptitSeb d8ae82c5f9 Added completely wrapped libutil.so.1 2019-06-27 11:27:36 +02:00
ptitSeb 56552528cb Added a wrapped function and syscall 355 (getrandom) 2019-06-26 22:28:49 +02:00
ptitSeb 0cab13f614 More wrapped function. Now dropbox kind of start, before crashing for unsupported lnx.armv7l platform on the Pandora 2019-06-26 22:17:41 +02:00
ptitSeb 020327969f [PANDORA] Add definition to __NR_sendmmsg if not present (should be ok, it's added in kernel since 3.2 and current one is 3.2.102) 2019-06-26 19:21:58 +02:00
ptitSeb e269cdaa6d And more libc wrapped function 2019-06-26 18:29:09 +02:00
ptitSeb c0f04ccf0e Added tentative wrapped version of fcntl64 (and lockf64 too) 2019-06-26 17:58:46 +02:00
ptitSeb d45f94ee2e Add some dbus wrapped function, including callbacks 2019-06-26 17:47:51 +02:00
ptitSeb 32017cdf6b A few wrapped functions for libc and pthread 2019-06-26 16:34:16 +02:00
ptitSeb 36db516db5 Added some more wrapped libc functions 2019-06-26 16:07:59 +02:00
ptitSeb 1d0bfe643e Fixed __udivdi3 and __umoddi3 wrapped functions 2019-06-23 21:27:26 +02:00
ptitSeb 269a96c5eb Merge pull request #29 from rajdakin/python_fix
Correct fix for the generator bug
2019-06-23 21:01:56 +02:00
rajdakin b9a160320b Updated version 2019-06-23 20:39:29 +02:00
rajdakin bb075ea82e Correct fix for the generator bug 2019-06-23 20:35:42 +02:00
ptitSeb fd873f8b8f Added a few functions to libc wrapper 2019-06-23 18:03:40 +02:00
ptitSeb 29a33b9836 Fix wrapper generator 2019-06-23 17:40:39 +02:00
ptitSeb 6b01e4226c Merge pull request #28 from rajdakin/python_fix
Upgrade the python generator
2019-06-23 16:57:59 +02:00
rajdakin 9aa0a6352d Forgot to check if the defines are configurable 2019-06-23 16:27:09 +02:00
rajdakin 26f50ca98c Upgrade the python generator (no more config skip) 2019-06-23 16:21:31 +02:00
ptitSeb 1e605a9561 Rebuilt test10 with g++ 5.5 (instead of 7.4), to lower requirement on x86 libstdc++/libgcc_s 2019-06-23 14:50:39 +02:00
ptitSeb 556ac3db76 Merge pull request #27 from rajdakin/test10
Test 10
2019-06-23 14:40:03 +02:00
rajdakin 83d1b68ef5 Added test number 10 (needs x86 library though) 2019-06-23 14:33:54 +02:00
ptitSeb 917d6df290 Added libpng12 wrapper with a few functions 2019-06-23 14:12:28 +02:00
ptitSeb 65d4af771d Don't put a message on NONE debug level if a Weak symbol is not found for Jump slot 2019-06-23 12:37:13 +02:00
rajdakin 34ae8d5274 Fixed a warning 2019-06-23 12:20:11 +02:00
ptitSeb f3d20f5605 Fixed some LOCK Opcode 2019-06-23 12:15:28 +02:00
ptitSeb de879d55e0 Added a few more Opcode to LOCK 2019-06-23 12:09:52 +02:00
ptitSeb 9271efd4ed Added LOCK mecanism (hopefully working well enough for GCC Atomics), and reorganised GS: opcodes too 2019-06-23 11:46:15 +02:00
ptitSeb 12c2798017 Wrappers in ARM version 2019-06-23 11:45:34 +02:00
ptitSeb e5d0da5042 Merge pull request #26 from rajdakin/python_fix
Python generator enhancement
2019-06-22 19:05:39 +02:00
rajdakin 3b29a5d7c6 Implemented the bad middle letter rejection 2019-06-22 18:01:54 +02:00
rajdakin 938bdabd26 Probably fixed some typos 2019-06-22 17:48:40 +02:00
ptitSeb 454fd20cf5 Merge pull request #25 from rajdakin/warning_removal
Fixed an ignored warning
2019-06-22 17:48:13 +02:00
rajdakin 03277cbf42 Use the correct define, enhance files
Enhances CMakeLists and the Python wrapper generator script
2019-06-22 17:46:46 +02:00
rajdakin 41433715c1 Fixed an ignored warning 2019-06-22 17:00:43 +02:00
ptitSeb b59e38519b Added ld-linux-armhf.so.3 to list of openned native ld-linux libs 2019-06-21 08:26:32 +02:00
ptitSeb 7500aa3c6d Small changes on FPU Round helper 2019-06-20 21:08:27 +02:00
ptitSeb 7655700eff Fix ARM build 2019-06-20 21:04:59 +02:00
ptitSeb 666cd30c2b Merge pull request #23 from rajdakin/warnings_removal
Remove almost all GCC warnings
2019-06-20 20:33:06 +02:00
rajdakin 9a2b00891b Merge branch 'master' of https://github.com/ptitSeb/box86 into warnings_removal 2019-06-20 18:53:13 +02:00
rajdakin 80c0213543 Major (unsure) fixes 2019-06-20 18:44:06 +02:00
rajdakin 0d9f841123 Minor fixes 2019-06-20 18:43:24 +02:00
rajdakin fe0bc588a8 Warnings removal 2019-06-20 18:42:39 +02:00
ptitSeb 9bc2b1fe44 Merge pull request #22 from rajdakin/master
Fixed the `NOLOADADDR` option
2019-06-20 17:38:12 +02:00
rajdakin 912e9388ba Fixed the NOLOADADDR option
Fixed the `NOLOADADDR` option: it can now be enabled (whereas before it was `NOLOADADDR,`, which is different)
2019-06-20 16:50:19 +02:00
ptitSeb a4078c5e73 Added NOLOADADDR cmake option 2019-06-20 11:09:17 +02:00
ptitSeb b0faec1c87 Try to implement olduname (109) and newuname (122) syscalls 2019-06-20 11:00:25 +02:00
ptitSeb 5f2ac78654 Added SDL_SetWindowDisplayMode wrapped function 2019-04-19 17:56:24 +02:00
ptitSeb 853552ca3a Added a few libc wrapped functions 2019-04-03 21:54:34 +02:00
ptitSeb dd00f1b1a1 Added sys_geteuid and sys_getegid syscall 2019-04-02 07:41:58 +02:00
ptitSeb 19095d3fd3 Merge pull request #18 from meveric/master
adding more missing functions
2019-03-31 12:19:05 +02:00
meveric 5cc4da0364 adding libc madvise and gnu_dev_makedev
see https://0x48.pw/libssh/include/x86_64-linux-gnu/sys/sysmacros.h.html for gnu_dev_makedev
2019-03-31 10:07:38 +00:00
meveric 565a0fdb1b adding libpthread __pthread_unwind_next 2019-03-31 09:59:10 +00:00
meveric 19a4b3188e adding libc ftok 2019-03-31 09:56:17 +00:00
meveric a9f584575a adding libc getresgid and getresuid 2019-03-31 09:54:25 +00:00
meveric 3030cb2fdc adding libc sigsuspend 2019-03-31 09:52:35 +00:00
meveric 21107c9a42 adding libc sigblock, siggetmask, sigsetmask, sigvec 2019-03-31 09:50:22 +00:00
meveric cb19661909 adding libc __fgets_chk 2019-03-31 09:46:43 +00:00
meveric 70845c2977 adding libc sigdelset and sigismember 2019-03-31 09:44:17 +00:00
meveric a2bf66da50 adding libc __signbit and __signbitf 2019-03-31 09:41:24 +00:00
meveric 2710f621ae adding libpthread __pthread_register_cancel and __pthread_unregister_cancel 2019-03-31 09:32:10 +00:00
meveric 370fbd6072 adding libc __libc_current_sigrtmax 2019-03-31 09:28:26 +00:00
meveric 6ce990ce36 adding libc wordexp, wordfree 2019-03-31 09:21:52 +00:00
meveric 235e99de96 adding libc wait3, wait4 2019-03-31 09:20:08 +00:00
meveric 08a0b537e8 adding libc __sched_cpucount 2019-03-31 09:16:59 +00:00
meveric 285f30c8c0 adding libc strnlen 2019-03-31 09:14:24 +00:00
meveric 48cea000dc adding libc creat64 2019-03-31 09:12:43 +00:00
meveric b405516719 adding libx11 XkbSetDetectableAutoRepeat 2019-03-31 09:10:11 +00:00
meveric d278f8c77a adding libm __expf_finite 2019-03-31 09:08:24 +00:00
meveric 58a731e6fd adding libc getdtablesize 2019-03-31 09:05:06 +00:00
meveric b9f0754140 adding x11 XScreenCount 2019-03-31 09:03:09 +00:00
meveric 1c0b79d783 adding libc getprotoent, getprotobyname, getprotobynumber, setprotoent, endprotoent 2019-03-31 08:57:48 +00:00
meveric 84ed9f5c50 adding libx11 XGetFontPath 2019-03-31 08:54:26 +00:00
meveric 691296bb57 adding libpthread pthread_mutexattr_setpshared 2019-03-31 08:44:56 +00:00
meveric 6af7acc980 adding libm feclearexcept, fegetexceptflag, feraiseexcept, fesetexceptflag, fetestexcept, fegetround, fesetround, fegetenv, feholdexcept, fesetenv, feupdateenv, feenableexcept, fedisableexcept, fegetexcept 2019-03-31 08:42:08 +00:00
ptitSeb b5c0ec57ec Added minimal libcrypto and libssl native support (Memoranda works now, even if not all needed functions are wrapped) 2019-03-30 11:09:50 +01:00
ptitSeb e3e3aafc29 Added sys_personality syscall 2019-03-28 07:37:38 +01:00
ptitSeb 30d585e008 Added another batch of MMX/SSE opcodes (for Rocketbird) 2019-03-25 17:10:53 +01:00
ptitSeb fa630b07f8 Fixed POP ESP 2019-03-25 15:51:08 +01:00
ptitSeb 95b32ae801 Improving cpu trace in multi-thread context 2019-03-25 15:48:04 +01:00
meveric 4abc5ca757 started working on Gratuitous Space Battles (#17)
* adding X11 XChangeWindowAttributes

* adding sdl2 SDL_SetRelativeMouseMode

* adding libc strverscmp

* adding libc getauxval (available in glibc 2.16 or higher)

* adding libc mlock, mlockall, munlock, munlockall

* adding libc inet_nsap_ntoa

* adding libc random_r, srandom_r, initstate_r, setstate_r

* adding libc ngettext, dngettext, dcngettext

* adding x11 XGetDefault

* adding libc bcopy

* adding x11 XAddExtension
2019-03-25 13:44:06 +01:00
ptitSeb ddc0523c10 Added a new batch of SSE/MMX opcodes 2019-03-25 10:45:53 +01:00
ptitSeb af8b188336 Added thread id on Unimplemented opcode message 2019-03-25 09:49:29 +01:00
ptitSeb b6bc5ccef0 Add aligment for epoll_event structure (and now steamcmd should the prompt) 2019-03-24 16:43:21 +01:00
ptitSeb daca7ac870 Some changes to thread and callbacks 2019-03-24 15:22:42 +01:00
ptitSeb 310c618a48 And one more, SSE this time 2019-03-24 13:30:41 +01:00
ptitSeb f8ce687308 And again one more mmx opcode 2019-03-24 12:16:55 +01:00
ptitSeb cafc5b07b7 Aded 2 more MMX opcodes 2019-03-24 11:35:54 +01:00
ptitSeb 18f07083b2 Added mmx version of pxor 2019-03-24 10:49:12 +01:00
ptitSeb d67bba49e4 Improvment to callbacks interface 2019-03-24 09:23:02 +01:00
ptitSeb 9d4af2ae1f And one more MMX opcode 2019-03-24 09:22:34 +01:00
ptitSeb 76ade17a44 Added dummy __(de)register_frame_info functions 2019-03-24 08:34:37 +01:00
ptitSeb 238c294a98 Try to improve a bit linked Shared Callback. Also use asked stacksize on Thread creation 2019-03-24 08:30:05 +01:00
ptitSeb d0c4223b2d Added PSHUFW MMX opcode 2019-03-24 07:51:36 +01:00
ptitSeb c01850ff6a Added more opcodes 2019-03-23 20:29:16 +01:00
ptitSeb bda2fca514 Added PADDW SSE2 opcode 2019-03-23 19:51:01 +01:00
ptitSeb 8857c4e566 Made init(s) of loaded libs have a correctly setupped stack (helps steamcmd) 2019-03-23 17:41:44 +01:00
ptitSeb 26c901a84d Try to let cache handle itself more (need to check which of 0 or 3 is better). Also added forgoten label from previous commit 2019-03-23 17:25:28 +01:00
ptitSeb 54382bcb22 Added PMULLW SSE opcode 2019-03-23 16:19:09 +01:00
ptitSeb 78a4e7046d Added an option to avoid handling of SigSEGV (can be usefull for debugging) 2019-03-23 16:19:09 +01:00
ptitSeb f8b795b0e6 Merge pull request #16 from meveric/master
Some cleanup and trying to get Rocketbirds to run
2019-03-23 16:04:31 +01:00
meveric e39bdb0078 adding missing libGL function glXGetCurrentDrawable 2019-03-23 14:53:50 +00:00
meveric 1656400a08 Merge branch 'master' of https://github.com/ptitSeb/box86 2019-03-23 13:35:56 +00:00
ptitSeb 816ee723ad Added two more wrapped functions 2019-03-23 14:34:19 +01:00
ptitSeb b489bc4b54 Added a precision on a log 2019-03-23 14:34:00 +01:00
ptitSeb d2ef0f0c6d Put some mutex on trace 2019-03-23 14:33:32 +01:00
meveric 4fe93aef9d adding missing #ifdef LD80BITS for several functions 2019-03-23 12:55:51 +00:00
ptitSeb 261e32ab8b Added some more wrapped function (and empty getcontext / makecontext) 2019-03-23 09:33:13 +01:00
ptitSeb 388eba5d2f Merge pull request #15 from meveric/master
working on A Bird Story
2019-03-23 08:07:39 +01:00
meveric 8196b61a3c autogen functions 2019-03-22 23:19:13 +00:00
meveric bfad527fcc adding libc sigaltstack 2019-03-22 23:18:01 +00:00
meveric 70c7adb06a adding libm acosh, acoshf, acoshl, acosl, asinl 2019-03-22 23:15:59 +00:00
meveric 1aeb73b040 adding libc ffs, ffsl, ffsll 2019-03-22 23:10:25 +00:00
meveric ad1a24c541 adding libc posix_fadvise64
unsure about off64_t it's said to be always 64 bit, but also said to be off_t on a 32bit system which is only 32bit.
2019-03-22 23:05:37 +00:00
meveric 6da33d8192 adding libc pipe2 2019-03-22 22:45:45 +00:00
meveric 33ad1a998c adding libm tgamma, tgammal, tgammaf, lgamma_r, lgammal_r, lgammaf_r, lgamma, lgammal and lgammaf 2019-03-22 22:41:35 +00:00
meveric 8e96b1e948 adding libc getgroups
not 100% sure of type gid_t list[] took it as gid_t = uint
2019-03-22 22:34:02 +00:00
meveric 7eacd670bc adding libc erfc, erfcf and erfcl 2019-03-22 22:27:59 +00:00
meveric 9a66e188d4 adding libc swapcontext, and libm asinh, asinhf, asinhl 2019-03-22 16:06:38 +00:00
meveric 469fb711a8 adding libc setrlimit64 2019-03-22 15:27:10 +00:00
meveric b903d208dd adding libc atanh, atanhf, atanhl 2019-03-22 15:25:13 +00:00
meveric ca31e209ec adding libc seekdir 2019-03-22 15:22:26 +00:00
meveric bff8f2fc19 adding libc ppoll 2019-03-22 15:19:46 +00:00
meveric bce1bbd9a2 adding libc chroot 2019-03-22 15:16:22 +00:00
meveric dcccc8bcfd adding libc setgroups 2019-03-22 15:15:25 +00:00
meveric fe1bf1b562 adding libc killpg 2019-03-22 15:13:18 +00:00
meveric 0c95fc166e adding libc initgroups 2019-03-22 15:05:31 +00:00
meveric 149d707edb adding libc getpgrp and setpgrp 2019-03-22 15:03:15 +00:00
meveric 37c1fffd97 adding libc getrlimit64 2019-03-22 14:29:01 +00:00
meveric 68863455fc adding libc euidaccess and eaccess 2019-03-22 14:25:22 +00:00
meveric da8f26e309 adding libc dup3 2019-03-22 14:23:11 +00:00
meveric b49d726835 adding libc telldir 2019-03-22 14:21:02 +00:00
meveric ba4722aeec adding libm erf, erff, erfl 2019-03-22 14:12:20 +00:00
meveric 8bbd79a065 adding libpthread pthread_attr_setguardsize and pthread_attr_getguardsize 2019-03-22 14:07:22 +00:00
meveric 426fdee8b7 adding libpthread pthread_getattr_np 2019-03-22 14:03:35 +00:00
meveric 0f025df81f fixing libc setresgid 2019-03-22 13:53:25 +00:00
meveric 13c8c97f2a adding libc setresuid 2019-03-22 13:51:44 +00:00
meveric 5eaccc69c4 adding libc utimensat 2019-03-22 13:31:16 +00:00
meveric 6c0942d9ca adding libpthread pthread_attr_getstack and pthread_attr_setstack 2019-03-22 13:12:39 +00:00
meveric c90bfa252f added missing libc function __libc_alloca_cutoff 2019-03-22 12:36:41 +00:00
meveric d4c5e5e332 adding libc __stpncpy 2019-03-22 12:26:54 +00:00
meveric 4cb2ee6803 added libc __read 2019-03-22 12:13:59 +00:00
ptitSeb 37961f5e4d Merge pull request #13 from M-HT/fixes
New instructions and other fixes
2019-03-22 07:37:17 +01:00
M-HT 93ec8163f0 Fix div function in libc wrapper 2019-03-22 00:25:16 +01:00
M-HT 026520da2f Add fnstsw, lahf, rep movsw instructions; Fix div function in libc wrapper; Use dummy error handler in function my_snd_lib_error_set_handler in libasound wrapper; Add interrupt flag to default emu flags 2019-03-21 22:39:58 +01:00
ptitSeb 09ca4b0398 Let's be less dramatic in the README 2019-03-21 22:29:49 +01:00
ptitSeb d7e5790cce Added a few more wrapped functions 2019-03-20 23:42:21 +01:00
ptitSeb 39822d9c20 Merge pull request #12 from meveric/master
most stuff needed for factorio
2019-03-20 19:05:04 +01:00
meveric 61a4b6bf26 adding glXGetConfig and XRootWindow 2019-03-20 17:55:02 +00:00
meveric fe95e0b4e4 fixing long double functions fmodl, powl and cbrtl 2019-03-20 17:42:34 +00:00
meveric f8c53bfd20 Merge branch 'master' of https://github.com/ptitSeb/box86 2019-03-20 17:34:05 +00:00
ptitSeb e5912fda9d Added syscall 265 2019-03-20 18:32:14 +01:00
meveric 82f7eb268c Merge branch 'master' of https://github.com/ptitSeb/box86 2019-03-20 17:25:25 +00:00
ptitSeb 8abb139f29 Added syscall 109 2019-03-20 18:24:24 +01:00
meveric f48e68402b adding libm __fpclassify and __fpclassifyf 2019-03-20 17:19:21 +00:00
meveric 210d571296 try adding powl 2019-03-20 17:17:01 +00:00
meveric 7b4266f443 adding libc fmodl 2019-03-20 17:08:26 +00:00
meveric 4db0e4c1ae adding mblen 2019-03-20 17:06:46 +00:00
meveric 36e8e55522 adding if_nametoindex and if_indextoname 2019-03-20 17:04:38 +00:00
meveric 0cb23d957a adding malloc_trim, __asinf_finite and __asin_finite 2019-03-20 17:00:40 +00:00
meveric fdea5394df wrapped libm cbrt, cbrtl, cbrtf functions 2019-03-20 16:47:32 +00:00
meveric 8c4bea9e52 adding wrapper for times function 2019-03-20 16:36:21 +00:00
ptitSeb e4a2fea4df Added on more opcode 2019-03-20 16:59:27 +01:00
ptitSeb cd6b9f69b3 A few more wrapped function (and now steamcmd start) 2019-03-20 15:04:22 +01:00
ptitSeb 54f785888d Fixed scandir64 wrapped function (steamcmd now updated itself) 2019-03-20 12:32:01 +01:00
ptitSeb ba44d9c07c More fixes to SSE2 opcodes (now steamcmd download updates) 2019-03-20 12:00:27 +01:00
ptitSeb d84888ec7c Fixed PACKUSWB opcode 2019-03-20 09:40:09 +01:00
ptitSeb c760f52e6d Revert to before SIMD Evrywhere. It's slower then before and also have some bugs. But there are some bug fixes too, so still need to study the opcodes 2019-03-20 08:11:11 +01:00
ptitSeb 7e0ce2cbce Some fixes to SIMD Evrywhere and some opcodes 2019-03-20 01:11:16 +01:00
ptitSeb c9868e094b Now using SIMD Everywhere for MMX/SSE/SSE2 emulation. Needs more testing but that seems to have fixed a lot of stuffs 2019-03-20 00:04:21 +01:00
ptitSeb 76d6dfe2bf Simplified a bit some primary operations 2019-03-18 23:24:10 +01:00
ptitSeb b0f15ea3ed Log output buff of snprintf when uisng BOX86_LOG=DEBUG 2019-03-18 23:23:41 +01:00
ptitSeb ebb6f3bcdb Merge pull request #11 from meveric/master
Working on KotoR2 adding functions on the way
2019-03-18 22:50:48 +01:00
meveric 20eb136c76 Working on KotoR2 adding functions on the way 2019-03-18 21:06:23 +00:00
ptitSeb 31dea5eccd Two more wrapped function, and some warning removed 2019-03-18 18:00:47 +01:00
ptitSeb fe2850a50a Merge pull request #10 from meveric/master
Add more wrapper functions
2019-03-18 17:46:29 +01:00
meveric ce16ff49cd Add more wrapper functions 2019-03-18 16:29:18 +00:00
ptitSeb 0af1112020 Added option to load PIE Program at a specific address (to help debugging) 2019-03-18 17:28:21 +01:00
ptitSeb ac441ab136 A new bunch of wrapped functions 2019-03-18 12:15:36 +01:00
ptitSeb f275040887 Added some more wrapped functions 2019-03-18 12:04:31 +01:00
ptitSeb 2f3efa1bec Added one more option to curl_easy_setopt 2019-03-18 11:54:05 +01:00
ptitSeb d1103f4ac6 Preliminary (incomplete) support for wrapped curl_easy_setopt 2019-03-18 11:39:49 +01:00
ptitSeb 7a25243cd2 Added MOVDDUP opcode 2019-03-18 10:08:43 +01:00
ptitSeb 5fb5872d0d Added a few more wrapped functions 2019-03-18 09:33:59 +01:00
ptitSeb b6ebf9f4ad Small changes to ioctl and fcntl to take into account the last param as vaarg 2019-03-17 21:35:58 +01:00
ptitSeb 080dc51f4b Small improvements to debug trace 2019-03-17 21:35:06 +01:00
ptitSeb 4ff6e20073 Merge pull request #9 from M-HT/fixes
Fixes for various issues
2019-03-17 20:46:26 +01:00
M-HT 44c9c28fa3 Add div, fcloseall, sync functions in libc wrapper 2019-03-17 20:00:01 +01:00
M-HT 7e8794fcf0 Add cmc, enter, pushfw instructions 2019-03-17 19:55:55 +01:00
M-HT 76b3afe8f9 Fix daa, das, imul, mul, shld, shrd instructions 2019-03-17 19:47:23 +01:00
M-HT 20db25cf89 Fix libasound wrapper 2019-03-17 19:43:27 +01:00
M-HT 7abea0870f Fix for filesystems with 64-bit inodes 2019-03-17 19:41:57 +01:00
ptitSeb 1ab062d899 Small optim for pshufd where src==dest 2019-03-17 14:37:35 +01:00
ptitSeb d60f7c319c Use direct native wrapped function for SDL1 version of SDL_BuildAudioCVT and SDL_ConvertAudio (for #7) 2019-03-17 14:36:30 +01:00
ptitSeb 0398803f1b This should take care of shared callback created and free inside callback (should fix #8) 2019-03-17 14:22:13 +01:00
ptitSeb 2538e7ef8c Added (untested, probably buggy) handling of syscall 120 (sys_clone) 2019-03-17 11:43:47 +01:00
ptitSeb f122665e3c Added syscall 42 2019-03-17 10:25:33 +01:00
ptitSeb 3e691791b6 better debug for statfv64 wrapped function 2019-03-17 10:14:57 +01:00
ptitSeb 430303d9c0 Forgot the table jump entry for rdtsc 2019-03-17 10:14:28 +01:00
ptitSeb ecdb0aab03 Added rdtsc instruction 2019-03-17 10:10:25 +01:00
ptitSeb 2522e9bb1d Removed the printf on tgkill 2019-03-16 21:30:59 +01:00
ptitSeb 822d8f45b6 Oops, another typo... 2019-03-16 21:27:38 +01:00
ptitSeb d036cab4c1 Slight change to poll wrapped function 2019-03-16 21:06:34 +01:00
ptitSeb 3ee1c2b282 Fixed a stupid typo, again 2019-03-16 21:06:18 +01:00
ptitSeb b2b2775504 Small fix for x86 build 2019-03-16 19:24:19 +01:00
ptitSeb 3a5ea0379a Special handling of open(64) when accessing /proc/sef/cmdline 2019-03-16 17:46:54 +01:00
ptitSeb dc3281203d Don't print Setting trace if trace is not enabled 2019-03-16 17:46:21 +01:00
ptitSeb d94a049cfd Some more cpuid leafs 2019-03-16 16:28:34 +01:00
ptitSeb c7b1c337e2 Small improvements to debug wrapped function traces 2019-03-16 16:28:09 +01:00
ptitSeb 116eaefd8f Added preliminary Signal handling 2019-03-16 12:21:20 +01:00
ptitSeb 8c70a9395d Added some support for atfork function 2019-03-16 10:09:51 +01:00
ptitSeb 29fbe46d41 Add proprer timer_create wrapped function (but because of the lack of signal handling, the timer will probably crash the app later) 2019-03-13 21:49:51 +01:00
ptitSeb aa4d982d4c Fixed some typo, fixing sdl1image, sdl2image and sdl1mixer (Also fix 'Benri and the Bandits') 2019-03-13 21:35:21 +01:00
ptitSeb fa6ab1c8c4 Change BOX86_LOG=DEBUG so a wrapped call that segfault is anyway printed in the log 2019-03-13 21:29:47 +01:00
ptitSeb a9216705e1 Added a few more wrapped function (should help 'Berni and the Bandits') 2019-03-12 08:25:57 +01:00
ptitSeb 20828213b2 Added a few wrapped function (should help Hollywood Player) 2019-03-11 22:04:58 +01:00
ptitSeb f4e228730f Added a few opcodes, needed by PixelJunk Shooter (also need LIBGL_GL=21 with gl4es) 2019-03-10 21:39:10 +01:00
ptitSeb bd9c8f0f12 Flush log trace at each write, to avoid half-written trace when segfault occurs 2019-03-10 18:09:05 +01:00
ptitSeb d07db1054a Added some more wrapped functions 2019-03-10 11:11:55 +01:00
ptitSeb 18deecddea Added a few more GS: operations 2019-03-10 11:11:29 +01:00
ptitSeb f3991199dd Improved trace with SDL_RWFromFile 2019-03-10 11:11:02 +01:00
ptitSeb 007411411b Some work to avoid Bus Error (NWN now enter in game... but crashes immediatly) 2019-03-05 21:48:48 +01:00
ptitSeb 75124ba900 Changed (again) the way elf dependancies are loaded to avoid beeing sensitive to the order of loading (fixes NWN, that crash just before the game with BusError) 2019-03-04 21:15:06 +01:00
ptitSeb 1d9589c093 New dev cycle 2019-03-04 20:47:28 +01:00
ptitSeb 6974d96f6e Update README.md 2019-03-03 21:30:04 +01:00
ptitSeb 5584e62db3 Bumped to v0.0.4 2019-03-03 21:24:04 +01:00
ptitSeb 9b968777a0 Refined the README 2019-03-03 21:04:07 +01:00
ptitSeb 62b7326a75 Remove the (now) useless while in main loop 2019-03-03 21:03:38 +01:00
ptitSeb 6b7275f475 Small syscall imrprovment 2019-03-03 19:30:52 +01:00
ptitSeb 7f174da3c7 Slightly improve debug trace 2019-03-03 18:58:29 +01:00
ptitSeb 5a1c7b50e7 Make sure Flags are clean when entering or leaving x86 emu 2019-03-03 16:59:25 +01:00
ptitSeb 39283bf99e Added (faked) CPUID Leaf 2 2019-03-03 16:58:59 +01:00
ptitSeb 95ec71bd0a Small work on syscalls 2019-03-03 16:58:22 +01:00
ptitSeb 756a7fddf2 Correct handling of .init_array sections 2019-03-03 15:52:49 +01:00
ptitSeb e1f897cab9 Added a few more syscall 2019-03-03 15:52:02 +01:00
ptitSeb eb35ed9a1b Added some more Desktop GL wrapped functions (GL 4.5 mainly) 2019-03-03 12:10:49 +01:00
ptitSeb f439a401a0 Update README.md 2019-03-03 09:24:22 +01:00
ptitSeb bfd4c8cb5c Fixed a stupid mistake on callback, fixing a large memory leak 2019-03-03 08:43:58 +01:00
ptitSeb 3fca45b256 Fixed SAHF opcode 2019-03-02 20:42:59 +01:00
ptitSeb bda27e69ba Added improved trace for glVertex2f 2019-03-02 20:15:19 +01:00
ptitSeb 1e88171d45 Added a few x87 opcodes 2019-03-02 17:23:02 +01:00
ptitSeb d9a2f6b7bb NeededLib are now loaded in the same order as listed in elf 2019-03-02 16:15:05 +01:00
ptitSeb 94de344d05 Fixed bad printing of missing symbol when applying R_386_TLS_DTPOFF32 or R_386_JMP_SLOT relocation 2019-03-02 15:58:24 +01:00
ptitSeb 3dd188dedd Added a bunch of NV and SGIX extentions to wrapped GL (should help run HumandRessouceMachine with NVidia card #2) 2019-03-02 15:51:17 +01:00
rajdakin a5562ea8bd Fixed i386 and amd64 build in wrappedlibc 2019-03-02 15:41:39 +01:00
ptitSeb 8f86acfef6 Try to avoid some warning 2019-03-02 14:39:24 +01:00
ptitSeb 890cf8841a Added some more libc wrapped functions 2019-03-02 14:36:19 +01:00
ptitSeb 55e0e5571b Added partial dladdr 2019-03-02 14:10:37 +01:00
ptitSeb 19e062a79c Setup stack before calling init instead of after in my___libc_start_main 2019-03-02 13:57:01 +01:00
ptitSeb 916a10fae8 Added some more wrapped functions 2019-03-02 08:35:06 +01:00
ptitSeb 4f8849e914 Forgot that one in previous commit 2019-03-01 18:36:30 +01:00
ptitSeb 713098471e Added a few (mostly undone) wrapped libs, plus some wrapped functions 2019-03-01 18:36:02 +01:00
ptitSeb bab00e6e42 Added 2 more opcodes 2019-03-01 17:13:52 +01:00
ptitSeb c0836a75ed Removed a warning 2019-03-01 16:46:38 +01:00
ptitSeb 6cb611971a Update README.md 2019-02-28 15:31:44 +01:00
ptitSeb 3ba09947d2 Update README.md 2019-02-27 10:40:11 +01:00
ptitSeb 523c3db8c4 Update README.md 2019-02-27 10:39:40 +01:00
ptitSeb d94b7fba23 Update README.md 2019-02-27 10:37:48 +01:00
ptitSeb ae76bbcafe Small changes in a few 0x66 prefixes opcodes 2019-02-26 07:48:56 +01:00
ptitSeb b987e9086a the mul and imul opcode now have defered flags 2019-02-25 21:36:39 +01:00
ptitSeb 47fc82a839 Remove the -no-pie and -fjump-table parameter option in the cmake, it's probably not really usefull 2019-02-25 21:36:00 +01:00
ptitSeb fcff7e85fe Some minor change to a few opcodes 2019-02-25 19:05:06 +01:00
ptitSeb 147ec021ea Implemented same fix for wide-char printf variants 2019-02-24 22:01:57 +01:00
ptitSeb cb7f4d373e Fix some border case (v/s/f)printf plus added a few wrapped functions 2019-02-24 22:00:14 +01:00
ptitSeb 3db9dfd7ea Fixed regular build (without USE_FLOAT) 2019-02-24 21:03:30 +01:00
ptitSeb 18fa4d2134 Improved callbacks, with shared and small variant 2019-02-24 16:45:58 +01:00
ptitSeb b63ec10cf7 Added a workaround for pthread_cond_t initialized statically 2019-02-24 14:49:32 +01:00
ptitSeb c44ce3acbd Fixed issue with pthread_cond_t statically initialized 2019-02-24 14:35:01 +01:00
ptitSeb fbd494d348 Added USE_FLOAT build option (hopefully a bit faster on the Pandora) 2019-02-24 13:58:31 +01:00
ptitSeb b98412de11 Added a few more instructions (Neverwinter Night start now) 2019-02-24 11:12:34 +01:00
ptitSeb cd17162a00 Save more register in EmuCall 2019-02-24 11:11:54 +01:00
ptitSeb dd63e8cc86 Made thread_once mecanism much simpler 2019-02-24 11:11:12 +01:00
ptitSeb 1d0ca9bf0c Some simplifications and improvments to emulated functions call 2019-02-24 11:10:33 +01:00
ptitSeb c0704f6a34 Update README.md 2019-02-24 09:02:05 +01:00
ptitSeb a7750a38b9 Added dependant libs when loading SDL1 2019-02-23 14:17:11 +01:00
ptitSeb 58307888df Added warning when symbol is not found on R_386_PC32 reloc 2019-02-23 14:16:39 +01:00
ptitSeb b1ad6f19c0 Added (dummy) Push/Pop ES and DS 2019-02-23 14:15:59 +01:00
ptitSeb b254c69771 Simplified thread handling, and implemented some workaround around pthread_cond_init 2019-02-23 12:42:35 +01:00
ptitSeb 0360d2562d Added a few data in wrapped libc 2019-02-23 12:41:53 +01:00
ptitSeb 2df3d1967e Fixed issue with DATAM and DATAW macros 2019-02-23 12:40:50 +01:00
ptitSeb 54c600660b Use prefetch with '3' as hint instead of '2' (not sure it changes anything on arm) 2019-02-23 11:14:43 +01:00
ptitSeb 4e8e889900 Fixed an issue with R_386_PC32 relocation 2019-02-23 11:13:39 +01:00
ptitSeb 66ed58df03 added a few more wrapped functions 2019-02-22 14:07:43 +01:00
ptitSeb a8d4175cd1 Added another readlink hack for self 2019-02-22 11:45:41 +01:00
ptitSeb 1c286c1c5e Added libopenal.so.0 alternative 2019-02-22 11:45:13 +01:00
ptitSeb 011a1057bf Handling of OggVorbis_File structure, that is 704 bytes on x86 and 720 on ARM (fixing Gemini Rue) 2019-02-22 09:58:14 +01:00
ptitSeb 1d8af4b523 Improve Trace handling 2019-02-22 09:57:27 +01:00
ptitSeb cbb12339c9 Added BOX86_TRACE_START (of course this slow down the HAVE_TRACE version) 2019-02-20 18:14:48 +01:00
ptitSeb c4c2a525fb Fixed setjmp/longjmp (fixing Pico8) 2019-02-20 18:13:01 +01:00
ptitSeb fd1a581598 Added a large bunch of wrapped function and library 2019-02-20 12:48:01 +01:00
ptitSeb 4902ba83c4 Added some EPI History when aborting with stack corrupted 2019-02-20 12:47:33 +01:00
ptitSeb 5c6453f931 Added syscall 242 2019-02-20 12:46:17 +01:00
ptitSeb 880de4491c added one mode to CPUID opcode 2019-02-20 12:46:00 +01:00
ptitSeb e9ed82bdc5 Added libudev.so.0 wrapped lib 2019-02-20 09:58:51 +01:00
ptitSeb 048acfda7b Added many X11 related wrapped functions and libs 2019-02-19 20:51:59 +01:00
ptitSeb ca2013fb97 Added an env. var. to have detail dlsym error 2019-02-19 18:24:25 +01:00
ptitSeb dad24e4fba Added MIT Licence 2019-02-19 15:23:49 +01:00
ptitSeb 0fea396a1b Added fpu rounding handling (fixes SuperMeatBoy) 2019-02-18 20:04:18 +01:00
ptitSeb 393358d936 Fixed libname for SDL2 2019-02-18 17:57:00 +01:00
ptitSeb 236e0f1f75 Try to improve ELFLoader... 2019-02-18 15:35:57 +01:00
ptitSeb cf78416e24 Fixed fork that was broken for some time 2019-02-18 11:59:20 +01:00
ptitSeb 80e64bab6d Added a few more libc wrapped functions 2019-02-17 21:30:47 +01:00
ptitSeb 98725002e6 A few more wrapped functions 2019-02-16 14:34:07 +01:00
ptitSeb e834fd31c8 Added a few more libc wrapped function (trip.bit.runner now seems to works) 2019-02-16 14:28:15 +01:00
ptitSeb 53d00d528c Fixed vorbisfile ov_open_callbaks, at last (but gemini_rue still crashes after 1st screen) 2019-02-16 13:08:17 +01:00
ptitSeb e6b31b2d7e Better handling of the 'self' notion in elfloader 2019-02-16 12:28:01 +01:00
ptitSeb b61ed02ee4 Add fixed a type in my_ov_open_callbacks 2019-02-16 12:27:35 +01:00
ptitSeb 512d06ae48 Some fixes to a few wrapped functions 2019-02-16 12:22:04 +01:00
ptitSeb 66c2faf379 Added a few libc wrapped functions 2019-02-15 23:17:57 +01:00
ptitSeb 4ba2a4ec27 Added wrapped function onXext for Shm XImage stuffs 2019-02-15 23:08:29 +01:00
ptitSeb 6d2d8b8a3c Added wrapped libXcursor (mostly complete) 2019-02-15 22:46:18 +01:00
ptitSeb e9570fe320 Improved CImage handling (help Xenonauts) 2019-02-15 22:14:24 +01:00
ptitSeb 97c5983a4e Added Wrapped libXrender (complete) 2019-02-14 08:32:42 +01:00
ptitSeb 4bdbb91d4d And a new batch of wrapped functions 2019-02-13 23:40:32 +01:00
ptitSeb e84ab5d5dd Added wrapped libXfixes (complete) 2019-02-13 22:54:23 +01:00
ptitSeb 4aaea970cd Added wrapped libogg and libvorbis (partial) 2019-02-13 22:41:44 +01:00
ptitSeb 614300d911 Enabled that one in libasound 2019-02-13 22:41:22 +01:00
ptitSeb ab4c78c288 Fix a small typo 2019-02-13 22:40:50 +01:00
ptitSeb d4590ee13e Disablings cleanup for now, the order seems incorrect (at least provoques some double-free) 2019-02-13 22:25:05 +01:00
ptitSeb 456d4f999d Added wrapped libXinerama 2019-02-13 21:20:44 +01:00
ptitSeb 1ecc2d930a Small fix for Pandora only 2019-02-13 21:12:17 +01:00
ptitSeb 7881e1ec14 Added a bunch of wrapped functions, including ov_open_callbacks 2019-02-13 18:49:27 +01:00
ptitSeb b9184bba5d Add a few more opcode, Xenonauts now start 2019-02-13 17:51:50 +01:00
ptitSeb ff51cf7c72 Added some more GS: stuffs (some are wild guess) 2019-02-13 17:02:35 +01:00
ptitSeb 18f13de0f0 Added 2 more X11 wrapped functions 2019-02-13 15:36:33 +01:00
ptitSeb fe1652bf7f Fixed a typo with SDL_GetEnv 2019-02-13 15:36:02 +01:00
ptitSeb 06c7772c0a Fixed a typo in SDL2 wrapper 2019-02-13 11:43:25 +01:00
ptitSeb dd56fd116e Fix for SDL_GameControllerButtonBindForAxis wrapped function 2019-02-13 11:30:07 +01:00
ptitSeb e7db118ef4 Optimized some callback, when it's just called inside the function 2019-02-13 11:27:21 +01:00
ptitSeb 14964b55b9 Added a bunch of wrapped function (needed by Xenonauts) 2019-02-13 08:51:31 +01:00
ptitSeb cf59aef0f5 Added a few wrapped functions 2019-02-12 23:07:28 +01:00
ptitSeb 59ccc7fdef Fixed a typo in the system lib folders 2019-02-12 22:07:14 +01:00
ptitSeb 5bb72f548f Added some 'system' path fr x86 libs 2019-02-12 21:41:08 +01:00
ptitSeb 58d96434e8 Fix a typo in a comment 2019-02-12 21:40:20 +01:00
ptitSeb a1093a9b37 Added a few more opcode 2019-02-12 18:02:46 +01:00
ptitSeb cccf15ce6c SDL_JoystickGetDeviceGUID also return a struct... 2019-02-12 17:59:09 +01:00
ptitSeb f977f8067e Add proprer (hopefully) handling of wrapped function that returns structs 2019-02-12 16:29:28 +01:00
ptitSeb 656e407e6d Fixed readlink hack with '/proc/self/exe' 2019-02-12 15:11:30 +01:00
ptitSeb 0b0309d5c3 Fixed ldiv wrapped function that return a struct (and so use a shadow pointer as 1st arg) 2019-02-12 12:24:35 +01:00
ptitSeb 112cee940e Added special case for readlink and '/proc/self/exe' 2019-02-12 12:05:51 +01:00
ptitSeb 82f5a3bff4 Added a few glX wrapped functions and extensions 2019-02-12 11:03:00 +01:00
ptitSeb 24c1fae0ce Small opcode optim 2019-02-12 10:49:38 +01:00
ptitSeb 9c8f25777c Ooops, fixed bsearch wrapped function 2019-02-12 10:49:25 +01:00
ptitSeb 3ec4dce187 Added a large bunch of wrapped functions (and callbacks) and a few opcodes 2019-02-12 07:59:23 +01:00
ptitSeb 9f7c0fa57a Added a generic error in dlerror (instead of aborting emulation) 2019-02-11 17:55:37 +01:00
ptitSeb fff085a79b Fixed my_zlib_free wrapper 2019-02-11 17:41:07 +01:00
ptitSeb 1ce5dcf37d Added wrapped libjpeg, libXext (partial), libcurl (partial) and add some handling of custom allocator in libz 2019-02-11 17:21:59 +01:00
ptitSeb 4b6a9486d8 Added a couple of x87 opcode 2019-02-11 12:18:34 +01:00
ptitSeb 8f1096a082 Added SDL_GL_ProcAddress toSDL1 and 2, plus a fix in putc, and added a few missing SDL2 wrapped functions 2019-02-11 12:13:54 +01:00
ptitSeb bee55277d9 New developpement cycle 2019-02-11 09:47:22 +01:00
425 changed files with 100306 additions and 13428 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: paypal.me/0ptitSeb
+4 -2
View File
@@ -1,3 +1,5 @@
build
build_llvm
build/
build*/
.vscode
.gdb_history
src/git_head.h
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Regular → Executable
+43
View File
@@ -1,3 +1,46 @@
v0.1.2
======
* The Dynarec now handle JIT code
* Added support for Unity games (not perfect yet)
* Added support for Wine (not perfect yet). You need an x86 build of Wine to use it
* Added support for Steam (not perfect yet). Note that steam have limited functionnalities on 32bits (only mini-mode is available)
* More wrapped libs
* Added support for "PltResolver", so order of library is less important and many symbol are resolved at runtime
* Added an option to build box86 as a lib (to wrapped dynamic library)
* Better Signal handling (not perfect yet)
* More opcodes added, more opcode fixes.
* More Dynarec opcodes.
* Added support for FS:, and creating custom selector (needed by Wine)
* There is now 1 x86emu_t structure per thread (simplifying/optimising many callback handling)
* Box86 now have a logo!
* Added options handling (only version and help for now). Now it's much usefull exept for version printing.
v0.1.0
=======
* Dynarec!!! Only for ARM (note that dynarec doesn't support JITed code for now)
* Added real support for getcontext/set/context/makecontext/swapcontext
* Preliminary signal handling
* Fixes to SDL(1/2) Image and SDL1 Mixer, and to SDL1.2 RWops usage
* Fixed numerous issues in opcodes (both interpretor and dynarec). FTL works fine now, among many others
* Added wrapped gtk support (still ongoing, many libs involved)
* Make loading of libs more configurable
* If a wrapped native libs is not found, try to use emulated one
* Add en env. var. to force use of emulated lib for certain libs
* Add an env. var. to define wich libGL to use
* Added Install / Uninstall target (using systemd binfmt)
* Added more hardware target (RPis, GameShell...)
* Wrapped more libs (including FreeType, smpeg, ncurses, sndfile...)
v0.0.4
=======
* Improved the Init of dependant Libs. More things work now.
* Added a lot of wrapped functions.
* Added a few wrapped libs (like libz or some other x11 related libs)
* For trace enabled build, Trace can be enabled only after a certain amount of opcodes (still, a debugger would be better)
* Some fixes in a few opcodes, and implemented x87 rounding (SuperMeatBoy behaves better now)
* FTL 1.6.9 still have corrupted music, but older 1.5.13 seems fine (different set of libs)
v0.0.2
=======
* A full commercial games runs fine on the Pandora: Airline Tycoon Deluxe
+480 -68
View File
@@ -3,20 +3,111 @@ cmake_minimum_required(VERSION 2.6)
project(box86)
enable_testing()
enable_language(C)
option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA})
option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(USE_FLOAT "Set to ON to use only float, no double, in all x87 Emulation" ${USE_FLOAT})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation (WIP, don't use yet)" ${ARM_DYNAREC})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
if(NOT PYTHONINTERP_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
endif()
if(${PYTHON_VERSION_MAJOR} LESS 3)
message( FATAL_ERROR "You need a Python 3 interpretor, CMake will exit." )
endif()
else()
find_package(Python3)
if(NOT Python3_Interpreter_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
endif()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
set(default_build_type "RelwithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# Pandora
if(PANDORA)
add_definitions(-DPANDORA)
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
# Gameshell
if(GAMESHELL)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(PYRA)
add_definitions(-mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI2)
add_definitions(-DRPI)
add_definitions(-DRPI2)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI3)
add_definitions(-DRPI)
add_definitions(-DRPI3)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI4)
add_definitions(-DRPI)
add_definitions(-DRPI3)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(ODROID)
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
set(BOX86_ELF_ADDRESS "0x02800000")
if(LD80BITS)
add_definitions(-DHAVE_LD80BITS)
endif()
@@ -29,7 +120,36 @@ if(HAVE_TRACE)
add_definitions(-DHAVE_TRACE)
endif()
add_definitions(-g -std=gnu99 -funwind-tables -O3 -fvisibility=hidden -no-pie -fjump-tables)
if(USE_FLOAT)
add_definitions(-DUSE_FLOAT)
endif()
if(ARM_DYNAREC)
add_definitions(-DDYNAREC)
add_definitions(-DARM)
add_definitions(-marm)
enable_language(ASM)
endif()
if(NOGETCLOCK)
add_definitions(-DNOGETCLOCK)
endif()
if(BOX86LIB)
add_definitions(-DBUILD_LIB)
if(BOX86DYNAMIC)
add_definitions(-DBUILD_DYNAMIC)
endif()
add_definitions(-fPIC)
if(NOT BOX86_ROOT)
message(FATAL_ERROR "BOX86_ROOT not set when build as lib")
endif()
else()
set(BOX86_ROOT ${CMAKE_HOME_DIRECTORY})
endif()
add_definitions(-std=gnu99 -funwind-tables -fvisibility=hidden)
if(USE_CCACHE)
find_program(CCACHE_FOUND ccache)
@@ -39,114 +159,406 @@ if(USE_CCACHE)
endif()
endif()
#include_directories(include)
include_directories(
"${BOX86_ROOT}/src/include"
"${BOX86_ROOT}/src"
"${BOX86_ROOT}/src/wrapped/generated"
)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\"\>${BOX86_ROOT}/src/git_head.h"
DEPEND "${BOX86_ROOT}/src/build_info.c"
VERBATIM
)
set(ELFLOADER_SRC
"${CMAKE_HOME_DIRECTORY}/src/bridge.c"
"${CMAKE_HOME_DIRECTORY}/src/main.c"
"${CMAKE_HOME_DIRECTORY}/src/pathcoll.c"
"${CMAKE_HOME_DIRECTORY}/src/box86context.c"
"${CMAKE_HOME_DIRECTORY}/src/fileutils.c"
"${CMAKE_HOME_DIRECTORY}/src/elfloader.c"
"${CMAKE_HOME_DIRECTORY}/src/elfparser.c"
"${CMAKE_HOME_DIRECTORY}/src/elfload_dump.c"
"${CMAKE_HOME_DIRECTORY}/src/library.c"
"${CMAKE_HOME_DIRECTORY}/src/librarian.c"
"${CMAKE_HOME_DIRECTORY}/src/stack.c"
"${CMAKE_HOME_DIRECTORY}/src/threads.c"
"${CMAKE_HOME_DIRECTORY}/src/wrapper.c"
"${CMAKE_HOME_DIRECTORY}/src/x86emu.c"
"${CMAKE_HOME_DIRECTORY}/src/x86run.c"
"${CMAKE_HOME_DIRECTORY}/src/x86run66.c"
"${CMAKE_HOME_DIRECTORY}/src/x86run_private.c"
"${CMAKE_HOME_DIRECTORY}/src/x86syscall.c"
"${CMAKE_HOME_DIRECTORY}/src/x86primop.c"
"${CMAKE_HOME_DIRECTORY}/src/x86trace.c"
"${CMAKE_HOME_DIRECTORY}/src/x86int3.c"
"${CMAKE_HOME_DIRECTORY}/src/x87emu_private.c"
"${CMAKE_HOME_DIRECTORY}/src/x87run.c"
"${CMAKE_HOME_DIRECTORY}/src/myalign.c"
"${CMAKE_HOME_DIRECTORY}/src/callback.c"
"${CMAKE_HOME_DIRECTORY}/src/sdl1rwops.c"
"${CMAKE_HOME_DIRECTORY}/src/sdl2rwops.c"
"${BOX86_ROOT}/src/git_head.h"
"${BOX86_ROOT}/src/main.c"
"${BOX86_ROOT}/src/box86context.c"
"${BOX86_ROOT}/src/build_info.c"
"${BOX86_ROOT}/src/tools/bridge.c"
"${BOX86_ROOT}/src/tools/pathcoll.c"
"${BOX86_ROOT}/src/tools/fileutils.c"
"${BOX86_ROOT}/src/tools/callback.c"
"${BOX86_ROOT}/src/tools/box86stack.c"
"${BOX86_ROOT}/src/tools/my_cpuid.c"
"${BOX86_ROOT}/src/tools/gtkclass.c"
"${BOX86_ROOT}/src/tools/wine_tools.c"
"${BOX86_ROOT}/src/elfs/elfloader.c"
"${BOX86_ROOT}/src/elfs/elfparser.c"
"${BOX86_ROOT}/src/elfs/elfload_dump.c"
"${BOX86_ROOT}/src/librarian/library.c"
"${BOX86_ROOT}/src/librarian/librarian.c"
"${BOX86_ROOT}/src/emu/x86emu.c"
"${BOX86_ROOT}/src/emu/x86run.c"
"${BOX86_ROOT}/src/emu/x86run66.c"
"${BOX86_ROOT}/src/emu/x86run_private.c"
"${BOX86_ROOT}/src/emu/x86syscall.c"
"${BOX86_ROOT}/src/emu/x86primop.c"
"${BOX86_ROOT}/src/emu/x86trace.c"
"${BOX86_ROOT}/src/emu/x86int3.c"
"${BOX86_ROOT}/src/emu/x86tls.c"
"${BOX86_ROOT}/src/emu/x87emu_private.c"
"${BOX86_ROOT}/src/emu/x87run.c"
"${BOX86_ROOT}/src/libtools/auxval.c"
"${BOX86_ROOT}/src/libtools/myalign.c"
"${BOX86_ROOT}/src/libtools/myalign64.c"
"${BOX86_ROOT}/src/libtools/myfts.c"
"${BOX86_ROOT}/src/libtools/obstack.c"
"${BOX86_ROOT}/src/libtools/sdl1rwops.c"
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
"${BOX86_ROOT}/src/libtools/signals.c"
"${BOX86_ROOT}/src/libtools/threads.c"
"${BOX86_ROOT}/src/dynarec/dynarec.c"
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
)
set(WRAPPEDS
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibc.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibpthread.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibrt.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibgl.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibglu.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibx11.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibasound.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibdl.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibm.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsdl1.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsdl1mixer.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsdl1image.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsdl2.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsdl2mixer.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsdl2image.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedsmpeg2.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedvorbisfile.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedpng16.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibxxf86vm.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibxrandr.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedlibz.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedopenal.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedalut.c"
"${CMAKE_HOME_DIRECTORY}/src/wrappedldlinux.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibpthread.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibm.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl1.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl1mixer.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl1image.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl1ttf.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX86_ROOT}/src/wrapped/wrappedvorbisfile.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibvorbis.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibogg.c"
"${BOX86_ROOT}/src/wrapped/wrappedpng12.c"
"${BOX86_ROOT}/src/wrapped/wrappedpng16.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxrandr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxext.c"
"${BOX86_ROOT}/src/wrapped/wrappedxinerama.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxfixes.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcursor.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxrender.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxi.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxss.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxpm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxdmcp.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxtst.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxt.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcomposite.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxdamage.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxmu.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX86_ROOT}/src/wrapped/wrappediconv.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibdrm.c"
"${BOX86_ROOT}/src/wrapped/wrappedcrypto.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibssl.c"
"${BOX86_ROOT}/src/wrapped/wrappedutil.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibuuid.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibresolv.c"
"${BOX86_ROOT}/src/wrapped/wrappedpulsesimple.c"
"${BOX86_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibsndfile.c"
"${BOX86_ROOT}/src/wrapped/wrappedfontconfig.c"
"${BOX86_ROOT}/src/wrapped/wrappedfreetype.c"
"${BOX86_ROOT}/src/wrapped/wrappedbz2.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibsm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibice.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibusb1.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncursesw.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibformw.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgio2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgmodule2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgobject2.c"
"${BOX86_ROOT}/src/wrapped/wrappedglib2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer010.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX86_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX86_ROOT}/src/wrapped/wrappedcairo.c"
"${BOX86_ROOT}/src/wrapped/wrappedpango.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX86_ROOT}/src/wrapped/wrappedgudev1.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibnm.c"
"${BOX86_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
"${BOX86_ROOT}/src/wrapped/wrappedmpg123.c"
"${BOX86_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
)
set(WRAPPER "${CMAKE_HOME_DIRECTORY}/src/wrapper.c" "${CMAKE_HOME_DIRECTORY}/src/wrapper.h")
add_custom_command(OUTPUT ${WRAPPER} COMMAND "${CMAKE_HOME_DIRECTORY}/rebuild_wrappers.py" "${CMAKE_HOME_DIRECTORY}" MAIN_DEPENDENCY "${CMAKE_HOME_DIRECTORY}/rebuild_wrappers.py" DEPENDS ${WRAPPEDS})
set_source_files_properties(${WRAPPER} PROPERTIES GENERATED TRUE)
add_executable(box86 ${ELFLOADER_SRC} ${WRAPPEDS})
target_link_libraries(box86 m dl rt pthread)
set(WRAPPEDS_HEAD "")
foreach(A ${WRAPPEDS})
string(REPLACE ".c" "_private.h" B ${A})
set(WRAPPEDS_HEAD ${WRAPPEDS_HEAD} ${B})
set_source_files_properties(${A} PROPERTIES OBJECT_DEPENDS ${B})
endforeach()
target_link_libraries(box86 -no-pie -Wl,-Ttext-segment,0xA8000000)
set(WRAPPER "${BOX86_ROOT}/src/wrapped/generated/wrapper.c" "${BOX86_ROOT}/src/wrapped/generated/wrapper.h")
add_test(test01 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "USE_FLOAT" "--" ${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
BYPRODUCTS ${WRAPPER}
)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/dynarec/last_run.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_printer.py" "${BOX86_ROOT}"
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_printer.py"
DEPENDS "${BOX86_ROOT}/src/dynarec/arm_instructions.txt"
BYPRODUCTS "${BOX86_ROOT}/src/dynarec/arm_printer.c"
)
add_custom_target(WRAPPERS DEPENDS "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt")
add_custom_target(PRINTER DEPENDS "${BOX86_ROOT}/src/dynarec/last_run.txt")
#this is to force build_info.c to be rebuilt all the time
set_source_files_properties("${BOX86_ROOT}/src/build_info.c" PROPERTIES OBJECT_OUTPUTS "dummy.c")
if(ARM_DYNAREC)
set(DYNAREC_SRC
"${BOX86_ROOT}/src/dynarec/dynablock.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_functions.c"
"${BOX86_ROOT}/src/dynarec/arm_printer.c"
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
"${BOX86_ROOT}/src/dynarec/arm_linker.S"
"${BOX86_ROOT}/src/dynarec/arm_table.S"
)
set(DYNAREC_PASS
"${BOX86_ROOT}/src/dynarec/dynarec_arm_helper.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_tests.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_math.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_logic.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_shift.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_pass.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_00.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_0f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_64.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_65.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_66.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_67.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_d8.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_d9.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_da.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_db.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_dc.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_dd.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_de.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_df.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f0.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_660f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f20f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f30f.c"
)
set(DYNAREC_PASS "${BOX86_ROOT}/src/wrapped/generated/wrapper.h" ${DYNAREC_PASS})
add_library(dynarec_arm OBJECT ${DYNAREC_SRC})
add_library(arm_pass0 OBJECT ${DYNAREC_PASS})
set_target_properties(arm_pass0 PROPERTIES COMPILE_FLAGS "-DSTEP=0")
add_library(arm_pass1 OBJECT ${DYNAREC_PASS})
set_target_properties(arm_pass1 PROPERTIES COMPILE_FLAGS "-DSTEP=1")
add_library(arm_pass2 OBJECT ${DYNAREC_PASS})
set_target_properties(arm_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
add_library(arm_pass3 OBJECT ${DYNAREC_PASS})
set_target_properties(arm_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
add_dependencies(arm_pass0 WRAPPERS)
add_dependencies(arm_pass1 WRAPPERS)
add_dependencies(arm_pass2 WRAPPERS)
add_dependencies(arm_pass3 WRAPPERS)
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_arm>
$<TARGET_OBJECTS:arm_pass0>
$<TARGET_OBJECTS:arm_pass1>
$<TARGET_OBJECTS:arm_pass2>
$<TARGET_OBJECTS:arm_pass3>
)
endif()
if(BOX86LIB)
#build a static or dynamic lib...
if(BOX86DYNAMIC)
add_library(box86 SHARED ${ELFLOADER_SRC} ${WRAPPEDS})
else()
add_library(box86 OBJECT ${ELFLOADER_SRC} ${WRAPPEDS})
endif()
if(ARM_DYNAREC)
target_link_libraries(box86 dynarec m dl rt pthread)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
set_target_properties(box86 PROPERTIES LINK_FLAGS -rdynamic)
else()
target_link_options(box86 PUBLIC -rdynamic)
endif()
add_dependencies(box86 WRAPPERS)
add_dependencies(box86 PRINTER)
else(BOX86LIB)
if(USE_FLOAT)
set(BOX86 box86f)
elseif(HAVE_TRACE)
set(BOX86 box86t)
else()
set(BOX86 box86)
endif()
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS})
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
target_link_libraries(${BOX86} m dl rt pthread)
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
else()
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
endif()
else()
target_link_options(${BOX86} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
endif()
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
add_test(test01 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test02 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test02 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test03 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test03 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test04 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test04 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test05 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test05 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test06 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test06 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test07 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test07 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test08 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test08 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test09 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/box86
add_test(test09 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test10 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test11 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref11.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test12 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref12.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test13 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test13 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test14 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endif(BOX86LIB)
Executable
+64
View File
@@ -0,0 +1,64 @@
Compiling
----
#### for Pandora
`mkdir build; cd build; cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for Pyra
`mkdir build; cd build; cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for Gameshell
`mkdir build; cd build; cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for RaspberryPI
_a build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
`mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
_For Pi4. Change to RPI2 or RPI3 for other models._
#### for ODROID
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for Other ARM Linux
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for x86 Linux
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### use ccmake
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
#### Customize your build
*use ccache if you have it*
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
*have some debug info*
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument make a build that is both optimized for speed, and have debug information embedded. That way, if you have a crash or try to analyse performances, you'll have some symbols.
*to have a Trace Enabled build*
To have a trace enabled build (warning, it will be slower), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system lib folders.
*to have ARM Dynarec*
The Dynarec is only avaiable on ARM Cpu. Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
----
Testing
----
A few tests are included.
They can be launched with `ctest`
They are very basic and don't test much for now.
Executable
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2018-2019 Sebastien Chevalier ("ptitSeb")
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Regular → Executable
+80 -8
View File
@@ -1,18 +1,90 @@
# box86
![Official logo](Box86Logo.png "Official Logo")
Linux Userspace x86 Emulator with a twist
Box86 will let run x86 Linux program (games) on non-x86 Linux, like ARM (needs to be 32bits little-endian).
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux, like ARM (host system needs to be 32bit little-endian).
Also, Box86 use native version for some "system" libraries, like libc, libm, or SDL and OpenGL, leading to more performance and easier integration with host system.
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only support 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized).
Most x86 Games needs OpenGL, so on ARM platform, a solution like gl4es is probably needed.
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use, and performance can be surprisingly high in some cases.
Current version is higly experimental and early, and most stuff wont run and run correctly. For now, WorldOfGoo does run correctly. FTL runs but sound is distorted...
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary.
If you are serious about developping Box86, you should install ccache and activate it's support in the cmake project (use ccmake for example)
To have the TRACE enabled (i.e. dumping to stdout all individual x86 instruction execute, with dump of registers), you'll also need [Zydis library](https://github.com/zyantific/zydis) accessible on your system.
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter.
Some x86 internal opcode use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/x86primop.c) for copyright details
Many games already work, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine (there a long list, among them are UNDERTALE, A Risk of Rain, and Cook Server Delicious)
Change log is accessible [here](CHANGELOG.md)
If you are serious about developing Box86, you should install ccache and activate its support in the cmake project (use ccmake for example)
To enable TRACE (i.e. dumping to stdout all individual x86 instructions executed, with dump of registers), you'll also need [Zydis library](https://github.com/zyantific/zydis) available on your system.
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/x86primop.c) for copyright details
Here are 6 videos, the first 2 of "Airline Tycoon Deluxe" and "Heretic 2" running on a gigahertz OpenPandora (the second one use the dynarec), and the next 2 of "Bit.Trip.Runner" and "Neverwinter Night" running on an ODroid XU4 (without dynarec), and the last 2 on a Pi4: Shovel Knight (video from @ITotalJustice) and Freedom Planet (video from @djazz), also without dynarec.
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
You can find many more Box86 video on [PI Lab Channel](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) [![PI Lab Channel](https://yt3.ggpht.com/a/AATXAJyMeWrgCjs78gr6To6yX4KtDPUCS7hsbX1rRA=s100-c-k-c0xffffffff-no-rj-mo)](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g).
Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="Box86Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
----
Compiling
----
Compilation instructions can be found [here](COMPILE.md)
----
Usage
----
There are a few environment variables avaiable to control the behaviour of Box86.
See [here](USAGE.md) for all variables and what they do.
Note that now the Dynarec of Box86 uses a mecanism with Memory Protection and a SegFault signal handler to handle JIT code. That means if you want to use gdb to debug running a program that use JIT'd code (like mono/Unity3D), you will have many "normal" segfaults triggering. I suggest you use something like `handle SIGSEGV nostop` in gdb to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
----
Version history
----
The change log is available [here](CHANGELOG.md)
----
A note about 64-bit platforms
----
Because Box86 works by directly translating function calls from x86 to host system, the host system (the one Box86 is running on) needs to have 32-bit libraries. Box86 doesn't include any 32-bit <-> 64-bit translation. So basically, to run Box86 on, for example, an ARM64 platform, you will need to build Box86 for ARM 32-bit, and also need to have a chroot with 32-bit libraries.
Also note that, even if, on day, there is a Box86_64, this one will only be able to run x86_64 binaries on 64-bit platforms. You will still need Box86 (and see 32-bit chroot) to run x86 binaries (in fact, the same is the case on actual x86_64 Linux).
----
A note about Unity game emulation
----
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with he new "protected memory" mechanism implemented it is running with correct performance now.
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
TL;DR: Not all Mono games work and can require a high OpenGL profile, but the speed, for the ones running, should be correct now.
----
A note about Wine
----
Wine is now partly supported. Wine integreted program all runs, annd some windows program and games now run fine. Don't forget most Windows games use Direct3D, that may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
----
Final words
----
(If you use Box86 in your project, please don't forget to mention Box86)
Executable
+132
View File
@@ -0,0 +1,132 @@
Usage
----
There are many environment variable to control Box86 behaviour.
##### BOX86_LOG
Controls the Verbose level of the log
* 0
* NONE : No message (except some fatal error)
* 1
* INFO : Current default. Show some log
* 2
* DEBUG : Verbose a lot of stuffs (like relocations or function called)
* 3
* DUMP : All DEBUG plus DUMP of all ELF Info
#### BOX86_LD_LIBRARY_PATH
Controls the folder scanned to look for x86 libs. Default is current folder and `lib` in current folder.
Also `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exists
#### BOX86_PATH
Controls the folder scanned to look for x86 executable. Default is current folder and `bin` in current folder.
#### BOX86_DLSYM_ERROR
* 0 : default. Don't log `dlsym` error
* 1 : Log dlsym error
#### BOX86_TRACE_FILE
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by actual PID of box86 instance
#### BOX86_TRACE
Only on build with trace enabled. Trace allow the logging of all instruction execute, along with register dump
* 0 : No trace
* 1 : Trace enabled. The trace start after the init of all depending libs is done
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found)
* 0xXXXXXXX-0xYYYYYYY : trace only between the 2 addresses
#### BOX86_TRACE_INIT
Use BOX86_TRACE_INIT instead of BOX_TRACE to start trace before init of Libs and main program
* 0 : No trace
* 1 : Trace enabled. The trace start with the init of all depending libs is done
#### BOX86_TRACE_START
Only on build with trace enabled.
* NNNNNNN : Start trace only after NNNNNNNN opcode execute (number is an `uint64_t`)
#### BOX86_TRACE_XMM
Only on build with trace enabled.
* 0 : Default, the XMM (i.e. SSE/SSE2) register will not be logged with the general and x87 registers
* 1 : Dump the XMM registers
#### BOX86_LOAD_ADDR
Try to load at 0xXXXXXX main binaray (if binary is a PIE)
* 0xXXXXXXXX the load address (only active on PIE programs)
#### BOX86_NOSIGSEGV
To disable handling of SigSEGV (to ease debugging mainly)
* 0 : default, let x86 program set sighandler for SEGV
* 1 : disable handling of SigSEGV
#### BOX86_NOSIGILL
To disable handling of SigILL (to ease debugging mainly)
* 0 : default, let x86 program set sighandler for Illegal Instruction
* 1 : disable handling of SigILL
#### BOX86_X11COLOR16
PANDORA only: to try convert X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows
* 0 : default, don't touch X11 colors
* 1 : Change colors arguments in XSetForeground, XSetBackground and XCreateGC
#### BOX86_X11THREADS
To call XInitThreads when loading X11 (for old Loki games with Loki_Compat lib)
* 0 : default, don't force call XInitThreads
* 1 : Call XInitThreads as soon as libX11 is loaded
#### BOX86_X11GLX
To Force libX11 GLX extension to be present
* 0 : Disable the force.
* 1 : default, GLX will always be present when using XQueryExtension
#### BOX86_DYNAREC_DUMP
* 0 : Disable Dynarec blocks dump (default)
* 1 : Enable Dynarec blocks dump
* 2 : Enable Dynarec blocks dump with some colors
#### BOX86_DYNAREC_LOG
Set level of DynaRec log
* 0 :
* NONE : No Log for DynaRec
* 1 :
* INFO : Minimum Dynarec Log (only unimplemented OpCode)
* 2 :
* DEBUG : Debug Log for Dynarec (with detail on block created / executed)
* 3 :
* VERBOSE : All above plus more
#### BOX86_DYNAREC
* 0 : Disable Dynarec
* 1 : Enable Dynarec (default)
#### BOX86_DYNAREC_LINKER
* 0 : Disable Dynarec Linker (use that on debug, with dynarec log >= 2, to have detail on wich block get executed)
* 1 : Enable Dynarec Linker (default)
#### BOX86_DYNAREC_TRACE
* 0 : Disable trace for generated code (default)
* 1 : Enable trace for generated code (like regular Trace, this will slow down a lot and generate huge logs)
#### BOX86_LIBGL
* libXXXX set the name for libGL (default to libGL.so.1)
* /PATH/TO/libGLXXX set the name and path for libGL
You can also use SDL_VIDEO_GL_DRIVER
#### BOX86_LD_PRELOAD
* XXXX[:YYYYY] force loading XXXX (and YYYY...) libraries with the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary
#### BOX86_EMULATED_LIBS
* XXXX[:YYYYY] force lib XXXX (and YYYY...) to be emulated (and not wrapped)
Some games use old version of some lib, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX86_ALLOWMISSINGLIBS
Allow box86 to continue even if a lib is missing
* 0 : default, stop if a lib cannot be loaded
* 1 : continue even if a needed lib cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_FIX_64BIT_INODES
* 0 : Don't fix 64bit inodes (default)
* 1 : Fix 64bit inodes. Helps when running on filesystems with 64bit inodes, the program uses API functions which don't support it and the program doesn't use inodes information.
+21
View File
@@ -0,0 +1,21 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)
+1984
View File
File diff suppressed because it is too large. Load diff
+304 -89
View File
@@ -1,84 +1,226 @@
#!/usr/bin/env python
import os
import glob
import sys
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'L', 'p', 'V']
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S']
def splitchar(s):
ret = [len(s)]
i = 0
for c in s:
i = i + 1
if i == 2:
continue
ret.append(values.index(c))
try:
ret = [len(s), values.index(s[0])]
for c in s[2:]:
ret.append(values.index(c))
return ret
except ValueError as e:
raise ValueError("Value is " + s) from e
def value(define):
return define[9:-1] if define.startswith("!") else define[8:-1]
def splitdef(dnf, defines):
cunjs = dnf.split(" || ")
clauses = [c.split(" && ") for c in cunjs]
ret = [len(cunjs)]
for cunj in clauses:
for c in cunj:
ret.append(len(c))
for cunj in clauses:
for c in cunj:
ret.append(defines.index(value(c)) * 2 + (1 if c.startswith("!") else 0))
ret.append(0)
return ret
def main(root):
# Initialize variables: gbl for all values, vals for file-per-file values, redirects for redirections
gbl = []
vals = {}
def invert(define):
return define[1:] if define.startswith("!") else ("!" + define)
def main(root, defines, files, ver):
global values
# Initialize variables: gbl for all values, redirects for redirections
gbl = {}
redirects = {}
# First read the files inside the headers
for filepath in glob.glob(os.path.join(root, "src", "wrapped*_private.h")):
for filepath in files:
filename = filepath.split("/")[-1]
locval = []
dependants = []
with open(filepath, 'r') as file:
for line in file:
ln = line.strip()
# If the line is a `#' line (#ifdef LD80BITS/#ifndef LD80BITS/header)
if ln.startswith("#"):
preproc_cmd = ln[1:].strip()
try:
if preproc_cmd.startswith("if defined(GO)"):
continue #if defined(GO) && defined(GOM)...
elif preproc_cmd.startswith("if !(defined(GO)"):
continue #if !(defined(GO) && defined(GOM)...)
elif preproc_cmd.startswith("error"):
continue #error meh!
elif preproc_cmd.startswith("endif"):
if dependants != []:
dependants.pop()
elif preproc_cmd.startswith("ifdef"):
if preproc_cmd[5:].strip() not in defines:
raise KeyError(preproc_cmd[5:].strip())
dependants.append("defined(" + preproc_cmd[5:].strip() + ")")
elif preproc_cmd.startswith("ifndef"):
if preproc_cmd[6:].strip() not in defines:
raise KeyError(preproc_cmd[6:].strip())
dependants.append("!defined(" + preproc_cmd[6:].strip() + ")")
elif preproc_cmd.startswith("else"):
dependants[-1] = invert(dependants[-1])
else:
raise NotImplementedError("Unknown preprocessor directive: {0} ({1}:{2})".format(
preproc_cmd.split(" ")[0], filename, line[:-1]
))
except KeyError as k:
raise NotImplementedError("Unknown key: {0} ({1}:{2})".format(
k.args[0], filename, line[:-1]
), k)
# If the line is a `GO...' line (GO/GOM/GO2/...)...
if ln.startswith("GO"):
elif ln.startswith("GO"):
# ... then look at the second parameter of the line
ln = ln.split(",")[1].split(")")[0].strip()
if ln[1] not in ["F"]:
raise NotImplementedError("Bad middle letter {0} ({1}:{2})".format(ln[1], filename, line[:-1]))
if any(c not in values for c in ln[2:]) or (('v' in ln[2:]) and (len(ln) > 3)):
old = ln
# This needs more work
acceptables = ['v', 'o', '0', '1'] + values
acceptables = ['v', '0', '1'] + values
if any(c not in acceptables for c in ln[2:]):
raise NotImplementedError("{0} ({1})".format(ln[2:], line))
# Ok, this is acceptable: there is 0, 1, stdout and void
raise NotImplementedError("{0} ({1}:{2})".format(ln[2:], filename, line[:-1]))
# Ok, this is acceptable: there is 0, 1 and/or void
ln = (ln
.replace("v", "") # void -> nothing
.replace("o", "p") # stdout -> pointer
.replace("0", "p") # 0 -> pointer
.replace("1", "i")) # 1 -> integer
redirects[old] = ln
redirects.setdefault(" && ".join(dependants), {})
redirects[" && ".join(dependants)][old] = ln
# Simply append the function name if it's not yet existing
if ln not in locval:
locval.append(ln)
if ln not in gbl:
gbl.append(ln)
# Sort the file local values and add it to the dictionary
locval.sort(key=lambda v: splitchar(v))
vals[filename] = locval
gbl.setdefault(" && ".join(dependants), [])
if ln not in gbl[" && ".join(dependants)]:
gbl[" && ".join(dependants)].append(ln)
# Sort the table
gbl.sort(key=lambda v: splitchar(v))
def length(s):
l = len(s)
if l < 10:
ret = "0" + str(l)
gbl_vals = {}
for k in gbl:
ks = k.split(" && ")
for v in gbl[k]:
if k == "":
gbl_vals[v] = []
continue
if v in gbl_vals:
if gbl_vals[v] == []:
continue
for other_key in gbl_vals[v]:
other_key_vals = other_key.split(" && ")
for other_key_val in other_key_vals:
if other_key_val not in ks:
break
else:
break
else:
gbl_vals[v].append(k)
else:
gbl_vals[v] = [k]
for v in gbl_vals:
for k in gbl_vals[v]:
if " && ".join([invert(v2) for v2 in k.split(" && ")]) in gbl_vals[v]:
gbl_vals[v] = []
break
gbl = {}
gbl_idxs = []
for k in gbl_vals:
if len(gbl_vals[k]) == 1:
key = gbl_vals[k][0]
else:
ret = str(l)
return ret
key = "(" + (") || (".join(gbl_vals[k])) + ")"
gbl[key] = gbl.get(key, []) + [k]
if (key not in gbl_idxs) and (key != "()"):
gbl_idxs.append(key)
gbl_idxs.sort(key=lambda v: splitdef(v, defines))
redirects_vals = {}
for k in redirects:
ks = k.split(" && ")
for v in redirects[k]:
if k == "":
redirects_vals[(v, redirects[k][v])] = []
continue
if (v, redirects[k][v]) in redirects_vals:
if redirects_vals[(v, redirects[k][v])] == []:
continue
for other_key in redirects_vals[(v, redirects[k][v])]:
if other_key == "()":
break
other_key_vals = other_key.split(" && ")
for other_key_val in other_key_vals:
if other_key_val not in ks:
break
else:
break
else:
redirects_vals[(v, redirects[k][v])].append(k)
else:
redirects_vals[(v, redirects[k][v])] = [k]
redirects = {}
redirects_idxs = []
for k, v in redirects_vals:
key = "(" + (") || (".join(redirects_vals[(k, v)])) + ")"
if key in redirects:
redirects[key].append([k, v])
else:
redirects[key] = [[k, v]]
if (key not in redirects_idxs) and (key != "()"):
redirects_idxs.append(key)
redirects_idxs.sort(key=lambda v: splitdef(v, defines))
# Sort the tables
for k in gbl:
gbl[k].sort(key=lambda v: splitchar(v))
values = values + ['0', '1']
for k in redirects:
redirects[k].sort(key=lambda v: splitchar(v[0]) + [0] + splitchar(v[1]))
values = values[:-2]
# Check if there was any new functions
functions_list = ""
for k in ["()"] + gbl_idxs:
for v in gbl[k]:
functions_list = functions_list + "#" + k + " " + v + "\n"
for k in ["()"] + redirects_idxs:
for v in redirects[k]:
functions_list = functions_list + "#" + k + " " + v[0] + " -> " + v[1] + "\n"
# functions_list is a unique string, compare it with the last run
try:
last_run = ""
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'r') as file:
last_run = file.read()
if last_run == functions_list:
# Mark as OK for CMake
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
file.write(functions_list)
#return 0
except IOError:
# The file does not exist yet, first run
pass
# Now the files rebuilding part
# File headers and guards
files_headers = {
"wrapper.c": """/*****************************************************************
* File automatically generated by rebuild_wrappers.py (v1.0.0.02)
* File automatically generated by rebuild_wrappers.py (v%s)
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "wrapper.h"
#include "x86emu_private.h"
#include "x87emu_private.h"
#include "emu/x86emu_private.h"
#include "emu/x87emu_private.h"
#include "regs.h"
#include "x86emu.h"
@@ -88,9 +230,32 @@ typedef union ui64_s {
uint32_t d[2];
} ui64_t;
extern void* my__IO_2_1_stderr_;
extern void* my__IO_2_1_stdin_ ;
extern void* my__IO_2_1_stdout_;
static void* io_convert(void* v)
{
if(!v)
return v;
if(v==my__IO_2_1_stderr_)
return stderr;
if(v==my__IO_2_1_stdin_)
return stdin;
if(v==my__IO_2_1_stdout_)
return stdout;
return v;
}
#ifdef USE_FLOAT
#define ST0val ST0.f
#else
#define ST0val ST0.d
#endif
int of_convert(int);
""",
"wrapper.h": """/*****************************************************************
* File automatically generated by rebuild_wrappers.py (v1.0.0.02)
* File automatically generated by rebuild_wrappers.py (v%s)
*****************************************************************/
#ifndef __WRAPPER_H_
#define __WRAPPER_H_
@@ -103,13 +268,16 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
// list of defined wrapper
// v = void, i = int32, u = uint32, U/I= (u)int64
// l = signed long, L = unsigned long (long is an int with the size of a pointer)
// p = pointer, P = callback
// f = float, d = double, D = long double, L = fake long double
// f = float, d = double, D = long double, K = fake long double
// V = vaargs, E = current x86emu struct, e = ref to current x86emu struct
// 0 = constant 0, 1 = constant 1
// o = stdout
// C = unsigned byte c = char
// W = unsigned short w = short
// O = libc O_ flags bitfield
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// Q = ...
// S8 = struct, 8 bytes
@@ -121,32 +289,52 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
"""
}
# Transform strings into arrays
gbl = [[c for c in v] for v in gbl]
# Rewrite the wrapper.h file:
with open(os.path.join(root, "src", "wrapper.h"), 'w') as file:
file.write(files_headers["wrapper.h"])
for v in gbl:
file.write("void " + ''.join(v) + "(x86emu_t *emu, uintptr_t fnc);\n")
for v in redirects:
file.write("void " + ''.join(v) + "(x86emu_t *emu, uintptr_t fnc);\n")
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.h"), 'w') as file:
file.write(files_headers["wrapper.h"] % ver)
for v in gbl["()"]:
file.write("void " + v + "(x86emu_t *emu, uintptr_t fnc);\n")
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
file.write("void " + v + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write("\n")
for v in redirects["()"]:
file.write("void " + v[0] + "(x86emu_t *emu, uintptr_t fnc);\n")
for k in redirects_idxs:
file.write("\n#if " + k + "\n")
for v in redirects[k]:
file.write("void " + v[0] + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write(files_guards["wrapper.h"])
# Rewrite the wrapper.c file:
with open(os.path.join(root, "src", "wrapper.c"), 'w') as file:
file.write(files_headers["wrapper.c"])
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
file.write(files_headers["wrapper.c"] % ver)
# First part: typedefs
for v in gbl:
# E e v c w i I C W u U f d D L p V
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "void*", "void*"]
for v in gbl["()"]:
# E e v c w i I C W u U f d D K l L p V O S
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
file.write("typedef " + types[values.index(v[0])] + " (*" + ''.join(v) + "_t)"
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
# E e v c w i I C W u U f d D K l L p V O S
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
file.write("#endif\n")
file.write("\n")
# Next part: function definitions
# Helper functions to write the function definitions
@@ -154,34 +342,38 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
if len(args) == 0:
return ""
if d % 4 != 0:
raise ValueError("{d} is not a multiple of 4. Did you try passing a V and something else?")
raise ValueError("{d} is not a multiple of 4. Did you try passing a V and something else?".format(d=d))
if args[0] == "0":
return "(void*)(R_ESP + {p}), ".format(p=d) + function_args(args[1:], d + 4)
elif args[0] == 1:
elif args[0] == "1":
return "1, " + function_args(args[1:], d)
arg = [
"emu, ", # E
"&emu, ", # e
"", # v
"*(int8_t*)(R_ESP + {p}), ", # c
"*(int16_t*)(R_ESP + {p}), ", # w
"*(int32_t*)(R_ESP + {p}), ", # i
"*(int64_t*)(R_ESP + {p}), ", # I
"*(uint8_t*)(R_ESP + {p}), ", # C
"*(uint16_t*)(R_ESP + {p}), ", # W
"*(uint32_t*)(R_ESP + {p}), ", # u
"*(uint64_t*)(R_ESP + {p}), ", # U
"*(float*)(R_ESP + {p}), ", # f
"*(double*)(R_ESP + {p}), ", # d
"*(long double*)(R_ESP + {p}), ", # D
"FromLD((void*)(R_ESP + {p})), ", # L
"*(void**)(R_ESP + {p}), ", # p
"(void*)(R_ESP + {p}), " # V
"emu, ", # E
"&emu, ", # e
"", # v
"*(int8_t*)(R_ESP + {p}), ", # c
"*(int16_t*)(R_ESP + {p}), ", # w
"*(int32_t*)(R_ESP + {p}), ", # i
"*(int64_t*)(R_ESP + {p}), ", # I
"*(uint8_t*)(R_ESP + {p}), ", # C
"*(uint16_t*)(R_ESP + {p}), ", # W
"*(uint32_t*)(R_ESP + {p}), ", # u
"*(uint64_t*)(R_ESP + {p}), ", # U
"*(float*)(R_ESP + {p}), ", # f
"*(double*)(R_ESP + {p}), ", # d
"*(long double*)(R_ESP + {p}), ", # D
"FromLD((void*)(R_ESP + {p})), ", # K
"*(intptr_t*)(R_ESP + {p}), ", # l
"*(uintptr_t*)(R_ESP + {p}), ", # L
"*(void**)(R_ESP + {p}), ", # p
"(void*)(R_ESP + {p}), ", # V
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
"io_convert(*(void**)(R_ESP + {p})), ", # S
]
# E e v c w i I C W u U f d D L p V
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 0]
# E e v c w i I C W u U f d D K l L p V O S
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4]
if len(values) != len(arg):
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
if len(values) != len(deltas):
@@ -202,27 +394,50 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
"R_EAX=(unsigned short)fn({0});", # W
"R_EAX=(uint32_t)fn({0});", # u
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
"float fl=fn({0}); fpu_do_push(emu); ST0.d = fl;", # f
"double db=fn({0}); fpu_do_push(emu); ST0.d = db;", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0.d = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0.d = db;", # L
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_EAX=(intptr_t)fn({0});", # l
"R_EAX=(uintptr_t)fn({0});", # L
"R_EAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
]
if len(values) != len(vals):
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
for v in gbl:
function_writer(file, ''.join(v), ''.join(v) + "_t", v[0], v[2:])
for v in redirects:
function_writer(file, v, redirects[v] + "_t", v[0], v[2:])
for v in gbl["()"]:
function_writer(file, v, v + "_t", v[0], v[2:])
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
function_writer(file, v, v + "_t", v[0], v[2:])
file.write("#endif\n")
file.write("\n")
for v in redirects["()"]:
function_writer(file, v[0], v[1] + "_t", v[0][0], v[0][2:])
for k in redirects_idxs:
file.write("\n#if " + k + "\n")
for v in redirects[k]:
function_writer(file, v[0], v[1] + "_t", v[0][0], v[0][2:])
file.write("#endif\n")
file.write(files_guards["wrapper.c"])
# Save the string for the next iteration, writing was successful
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
file.write(functions_list)
return 0
if __name__ == '__main__':
if main(sys.argv[1]) != 0:
limit = []
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
if main(sys.argv[1], sys.argv[2:limit[0]], sys.argv[limit[0]+1:], "1.2.0.09") != 0:
exit(2)
exit(0)
+8
View File
@@ -13,6 +13,14 @@ if( NOT TEST_REFERENCE )
endif( NOT TEST_REFERENCE )
set(ENV{BOX86_LOG} 0)
if( EXISTS ${CMAKE_SOURCE_DIR}/x86lib )
# we are inside box86 folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x86lib)
else()
# we are inside build folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/../x86lib)
endif( EXISTS ${CMAKE_SOURCE_DIR}/x86lib )
# run the test program, capture the stdout/stderr and the result var
execute_process(
COMMAND ${TEST_PROGRAM} ${TEST_ARGS} ${TEST_ARGS2}
+422 -45
View File
@@ -1,8 +1,9 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
#include <signal.h>
#include "box86context.h"
#include "elfloader.h"
@@ -13,89 +14,434 @@
#include "bridge.h"
#include "library.h"
#include "callback.h"
#include "wrapper.h"
#include "myfts.h"
#include "threads.h"
#include "x86trace.h"
#include "signals.h"
#ifdef DYNAREC
#include <sys/mman.h>
#include "dynablock.h"
#define MMAPSIZE (4*1024*1024) // allocate 4Mo sized blocks
#define MMAPBLOCK 256 // minimum size of a block
typedef struct mmaplist_s {
void* block;
uint8_t map[MMAPSIZE/(8*MMAPBLOCK)]; // map of allocated sub-block
} mmaplist_t;
// get first subblock free in map, stating at start. return -1 if no block, else first subblock free, filling size (in subblock unit)
static int getFirstBlock(mmaplist_t *map, int start, int maxsize, int* size)
{
#define ISFREE(A) (((map->map[(A)>>3]>>((A)&7))&1)?0:1)
if(start<0) start = 0;
while(start<MMAPSIZE/(8*MMAPBLOCK)) { // still a chance...
if(ISFREE(start)) {
// free, now get size...
int end = start+1;
while(end<MMAPSIZE/(8*MMAPBLOCK)) {
if(!ISFREE(end) || (end-start==maxsize)) {
if(size) *size = end-start;
return start;
}
++end;
}
if(size) *size = end-start;
return start;
}
++start;
}
return -1;
}
static void allocBlock(mmaplist_t *map, int start, int size)
{
for(int i=0; i<size; ++i) {
map->map[start/8]|=(1<<(start&7));
++start;
}
}
static void freeBlock(mmaplist_t *map, int start, int size)
{
for(int i=0; i<size; ++i) {
map->map[start/8]&=~(1<<(start&7));
++start;
}
}
uintptr_t AllocDynarecMap(int size, int nolinker)
{
if(size>MMAPSIZE) {
void* p = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(p==MAP_FAILED) {
dynarec_log(LOG_DEBUG, "Cannot create dynamic map of %d bytes\n", size);
return 0;
}
return (uintptr_t)p;
}
pthread_mutex_lock(&my_context->mutex_mmap);
int bsize = (size+MMAPBLOCK-1)/MMAPBLOCK;
// look for free space
for(int i=0; i<my_context->mmapsize; ++i) {
int rsize = 0;
int start = 0;
do {
start = getFirstBlock(my_context->mmaplist+i, start, bsize, &rsize);
if(start!=-1 && rsize>=bsize) {
allocBlock(my_context->mmaplist+i, start, bsize);
uintptr_t ret = (uintptr_t)my_context->mmaplist[i].block + start*MMAPBLOCK;
pthread_mutex_unlock(&my_context->mutex_mmap);
return ret;
}
if(start!=-1)
start += rsize;
} while (start!=-1);
}
// no luck, add a new one !
int i = my_context->mmapsize++; // yeah, useful post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", my_context->mmapsize);
my_context->mmaplist = (mmaplist_t*)realloc(my_context->mmaplist, my_context->mmapsize*sizeof(mmaplist_t));
void* p = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(p==MAP_FAILED) {
dynarec_log(LOG_DEBUG, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
--my_context->mmapsize;
pthread_mutex_unlock(&my_context->mutex_mmap);
return 0;
}
my_context->mmaplist[i].block = p;
memset(my_context->mmaplist[i].map, 0, sizeof(my_context->mmaplist[i].map));
allocBlock(my_context->mmaplist+i, 0, bsize);
pthread_mutex_unlock(&my_context->mutex_mmap);
return (uintptr_t)p;
}
void FreeDynarecMap(uintptr_t addr, uint32_t size)
{
if(size>MMAPSIZE) {
munmap((void*)addr, size);
return;
}
pthread_mutex_lock(&my_context->mutex_mmap);
int bsize = (size+MMAPBLOCK-1)/MMAPBLOCK;
// look for free space
for(int i=0; i<my_context->mmapsize; ++i) {
if(addr>=(uintptr_t)my_context->mmaplist[i].block && ((uintptr_t)my_context->mmaplist[i].block+MMAPSIZE)>=addr+size) {
int start = (addr - (uintptr_t)my_context->mmaplist[i].block) / MMAPBLOCK;
freeBlock(my_context->mmaplist+i, start, bsize);
pthread_mutex_unlock(&my_context->mutex_mmap);
return;
}
}
pthread_mutex_unlock(&my_context->mutex_mmap);
}
// each dynmap is 64k of size
dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
int idx = (addr>>16);
if(!my_context->dynmap[idx]) {
return NULL;
}
return my_context->dynmap[idx]->dynablocks;
}
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>16);
uintptr_t end = ((addr+size-1)>>16);
for (uintptr_t i=idx; i<=end; ++i) {
if(!my_context->dynmap[i]) {
my_context->dynmap[i] = (dynmap_t*)calloc(1, sizeof(dynmap_t));
my_context->dynmap[i]->dynablocks = NewDynablockList(i<<16, i<<16, 1<<16, 1, 0);
}
}
protectDB(addr, size);
}
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
{
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>16):(addr>>16);
uintptr_t end = ((addr+size-1)>>16);
for (uintptr_t i=idx; i<=end; ++i) {
dynmap_t* dynmap = my_context->dynmap[i];
if(dynmap) {
uintptr_t startdb = StartDynablockList(dynmap->dynablocks);
uintptr_t enddb = EndDynablockList(dynmap->dynablocks);
uintptr_t startaddr = addr;
if(startaddr<startdb) startaddr = startdb;
uintptr_t endaddr = addr + size - 1;
if(endaddr>enddb) endaddr = enddb;
if(startaddr==startdb && endaddr==enddb) {
if(destroy) {
my_context->dynmap[i] = NULL;
FreeDynablockList(&dynmap->dynablocks);
free(dynmap);
} else
MarkDynablockList(&dynmap->dynablocks);
} else
if(destroy)
FreeRangeDynablock(dynmap->dynablocks, startaddr, endaddr-startaddr+1);
else
MarkRangeDynablock(dynmap->dynablocks, startaddr, endaddr-startaddr+1);
}
}
}
// Remove the Write flag from an adress range, so DB can be executed
// no log, as it can be executed inside a signal handler
void protectDB(uintptr_t addr, uintptr_t size)
{
uintptr_t start = (addr)&~(box86_pagesize-1);
uintptr_t end = (addr+size+(box86_pagesize-1))&~(box86_pagesize-1);
// should get "end" according to last block inside the window
mprotect((void*)start, end-start, PROT_READ|PROT_EXEC);
}
// Add the Write flag from an adress range, and mark all block as dirty
// no log, as it can be executed inside a signal handler
void unprotectDB(uintptr_t addr, uintptr_t size)
{
uintptr_t start = (addr)&~(box86_pagesize-1);
uintptr_t end = (addr+size+(box86_pagesize-1))&~(box86_pagesize-1);
// should get "end" according to last block inside the window
mprotect((void*)start, end-start, PROT_READ|PROT_WRITE|PROT_EXEC);
cleanDBFromAddressRange(start, end-start, 0);
}
#endif
EXPORTDYN
void initAllHelpers(box86context_t* context)
{
static int inited = 0;
if(inited)
return;
my_context = context;
init_pthread_helper();
init_signal_helper();
inited = 1;
}
EXPORTDYN
void finiAllHelpers()
{
static int finied = 0;
if(finied)
return;
fini_pthread_helper();
fini_signal_helper();
finied = 1;
}
void x86Syscall(x86emu_t *emu);
/// maxval not inclusive
int getrand(int maxval)
{
if(maxval<1024) {
return ((random()&0x7fff)*maxval)/0x7fff;
} else {
uint64_t r = random();
r = (r*maxval) / RAND_MAX;
return r;
}
}
void free_tlsdatasize(void* p)
{
if(!p)
return;
tlsdatasize_t *data = (tlsdatasize_t*)p;
free(data->tlsdata);
free(p);
}
EXPORTDYN
box86context_t *NewBox86Context(int argc)
{
#ifdef BUILD_DYNAMIC
if(my_context) {
++my_context->count;
return my_context;
}
#endif
// init and put default values
box86context_t *context = (box86context_t*)calloc(1, sizeof(box86context_t));
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
context->deferedInit = 1;
context->maplib = NewLibrarian();
#endif
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
context->system = NewBridge();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x86Syscall);
context->vsyscall = AddBridge(context->system, vFv, x86Syscall, 0);
#ifdef BUILD_LIB
context->box86lib = RTLD_DEFAULT; // not ideal
#else
context->box86lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
#endif
context->dlprivate = NewDLPrivate();
context->callbacks = NewCallbackList();
context->argc = argc;
context->argv = (char**)calloc(context->argc, sizeof(char*));
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
pthread_mutex_init(&context->mutex_once, NULL);
pthread_mutex_init(&context->mutex_once2, NULL);
pthread_mutex_init(&context->mutex_trace, NULL);
pthread_mutex_init(&context->mutex_lock, NULL);
pthread_mutex_init(&context->mutex_thread, NULL);
pthread_key_create(&context->tlskey, free_tlsdatasize);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_blocks, NULL);
pthread_mutex_init(&context->mutex_mmap, NULL);
context->dynablocks = NewDynablockList(0, 0, 0, 0, 0);
#endif
InitFTSMap(context);
for (int i=0; i<4; ++i) context->canary[i] = 1 + getrand(255);
context->canary[getrand(4)] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
initAllHelpers(context);
return context;
}
EXPORTDYN
void FreeBox86Context(box86context_t** context)
{
#ifdef BUILD_DYNAMIC
if(--(*context)->count)
return;
#endif
if(!context)
return;
if(--(*context)->forked >= 0)
return;
if((*context)->emu)
FreeX86Emu(&(*context)->emu);
box86context_t* ctx = *context; // local copy to do the cleanning
FreeCollection(&(*context)->box86_path);
FreeCollection(&(*context)->box86_ld_lib);
if((*context)->zydis)
DeleteX86Trace(*context);
if((*context)->deferedInitList)
free((*context)->deferedInitList);
if((*context)->box86lib)
dlclose((*context)->box86lib);
FreeDLPrivate(&(*context)->dlprivate);
if((*context)->maplib)
FreeLibrarian(&(*context)->maplib);
for(int i=0; i<(*context)->argc; ++i)
free((*context)->argv[i]);
free((*context)->argv);
for (int i=0; i<(*context)->envc; ++i)
free((*context)->envv[i]);
free((*context)->envv);
for(int i=0; i<(*context)->elfsize; ++i) {
FreeElfHeader(&(*context)->elfs[i]);
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
}
free((*context)->elfs);
free(ctx->elfs);
free((*context)->stack);
FreeFTSMap(ctx);
FreeBridge(&(*context)->system);
if(ctx->maplib)
FreeLibrarian(&ctx->maplib);
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib);
if((*context)->glwrappers)
freeProcWrapper(&(*context)->glwrappers);
if((*context)->alwrappers)
freeProcWrapper(&(*context)->alwrappers);
#ifdef DYNAREC
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
if(ctx->dynablocks)
FreeDynablockList(&ctx->dynablocks);
for (int i=0; i<ctx->mmapsize; ++i)
if(ctx->mmaplist[i].block)
munmap(ctx->mmaplist[i].block, MMAPSIZE);
free(ctx->mmaplist);
pthread_mutex_destroy(&ctx->mutex_blocks);
pthread_mutex_destroy(&ctx->mutex_mmap);
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
cleanDBFromAddressRange(0, 0xffffffff, 1);
#endif
*context = NULL; // bye bye my_context
FreeCallbackList(&(*context)->callbacks);
CleanStackSize(ctx);
pthread_mutex_destroy(&(*context)->mutex_once);
FreeCollection(&ctx->box86_path);
FreeCollection(&ctx->box86_ld_lib);
FreeCollection(&ctx->box86_emulated_libs);
// stop trace now
if(ctx->dec)
DeleteX86TraceDecoder(&ctx->dec);
if(ctx->zydis)
DeleteX86Trace(ctx);
free(*context);
*context = NULL;
if(ctx->deferedInitList)
free(ctx->deferedInitList);
#ifndef BUILD_LIB
if(ctx->box86lib)
dlclose(ctx->box86lib);
#endif
FreeDLPrivate(&ctx->dlprivate);
free(ctx->argv);
for (int i=0; i<ctx->envc; ++i)
free(ctx->envv[i]);
free(ctx->envv);
free(ctx->stack);
free(ctx->fullpath);
free(ctx->box86path);
FreeBridge(&ctx->system);
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
FreeCallbackList(&ctx->callbacks);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
pthread_setspecific(ctx->tlskey, NULL);
}
pthread_key_delete(ctx->tlskey);
if(ctx->tlsdata)
free(ctx->tlsdata);
for(int i=0; i<3; ++i) {
if(ctx->segtls[i].present) {
// key content not handled by box86, so not doing anything with it
pthread_key_delete(ctx->segtls[i].key);
}
}
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
pthread_mutex_destroy(&ctx->mutex_lock);
pthread_mutex_destroy(&ctx->mutex_thread);
free_neededlib(&ctx->neededlibs);
if(ctx->atfork_sz) {
free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
for(int i=0; i<MAX_SIGNAL; ++i)
if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
signal(i, SIG_DFL);
}
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
finiAllHelpers();
free(ctx);
}
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
@@ -110,3 +456,34 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
return idx;
}
int AddTLSPartition(box86context_t* context, int tlssize) {
int oldsize = context->tlssize;
context->tlssize += tlssize;
context->tlsdata = realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
memset(context->tlsdata, 0, tlssize); // fill new space with 0 (not mandatory)
return -context->tlssize; // negative offset
}
void add_neededlib(needed_libs_t* needed, library_t* lib)
{
if(!needed)
return;
if(needed->size == needed->cap) {
needed->cap += 8;
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
}
needed->libs[needed->size++] = lib;
}
void free_neededlib(needed_libs_t* needed)
{
if(!needed)
return;
needed->cap = 0;
needed->size = 0;
if(needed->libs)
free(needed->libs);
needed->libs = NULL;
}
-83
View File
@@ -1,83 +0,0 @@
#ifndef __BOX86CONTEXT_H_
#define __BOX86CONTEXT_H_
#include <stdint.h>
#include <pthread.h>
#include "pathcoll.h"
typedef struct elfheader_s elfheader_t;
typedef struct x86emu_s x86emu_t;
typedef struct zydis_s zydis_t;
typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct dlprivate_s dlprivate_t;
typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct callbacklist_s callbacklist_t;
typedef struct library_s library_t;
typedef void* (*procaddess_t)(const char* name);
typedef struct box86context_s {
path_collection_t box86_path; // PATH env. variable
path_collection_t box86_ld_lib; // LD_LIBRARY_PATH env. variable
int x86trace;
zydis_t *zydis; // dlopen the zydis dissasembler
void* box86lib; // dlopen on box86 itself
int argc;
char** argv;
int envc;
char** envv;
char* fullpath;
uint32_t stacksz;
int stackalign;
void* stack; // alocated stack
elfheader_t **elfs; // elf headers and memory
int elfcap;
int elfsize; // number of elf loaded
uintptr_t ep; // entry point
x86emu_t *emu; // CPU / FPU / MMX&SSE regs
lib_t *maplib; // lib and symbols handling
bridge_t *threads; // threads
bridge_t *system; // other bridges
uintptr_t vsyscall; // vsyscall bridge value
dlprivate_t *dlprivate; // dlopen library map
kh_symbolmap_t *glwrappers; // the map of wrapper for glProcs (for GLX or SDL1/2)
procaddess_t glxprocaddress;
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
callbacklist_t *callbacks; // all callbacks
pthread_mutex_t mutex_once;
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
library_t *sdl1lib; // shortcut to SDL1 library (if loaded)
library_t *sdl1mixerlib;
library_t *sdl1imagelib;
library_t *sdl2lib; // shortcut to SDL2 library (if loaded)
library_t *sdl2mixerlib;
library_t *sdl2imagelib;
int deferedInit;
elfheader_t **deferedInitList;
int deferedInitSz;
int deferedInitCap;
int forked; // how many forks... cleanup only when < 0
} box86context_t;
box86context_t *NewBox86Context(int argc);
void FreeBox86Context(box86context_t** context);
int AddElfHeader(box86context_t* ctx, elfheader_t* head); // return the index of header
#endif //__BOX86CONTEXT_H_
+1 -1
View File
@@ -2,7 +2,7 @@
#define __BOX86_VERSION_H_
#define BOX86_MAJOR 0
#define BOX86_MINOR 0
#define BOX86_MINOR 1
#define BOX86_REVISION 2
#endif //__BOX86_VERSION_H_
+28
View File
@@ -0,0 +1,28 @@
#include <stdio.h>
#include "debug.h"
#include "box86version.h"
#include "git_head.h"
void PrintBox86Version()
{
printf("Box86%s%s%s v%d.%d.%d %s built on %s %s\n",
#ifdef HAVE_TRACE
" with trace",
#else
"",
#endif
#ifdef DYNAREC
" with Dynarec",
#else
"",
#endif
#ifdef USE_FLOAT
" (float only)",
#else
"",
#endif
BOX86_MAJOR, BOX86_MINOR, BOX86_REVISION,
GITREV,
__DATE__, __TIME__);
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef __BUILD_INFO_H__
#define __BUILD_INFO_H__
void PrintBox86Version();
#endif //__BUILD_INFO_H__
-134
View File
@@ -1,134 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "debug.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "box86context.h"
#include "stack.h"
#include "khash.h"
typedef struct onecallback_s {
x86emu_t *emu;
uintptr_t fnc;
int nb_args;
void* arg[8];
void* stack;
} onecallback_t;
KHASH_MAP_INIT_INT(callbacks, onecallback_t*)
typedef struct callbacklist_s {
kh_callbacks_t *list;
int cap;
int sz;
} callbacklist_t;
x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4)
{
callbacklist_t *callbacks = emu->context->callbacks;
int stsize = 1024*1024;
void* stack = malloc(stsize);
x86emu_t * newemu = NewX86Emu(emu->context, fnc, (uintptr_t)stack, stsize);
SetupX86Emu(newemu, emu->shared_global, emu->globals);
newemu->trace_start = emu->trace_start;
newemu->trace_end = emu->trace_end;
onecallback_t * cb;
int ret;
khint_t k = kh_put(callbacks, callbacks->list, (uintptr_t)newemu, &ret);
cb = kh_value(callbacks->list, k) = (onecallback_t*)calloc(1, sizeof(onecallback_t));
cb->stack = stack;
cb->emu = newemu;
cb->fnc = fnc;
cb->nb_args = nb_args;
cb->arg[0] = arg1;
cb->arg[1] = arg2;
cb->arg[2] = arg3;
cb->arg[3] = arg4;
return newemu;
}
onecallback_t* FindCallback(x86emu_t* emu)
{
// find the callback first
callbacklist_t *callbacks = emu->context->callbacks;
khint_t k = kh_get(callbacks, callbacks->list, (uintptr_t)emu);
if(k==kh_end(callbacks->list))
return NULL;
return kh_value(callbacks->list, k);
}
void FreeCallback(x86emu_t* emu)
{
// find the callback first
callbacklist_t *callbacks = emu->context->callbacks;
khint_t k = kh_get(callbacks, callbacks->list, (uintptr_t)emu);
if(k==kh_end(callbacks->list))
return;
onecallback_t* cb = kh_value(callbacks->list, k);
FreeX86Emu(&cb->emu);
free(cb->stack);
free(cb);
kh_del(callbacks, callbacks->list, k);
}
uint32_t RunCallback(x86emu_t* emu)
{
onecallback_t *cb = FindCallback(emu);
if(cb) {
for (int i=cb->nb_args-1; i>=0; --i) // reverse order
Push(emu, (uint32_t)cb->arg[i]);
EmuCall(emu, cb->fnc);
return R_EAX;
}
printf_log(LOG_INFO, "Warning, Callback not found?!\n");
return 0;
}
void SetCallbackArg(x86emu_t* emu, int arg, void* val)
{
onecallback_t *cb = FindCallback(emu);
if(cb) {
cb->arg[arg] = val;
}
}
void SetCallbackNArg(x86emu_t* emu, int narg)
{
onecallback_t *cb = FindCallback(emu);
if(cb) {
cb->nb_args = narg;
}
}
callbacklist_t* NewCallbackList()
{
callbacklist_t* callbacks = (callbacklist_t*)calloc(1, sizeof(callbacklist_t));
callbacks->list = kh_init(callbacks);
return callbacks;
}
void FreeCallbackList(callbacklist_t** callbacks)
{
if(!callbacks)
return;
if(!*callbacks)
return;
onecallback_t* cb;
kh_foreach_value((*callbacks)->list, cb,
FreeX86Emu(&cb->emu);
free(cb->stack);
free(cb);
);
kh_destroy(callbacks, (*callbacks)->list);
free(*callbacks);
*callbacks = NULL;
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef __CALLBACK_H__
#define __CALLBACK_H__
#include <stdint.h>
typedef struct callbacklist_s callbacklist_t;
typedef struct x86emu_s x86emu_t;
callbacklist_t* NewCallbackList();
void FreeCallbackList(callbacklist_t** callbacks);
x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
void FreeCallback(x86emu_t* emu);
uint32_t RunCallback(x86emu_t* emu);
void SetCallbackArg(x86emu_t* emu, int arg, void* val);
void SetCallbackNArg(x86emu_t* emu, int narg);
#endif //__CALLBACK_H__
-17
View File
@@ -1,17 +0,0 @@
#ifndef __DEBUG_H_
#define __DEBUG_H_
extern int box86_log; // log level
extern int trace_xmm; // include XMM reg in trace?
#define LOG_NONE 0
#define LOG_INFO 1
#define LOG_DEBUG 2
#define LOG_DUMP 3
extern FILE* ftrace;
#define printf_log(L, ...) if(L<=box86_log) fprintf(ftrace, __VA_ARGS__)
#define EXPORT __attribute__((visibility("default")))
#endif //__DEBUG_H_
+1116
View File
File diff suppressed because it is too large. Load diff
+27
View File
@@ -0,0 +1,27 @@
//arm epilog for dynarec
//Save stuff, prepare stack and register
//called with pointer to emu as 1st parameter
//and address to jump to as 2nd parameter
.text
.align 4
.global arm_epilog
arm_epilog:
//update register -> emu
//pop {r0}
stm r0, {r4-r12} // put back reg value in emu, including EIP (so r12 must be EIP now)
//restore all used register
//vpop {d8-d15}
pop {r4-r11, pc}
//end, return...
//bx lr
.global arm_epilog_fast
arm_epilog_fast:
//restore all used register
//vpop {d8-d15}
pop {r4-r11, pc}
//end, return...
//bx lr
+594
View File
@@ -0,0 +1,594 @@
; TYPE fields separated by spaces Assembler syntax
; When there are mutiple assembler syntax (like for LDR (immediate)), separate them based on the bytes
; E.G. for LDR (immediate), there are 3 lines with the 3 different asm syntaxes
# Field options:
# --------------
# Syntax: ... field/coption1(coption2)* ... (inside fields)
# Where each c correspond to the option character
# and optionN to the Nth option value
# ---
# c = '0'..'9'/'A'..'F': option=[01]
# Force the cth bit (hex) of the field (starting from LSB) to be <option>
# c = '=': option=[01x]{field_len}
# Force the field to have the given bits (where x = anything, starts from MSB)
# Post-fields option:
# -------------------
# Syntax: [fields] @ typeoption1 args1 typeoption2 args2 @ [Assembler syntax]
# ---
# typeoption contains '=' (l=r): args1=((.*) )?([^, ]*),([^, ]*),([^, ]*)@
# Changes a value between two other depending on whether l == r
# \2 is init (suffixed by ';', optional), \3 is set to \4 if true or \5 if false
# (cf VMOV/VORR aka V\op\, VEOR/VBIF/VBIT/VBSL aka V\op\)
# The 'true regex' is typeoption=([^= ]*)(=([^= ]*))+
# args1=((.*) )?([^, ]*),(([^, ]*),)+([^, ]*)@
# with the number of typeoption:\2 being equal to the number of args1:\4
# <a>=<b>[=<c>...] <initialization> <variable-changed>,<changed-into-if-a=b>[,<changed-into-if-a=c>...],<changed-into-else>@
# OR
# typeoption is discarded and must be set to '=', args1=((.*) )?(@@ (( ?.*[^@])*)@ )+([^, ]*),(([^, ]*),)+([^, ]*)
# \2 is init (suffixed by ';', optional), \6 is set to \7 if true or \8 if false
# The difference with the simple switch is that \4 is the test (inside the `if`)
# If there are multiple @@s, there are multiple `if`s (separated by `else`s)
# The 'true regex' is [DISCARDED]typeoption==
# args1=((.*) )?(@@ (( ?.*[^@])*)@ )+([^, ]*),([^, ]*),([^, ]*)
# <.>=<.>[=<c>...] <initialization> @@ <test>@[ @@ <test2>@...] <variable-changed>,<changed-into-if-a=b>,<changed-into-else>
# OR
# args1=((.*) )?!@(( [^%]*[^%@])*)%(( ?[^%]*[^%@])*)@(( .*[^@])*)@(( .*[^@])*)@
# Replaced by '\1; if (<equality>) { \3\7\5; } else { \3\9\5; }'
# Meaning, <.=.> <initialization> !@ <common-left-part>%<common-right-part>@ <substitute-true>@ <substitute-false>@ <...>
# (cf VMOV/VORR, aka V\op\ with the lastop variable)
# You can also add more '=' with corresponding substitutes.
# You can also add more '%' with corresponding substitutes.
# ----
# Inside the assembler syntax, you can add \var\ to mark a variable to be replaced
# (Meaning, %s and `var` as argument to printf)
# Full syntax: \\(%[0-9+]*.)?(.*)\\
# If \1 != "", add \1 to the string in printf, and in any case append \2 as argument to printf
! HACKS: (list of notable differences between the doc and this file)
! ------
! In theory, (0) and (1) bits are as important as 0 and 1:
! > An instruction is UNPREDICTABLE if:
! > • It is declared as UNPREDICTABLE in an instruction description or in this chapter.
! > • The pseudocode for that encoding does not indicate that a different special case applies, and a bit marked (0)
! or (1) in the encoding diagram of an instruction is not 0 or 1 respectively.
! - ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
! In practice, they are ignored here.
! SWP, SWPB, VMOV (VFPU): Rt2 (field and assembly) -> Rn (field and assembly)
! BKPT: must be AL, so cond (field) -> cond/=1110 (constrained field)
! PKHBT and PKHTB: {, LSL/ASR #<imm>} (assembly) -> {, <shift>} (assembly)
! PKHBT and PKHTB: immediate shift but shift & 1 -> ARMs (type)
! All NEON operations (advanced SIMD): limited, so multiply the lines
! VMOV (register): Vm ... Vm VMOV (field, assembly) -> Vn ... Vm @ m=n ...@ @ V\op\ (field, switchable var, assembly)
! VMOV is VORR constrained -> (removed VORR)
! VEOR, VBSL, VBIT, VBIF differ only depending on 2 bits: 0/1 0/1 ... VEOR -> @<2> ... @ ... @ V\op\ (field, switchable var, assembly)
! Three registers of different lengths (when having L and W variants): op (field) -> Q (field)
; ========== BEGINNING OF REGISTERED INSTRUCTIONS =========
# This instruction changes the instruction set to Thumb! Disabled (but valid)
#ARM_ 1 1 1 1 1 0 1 @<1> imm24 @ set imm24 = (imm24 << 2) + (param << 1)@ @ BLX <label>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 0 Vn Vd 0 0 0 1 N Q M 1 Vm VAND<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 1 Vn Vd 0 0 0 1 N Q M 1 Vm VBIC<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 0 Vn Vd 0 0 0 1 N Q M 1 Vm @ m=n const char* op op,"MOV","ORR"@ m=n char lastop[6] !@ %@ lastop[0] = '\0'@ sprintf(lastop, ", %s", vecname[(q << 5) + 0x20 + n])@ @ V\op\<c> <Qd>, <Qm>\lastop\
NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 op 0 D size Vn Vd 1 0 0 0 N Q M 0 Vm @ op=0 const char* opname opname,"ADD","SUB"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VTST<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VCEQ<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 0 Vm @ set size = 8 << size@ @ VML\(u ? "S" : "A")\<c>.I\%dsize\ <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 1 Vm VMUL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQRDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q/=0 M 1 Vm VPADD<c>.<dt> <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 0 N Q M 1 Vm @ u=0 const char* y y,"A","S"@ @ VFM\y\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm @ u=0 const char* op op,"ADD","SUB"@ @ V\op\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q/=0 M 0 Vm VPADD.F32 <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 1 0 D 1 sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm VABD.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VML\(op ? "S" : "A")\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VMUL.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm VCEQ.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm @ op=1 const char* strict strict,"T","E"@ @ VCG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 1 Vm @ op=1 const char* strict strict,"T","E"@ @ VACG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRECPS.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRSQRTS.F32 <Qd>, <Qn>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 <1> 0 <23>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=11xx 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=1 1 imm4 VBIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=1 1 imm4 BIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=110x 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
;INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <3> <4> <4>/=1111 0 <1> <1>/=1 1 <4>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
# Special case for VMOVL (harder to do it on the documented place)
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 0 L Q M 1 Vm VRSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 1 L Q M 1 Vm VRSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 1 0 1 0 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #<imm>
; VCVT: if imm6 IN "0xxxxx" then UNDEFINED;
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 <9> 1 1 1 <1> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.S32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.S32.F32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.U32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.U32.F32 <Qd>, <Qm>, #<fbits>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <18> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 1 1 Vn Vd IMM4 N Q M 0 Vm VEXT<c>.8 <Qd>, <Qn>, <Qm>, #<imm>
# size + param < 3
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=11 0 0 <4> 0 0 0 <2> <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 0 Q M 0 Vm VCNT<c>.8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 1 Q M 0 Vm VMVN<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 0 U Q M 0 Vm VPADAL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 0 Q M 0 Vm VQABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 1 Q M 0 Vm VQNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 0 Q M 0 Vm VCGT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 1 Q M 0 Vm VCGE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 0 Q M 0 Vm VCEQ<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 1 Q M 0 Vm VCLE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 0 0 Q M 0 Vm VCLT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 0 Q M 0 Vm VABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 1 Q M 0 Vm VNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 1 0 Vd 0 0 0 0 0 Q M 0 Vm VSWP<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 0 1 Q M 0 Vm VTRN<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set u = 1 - u@ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 0 Q M 0 Vm VRECPE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 1 Q M 0 Vm VRSQRTE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 0 Q M 0 Vm VCVT<c>.F32.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 1 Q M 0 Vm VCVT<c>.S32.F32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 0 Q M 0 Vm VCVT<c>.F32.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 1 Q M 0 Vm VCVT<c>.U32.F32 <Qd>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <8> 0 <6> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 Vn Vd 1 0 @<2> N op M 0 Vm @ param=0b00 char list[10] !@ sprintf(list, %)@ "{%s}", vecname[0x20 + n]@ "{%s-%s}", vecname[0x20 + n], vecname[0x20 + n + param]@ @ VTB\(op ? "X" : "L")\<c>.8 <Dd>, \list\, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 imm4 Vd 1 1 0 0 0 Q M 0 Vm VDUP<c>.\%dsize\ <Qd>, <Dm[x]>
; size != 11
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 1 1 <13> 0 <1> 0 <4>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 0 Q N 0 M 0 Vm VADD\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 1 Q N 0 M 0 Vm VSUB\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm @ set size = 16 << size@ @ VADDHN<c>.I\%dsize\ <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm VRADDHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 0 1 N 0 M 0 Vm VABAL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VRSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 1 1 N 0 M 0 Vm VABDL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 op 0 N 0 M 0 Vm VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 op 1 N 0 M 0 Vm VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 1 0 0 N 0 M 0 Vm VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 1 0 1 N 0 M 0 Vm VQDMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U/=0 1 D size/=00 Vn Vd 1 1 1 0 N 0 M 0 Vm @ set uint8_t size = 0@ @ VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
; Put after, otherwise some instructions are shadowed
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 0 op 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 op 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 op 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 0 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMUL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 0 0 <22>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <20>
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 0 0 <20>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 1 0 <22>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <20>
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 1 0 <20>
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
; ===== No more 1 1 1 1 ..., so invalidate all of them ====
INVALIDATE 1 1 1 1 <28>
ARMS cond 0 0 0 0 0 0 0 S Rn Rd imm5 type 0 Rm AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 0 S Rd (0) (0) (0) (0) Rm 1 0 0 1 Rn MUL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 0 1 S Rn Rd imm5 type 0 Rm EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 1 S Rd Ra Rm 1 0 0 1 Rn MLA{S}<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 0 1 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSBT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSHT<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 1 0 S Rn Rd imm5 type 0 Rm SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 0 0 RdHi RdLo Rm 1 0 0 1 Rn UMAAL<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 0 1 1 S Rn Rd imm5 type 0 Rm RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 1 0 Rd Ra Rm 1 0 0 1 Rn MLS<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 1 1 0 Rn Rt imm4H 1 0 1 1 imm4L STRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 0 1 1 imm4L LDRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSBT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 1 0 0 S Rn Rd imm5 type 0 Rm ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 0 S RdHi RdLo Rm 1 0 0 1 Rn UMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 0 1 S Rn Rd imm5 type 0 Rm ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 1 S RdHi RdLo Rm 1 0 0 1 Rn UMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 0 S Rn Rd imm5 type 0 Rm SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 0 S RdHi RdLo Rm 1 0 0 1 Rn SMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 1 S Rn Rd imm5 type 0 Rm RSC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 1 S RdHi RdLo Rm 1 0 0 1 Rn SMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 0 0 Rn SMLABB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 1 0 Rn SMLATB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 0 0 Rn SMLABT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 1 0 Rn SMLATT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWP<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
ARM_ cond/=1110 0 0 0 1 0 0 1 0 imm12 0 1 1 1 imm4 BKPT #<imm16>
ARMS cond 0 0 0 1 0 0 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TEQ<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 0 1 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWPB<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 0 1 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMP<c> <Rn>, <Rm>{, <shift>}
ARMS cond 0 0 0 1 0 1 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMN<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 1 0 0 S Rn Rd imm5 type 0 Rm ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 0 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREX<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREX<c> <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 0 0 0 Rm MOV{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 0 0 Rm LSL{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 0 1 Rn LSL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 1 0 Rm LSR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 1 1 Rn LSR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 0 0 Rm ASR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 0 1 Rn ASR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 1 1 0 Rm RRX{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 1 0 Rm ROR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 1 1 Rn ROR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXD<c> <Rd>, <Rt>, <Rt2>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXD<c> <Rt>, <Rt2>, [<Rn>]
ARMS cond 0 0 0 1 1 1 0 S Rn Rd imm5 type 0 Rm BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXB<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXB<c> <Rt>, [<Rn>]
ARMS cond 0 0 0 1 1 1 1 S (0) (0) (0) (0) Rd imm5 type 0 Rm MVN{S}<c> <Rd>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXH<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXH<c> <Rt>, [<Rn>]
ARM_ cond 0 0 1 0 0 0 0 S Rn Rd imm12 AND{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 0 1 S Rn Rd imm12 EOR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 0 S Rn Rd imm12 SUB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 1 S Rn Rd imm12 RSB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 0 S Rn Rd imm12 ADD{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 1 S Rn Rd imm12 ADC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 0 S Rn Rd imm12 SBC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 1 1 Rn (0) (0) (0) (0) imm12 CMN<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 0 S Rn Rd imm12 ORR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 1 S (0) (0) (0) (0) Rd imm12 MOV{S}<c> <Rd>, #<const>
ARM_ cond 0 0 1 1 1 1 0 S Rn Rd imm12 BIC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 1 1 S (0) (0) (0) (0) Rd imm12 MVN{S}<c> <Rd>, #<const>
ARM_ cond 0 1 0 0 1 0 0 1 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 POP<c> {<Rt>}
ARM_ cond 0 1 0 0 U 0 0 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 0 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 0 Rn Rt imm12 STRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 1 Rn Rt imm12 LDRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 0 Rn Rt imm12 STRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 1 Rn Rt imm12 LDRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 1 0 0 1 0 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 PUSH<c> {<Rt>}
ARM_ cond 0 1 0 1 U 0 W 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 0 W 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm SSAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm SSUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm SSUB8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm USAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm USUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm USUB8<c> <Rd>, <Rn>, <Rm>
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 0 0 1 Rm PKHBT<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 1 0 1 Rm PKHTB<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 1 1 0 1 0 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 0 1 sat_imm Rd imm5 sh 0 1 Rn SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 0 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn SSAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 0 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 0 0 1 1 Rm REV<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REV16<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 1 1 sat_imm Rd imm5 sh 0 1 Rn USAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 1 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn USAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 1 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REVSH<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 1 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 U 0 0 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 0 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 0 Rn Rt imm5 type 0 Rm STRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 1 Rn Rt imm5 type 0 Rm LDRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARM_ cond 0 1 1 1 1 0 0 0 Rd 1 1 1 1 Rm 0 0 0 1 Rn USAD8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn register_list LDMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn/=1101 register_list STMEA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn register_list STM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 0 1 Rn/=1101 register_list LDMEA<c> <Rn>, <registers>
ARM_ cond 1 0 0 0 1 0 1 1 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"POP","LDMEA"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 0 1 0 W 1 Rn register_list LDM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 0 0 Rn/=1101 register_list STMFD<c> <Rn>, <registers>
ARM_ cond 1 0 0 1 0 0 1 0 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"PUSH","STMFD"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 1 0 0 W 0 Rn register_list STMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn/=1101 register_list LDMFD<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn register_list LDMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn/=1101 register_list STMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn register_list STMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn/=1101 register_list LDMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn register_list LDMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 1 0 imm24 B<c> <label>
ARM_ cond 1 0 1 1 imm24 BL<c> <label>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Sm>, <Sm1>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Sm>, <Sm1>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Dm>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Dm>
;INVALIDATE <4> 1 1 0 0 0 1 0 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
INVALIDATE <4> 1 1 0 <25>
INVALIDATE <4> 1 1 1 0 0 0 <1> 0 <8> 1 0 1 1 <1> 1 0 1 (0) (0) (0) (0)
;INVALIDATE <4> 1 1 1 0 1 <2> 0 <8> 1 0 1 1 <1> 0 <1> 1 (0) (0) (0) (0)
VFPU cond 1 1 1 0 0 0 0 0 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Sn>, <Rt>
VFPU cond 1 1 1 0 1 1 1 0 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMSR<c> FPSCR, <Rt>
VFPU cond 1 1 1 0 0 @<2> 0 Vd Rt 1 0 1 1 D @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (param1_2 << 2) + param2_2@ = uint8_t shift @@ (opc & 0b1000) == 0b1000@ @@ (opc & 0b1001) == 0b0001@ @@ (opc & 0b1011) == 0b0000@ shift,0,1,2,0xFF@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.\%d8 &l&l shift\ <Dd[x]>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VNML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 1 M 0 Vm VNMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 0 M 0 Vm VADD<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 1 M 0 Vm VSUB<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VDIV<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VFNM\(op ? "A" : "S")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 1 0 Vn Vd 1 0 1 sz N op M 0 Vm VFM\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
!/VFPU cond 1 1 1 0 1 x 1 1 opc2 <4> 1 0 1 <1> - - <1> 0 opc4 Table A7-17
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 0 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set float mantissa = 16 + param2_4@ set float imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F32 <Sd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 1 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set double mantissa = 16 + param2_4@ set double imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F64 <Dd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 0 1 M 0 Vm VMOV<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 1 1 M 0 Vm VABS<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 0 1 M 0 Vm VNEG<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 1 1 M 0 Vm VSQRT<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 0 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F32.F16 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 1 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F16.F32 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 1 Vd 1 0 1 sz op 1 (0) 0 (0) (0) (0) (0) VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, #0.0
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
;INVALIDATE <4> 1 1 1 0 1 <1> 1 1 <8> 1 0 1 <4> 0 <4>
;INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 0 <4>
; ============= END OF REGISTERED INSTRUCTIONS ============
INVALIDATE <32>
+25
View File
@@ -0,0 +1,25 @@
//arm update linker table for dynarec
//called with pointer to emu as 1st parameter
//and address of table to as 2nd parameter
//ip is at r12
.text
.align 4
.extern UpdateLinkTable
.global arm_linker
arm_linker:
// emu is r0
stm r0, {r4-r12} // put back reg value in emu, including EIP (easier debugging, and safer)
// table offset is r1
// IP address is r12
push {r0, r1, r12}
mov r2, r12
// call the function
bl UpdateLinkTable
// return offset is jump address
mov r3, r0
pop {r0, r1, r12}
bx r3
File diff suppressed because it is too large. Load diff
+6
View File
@@ -0,0 +1,6 @@
#ifndef _ARM_PRINTER_H_
#define _ARM_PRINTER_H_
const char* arm_print(uint32_t opcode);
#endif //_ARM_PRINTER_H_
+19
View File
@@ -0,0 +1,19 @@
//arm prologue for dynarec
//Save stuff, prepare stack and register
//called with pointer to emu as 1st parameter
//and address to jump to as 2nd parameter
.text
.align 4
.global arm_prolog
arm_prolog:
//save all used register
push {r4-r11, lr}
//vpush {d8-d15}
//setup emu -> register
//push {r0}
ldm r0, {r4-r11} // all 8 register in direct access, no EIP (so r12 can be used as scratch)
//TODO
//jump to function
bx r1
+19
View File
@@ -0,0 +1,19 @@
//arm try to update linker table for dynarec
//and address of table to as 1st parameter
//jump addres as second and ip as third
// don't retry if failed to write...
.text
.align 4
.global arm_tableupdate
arm_tableupdate:
// jump address is r0 and IP address is r1
// table offset is r2
push {r4, r5}
ldrexd r4, r5, [r2]
strexd r3, r0, r1, [r2]
pop {r4, r5}
mov r0, r3
bx lr
+587
View File
@@ -0,0 +1,587 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "tools/bridge_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynablock.h"
#include "dynablock_private.h"
#include "dynarec_private.h"
#include "elfloader.h"
#ifdef ARM
#include "dynarec_arm.h"
#else
#error Unsupported architecture!
#endif
#include "khash.h"
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
KHASH_SET_INIT_INT(mark)
uint32_t X31_hash_code(void* addr, int len)
{
if(!len) return 0;
uint8_t* p = (uint8_t*)addr;
int32_t h = *p;
for (--len, ++p; len; --len, ++p) h = (h << 5) - h + (int32_t)*p;
return (uint32_t)h;
}
dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, int nolinker, int direct)
{
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->blocks = (nolinker && direct)?NULL:kh_init(dynablocks);
ret->base = base;
ret->text = text;
ret->textsz = textsz;
ret->nolinker = nolinker;
pthread_rwlock_init(&ret->rwlock_blocks, NULL);
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
}
return ret;
}
void FreeDynablock(dynablock_t* db)
{
if(db) {
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, tablesz=%d, %swith %d son(s)\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->tablesz, db->marks?"with marks, ":"", db->sons_size);
db->done = 0;
// remove from direct if there
uintptr_t startdb = db->parent->text;
uintptr_t enddb = db->parent->text + db->parent->textsz;
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x86_addr;
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
// remove from hash if there
if (db->parent->blocks) {
khint_t kdb;
kdb = kh_get(dynablocks, db->parent->blocks, (uintptr_t) db->x86_addr - db->parent->base);
if(kdb!=kh_end(db->parent->blocks))
kh_del(dynablocks, db->parent->blocks, kdb);
}
if(db->marks) {
// Follow mark and set arm_linker instead
khint_t k;
kh_foreach_key(db->marks, k,
void** p = (void**)(uintptr_t)k;
dynarec_log(LOG_DEBUG, " -- resettable(%p)\n", p);
resettable(p);
);
// free mark
kh_destroy(mark, db->marks);
db->marks = NULL;
}
for(int i=0; i<db->tablesz; i+=4) {
dynablock_t* p = (dynablock_t*)db->table[i+3];
dynarec_log(LOG_DEBUG, " -- table[%d+3] = %p ", i, p);
if(p && p!=db && p->marks) {
khint_t kd = kh_get(mark, p->marks, (uintptr_t)(&db->table[i+0]));
if(kd!=kh_end(p->marks)) {
kh_del(mark, p->marks, kd);
dynarec_log(LOG_DEBUG, "cleaned");
}
else {dynarec_log(LOG_DEBUG, "not found");}
}
dynarec_log(LOG_DEBUG, "\n");
}
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = db->sons[i];
db->sons[i] = NULL;
FreeDynablock(son);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap((uintptr_t)db->block, db->size);
}
free(db->sons);
free(db->table);
free(db);
}
}
void FreeDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_INFO, "Free %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %s\n", (*dynablocks)->blocks?kh_size((*dynablocks)->blocks):0, (*dynablocks)->blocks?kh_n_buckets((*dynablocks)->blocks):0, (*dynablocks)->nolinker, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynablock_t* db;
if((*dynablocks)->blocks) {
// create a list of the parent db to delete (because there are sons in the middle that will be invalid if father is removed)
dynablock_t** list = (dynablock_t**)calloc(kh_size((*dynablocks)->blocks), sizeof(dynablock_t*));
int n = 0;
kh_foreach_value((*dynablocks)->blocks, db,
if(!db->father) list[n++] = db;
);
for (int i=0; i<n; ++i)
FreeDynablock(list[i]);
kh_destroy(dynablocks, (*dynablocks)->blocks);
(*dynablocks)->blocks = NULL;
free(list);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i]);
}
free((*dynablocks)->direct);
}
(*dynablocks)->direct = 0;
pthread_rwlock_destroy(&(*dynablocks)->rwlock_blocks);
free(*dynablocks);
*dynablocks = NULL;
}
void MarkDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->marks && !db->need_test) {
// Follow mark and set arm_linker instead
khint_t k;
kh_foreach_key(db->marks, k,
void** p = (void**)(uintptr_t)k;
resettable(p);
);
// free mark
kh_clear(mark, db->marks);
}
db->need_test = 1;
}
}
void ProtectDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
return; // protect only father, child(ren) will be automatically
protectDB((uintptr_t)db->x86_addr, db->x86_size);
}
}
void RemoveMark(void** table)
{
// remove old value if any
dynablock_t *old = (dynablock_t*)table[3];
if(old && old->father)
old = old->father;
if(old && old->marks) {
khint_t kd = kh_get(mark, old->marks, (uintptr_t)table);
if(kd!=kh_end(old->marks))
kh_del(mark, old->marks, kd);
}
table[3] = NULL;
}
// source is linked to dest (i.e. source->table[x] = dest->block), so add a "mark" in dest, add a "linked" info to source
void AddMark(dynablock_t* source, dynablock_t* dest, void** table)
{
int ret;
// remove old value if any
dynablock_t *old = (dynablock_t*)table[3];
if(old && old->father)
old = old->father;
if(old && old->marks) {
khint_t kd = kh_get(mark, old->marks, (uintptr_t)table);
if(kd!=kh_end(old->marks))
kh_del(mark, old->marks, kd);
}
// add mark if needed
if(dest->father)
dest = dest->father;
if(dest->marks) {
kh_put(mark, dest->marks, (uintptr_t)table, &ret);
table[3] = (void*)dest;
} else
table[3] = NULL;
}
void MarkDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Marked %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynablock_t* db;
if((*dynablocks)->blocks) {
kh_foreach_value((*dynablocks)->blocks, db,
MarkDynablock(db);
);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
MarkDynablock((*dynablocks)->direct[i]);
}
}
}
void ProtectkDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Protect %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynablock_t* db;
if((*dynablocks)->blocks) {
kh_foreach_value((*dynablocks)->blocks, db,
ProtectDynablock(db);
);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
ProtectDynablock((*dynablocks)->direct[i]);
}
}
}
uintptr_t StartDynablockList(dynablocklist_t* db)
{
if(db)
return db->text;
return 0;
}
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz;
return 0;
}
void FreeDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if(dynablocks->direct[i-startdb]) {
FreeDynablock(dynablocks->direct[i-startdb]);
}
}
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if(dynablocks->direct[i-startdb]) {
MarkDynablock(dynablocks->direct[i-startdb]);
}
}
void ProtectDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
protectDB(start, end-start); //no +1; as end/enddb is exclusive and not inclusive
}
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct)
FreeDirectDynablock(dynablocks, addr, size);
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->x86_addr;
e = (uintptr_t)db->x86_addr+db->x86_size-1;
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size)))
ProtectDynablock(db);
);
}
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct)
MarkDirectDynablock(dynablocks, addr, size);
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->x86_addr;
e = (uintptr_t)db->x86_addr+db->x86_size-1;
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size)))
MarkDynablock(db);
);
}
}
dynablock_t* FindDynablockDynablocklist(void* addr, dynablocklist_t* dynablocks)
{
if(!dynablocks)
return NULL;
if(dynablocks->direct)
for(int i=0; i<dynablocks->textsz; ++i) {
if(dynablocks->direct[i]) {
dynablock_t* db = dynablocks->direct[i];
uintptr_t s = (uintptr_t)db->block;
uintptr_t e = (uintptr_t)db->block+db->size;
if(s>=(uintptr_t)addr && e<(uintptr_t)addr)
return db->father?db->father:db;
}
}
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->block;
e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
);
}
return NULL;
}
dynablock_t* FindDynablockFromNativeAddress(void* addr)
{
// unoptimized search through all dynablockslist for the dynablock that contains native addr (NULL if not found)
// search "volatile" dynarec first
dynablock_t *ret = NULL;
for(int idx=0; idx<65536 && !ret; ++idx)
if(my_context->dynmap[idx])
ret = FindDynablockDynablocklist(addr, my_context->dynmap[idx]->dynablocks);
if(ret)
return ret;
// search elfs
for(int idx=0; idx<my_context->elfsize && !ret; ++idx)
ret = FindDynablockDynablocklist(addr, GetDynablocksFromElf(my_context->elfs[idx]));
// last, search context dynablocks
if(my_context->dynablocks)
ret = FindDynablockDynablocklist(addr, my_context->dynablocks);
return ret;
}
void ConvertHash2Direct(dynablocklist_t* dynablocks)
{
if(dynablocks->textsz==0 || dynablocks->text==0 || !dynablocks->blocks)
return; // nothing to do
// create the new set
dynablock_t **direct = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
kh_dynablocks_t *blocks = kh_init(dynablocks);
// transfert
int ret;
khint_t k;
dynablock_t* db;
uintptr_t key;
uintptr_t start = dynablocks->text;
uintptr_t end = start + dynablocks->textsz;
kh_foreach(dynablocks->blocks, key, db,
key += dynablocks->base;
if(key>=start && key<end)
direct[key-start] = db;
else {
k = kh_put(dynablocks, blocks, key-dynablocks->base, &ret);
if(ret) { // don't try to insert if already done...
kh_value(blocks, k) = db;
}
}
);
// destroy old and do the swap (should swap before destroy, but hash access is always behind mutex)
kh_destroy(dynablocks, dynablocks->blocks);
dynablocks->blocks = blocks;
dynablocks->direct = direct;
}
#define MAGIC_SIZE 256
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int with_marks, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynblock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
return NULL;
}
khint_t k;
int ret;
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
}
if(dynablocks->blocks) {
pthread_rwlock_rdlock(&dynablocks->rwlock_blocks);
// check if the block exist
khint_t k;
k = kh_get(dynablocks, dynablocks->blocks, addr-dynablocks->base);
if(k!=kh_end(dynablocks->blocks)) {
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
*created = 0;
return block;
}
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
}
if (!*created)
return block;
// Lock as write now!
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
// create and add new block
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text] = (dynablock_t*)calloc(1, sizeof(dynablock_t));
} else {
if(dynablocks->nolinker && ((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz)))) {
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, with_marks, created);
}
k = kh_put(dynablocks, dynablocks->blocks, addr-dynablocks->base, &ret);
if(!ret) {
// Ooops, block is already there? retreive it and bail out
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
*created = 0;
return block;
}
block = kh_value(dynablocks->blocks, k) = (dynablock_t*)calloc(1, sizeof(dynablock_t));
// check if size of hash map == magic size, if yes, convert to direct before unlocking
if(!dynablocks->direct && kh_size(dynablocks->blocks)==MAGIC_SIZE)
ConvertHash2Direct(dynablocks);
}
block->parent = dynablocks;
// add mark if needed
if(with_marks)
block->marks = kh_init(mark);
// create an empty block first, so if other thread want to execute the same block, they can, but using interpretor path
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
*created = 1;
return block;
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t* current)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
dynablocks = current->parent;
if(!(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
else if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
}
}
// nope, lets do the long way
if(!dynablocks)
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
// check direct first, without lock
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz)))
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, (dynablocks->nolinker)&&(dynablocks->direct), &created);
if(!created || !create)
return block; // existing block...
if(box86_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_lock);
// fill the block
block->x86_addr = (void*)addr;
FillBlock(block);
if(box86_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_lock);
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, %swith %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+block->x86_size), block->block, block->size, block->marks?"with Marks, ":"", block->sons_size);
return block;
}
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
{
dynablock_t *db = internalDBGetBlock(emu, addr, create, *current);
if(db && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X)%s with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->marks?" with Mark,":"", father->sons_size);
// no more current if it gets invalidated too
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, create, *current);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
}
}
return db;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef __DYNABLOCK_PRIVATE_H_
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
typedef struct kh_mark_s kh_mark_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
kh_mark_t* marks; // List of blocks that marked this block
void* block;
int size;
void* x86_addr;
int x86_size;
uint32_t hash;
int need_test;
uintptr_t* table;
int tablesz;
int done;
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
} dynablock_t;
typedef struct dynablocklist_s {
kh_dynablocks_t *blocks;
pthread_rwlock_t rwlock_blocks;
uintptr_t base;
uintptr_t text;
int textsz;
int nolinker; // in case this dynablock can disapear (also, block memory are allocated with a temporary scheme)
dynablock_t **direct; // direct mapping (waste of space, so not always there)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+186
View File
@@ -0,0 +1,186 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "tools/bridge_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynablock_private.h"
#endif
#ifdef ARM
void arm_prolog(x86emu_t* emu, void* addr) EXPORTDYN;
void arm_epilog() EXPORTDYN;
void arm_epilog_fast() EXPORTDYN;
void arm_linker() EXPORTDYN;
int arm_tableupdate(void* jump, uintptr_t addr, void** table) EXPORTDYN;
#endif
void tableupdate(void* jumpto, uintptr_t ref, void** table)
{
#ifdef ARM
if(arm_tableupdate(jumpto, ref, table))
#endif
{
table[0] = jumpto;
table[1] = (void*)ref;
}
}
void resettable(void** table)
{
void* p = table[1];
#ifdef ARM
tableupdate(arm_linker, (uintptr_t)p, table);
#endif
//table[2] = own_dynablock // unchanged
table[3] = NULL; // removed "linked" information
}
#ifdef DYNAREC
void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
{
dynablock_t* current = (dynablock_t*)table[2];
if(current->father)
current = current->father;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!current) { // current has been invalidated, stop running it...
//dynarec_log(LOG_DEBUG, "--- Current invalidated while linking.\n");
return arm_epilog_fast;
}
if(table[3]) {
//dynarec_log(LOG_DEBUG, "--- Remove mark from %p (%p)\n", current, table[3]);
RemoveMark(table);
}
if(!block) {
// no block, don't try again, ever
tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
if(!block->done) {
// not finished yet... leave linker
//tableupdate(arm_linker, addr, table);
return arm_epilog_fast;
}
if(!block->block) {
// null block, but done: go to epilog, no linker here
tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
dynablock_t *father = block->father?block->father:block;
if(!block->parent->nolinker || (current && father->marks)) {
//dynarec_log(LOG_DEBUG, "--- Linking %p/%p to %p (table=%p[%p/%p/%p/%p])\n", block, block->block, current, table, table[0], table[1], table[2], table[3]);
// only update block if linker is allowed or if marks is possibe
if(current && father->marks && current!=father)
AddMark(current, father, table);
tableupdate(block->block, addr, table);
}
return block->block;
}
#endif
void DynaCall(x86emu_t* emu, uintptr_t addr)
{
#ifdef DYNAREC
if(!box86_dynarec)
#endif
EmuCall(emu, addr);
#ifdef DYNAREC
else {
uint32_t old_esp = R_ESP;
uint32_t old_ebx = R_EBX;
uint32_t old_edi = R_EDI;
uint32_t old_esi = R_ESI;
uint32_t old_ebp = R_EBP;
uint32_t old_eip = R_EIP;
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
current = (block && !block->parent->nolinker)?block:NULL;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "Calling Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "Calling DynaRec Block @%p (%p) of %d x86 instructions (nolinker=%d, father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize ,block->parent->nolinker, block->father, emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
}
}
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
emu->longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
R_ESI = old_esi;
R_EBP = old_ebp;
R_ESP = old_esp;
R_EIP = old_eip; // and set back instruction pointer
}
}
#endif
}
int DynaRun(x86emu_t* emu)
{
#ifdef DYNAREC
if(!box86_dynarec)
#endif
return Run(emu, 0);
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
current = (block && !block->parent->nolinker)?block:NULL;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "Running Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "Running DynaRec Block @%p (%p) of %d x86 insts (nolinker=%d, father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize, block->parent->nolinker, block->father, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
}
}
}
return 0;
#endif
}
+281
View File
@@ -0,0 +1,281 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "tools/bridge_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynablock.h"
#include "dynablock_private.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "elfloader.h"
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
uint32_t a = *(uint32_t*)(ip+3);
if(a==0) {
dynarec_log(LOG_NONE, "%s%p: Exit x86emu%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (box86_dynarec_dump>1)?"\e[m":"");
} else {
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (void*)a, (box86_dynarec_dump>1)?"\e[m":"");
}
} else {
if(dec) {
dynarec_log(LOG_NONE, "%s%p: %s", (box86_dynarec_dump>1)?"\e[1m":"", ip, DecodeX86Trace(dec, inst->addr));
} else {
dynarec_log(LOG_NONE, "%s%p: ", (box86_dynarec_dump>1)?"\e[1m":"", ip);
for(int i=0; i<inst->size; ++i) {
dynarec_log(LOG_NONE, "%02X ", ip[i]);
}
dynarec_log(LOG_NONE, " %s", name);
}
// print Call function name if possible
if(ip[0]==0xE8 || ip[0]==0xE9) { // Call / Jmp
uintptr_t nextaddr = (uintptr_t)ip + 5 + *((int32_t*)(ip+1));
printFunctionAddr(nextaddr, "=> ");
} else if(ip[0]==0xFF) {
if(ip[1]==0x25) {
uintptr_t nextaddr = (uintptr_t)ip + 6 + *((int32_t*)(ip+2));
printFunctionAddr(nextaddr, "=> ");
}
}
// end of line and colors
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
}
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
dyn->next[dyn->next_sz++] = addr;
}
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
// get closest, but no addresses befores
uintptr_t best = 0;
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
memmove(dyn->next+i, dyn->next+i+1, (dyn->next_sz-i-1)*sizeof(uintptr_t));
--dyn->next_sz;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
++i;
}
}
return best;
}
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
#define PK(A) (*((uint8_t*)(addr+(A))))
if(!n)
return 1;
if(PK(0)==0x90)
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
return is_nops(dyn, addr+3, n-3);
if(n>2 && PK(0)==0x8d && PK(1)==0x76 && PK(2)==0x00) // lea esi, [esi]
return is_nops(dyn, addr+3, n-3);
if(n>3 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x40 && PK(3)==0x00)
return is_nops(dyn, addr+4, n-4);
if(n>3 && PK(0)==0x8d && PK(1)==0x74 && PK(2)==0x26 && PK(3)==0x00)
return is_nops(dyn, addr+4, n-4);
if(n>4 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x44 && PK(3)==0x00 && PK(4)==0x00)
return is_nops(dyn, addr+5, n-5);
if(n>5 && PK(0)==0x8d && PK(1)==0xb6 && PK(2)==0x00 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00)
return is_nops(dyn, addr+6, n-6);
if(n>6 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x80 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00)
return is_nops(dyn, addr+7, n-7);
if(n>6 && PK(0)==0x8d && PK(1)==0xb4 && PK(2)==0x26 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00) // lea esi, [esi+0]
return is_nops(dyn, addr+7, n-7);
if(n>7 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x84 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00 && PK(7)==0x00)
return is_nops(dyn, addr+8, n-8);
return 0;
#undef PK
}
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
{
if(ninst == dyn->size || (recurse==5))
return X_ALL; // no more instructions, or too many jmp loop, stop
uint32_t needed = dyn->insts[ninst].x86.use_flags;
if(needed) {
setf &= ~needed;
if(!setf) // all flags already used, no need to continue
return needed;
}
if(!needed && !dyn->insts[ninst].x86.set_flags && !dyn->insts[ninst].x86.jmp_insts) {
int start = ninst;
int end = ninst;
while(end<dyn->size && !dyn->insts[end].x86.use_flags && !dyn->insts[end].x86.set_flags && !dyn->insts[end].x86.jmp_insts)
++end;
needed = needed_flags(dyn, end, setf, recurse);
for(int i=start; i<end; ++i)
dyn->insts[i].x86.need_flags = needed;
return needed;
}
if(dyn->insts[ninst].x86.set_flags && (dyn->insts[ninst].x86.state_flags!=SF_MAYSET)) {
if((setf & ~dyn->insts[ninst].x86.set_flags) == 0)
return needed; // all done, gives all the flags needed
setf |= dyn->insts[ninst].x86.set_flags; // add new flags to continue
}
int jinst = dyn->insts[ninst].x86.jmp_insts;
if(dyn->insts[ninst].x86.jmp) {
dyn->insts[ninst].x86.need_flags = (jinst==-1)?X_PEND:needed_flags(dyn, jinst, setf, recurse+1);
if(dyn->insts[ninst].x86.use_flags) // conditionnal jump
dyn->insts[ninst].x86.need_flags |= needed_flags(dyn, ninst+1, setf, recurse);
} else
dyn->insts[ninst].x86.need_flags = needed_flags(dyn, ninst+1, setf, recurse);
if(dyn->insts[ninst].x86.state_flags==SF_MAYSET)
needed |= dyn->insts[ninst].x86.need_flags;
else
needed |= (dyn->insts[ninst].x86.need_flags & ~dyn->insts[ninst].x86.set_flags);
if(needed == (X_PEND|X_ALL))
needed = X_ALL;
return needed;
}
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
void* FillBlock(dynablock_t* block) {
// init the helper
uintptr_t addr = (uintptr_t)block->x86_addr;
dynarec_arm_t helper = {0};
helper.nolinker = box86_dynarec_linker?(block->parent->nolinker):1;
helper.start = addr;
arm_pass0(&helper, addr);
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
block->done = 1;
free(helper.next);
return (void*)block;
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
// pass 1, addresses, x86 jump addresses, flags
arm_pass1(&helper, addr);
// calculate barriers
uintptr_t start = helper.insts[0].x86.addr;
uintptr_t end = helper.insts[helper.size].x86.addr+helper.insts[helper.size].x86.size;
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end)
helper.insts[i].x86.jmp_insts = -1;
else {
// find jump address instruction
int k=-1;
for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x86.addr==j)
k=i2;
}
if(k!=-1) // -1 if not found, mmm, probably wrong, exit anyway
helper.insts[k].x86.barrier = 1;
helper.insts[i].x86.jmp_insts = k;
}
}
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.set_flags && !helper.insts[i].x86.need_flags) {
helper.insts[i].x86.need_flags = needed_flags(&helper, i+1, helper.insts[i].x86.set_flags, 0);
if((helper.insts[i].x86.need_flags&X_PEND) && (helper.insts[i].x86.state_flags==SF_MAYSET))
helper.insts[i].x86.need_flags = X_ALL;
}
// pass 2, instruction size
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size;
void* p = (void*)AllocDynarecMap(sz, block->parent->nolinker);
if(p==NULL) {
free(helper.insts);
free(helper.next);
return (void*)block;
}
helper.block = p;
helper.arm_start = (uintptr_t)p;
helper.tablesz = helper.tablei;
if(helper.tablesz)
helper.table = (uintptr_t*)calloc(helper.tablesz, sizeof(uintptr_t));
if(helper.sons_size) {
helper.sons_x86 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
}
// pass 3, emit (log emit arm opcode)
if(box86_dynarec_dump) {
dynarec_log(LOG_NONE, "%sEmitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
helper.arm_size = 0;
arm_pass3(&helper, addr);
if(sz!=helper.arm_size) {printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);}
// all done...
__builtin___clear_cache(p, p+sz); // need to clear the cache before execution...
free(helper.insts);
free(helper.next);
block->table = helper.table;
block->tablesz = helper.tablesz;
for (int i=0; i<helper.tablesz/4; ++i)
block->table[i*4+2] = (uintptr_t)block;
block->size = sz;
block->isize = helper.size;
block->block = p;
block->need_test = 0;
block->x86_addr = (void*)start;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
block->hash = (helper.nolinker)?X31_hash_code(block->x86_addr, block->x86_size):0;
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
sons = (dynablock_t**)calloc(helper.sons_size, sizeof(dynablock_t*));
for (int i=0; i<helper.sons_size; ++i) {
int created = 1;
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], 0, &created);
if(created) { // avoid breaking a working block! also, block could be outside this parent...
son->block = helper.sons_arm[i];
son->x86_addr = (void*)helper.sons_x86[i];
son->x86_size = end-helper.sons_x86[i];
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
son->father = block;
son->done = 1;
sons[sons_size++] = son;
}
}
if(sons_size) {
block->sons = sons;
block->sons_size = sons_size;
} else
free(sons);
}
if(block->parent->nolinker)
protectDB((uintptr_t)block->x86_addr, block->x86_size);
block->done = 1;
return (void*)block;
}
+2638
View File
File diff suppressed because it is too large. Load diff
+2253
View File
File diff suppressed because it is too large. Load diff
+155
View File
@@ -0,0 +1,155 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t i32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int fixedaddress;
switch(opcode) {
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_xor32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x3B:
INST_NAME("CMP Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_fsdata(dyn, addr, ninst, x12);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STR_REG_LSL_IMM5(gd, ed, x12, 0);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
grab_fsdata(dyn, addr, ninst, x12);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ed");
grab_fsdata(dyn, addr, ninst, x12);
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7))));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, ed, x12, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Id");
grab_fsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
LDR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(xEAX, x1, 0);
}
break;
case 0xA3:
INST_NAME("MOV FS:Od, EAX");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F32;
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STR_IMM9(xEAX, x2, 0);
break;
case 0xC7:
INST_NAME("MOV FS:Ed, Id");
grab_fsdata(dyn, addr, ninst, x12);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x12, 0);
}
break;
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH Ed");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+133
View File
@@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t i32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int fixedaddress;
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_add32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x2B:
INST_NAME("SUB Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_sub32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x33:
INST_NAME("XOR Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_xor32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x89:
INST_NAME("MOV GS:Ed, Gd");
grab_tlsdata(dyn, addr, ninst, x12);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STR_REG_LSL_IMM5(gd, ed, x12, 0);
}
break;
case 0x8B:
INST_NAME("MOV Gd, GS:Ed");
grab_tlsdata(dyn, addr, ninst, x12);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, GS:Id");
grab_tlsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
LDR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(xEAX, x1, 0);
}
break;
case 0xA3:
INST_NAME("MOV GS:Od, EAX");
grab_tlsdata(dyn, addr, ninst, x1);
u32 = F32;
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STR_IMM9(xEAX, x2, 0);
break;
case 0xC7:
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x12);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x12, 0);
}
break;
default:
DEFAULT;
}
return addr;
}
+1004
View File
File diff suppressed because it is too large. Load diff
+1603
View File
File diff suppressed because it is too large. Load diff
+96
View File
@@ -0,0 +1,96 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop;
int8_t i8;
int32_t i32;
MAYUSE(i32);
nextop = F8;
switch(nextop) {
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
Bcond(NO, i32); \
jump_to_linker(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
UXTH(x1, xECX, 0);
SUBS_IMM8(x1, x1, 1);
BFI(xECX, x1, 0, 16);
B_NEXT(cEQ); // CX is 0, no LOOP
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
GO(cNE, cEQ);
break;
case 0xE1:
INST_NAME("LOOPZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
UXTH(x1, xECX, 0);
SUBS_IMM8(x1, x1, 1);
BFI(xECX, x1, 0, 16);
B_NEXT(cEQ); // CX is 0, no LOOP
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
GO(cEQ, cNE);
break;
case 0xE2:
INST_NAME("LOOP (16bits)");
i8 = F8S;
UXTH(x1, xECX, 0);
SUBS_IMM8(x1, x1, 1);
BFI(xECX, x1, 0, 16);
GO(cEQ, cNE);
break;
case 0xE3:
INST_NAME("JCXZ");
i8 = F8S;
UXTH(x1, xECX, 0);
TSTS_REG_LSL_IMM5(x1, x1, 0);
GO(cNE, cEQ);
break;
#undef GO
default:
DEFAULT;
}
return addr;
}
+291
View File
@@ -0,0 +1,291 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback;
int v1, v2;
int s0;
int d1;
int fixedaddress;
int parity;
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(v1);
MAYUSE(v2);
MAYUSE(ed);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VADD_F64(v1, v1, v2);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMUL_F64(v1, v1, v2);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FSUB ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v1, v2);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v2, v1);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v1, v2);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v2, v1);
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VADD_F64(v1, v1, d1);
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VMUL_F64(v1, v1, d1);
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
FCOM(x1, x2);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, v1, d1);
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, d1, v1);
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, v1, d1);
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, d1, v1);
break;
default:
DEFAULT;
}
}
return addr;
}
+348
View File
@@ -0,0 +1,348 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
static double d_1 = 1.0;
static double d_l2t = L2T;
static double d_l2e = L2E;
static double d_pi = PI;
static double d_lg2 = LG2;
static double d_ln2 = LN2;
static double d_0 = 0.0;
uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
int fixedaddress;
int v1, v2;
int s0;
int i1, i2, i3;
int parity;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v2 = x87_do_push(dyn, ninst);
VMOV_64(v2, v1);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FXCH STx");
// swap the cache value, not the double value itself :p
i1 = x87_get_cache(dyn, ninst, x1, x2, nextop&7);
i2 = x87_get_cache(dyn, ninst, x1, x2, 0);
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
break;
case 0xD0:
INST_NAME("FNOP");
break;
case 0xE0:
INST_NAME("FCHS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VNEG_F64(v1, v1);
break;
case 0xE1:
INST_NAME("FABS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VABS_F64(v1, v1);
break;
case 0xE4:
INST_NAME("FTST");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VCMP_F64_0(v1);
FCOM(x1, x2); // same flags...
break;
case 0xE5:
INST_NAME("FXAM");
x87_refresh(dyn, ninst, x1, x2, 0);
CALL(fpu_fxam, -1, 0); // should be possible inline, but is it worth it?
break;
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_1));
VLDR_64(v1, x2, 0);
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_l2t));
VLDR_64(v1, x2, 0);
break;
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_l2e));
VLDR_64(v1, x2, 0);
break;
case 0xEB:
INST_NAME("FLDPI");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_pi));
VLDR_64(v1, x2, 0);
break;
case 0xEC:
INST_NAME("FLDLG2");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_lg2));
VLDR_64(v1, x2, 0);
break;
case 0xED:
INST_NAME("FLDLN2");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_ln2));
VLDR_64(v1, x2, 0);
break;
case 0xEE:
INST_NAME("FLDZ");
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_0));
VLDR_64(v1, x2, 0);
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VSQRT_F64(v1, v1);
break;
case 0xFC:
INST_NAME("FRNDINT");
// use C helper for now, nothing staightforward is available
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_frndint, -1, 0);
/*
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cVS); // Unordered, skip
B_NEXT(cEQ); // Zero, skip
u8 = x87_setround(dyn, ninst, x1, x2, x3);
VCVT_S32_F64(x1, v1); // limit to 32bits....
VCVT_F64_S32(v1, x1);
x87_restoreround(dyn, ninst, u8);
*/
break;
case 0xF0:
INST_NAME("F2XM1");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_f2xm1, -1, 0);
break;
case 0xF1:
INST_NAME("FYL2X");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fyl2x, -1, 0);
x87_do_pop(dyn, ninst);
break;
case 0xF2:
INST_NAME("FTAN");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_ftan, -1, 0);
v1 = x87_do_push(dyn, ninst);
MOV32(x2, (&d_1));
VLDR_64(v1, x2, 0);
break;
case 0xF3:
INST_NAME("FPATAN");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fpatan, -1, 0);
x87_do_pop(dyn, ninst);
break;
case 0xF4:
INST_NAME("FXTRACT");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1, 0);
break;
case 0xF8:
INST_NAME("FPREM");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem, -1, 0);
break;
case 0xF9:
INST_NAME("FYL2XP1");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fyl2xp1, -1, 0);
x87_do_pop(dyn, ninst);
break;
case 0xFB:
INST_NAME("FSINCOS");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fsincos, -1, 0);
break;
case 0xFD:
INST_NAME("FSCALE");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fscale, -1, 0);
break;
case 0xFE:
INST_NAME("FSIN");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fsin, -1, 0);
break;
case 0xFF:
INST_NAME("FCOS");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fcos, -1, 0);
break;
case 0xD1:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE2:
case 0xE3:
case 0xE6:
case 0xE7:
case 0xEF:
case 0xF5:
case 0xF6:
case 0xF7:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
VCVT_F64_F32(v1, s0);
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FLDENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
MOVW(x2, 0);
CALL(fpu_loadenv, -1, 0);
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1);
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x1, x1, 10, 2); // extract round
STR_IMM9(x1, xEmu, offsetof(x86emu_t, round));
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
ed = x1;
wb1 = 1;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw));
EWBACK;
break;
default:
DEFAULT;
}
}
return addr;
}
+222
View File
@@ -0,0 +1,222 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int32_t i32;
uint8_t ed;
uint8_t wback;
int v1, v2;
int d0;
int s0;
int fixedaddress;
MAYUSE(s0);
MAYUSE(d0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(ed);
MAYUSE(i32);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FCMOVB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cNE, v1, v2); // F_CF==1
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FCMOVE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cNE, v1, v2); // F_ZF==1
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCMOVBE ST0, STx");
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
VMOVcond_64(cNE, v1, v2); // F_CF==1 | F_ZF==1
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCMOVU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cNE, v1, v2); // F_PF==1
break;
case 0xE9:
INST_NAME("FUCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
x87_do_pop(dyn, ninst);
break;
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFD:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VADD_F64(v1, v1, d0);
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VMUL_F64(v1, v1, d0);
break;
case 2:
INST_NAME("FICOM ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VCMP_F64(v1, d0);
FCOM(x1, x2);
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VCMP_F64(v1, d0);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VSUB_F64(v1, v1, d0);
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VSUB_F64(v1, d0, v1);
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VDIV_F64(v1, v1, d0);
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VDIV_F64(v1, d0, v1);
break;
}
}
return addr;
}
+278
View File
@@ -0,0 +1,278 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "emu/x87emu_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
int32_t i32;
uint8_t ed;
uint8_t wback;
int v1, v2;
int s0;
int fixedaddress;
int parity;
MAYUSE(s0);
MAYUSE(v1);
MAYUSE(v2);
MAYUSE(i32);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FCMOVNB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cEQ, v1, v2); // F_CF==0
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FCMOVNE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCMOVNBE ST0, STx");
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
VMOVcond_64(cEQ, v1, v2); // F_CF==0 | F_ZF==0
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCMOVNU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cEQ, v1, v2); // F_PF==0
break;
case 0xE2:
INST_NAME("FNCLEX");
MOVW(x1, 0);
LDRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
BFI(x2, x1, 0, 8); // IE .. PE, SF, ES
BFI(x2, x1, 15, 1); // B
STRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
break;
case 0xE3:
INST_NAME("FNINIT");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
CALL(reset_fpu, -1, 0);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
break;
case 0xE0:
case 0xE1:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_S32(v1, s0);
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
VMRS(x12); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x12, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVT_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
VMOVfrV(ed, s0);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
WBACK;
VMSR(x12); // put back values
x87_do_pop(dyn, ninst);
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
WBACK;
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// The FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (denormal and overflow only)
VMOVfrV(ed, s0);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
WBACK;
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FLD tbyte");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
CALL(arm_fld, -1, 0);
break;
case 7:
INST_NAME("FSTP tbyte");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
CALL(arm_fstp, -1, 0);
x87_do_pop(dyn, ninst);
break;
default:
DEFAULT;
}
}
return addr;
}
+284
View File
@@ -0,0 +1,284 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t wback;
int v1, v2;
int d1;
int fixedaddress;
int parity;
MAYUSE(d1);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FADD STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VADD_F64(v1, v1, v2);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FMUL STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMUL_F64(v1, v1, v2);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCOM ST0, STx"); //yep
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FSUBR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v2, v1);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FSUB STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v1, v2);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FDIVR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v2, v1);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
INST_NAME("FDIV STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v1, v2);
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VADD_F64(v1, v1, d1);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VMUL_F64(v1, v1, d1);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VCMP_F64(v1, d1);
FCOM(x1, x2);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VCMP_F64(v1, d1);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VSUB_F64(v1, v1, d1);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VSUB_F64(v1, d1, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VDIV_F64(v1, v1, d1);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VDIV_F64(v1, d1, v1);
break;
}
}
return addr;
}
+216
View File
@@ -0,0 +1,216 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "emu/x87emu_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int fixedaddress;
int parity;
uint8_t ed;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREE STx");
break; // not handling Tag...
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FST ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMOV_64(v2, v1);
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
x87_do_pop(dyn, ninst);
break;
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FSTP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMOV_64(v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FUCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst);
#if 0
// can bus error...
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
#else
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
VMOVtoV_D(v1, x2, x3);
}
#endif
break;
case 1:
INST_NAME("FISTTP i64, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistp64, -1, 0);
x87_do_pop(dyn, ninst);
break;
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FRSTOR m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_frstor, -1, 0);
break;
case 6:
INST_NAME("FSAVE m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fsave, -1, 0);
break;
default:
DEFAULT;
}
}
return addr;
}
+155
View File
@@ -0,0 +1,155 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FADDP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VADD_F64(v2, v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FMULP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMUL_F64(v2, v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xD9: /* FCOMPP */
INST_NAME("FCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FSUBRP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v2, v1, v2);
x87_do_pop(dyn, ninst);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FSUBP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v2, v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FDIVRP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v2, v1, v2);
x87_do_pop(dyn, ninst);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
INST_NAME("FDIVP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v2, v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
default:
DEFAULT;
}
}
return addr;
}
+241
View File
@@ -0,0 +1,241 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "emu/x87emu_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
int32_t i32;
uint8_t wback;
uint8_t ed;
int v1, v2;
int s0;
int fixedaddress;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(i32);
switch(nextop) {
case 0xE0:
INST_NAME("FNSTSW AX");
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
AND_IMM8(x2, x2, 7);
BFI(x1, x2, 11, 3); // inject top
BFI(xEAX, x1, 0, 16);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
LDRSH_IMM8(x1, wback, fixedaddress);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, x1);
VCVT_F64_S32(v1, s0);
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
VCVT_S32_F64(s0, v1);
VMOVfrV(ed, s0);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
VCVTR_S32_F64(s0, v1);
VMOVfrV(ed, s0);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
VCVTR_S32_F64(s0, v1);
VMOVfrV(ed, s0);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fbld, -1, 0);
break;
case 5: // could be inlined for most thing, but is it usefull?
INST_NAME("FILD ST0, i64");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fild64, -1, 0);
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fbst, -1, 0);
x87_do_pop(dyn, ninst);
break;
case 7: // could be inlined for most thing, but is it usefull?
INST_NAME("FISTP i64, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistp64, -1, 0);
x87_do_pop(dyn, ninst);
break;
default:
DEFAULT;
}
}
return addr;
}
+1066
View File
File diff suppressed because it is too large. Load diff
+2291
View File
File diff suppressed because it is too large. Load diff
+280
View File
@@ -0,0 +1,280 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_shl32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
if(c==0) {
IFX(F_OF) {
MOVW(s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
IFX(X_CF) {
UBFX(s3, s1, c, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_ZF|X_OF) {
MOVS_REG_LSL_IMM5(s1, s1, c);
} else {
MOV_REG_LSL_IMM5(s1, s1, c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {UBFX(s3, s1, 31, 1);}
XOR_IMM8_COND(cCS, s3, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_OF]));
} else {
MOVW(s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_shr32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
IFX(X_ZF|X_CF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
MOV_REG_LSR_IMM5(s1, s1, c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_CF) {
MOVW_COND(cCC, s3, 0);
MOVW_COND(cCS, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_SF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_sar32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
IFX(X_ZF|X_CF) {
MOVS_REG_ASR_IMM5(s1, s1, c);
} else {
MOV_REG_ASR_IMM5(s1, s1, c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_CF) {
MOVW_COND(cCC, s3, 0);
MOVW_COND(cCS, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_SF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_rol32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
MOV_REG_ROR_IMM5(s1, s1, 32-c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
AND_IMM8(s3, s1, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_OF) {
if(c==1) {
ADD_REG_LSR_IMM5(s3, s1, s1, 31);
AND_IMM8(s3, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
}
}
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_ror32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
MOV_REG_ROR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
}
}
+484
View File
@@ -0,0 +1,484 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_cmp32);
} else {
MOVW(s4, 0);
}
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SUBS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
IFX(X_PEND) {
MOVW(s4, 0);
}
// first the easy flag, also found on ARM
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_OF) {
IFX(X_ZF|X_PEND) {
MOVW(s4, 0);
}
MOVW_COND(cVS, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
IFX(X_CF) {
IFX(X_ZF|X_OF|X_PEND) {
MOVW(s4, 0);
}
MOVW_COND(cCC, s4, 1); // Carry flags on ARM is reversed compared to x86 one
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_SF) {
UBFX(s4, s3, 31, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// and now the tricky ones (and mostly unused), PF and AF
IFX(X_AF) {
// bc = (res & (~d | s)) | (~d & s)
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
ORR_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = ~d | s
AND_REG_LSL_IMM5(s4, s4, s3, 0); // s4 = res & (~d | s)
BIC_REG_LSL_IMM5(s3, s2, s1, 0); // loosing res... s3 = s & ~d
ORR_REG_LSL_IMM5(s3, s4, s3, 0); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_AF) {
UBFX(s4, s3, 3, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
}
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_CF|X_AF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_cmp32);
}
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SUBS_IMM8(s3, s1, 0); // res = s1 - 0
IFX(X_PEND) {
IFX(X_ZF|X_OF|X_CF|X_AF) {
MOVW(s4, 0);
}
}
// and now the tricky ones (and mostly unused), PF and AF
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x80000000
}
IFX(X_AF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
IFX(X_ZF) {
// first the easy flags, also found on ARM
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s3, 31, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit CMP16 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_cmp16);
} else {
MOVW(s3, 0);
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df)); // reset flags
SUB_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW(s4, 0xffff);
TSTS_REG_LSL_IMM5(s3, s4, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s3, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
ORR_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = ~d | s
AND_REG_LSL_IMM5(s4, s4, s3, 0); // s4 = res & (~d | s)
BIC_REG_LSL_IMM5(s3, s2, s1, 0); // loosing res... s3 = s & ~d
ORR_REG_LSL_IMM5(s3, s4, s3, 0); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
UBFX(s4, s3, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x8000
}
IFX(X_AF) {
UBFX(s4, s3, 3, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
}
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s3, 14);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
IFX(X_CF|X_AF|X_OF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MOVW(s3, 0);
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
MOVW(s3, d_cmp16);
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df)); // reset flags
IFX(X_OF|X_CF|X_AF) {
MOVW(s4, 0);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x8000
}
IFX(X_AF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
IFX(X_ZF) {
MOVW(s4, 0xffff);
TSTS_REG_LSL_IMM5(s1, s4, 0);
MOVW(s4, 0);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s1, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s4, d_cmp8);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
} else {
MOVW(s4, 0);
}
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SUB_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
IFX(X_PEND) {
MOVW(s4, 0);
}
TSTS_IMM8(s3, 0xff);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s3, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
ORR_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = ~d | s
AND_REG_LSL_IMM5(s4, s4, s3, 0); // s4 = res & (~d | s)
BIC_REG_LSL_IMM5(s3, s2, s1, 0); // loosing res... s3 = s & ~d
ORR_REG_LSL_IMM5(s3, s4, s3, 0); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
UBFX(s4, s3, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x80
}
IFX(X_AF) {
UBFX(s4, s3, 3, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
}
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s3, 6);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
IFX(X_CF|X_AF|X_OF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_cmp8);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x80
}
IFX(X_AF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s1, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit TEST32 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_tst32);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s3, 31, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_tst16);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s3, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_tst8);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
}
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s4, s3, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
}
}
+105
View File
@@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = PK(0); // don't increment addr
int locked = 0;
switch(nextop) {
// generic case
#define GO(A) \
case A+0x00: \
case A+0x01: \
case A+0x02: \
case A+0x03: \
case A+0x04: \
case A+0x05:
GO(0x00);
GO(0x08);
GO(0x10);
GO(0x18);
GO(0x20);
GO(0x28);
GO(0x30);
#undef GO
case 0x81:
case 0x83:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
case 0x87:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x0F:
nextop = PK(1);
switch(nextop) {
case 0xB0:
case 0xB1:
case 0xB3:
case 0xBA:
case 0xBB:
case 0xC0:
case 0xC1:
case 0xC7:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog);
break;
default:
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog); // no lock, regular instruction...
}
break;
case 0xFF:
nextop = PK(1);
switch((nextop>>3)&7)
{
case 0:
case 1:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
break;
default:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
}
break;
default:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
}
if(locked) {UNLOCK;}
return addr;
}
+316
View File
@@ -0,0 +1,316 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
#define GETEX(a) \
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7); \
} else { \
parity = getedparity(dyn, ninst, addr, nextop, 3); \
a = fpu_get_scratch_double(dyn); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3); \
VLDR_64(a, ed, fixedaddress); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);\
LDR_IMM9(x2, ed, fixedaddress+0); \
LDR_IMM9(x3, ed, fixedaddress+4); \
VMOVtoV_D(a, x2, x3); \
} \
}
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int v0, v1;
int d0, d1;
int s0;
int fixedaddress;
int parity;
MAYUSE(s0);
MAYUSE(d1);
MAYUSE(d0);
switch(nextop) {
case 0x10:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(v0, d0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
VEOR(v0+1, v0+1, v0+1); // upper 64bits set to 0
}
break;
case 0x11:
INST_NAME("MOVSD Ex, Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(d0, v0);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
}
break;
case 0x12:
INST_NAME("MOVDDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(v0, d0);
VMOVD(v0+1, d0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
VMOVD(v0+1, v0);
}
break;
case 0x2A:
INST_NAME("CVTSI2SD Gx, Ed");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETED;
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(v0, s0);
break;
case 0x2C:
INST_NAME("CVTTSD2SI Gd, Ex");
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
VCVT_S32_F64(s0, d0);
VMOVfrV(gd, s0);
break;
case 0x2D:
INST_NAME("CVTSD2SI Gd, Ex");
u8 = x87_setround(dyn, ninst, x1, x2, x12);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
VCVTR_S32_F64(s0, d0);
VMOVfrV(gd, s0);
x87_restoreround(dyn, ninst, u8);
break;
case 0x51:
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
VSQRT_F64(v0, d0);
break;
case 0x58:
INST_NAME("ADDSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
VADD_F64(v0, v0, d0);
break;
case 0x59:
INST_NAME("MULSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
VMUL_F64(v0, v0, d0);
break;
case 0x5A:
INST_NAME("CVTSD2SS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
d1 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, d0);
VMOV_64(d1, v0);
VMOV_32(d1*2, s0);
VMOV_64(v0, d1);
break;
case 0x5C:
INST_NAME("SUBSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
VSUB_F64(v0, v0, d0);
break;
case 0x5D:
INST_NAME("MINSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
VCMP_F64(v0, d0);
VMRS_APSR();
VMOVcond_64(cPL, v0, d0);
break;
case 0x5E:
INST_NAME("DIVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
VDIV_F64(v0, v0, d0);
break;
case 0x5F:
INST_NAME("MAXSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
VCMP_F64(d0, v0);
VMRS_APSR();
VMOVcond_64(cPL, v0, d0);
break;
case 0x70:
INST_NAME("PSHUFLW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
u8 = F8;
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u32 = 0;
for (int i=0; i<2; ++i) {
u32 |= (((u8>>(i*2))&3)*2+0)<<(i*16+0);
u32 |= (((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV32(x2, u32);
u32 = 0;
for (int i=2; i<4; ++i) {
u32 |= (((u8>>(i*2))&3)*2+0)<<((i-2)*16+0);
u32 |= (((u8>>(i*2))&3)*2+1)<<((i-2)*16+8);
}
MOV32(x3, u32);
d0 = fpu_get_scratch_double(dyn);
VMOVtoV_D(d0, x2, x3);
VTBL1_8(v0, v1, d0);
if(v0!=v1) {
VMOVD(v0+1, v1+1);
}
break;
case 0x7C:
INST_NAME("HADDPS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
VPADD_F32(v0, v0, v0+1);
if(v0==v1) {
VMOVD(v0+1, v0);
} else {
VPADD_F32(v0+1, v1, v1+1);
}
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
VCMP_F64(v0, d0);
VMRS_APSR();
MOVW(x2, 0);
u8 = F8;
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: MVN_COND_REG_LSL_IMM5(cPL, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0, x2, x2);
break;
default:
DEFAULT;
}
return addr;
}
+575
View File
@@ -0,0 +1,575 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// Get Ex as a single, not a quad, with b a intermediary double
#define GETEX(a, b) \
if((nextop&0xC0)==0xC0) { \
b = sse_get_reg(dyn, ninst, x1, nextop&7); \
if(b<16) \
a = b; \
else { \
a = fpu_get_scratch_double(dyn); \
VMOV_64(a, b); \
} \
a *= 2; \
} else { \
b = fpu_get_scratch_double(dyn); \
a = b*2; \
parity = getedparity(dyn, ninst, addr, nextop, 2); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0); \
VLDR_32(a, ed, fixedaddress); \
} else { \
GETED; \
VMOVtoV(a, ed); \
} \
}
#define GETGX(a) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd)
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int fixedaddress;
int v0, v1;
int s0, s1, s2;
int d0, d1;
int q0;
int parity;
MAYUSE(s1);
MAYUSE(s2);
MAYUSE(i32);
switch(opcode) {
case 0x10:
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
q0 = sse_get_reg(dyn, ninst, x1, nextop&7);
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOVD(d0, v0);
}
if(q0<16)
d1 = q0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOVD(d1, q0);
}
VMOV_32(d0*2, d1*2);
if(v0!=d0) {
VMOVD(v0, d0);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
VEORQ(v0, v0, v0);
VMOVtoDx_32(v0, 0, x2);
}
break;
case 0x11:
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7);
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOVD(d0, v0);
}
if(q0<16)
d1 = q0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOVD(d1, q0);
}
VMOV_32(d1*2, d0*2);
if(q0!=d1) {
VMOVD(q0, d1);
}
} else {
VMOVfrDx_32(x2, v0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
STR_IMM9(x2, ed, fixedaddress);
}
break;
case 0x1E:
INST_NAME("NOP / ENDBR32 / ENDBR64");
nextop = F8;
FAKEED;
break;
case 0x1F:
INST_NAME("REP NOP");
nextop = F8;
FAKEED;
break;
case 0x2A:
INST_NAME("CVTSI2SS Gx, Ed");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETED;
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VMOVtoV(s0, ed);
VCVT_F32_S32(s0, s0);
if(d0!=v0) {
VMOV_64(v0, d0);
}
break;
case 0x2C:
INST_NAME("CVTTSS2SI Gd, Ex");
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
VMOV_32(s0, d0*2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
}
VCVT_S32_F32(s0, s0);
VMOVfrV(gd, s0);
break;
case 0x2D:
INST_NAME("CVTSS2SI Gd, Ex");
u8 = x87_setround(dyn, ninst, x1, x2, x12);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
VMOV_32(s0, d0*2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
}
VCVTR_S32_F32(s0, s0);
VMOVfrV(gd, s0);
x87_restoreround(dyn, ninst, u8);
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VSQRT_F32(s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x52:
INST_NAME("RSQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
s2 = fpu_get_scratch_single(dyn);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
VMOV_i_32(s2, 0b01110000);
VSQRT_F32(s0, s1);
VDIV_F32(s0, s2, s0);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x53:
INST_NAME("RCPSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
s2 = fpu_get_scratch_single(dyn);
VMOV_i_32(s2, 0b01110000);
VDIV_F32(s0, s2, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x58:
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VADD_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x59:
INST_NAME("MULSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VMUL_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s0, d0);
VCVT_F64_F32(v0, s0);
break;
case 0x5B:
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VCVTQ_S32_F32(v0, v1);
break;
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VSUB_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5D:
INST_NAME("MINSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
VCMP_F32(s0, s1);
VMRS_APSR();
VMOVcond_32(cPL, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VDIV_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5F:
INST_NAME("MAXSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
VCMP_F32(s1, s0);
VMRS_APSR();
VMOVcond_32(cPL, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x6F:
INST_NAME("MOVDQU Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
LDR_IMM9(x2, ed, fixedaddress+8);
LDR_IMM9(x3, ed, fixedaddress+12);
VMOVtoV_D(v0+1, x2, x3);
}
break;
case 0x70:
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
u8 = F8;
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u32 = 0;
for (int i=0; i<2; ++i) {
u32 |= (((u8>>(i*2))&3)*2+0)<<(i*16+0);
u32 |= (((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV32(x2, u32);
u32 = 0;
for (int i=2; i<4; ++i) {
u32 |= (((u8>>(i*2))&3)*2+0)<<((i-2)*16+0);
u32 |= (((u8>>(i*2))&3)*2+1)<<((i-2)*16+8);
}
MOV32(x3, u32);
d0 = fpu_get_scratch_double(dyn);
VMOVtoV_D(d0, x2, x3);
VTBL1_8(v0+1, v1+1, d0);
if(v0!=v1) {
VMOVD(v0, v1);
}
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VLD1_64(v0, ed);
}
VEOR(v0+1, v0+1, v0+1);
break;
case 0x7F:
INST_NAME("MOVDQU Ex,Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, gd);
VMOVQ(v1, v0);
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
VMOVfrV_D(x2, x3, v0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
VMOVfrV_D(x2, x3, v0+1);
STR_IMM9(x2, ed, fixedaddress+8);
STR_IMM9(x3, ed, fixedaddress+12);
}
break;
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SET);
nextop = F8;
GETED;
GETGD;
TSTS_REG_LSL_IMM5(ed, ed, 0);
RBIT(x1, ed); // reverse
CLZ(gd, x1); // x2 gets leading 0 == TZCNT
MOVW_COND(cEQ, x1, 1);
MOVW_COND(cNE, x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
RSB_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
break;
case 0xC2:
INST_NAME("CMPSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VCMP_F32(s0, s1);
VMRS_APSR();
MOVW(x2, 0);
u8 = F8;
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: MVN_COND_REG_LSL_IMM5(cPL, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoDx_32(v0, 0, x2);
break;
default:
DEFAULT;
}
return addr;
}
+308
View File
@@ -0,0 +1,308 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "tools/bridge_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "emu/x87emu_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
void arm_popf(x86emu_t* emu, uint32_t f)
{
emu->packed_eflags.x32 = (f & 0x3F7FD7) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
RESET_FLAGS(emu);
}
void arm_fstp(x86emu_t* emu, void* p)
{
if(ST0.ll!=STld(0).ref)
D2LD(&ST0.d, p);
else
memcpy(p, &STld(0).ld, 10);
}
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n)
{
dynarec_log(LOG_DEBUG, "R%d=0x%x (%d)\n", n, reg, reg);
}
void arm_f2xm1(x86emu_t* emu)
{
ST0.d = exp2(ST0.d) - 1.0;
}
void arm_fyl2x(x86emu_t* emu)
{
ST(1).d = log2(ST0.d)*ST(1).d;
}
void arm_ftan(x86emu_t* emu)
{
ST0.d = tan(ST0.d);
}
void arm_fpatan(x86emu_t* emu)
{
ST1.d = atan2(ST1.d, ST0.d);
}
void arm_fxtract(x86emu_t* emu)
{
int32_t tmp32s = (ST1.ll&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
}
void arm_fprem(x86emu_t* emu)
{
int32_t tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
void arm_fyl2xp1(x86emu_t* emu)
{
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
}
void arm_fsincos(x86emu_t* emu)
{
sincos(ST1.d, &ST1.d, &ST0.d);
}
void arm_frndint(x86emu_t* emu)
{
ST0.d = fpu_round(emu, ST0.d);
}
void arm_fscale(x86emu_t* emu)
{
ST0.d *= exp2(trunc(ST1.d));
}
void arm_fsin(x86emu_t* emu)
{
ST0.d = sin(ST0.d);
}
void arm_fcos(x86emu_t* emu)
{
ST0.d = cos(ST0.d);
}
void arm_fbld(x86emu_t* emu, uint8_t* ed)
{
fpu_fbld(emu, ed);
}
void arm_fild64(x86emu_t* emu, int64_t* ed)
{
ST0.d = *ed;
STll(0).ll = *ed;
STll(0).ref = ST0.ll;
}
void arm_fbstp(x86emu_t* emu, uint8_t* ed)
{
fpu_fbst(emu, ed);
}
void arm_fistp64(x86emu_t* emu, int64_t* ed)
{
if(STll(0).ref==ST(0).ll) {
*ed = STll(0).ll;
} else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
*ed = 0x8000000000000000LL;
else
*ed = (int64_t)ST0.d;
}
}
void arm_fld(x86emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).ref = ST0.ll;
}
void arm_ud(x86emu_t* emu)
{
kill(getpid(), SIGILL);
}
void arm_fxsave(x86emu_t* emu, uint8_t* ed)
{
// should save flags & all
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(ed+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(ed+160, &emu->xmm[0], sizeof(emu->xmm));
// put also FPU regs in a reserved area...
for(int i=0; i<8; ++i)
memcpy(ed+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
}
void arm_fxrstor(x86emu_t* emu, uint8_t* ed)
{
// should restore flags & all
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx[i], ed+32+i*16, sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&emu->xmm[0], ed+160/4, sizeof(emu->xmm));
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], ed+416+i*8, sizeof(emu->fpu[0]));
}
void arm_fsave(x86emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
d = ST(i).f;
LD2D(p, &d);
#else
LD2D(p, &ST(i).d);
#endif
p+=10;
}
}
void arm_frstor(x86emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
D2LD(&d, p);
ST(i).f = d;
#else
D2LD(&ST(i).d, p);
#endif
p+=10;
}
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
{
return dyn->fpu_scratch++; // return an Sx
}
// Get a FPU double scratch reg
int fpu_get_scratch_double(dynarec_arm_t* dyn)
{
int i = (dyn->fpu_scratch+1)&(~1);
dyn->fpu_scratch = i+2;
return i/2; // return a Dx
}
// Get a FPU quad scratch reg
int fpu_get_scratch_quad(dynarec_arm_t* dyn)
{
int i = (dyn->fpu_scratch+3)&(~3);
dyn->fpu_scratch = i+4;
return i/2; // Return a Dx, not a Qx
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->fpu_scratch = 0;
}
#define FPUFIRST 8
// Get a FPU double reg
int fpu_get_reg_double(dynarec_arm_t* dyn)
{
// TODO: check upper limit?
int i=0;
while (dyn->fpuused[i]) ++i;
dyn->fpuused[i] = 1;
return i+FPUFIRST; // return a Dx
}
// Free a FPU double reg
void fpu_free_reg_double(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
int i=reg-FPUFIRST;
dyn->fpuused[i] = 0;
}
// Get a FPU quad reg
int fpu_get_reg_quad(dynarec_arm_t* dyn)
{
int i=0;
while (dyn->fpuused[i] || dyn->fpuused[i+1]) i+=2;
dyn->fpuused[i] = dyn->fpuused[i+1] = 1;
return i+FPUFIRST; // Return a Dx, not a Qx
}
// Free a FPU quad reg
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
{
int i=reg-FPUFIRST;
dyn->fpuused[i] = dyn->fpuused[i+1] = 0;
}
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->fpu_reg = 0;
for (int i=0; i<24; ++i)
dyn->fpuused[i]=0;
}
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity)
{
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
uint32_t tested = (1<<parity)-1;
if((nextop&0xC0)==0xC0)
return 0; // direct register, no parity...
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = (sib>>3)&7;
if((sib&0x7)==5) {
uint32_t tmp = F32;
if (sib_reg!=4) {
// if XXXXXX+reg<<N then check parity of XXXXX and N should be enough
return ((tmp&tested)==0 && (sib>>6)>=parity)?1:0;
} else {
// just a constant...
return (tmp&tested)?0:1;
}
} else {
if(sib_reg==4)
return 0; // simple [reg]
// don't try [reg1 + reg2<<N], unless reg1 is ESP
return ((sib&0x7)==4 && (sib>>6)>=parity)?1:0;
}
} else if((nextop&7)==5) {
uint32_t tmp = F32;
return (tmp&tested)?0:1;
} else {
return 0;
}
} else {
return 0; //Form [reg1 + reg2<<N + XXXXXX]
}
#undef F8
#undef F32
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef __DYNAREC_ARM_FUNCTIONS_H__
#define __DYNAREC_ARM_FUNCTIONS_H__
typedef struct x86emu_s x86emu_t;
void arm_popf(x86emu_t* emu, uint32_t f);
void arm_fstp(x86emu_t* emu, void* p);
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n);
void arm_f2xm1(x86emu_t* emu);
void arm_fyl2x(x86emu_t* emu);
void arm_ftan(x86emu_t* emu);
void arm_fpatan(x86emu_t* emu);
void arm_fxtract(x86emu_t* emu);
void arm_fprem(x86emu_t* emu);
void arm_fyl2xp1(x86emu_t* emu);
void arm_fsincos(x86emu_t* emu);
void arm_frndint(x86emu_t* emu);
void arm_fscale(x86emu_t* emu);
void arm_fsin(x86emu_t* emu);
void arm_fcos(x86emu_t* emu);
void arm_fbld(x86emu_t* emu, uint8_t* ed);
void arm_fild64(x86emu_t* emu, int64_t* ed);
void arm_fbstp(x86emu_t* emu, uint8_t* ed);
void arm_fistp64(x86emu_t* emu, int64_t* ed);
void arm_fld(x86emu_t* emu, uint8_t* ed);
void arm_fxsave(x86emu_t* emu, uint8_t* ed);
void arm_fxrstor(x86emu_t* emu, uint8_t* ed);
void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_ud(x86emu_t* emu);
// Get an FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn);
// Get an FPU double scratch reg
int fpu_get_scratch_double(dynarec_arm_t* dyn);
// Get an FPU quad scratch reg
int fpu_get_scratch_quad(dynarec_arm_t* dyn);
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn);
// Get an FPU double reg
int fpu_get_reg_double(dynarec_arm_t* dyn);
// Free a FPU double reg
void fpu_free_reg_double(dynarec_arm_t* dyn, int reg);
// Get an FPU quad reg
int fpu_get_reg_quad(dynarec_arm_t* dyn);
// Free a FPU quad reg
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg);
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+1147
View File
File diff suppressed because it is too large. Load diff
+629
View File
@@ -0,0 +1,629 @@
#ifndef __DYNAREC_ARM_HELPER_H__
#define __DYNAREC_ARM_HELPER_H__
#if STEP == 0
#include "dynarec_arm_pass0.h"
#elif STEP == 1
#include "dynarec_arm_pass1.h"
#elif STEP == 2
#include "dynarec_arm_pass2.h"
#elif STEP == 3
#include "dynarec_arm_pass3.h"
#endif
#include "debug.h"
#include "arm_emitter.h"
#include "../emu/x86primop.h"
#define F8 *(uint8_t*)(addr++)
#define F8S *(int8_t*)(addr++)
#define F16 *(uint16_t*)(addr+=2, addr-2)
#define F16S *(int16_t*)(addr+=2, addr-2)
#define F32 *(uint32_t*)(addr+=4, addr-4)
#define F32S *(int32_t*)(addr+=4, addr-4)
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(uint32_t*)(addr+a)
#define PK16(a) *(uint16_t*)(addr+a)
#define PKip(a) *(uint8_t*)(ip+a)
// GETGD get x86 register in gd
#define GETGD gd = xEAX+((nextop&0x38)>>3)
//GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETED if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0); \
LDR_IMM9(x1, wback, fixedaddress); \
ed = x1; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
#define GETEDH(hint) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0); \
LDR_IMM9(hint, wback, fixedaddress); \
ed = hint; \
}
//GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
#define GETEDW(hint, ret) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
MOV_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0); \
ed = ret; \
LDR_IMM9(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress);}
// Send back wb to either ed or wback
#define SBACK(wb) if(wback) {STR_IMM9(wb, wback, fixedaddress);} else {MOV_REG(ed, wb);}
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDO(O) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0); \
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
ed = x1; \
}
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0);}
//FAKEELike GETED, but doesn't get anything
#define FAKEED if((nextop&0xC0)!=0xC0) { \
addr = fakeed(dyn, addr, ninst, nextop); \
}
// GETGW extract x86 register in gd, that is i
#define GETGW(i) gd = xEAX+((nextop&0x38)>>3); UXTH(i, gd, 0); gd = i;
//GETEWW will use i for ed, and can use w for wback.
#define GETEWW(w, i) if((nextop&0xC0)==0xC0) { \
wback = xEAX+(nextop&7);\
UXTH(i, wback, 0); \
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
//GETEW will use i for ed, and can use r3 for wback.
#define GETEW(i) if((nextop&0xC0)==0xC0) { \
wback = xEAX+(nextop&7);\
UXTH(i, wback, 0); \
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
//GETSEW will use i for ed, and can use r3 for wback. This is the Signed version
#define GETSEW(i) if((nextop&0xC0)==0xC0) { \
wback = xEAX+(nextop&7);\
SXTH(i, wback, 0); \
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
LDRSH_IMM8(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
}
// Write ed back to original register / memory
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress);} else {BFI(wback, ed, 0, 16);}
// Write w back to original register / memory
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress);} else {BFI(wback, w, 0, 16);}
// Write back gd in correct register
#define GWBACK BFI((xEAX+((nextop&0x38)>>3)), gd, 0, 16);
//GETEB will use i for ed, and can use r3 for wback.
#define GETEB(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
wb2 = (wback>>2); \
wback = xEAX+(wback&3); \
UXTB(i, wback, wb2); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
#define GETSEB(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
wb2 = (wback>>2); \
wback = xEAX+(wback&3); \
SXTB(i, wback, wb2); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
LDRSB_IMM8(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress);} else {BFI(wback, ed, wb2*8, 8);}
//GETGB will use i for gd
#define GETGB(i) gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
gb1 = xEAX+(gd&3); \
gd = i; \
UXTB(gd, gb1, gb2);
//GETSGB signe extend GB, will use i for gd
#define GETSGB(i) gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
gb1 = xEAX+(gd&3); \
gd = i; \
SXTB(gd, gb1, gb2);
// Write gb (gd) back to original register / memory
#define GBBACK BFI(gb1, gd, gb2*8, 8);
// Get Direction with size Z and based of F_DF flag, on register r ready for LDR/STR fetching
#define GETDIR(r, A) \
LDR_IMM9(r, xEmu, offsetof(x86emu_t, flags[F_DF])); \
CMPS_IMM8(r, 1); \
MOVW(r, A); \
RSB_COND_IMM8(cEQ, r, r, 0)
// CALL will use x12 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL(F, ret, M) call_c(dyn, ninst, F, x12, ret, M)
// CALL_ will use x3 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL_(F, ret, M) call_c(dyn, ninst, F, x3, ret, M)
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
// Branch to MARK if cond (use i32)
#define B_MARK(cond) \
i32 = GETMARK-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to MARK2 if cond (use i32)
#define B_MARK2(cond) \
i32 = GETMARK2-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to MARK3 if cond (use i32)
#define B_MARK3(cond) \
i32 = GETMARK3-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to next instruction if cond (use i32)
#define B_NEXT(cond) \
i32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
Bcond(cond, i32)
// Branch to MARKSEG if cond (use i32)
#define B_MARKSEG(cond) \
i32 = GETMARKSEG-(dyn->arm_size+8); \
Bcond(cond, i32)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A)))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2) \
VMRS_APSR(); /* 0b0100011100000000 */ \
LDRH_IMM8(s2, xEmu, offsetof(x86emu_t, sw)); /*offset is 8bits right?*/ \
MOVW(s1, 0b0100011100000000); \
BIC_REG_LSL_IMM5(s2, s2, s1, 0); \
MOVW_COND(cVS, s1, 0b0100010100000000); /* unordered */ \
MOVW_COND(cEQ, s1, 0b0100000000000000); /* zero */ \
MOVW_COND(cGT, s1, 0b0000000000000000); /* greater than */ \
MOVW_COND(cLO, s1, 0b0000000100000000); /* less than */ \
ORR_REG_LSL_IMM5(s2, s2, s1, 0); \
STRH_IMM8(s2, xEmu, offsetof(x86emu_t, sw))
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2) \
VMRS_APSR(); /* 0b111 */ \
XOR_REG_LSL_IMM5(s2, s2, s2, 0); \
MOVW_COND(cVS, s1, 0b111); /* unordered */ \
MOVW_COND(cEQ, s1, 0b100); /* zero */ \
MOVW_COND(cGT, s1, 0b000); /* greater than */ \
MOVW_COND(cLO, s1, 0b001); /* less than */ \
IFX(X_CF|X_PEND) { \
UBFX(s2, s1, 0, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_CF]));\
} \
IFX(X_PF|X_PEND) { \
UBFX(s2, s1, 1, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_PF]));\
} \
IFX(X_ZF|X_PEND) { \
UBFX(s2, s1, 2, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_ZF]));\
} \
MOVW(s2, d_none); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, df)); \
IFX(X_OF|X_PEND) { \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_OF]));\
} \
IFX(X_AF|X_PEND) { \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_AF]));\
} \
IFX(X_SF|X_PEND) { \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_SF]));\
} \
#ifndef READFLAGS
#define READFLAGS(A) \
if(dyn->state_flags!=SF_SET) { \
if(dyn->state_flags!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
TSTS_REG_LSL_IMM5(x3, x3, 0); \
i32 = (GETMARKF)-(dyn->arm_size+8); \
Bcond(cEQ, i32); \
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->state_flags = SF_SET; \
}
#endif
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x86.need_flags&(~((A)|X_PEND)))) \
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A))); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
#endif
#ifndef JUMP
#define JUMP(A)
#endif
#ifndef BARRIER
#define BARRIER(A)
#endif
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, 0, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, 0, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, 0, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, 0, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {MOVW(r, A); STR_IMM9(r, 0, offsetof(x86emu_t, df));}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x86.need_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
#ifndef NEW_BARRIER_INST
#define NEW_BARRIER_INST
#endif
// Emit the LOCK mutex (x1, x2 and x3 are lost)
#define LOCK emit_lock(dyn, addr, ninst)
// Emit the UNLOCK mutex (x1, x2 and x3 are lost)
#define UNLOCK emit_unlock(dyn, addr, ninst)
void arm_epilog();
void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#ifndef STEPNAME
#define STEPNAME3(N,M) N##M
#define STEPNAME2(N,M) STEPNAME3(N,M)
#define STEPNAME(N) STEPNAME2(N, STEP)
#endif
#define arm_pass STEPNAME(arm_pass)
#define dynarec00 STEPNAME(dynarec00)
#define dynarec0F STEPNAME(dynarec0F)
#define dynarecFS STEPNAME(dynarecFS)
#define dynarecGS STEPNAME(dynarecGS)
#define dynarec66 STEPNAME(dynarec66)
#define dynarec67 STEPNAME(dynarec67)
#define dynarecD8 STEPNAME(dynarecD8)
#define dynarecD9 STEPNAME(dynarecD9)
#define dynarecDA STEPNAME(dynarecDA)
#define dynarecDB STEPNAME(dynarecDB)
#define dynarecDC STEPNAME(dynarecDC)
#define dynarecDD STEPNAME(dynarecDD)
#define dynarecDE STEPNAME(dynarecDE)
#define dynarecDF STEPNAME(dynarecDF)
#define dynarecF0 STEPNAME(dynarecF0)
#define dynarec660F STEPNAME(dynarec660F)
#define dynarecF20F STEPNAME(dynarecF20F)
#define dynarecF30F STEPNAME(dynarecF30F)
#define geted STEPNAME(geted_)
#define fakeed STEPNAME(fakeed_)
#define jump_to_epilog STEPNAME(jump_to_epilog_)
#define jump_to_linker STEPNAME(jump_to_linker_)
#define ret_to_epilog STEPNAME(ret_to_epilog_)
#define retn_to_epilog STEPNAME(retn_to_epilog_)
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define grab_fsdata STEPNAME(grab_fsdata_)
#define grab_tlsdata STEPNAME(grab_tlsdata_)
#define isNativeCall STEPNAME(isNativeCall_)
#define emit_lock STEPNAME(emit_lock)
#define emit_unlock STEPNAME(emit_unlock)
#define emit_cmp8 STEPNAME(emit_cmp8)
#define emit_cmp16 STEPNAME(emit_cmp16)
#define emit_cmp32 STEPNAME(emit_cmp32)
#define emit_cmp8_0 STEPNAME(emit_cmp8_0)
#define emit_cmp16_0 STEPNAME(emit_cmp16_0)
#define emit_cmp32_0 STEPNAME(emit_cmp32_0)
#define emit_test8 STEPNAME(emit_test8)
#define emit_test16 STEPNAME(emit_test16)
#define emit_test32 STEPNAME(emit_test32)
#define emit_add32 STEPNAME(emit_add32)
#define emit_add32c STEPNAME(emit_add32c)
#define emit_add8 STEPNAME(emit_add8)
#define emit_add8c STEPNAME(emit_add8c)
#define emit_sub32 STEPNAME(emit_sub32)
#define emit_sub32c STEPNAME(emit_sub32c)
#define emit_sub8 STEPNAME(emit_sub8)
#define emit_sub8c STEPNAME(emit_sub8c)
#define emit_or32 STEPNAME(emit_or32)
#define emit_or32c STEPNAME(emit_or32c)
#define emit_xor32 STEPNAME(emit_xor32)
#define emit_xor32c STEPNAME(emit_xor32c)
#define emit_and32 STEPNAME(emit_and32)
#define emit_and32c STEPNAME(emit_and32c)
#define emit_or8 STEPNAME(emit_or8)
#define emit_or8c STEPNAME(emit_or8c)
#define emit_xor8 STEPNAME(emit_xor8)
#define emit_xor8c STEPNAME(emit_xor8c)
#define emit_and8 STEPNAME(emit_and8)
#define emit_and8c STEPNAME(emit_and8c)
#define emit_add16 STEPNAME(emit_add16)
#define emit_add16c STEPNAME(emit_add16c)
#define emit_sub16 STEPNAME(emit_sub16)
#define emit_sub16c STEPNAME(emit_sub16c)
#define emit_or16 STEPNAME(emit_or16)
#define emit_or16c STEPNAME(emit_or16c)
#define emit_xor16 STEPNAME(emit_xor16)
#define emit_xor16c STEPNAME(emit_xor16c)
#define emit_and16 STEPNAME(emit_and16)
#define emit_and16c STEPNAME(emit_and16c)
#define emit_inc32 STEPNAME(emit_inc32)
#define emit_inc16 STEPNAME(emit_inc16)
#define emit_inc8 STEPNAME(emit_inc8)
#define emit_dec32 STEPNAME(emit_dec32)
#define emit_dec16 STEPNAME(emit_dec16)
#define emit_dec8 STEPNAME(emit_dec8)
#define emit_adc32 STEPNAME(emit_adc32)
#define emit_adc32c STEPNAME(emit_adc32c)
#define emit_adc8 STEPNAME(emit_adc8)
#define emit_adc8c STEPNAME(emit_adc8c)
#define emit_adc16 STEPNAME(emit_adc16)
#define emit_adc16c STEPNAME(emit_adc16c)
#define emit_sbb32 STEPNAME(emit_sbb32)
#define emit_sbb32c STEPNAME(emit_sbb32c)
#define emit_sbb8 STEPNAME(emit_sbb8)
#define emit_sbb8c STEPNAME(emit_sbb8c)
#define emit_sbb16 STEPNAME(emit_sbb16)
#define emit_sbb16c STEPNAME(emit_sbb16c)
#define emit_neg32 STEPNAME(emit_neg32)
#define emit_neg16 STEPNAME(emit_neg16)
#define emit_neg8 STEPNAME(emit_neg8)
#define emit_shl32c STEPNAME(emit_shl32c)
#define emit_shr32c STEPNAME(emit_shr32c)
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
#define x87_do_pop STEPNAME(x87_do_pop)
#define x87_get_cache STEPNAME(x87_get_cache)
#define x87_get_st STEPNAME(x87_get_st)
#define x87_refresh STEPNAME(x87_refresh)
#define x87_forget STEPNAME(x87_forget)
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_setround STEPNAME(x87_setround)
#define x87_restoreround STEPNAME(x87_restoreround)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_purgecache STEPNAME(fpu_purgecache)
#ifdef HAVE_TRACE
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
#define cstack_push STEPNAME(cstack_push)
#define cstack_pop STEPNAME(cstack_pop)
// get the single reg that from the double "reg" (so Dx[idx])
#define fpu_get_single_reg STEPNAME(fpu_get_single_reg)
// put back (if needed) the single reg in place
#define fpu_putback_single_reg STEPNAME(fpu_putback_single_reg)
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// generic x86 helper
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask);
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_adc32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_neg32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
// x87 helper
// cache of the local stack counter, to avoid upadte at every call
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
// fpu push. Return the Dd value to be used
int x87_do_push(dynarec_arm_t* dyn, int ninst);
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1);
// fpu pop. All previous returned Dd should be considered invalid
void x87_do_pop(dynarec_arm_t* dyn, int ninst);
// get cache index for a x87 reg, create the entry if needed
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
// get vfpu register for a x87 reg, create the entry if needed
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
// refresh a value from the cache ->emu (nothing done if value is not cached)
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh the cache value from emu
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
//MMX helpers
// get neon register for a MMX reg, create the entry if needed
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
//SSE/SSE2 helpers
// get neon register for a SSE reg, create the entry if needed
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn, int ninst);
// purge the FPU cache (needs 3 scratch registers)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
// get the single reg that from the double "reg" (so Dx[idx])
int fpu_get_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx);
// put back (if needed) the single reg in place
void fpu_putback_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx, int s);
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
// PUSH a x86/native couple of address in cstack, using s1, s2, s2+1
void cstack_push(dynarec_arm_t* dyn, int ninst, uintptr_t x86ip, uintptr_t armip, int s1, int s2);
// POP a x86/native couple of address from cstack, and generate the jump is x86 address is s0, use s1, s2 and s2+1 as scratch
void cstack_pop(dynarec_arm_t* dyn, int ninst, int s0, int s1, int s2);
#if STEP < 2
#define PASS2(A)
#else
#define PASS2(A) A
#endif
#if STEP < 3
#define PASS3(A)
#else
#define PASS3(A) A
#endif
#if STEP < 3
#define MAYUSE(A) (void)A
#else
#define MAYUSE(A)
#endif
#endif //__DYNAREC_ARM_HELPER_H__
+94
View File
@@ -0,0 +1,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
#ifndef STEP
#error No STEP defined
#endif
void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
int ok = 1;
int ninst = 0;
uintptr_t ip = addr;
int need_epilog = 1;
dyn->tablei = 0;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->state_flags = 0;
fpu_reset(dyn, ninst);
// ok, go now
INIT;
while(ok) {
if(dyn->insts && (ninst>dyn->size)) {dynarec_log(LOG_NONE, "Warning, too many inst treated (%d / %d)\n",ninst, dyn->size);}
ip = addr;
if(dyn->insts && (dyn->insts[ninst].x86.barrier==1)) {
NEW_BARRIER_INST;
}
NEW_INST;
fpu_reset_scratch(dyn);
#ifdef HAVE_TRACE
if(my_context->dec && box86_dynarec_trace) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip <= trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
MOV32(1, ip);
STM(0, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
STR_IMM9(1, 0, offsetof(x86emu_t, ip));
MOV32(2, 1);
CALL(PrintTrace, -1, 0);
MESSAGE(LOG_DUMP, "----------\n");
}
}
#endif
addr = dynarec00(dyn, addr, ip, ninst, &ok, &need_epilog);
INST_EPILOG;
if(dyn->insts && dyn->insts[ninst+1].x86.barrier) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(dyn->insts[ninst+1].x86.barrier!=2)
dyn->state_flags = 0;
}
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
ok = 1;
}
if(!ok && !need_epilog && !dyn->insts) { // check if need to continue
uintptr_t next = get_closest_next(dyn, addr);
if(next && ((next-addr)<15) && is_nops(dyn, addr, next-addr)) {
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
ok = 1;
} else if(next && (next-addr)<15) {
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4));
}
}
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
}
if(need_epilog) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
}
+22
View File
@@ -0,0 +1,22 @@
#define INIT uintptr_t sav_addr=addr
#define FINI dyn->isize = addr-sav_addr
#define MESSAGE(A, ...)
#define SETFLAGS(A, B)
#define READFLAGS(A)
#define EMIT(A)
#define JUMP(A) add_next(dyn, (uintptr_t)A)
#define NEW_INST ++dyn->size
#define INST_EPILOG
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
dynarec_log(LOG_INFO, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X (%s)\n", \
(void*)ip, PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
PKip(10),PKip(11),PKip(12), \
PKip(13),PKip(14), \
GetNativeName((void*)addr))
+17
View File
@@ -0,0 +1,17 @@
#define INIT
#define FINI \
dyn->insts[ninst].x86.addr = addr; \
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
#define MESSAGE(A, ...)
#define EMIT(A)
#define READFLAGS(A) dyn->insts[ninst].x86.use_flags = A
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
#define JUMP(A) dyn->insts[ninst].x86.jmp = A
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst+1<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
dyn->insts[ninst].x86.addr = ip; \
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
#define INST_EPILOG
#define INST_NAME(name)
+9
View File
@@ -0,0 +1,9 @@
#define INIT dyn->arm_size = 0
#define FINI if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define MESSAGE(A, ...)
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
#define NEW_INST if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
+33
View File
@@ -0,0 +1,33 @@
#define INIT
#define FINI
#define EMIT(A) \
if(box86_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (A), arm_print(A));} \
*(uint32_t*)(dyn->block) = A; \
dyn->block += 4; dyn->arm_size += 4
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
#define INST_EPILOG
#define INST_NAME(name) \
if(box86_dynarec_dump) {\
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, state=%d/%d, set=%X, use=%X, need=%X%s\n", \
(box86_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
dyn->insts[ninst].x86.state_flags, \
dyn->state_flags, \
dyn->insts[ninst].x86.set_flags, \
dyn->insts[ninst].x86.use_flags, \
dyn->insts[ninst].x86.need_flags, \
(box86_dynarec_dump>1)?"\e[m":""); \
}
#define NEW_BARRIER_INST \
if(ninst) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here\n");\
++dyn->sons_size; \
}
+52
View File
@@ -0,0 +1,52 @@
#ifndef __DYNAREC_ARM_PRIVATE_H_
#define __DYNAREC_ARM_PRIVATE_H_
#include "dynarec_private.h"
typedef struct x86emu_s x86emu_t;
typedef struct instruction_arm_s {
instruction_x86_t x86;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
int size; // size of the arm emited instruction
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markseg;
} instruction_arm_t;
typedef struct dynarec_arm_s {
instruction_arm_t *insts;
int32_t size;
int32_t cap;
uintptr_t start; // start of the block
uint32_t isize; // size in byte of x86 instructions included
void* block; // memory pointer where next instruction is emited
uintptr_t arm_start; // start of the arm code
int arm_size; // size of emitted arm code
uintptr_t* table; // jump table
int tablesz; // size of the jump table
int tablei; // index
int state_flags;// actual state for on-demand flags
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int x87reg[8]; // reg used for x87cache entry
int mmxcache[8];// cache status for the 8 MMX registers
int ssecache[8];// cache status for the 8 SSE(2) registers
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
int x87stack; // cache stack counter
int fpu_scratch;// scratch counter
int fpu_reg; // x87/sse/mmx reg counter
int nolinker; // disable use of (smart) linker in the block
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
#endif //__DYNAREC_ARM_PRIVATE_H_
+37
View File
@@ -0,0 +1,37 @@
#ifndef __DYNAREC_PRIVATE_H_
#define __DYNAREC_PRIVATE_H_
// all flags for the use_flags field
#define X_CF (1<<0)
#define X_PF (1<<1)
#define X_AF (1<<2)
#define X_ZF (1<<3)
#define X_SF (1<<4)
#define X_OF (1<<5)
#define X_ALL ((1<<6)-1)
#define X_PEND (0x1000)
// all state flags
#define SF_UNKNOWN 0
#define SF_SET 1
#define SF_PENDING 2
#define SF_MAYSET 3
#define SF_SUBSET 4
typedef struct instruction_x86_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
int barrier; // next instruction is a jump point, so no optim allowed
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint32_t use_flags; // 0 or combination of X_?F
uint32_t set_flags; // 0 or combination of X_?F
uint32_t need_flags; // calculated
int state_flags; // One of SF_XXX state
} instruction_x86_t;
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
void tableupdate(void* jumpto, uintptr_t ref, void** table);
void resettable(void** table);
#endif //__DYNAREC_PRIVATE_H_
+475
View File
@@ -0,0 +1,475 @@
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 0 Vn Vd 0 0 0 1 N Q M 1 Vm VAND<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 1 Vn Vd 0 0 0 1 N Q M 1 Vm VBIC<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 0 Vn Vd 0 0 0 1 N Q M 1 Vm @ m=n const char* op op,"MOV","ORR"@ m=n char lastop[6] !@ %@ lastop[0] = '\0'@ sprintf(lastop, ", %s", vecname[(q << 5) + 0x20 + n])@ @ V\op\<c> <Qd>, <Qm>\lastop\
NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 op 0 D size Vn Vd 1 0 0 0 N Q M 0 Vm @ op=0 const char* opname opname,"ADD","SUB"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VTST<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VCEQ<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 0 Vm @ set size = 8 << size@ @ VML\(u ? "S" : "A")\<c>.I\%dsize\ <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 1 Vm VMUL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQRDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q/=0 M 1 Vm VPADD<c>.<dt> <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 0 N Q M 1 Vm @ u=0 const char* y y,"A","S"@ @ VFM\y\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm @ u=0 const char* op op,"ADD","SUB"@ @ V\op\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q/=0 M 0 Vm VPADD.F32 <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 1 0 D 1 sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm VABD.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VML\(op ? "S" : "A")\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VMUL.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm VCEQ.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm @ op=1 const char* strict strict,"T","E"@ @ VCG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 1 Vm @ op=1 const char* strict strict,"T","E"@ @ VACG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRECPS.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRSQRTS.F32 <Qd>, <Qn>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 <1> 0 <23>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=11xx 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=1 1 imm4 VBIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=1 1 imm4 BIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=110x 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 0 L Q M 1 Vm VRSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 1 L Q M 1 Vm VRSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 1 0 1 0 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 <9> 1 1 1 <1> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.S32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.S32.F32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.U32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.U32.F32 <Qd>, <Qm>, #<fbits>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <18> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 1 1 Vn Vd IMM4 N Q M 0 Vm VEXT<c>.8 <Qd>, <Qn>, <Qm>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=11 0 0 <4> 0 0 0 <2> <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 0 Q M 0 Vm VCNT<c>.8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 1 Q M 0 Vm VMVN<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 0 U Q M 0 Vm VPADAL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 0 Q M 0 Vm VQABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 1 Q M 0 Vm VQNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 0 Q M 0 Vm VCGT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 1 Q M 0 Vm VCGE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 0 Q M 0 Vm VCEQ<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 1 Q M 0 Vm VCLE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 0 0 Q M 0 Vm VCLT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 0 Q M 0 Vm VABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 1 Q M 0 Vm VNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 1 0 Vd 0 0 0 0 0 Q M 0 Vm VSWP<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 0 1 Q M 0 Vm VTRN<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set u = 1 - u@ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 0 Q M 0 Vm VRECPE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 1 Q M 0 Vm VRSQRTE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 0 Q M 0 Vm VCVT<c>.F32.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 1 Q M 0 Vm VCVT<c>.S32.F32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 0 Q M 0 Vm VCVT<c>.F32.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 1 Q M 0 Vm VCVT<c>.U32.F32 <Qd>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <8> 0 <6> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 Vn Vd 1 0 @<2> N op M 0 Vm @ param=0b00 char list[10] !@ sprintf(list, %)@ "{%s}", vecname[0x20 + n]@ "{%s-%s}", vecname[0x20 + n], vecname[0x20 + n + param]@ @ VTB\(op ? "X" : "L")\<c>.8 <Dd>, \list\, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 imm4 Vd 1 1 0 0 0 Q M 0 Vm VDUP<c>.\%dsize\ <Qd>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 1 1 <13> 0 <1> 0 <4>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 0 Q N 0 M 0 Vm VADD\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 1 Q N 0 M 0 Vm VSUB\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm @ set size = 16 << size@ @ VADDHN<c>.I\%dsize\ <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm VRADDHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 0 1 N 0 M 0 Vm VABAL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VRSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 1 1 N 0 M 0 Vm VABDL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 op 0 N 0 M 0 Vm VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 op 1 N 0 M 0 Vm VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 1 0 0 N 0 M 0 Vm VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 1 0 1 N 0 M 0 Vm VQDMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U/=0 1 D size/=00 Vn Vd 1 1 1 0 N 0 M 0 Vm @ set uint8_t size = 0@ @ VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 0 op 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 op 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 op 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 0 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMUL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
INVALIDATE 1 1 1 1 <28>
ARMS cond 0 0 0 0 0 0 0 S Rn Rd imm5 type 0 Rm AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 0 S Rd (0) (0) (0) (0) Rm 1 0 0 1 Rn MUL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 0 1 S Rn Rd imm5 type 0 Rm EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 1 S Rd Ra Rm 1 0 0 1 Rn MLA{S}<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 0 1 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSBT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSHT<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 1 0 S Rn Rd imm5 type 0 Rm SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 0 0 RdHi RdLo Rm 1 0 0 1 Rn UMAAL<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 0 1 1 S Rn Rd imm5 type 0 Rm RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 1 0 Rd Ra Rm 1 0 0 1 Rn MLS<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 1 1 0 Rn Rt imm4H 1 0 1 1 imm4L STRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 0 1 1 imm4L LDRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSBT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 1 0 0 S Rn Rd imm5 type 0 Rm ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 0 S RdHi RdLo Rm 1 0 0 1 Rn UMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 0 1 S Rn Rd imm5 type 0 Rm ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 1 S RdHi RdLo Rm 1 0 0 1 Rn UMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 0 S Rn Rd imm5 type 0 Rm SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 0 S RdHi RdLo Rm 1 0 0 1 Rn SMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 1 S Rn Rd imm5 type 0 Rm RSC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 1 S RdHi RdLo Rm 1 0 0 1 Rn SMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 0 0 Rn SMLABB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 1 0 Rn SMLATB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 0 0 Rn SMLABT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 1 0 Rn SMLATT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWP<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
ARM_ cond/=1110 0 0 0 1 0 0 1 0 imm12 0 1 1 1 imm4 BKPT #<imm16>
ARMS cond 0 0 0 1 0 0 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TEQ<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 0 1 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWPB<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 0 1 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMP<c> <Rn>, <Rm>{, <shift>}
ARMS cond 0 0 0 1 0 1 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMN<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 1 0 0 S Rn Rd imm5 type 0 Rm ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 0 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREX<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREX<c> <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 0 0 0 Rm MOV{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 0 0 Rm LSL{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 0 1 Rn LSL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 1 0 Rm LSR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 1 1 Rn LSR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 0 0 Rm ASR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 0 1 Rn ASR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 1 1 0 Rm RRX{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 1 0 Rm ROR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 1 1 Rn ROR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXD<c> <Rd>, <Rt>, <Rt2>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXD<c> <Rt>, <Rt2>, [<Rn>]
ARMS cond 0 0 0 1 1 1 0 S Rn Rd imm5 type 0 Rm BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXB<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXB<c> <Rt>, [<Rn>]
ARMS cond 0 0 0 1 1 1 1 S (0) (0) (0) (0) Rd imm5 type 0 Rm MVN{S}<c> <Rd>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXH<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXH<c> <Rt>, [<Rn>]
ARM_ cond 0 0 1 0 0 0 0 S Rn Rd imm12 AND{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 0 1 S Rn Rd imm12 EOR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 0 S Rn Rd imm12 SUB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 1 S Rn Rd imm12 RSB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 0 S Rn Rd imm12 ADD{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 1 S Rn Rd imm12 ADC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 0 S Rn Rd imm12 SBC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 1 1 Rn (0) (0) (0) (0) imm12 CMN<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 0 S Rn Rd imm12 ORR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 1 S (0) (0) (0) (0) Rd imm12 MOV{S}<c> <Rd>, #<const>
ARM_ cond 0 0 1 1 1 1 0 S Rn Rd imm12 BIC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 1 1 S (0) (0) (0) (0) Rd imm12 MVN{S}<c> <Rd>, #<const>
ARM_ cond 0 1 0 0 1 0 0 1 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 POP<c> {<Rt>}
ARM_ cond 0 1 0 0 U 0 0 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 0 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 0 Rn Rt imm12 STRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 1 Rn Rt imm12 LDRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 0 Rn Rt imm12 STRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 1 Rn Rt imm12 LDRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 1 0 0 1 0 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 PUSH<c> {<Rt>}
ARM_ cond 0 1 0 1 U 0 W 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 0 W 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm SSAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm SSUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm SSUB8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm USAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm USUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm USUB8<c> <Rd>, <Rn>, <Rm>
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 0 0 1 Rm PKHBT<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 1 0 1 Rm PKHTB<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 1 1 0 1 0 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 0 1 sat_imm Rd imm5 sh 0 1 Rn SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 0 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn SSAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 0 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 0 0 1 1 Rm REV<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REV16<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 1 1 sat_imm Rd imm5 sh 0 1 Rn USAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 1 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn USAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 1 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REVSH<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 1 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 U 0 0 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 0 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 0 Rn Rt imm5 type 0 Rm STRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 1 Rn Rt imm5 type 0 Rm LDRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARM_ cond 0 1 1 1 1 0 0 0 Rd 1 1 1 1 Rm 0 0 0 1 Rn USAD8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn register_list LDMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn/=1101 register_list STMEA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn register_list STM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 0 1 Rn/=1101 register_list LDMEA<c> <Rn>, <registers>
ARM_ cond 1 0 0 0 1 0 1 1 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"POP","LDMEA"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 0 1 0 W 1 Rn register_list LDM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 0 0 Rn/=1101 register_list STMFD<c> <Rn>, <registers>
ARM_ cond 1 0 0 1 0 0 1 0 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"PUSH","STMFD"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 1 0 0 W 0 Rn register_list STMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn/=1101 register_list LDMFD<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn register_list LDMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn/=1101 register_list STMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn register_list STMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn/=1101 register_list LDMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn register_list LDMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 1 0 imm24 B<c> <label>
ARM_ cond 1 0 1 1 imm24 BL<c> <label>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Sm>, <Sm1>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Sm>, <Sm1>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Dm>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Dm>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
INVALIDATE <4> 1 1 0 <25>
INVALIDATE <4> 1 1 1 0 0 0 <1> 0 <8> 1 0 1 1 <1> 1 0 1 (0) (0) (0) (0)
VFPU cond 1 1 1 0 0 0 0 0 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Sn>, <Rt>
VFPU cond 1 1 1 0 1 1 1 0 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMSR<c> FPSCR, <Rt>
VFPU cond 1 1 1 0 0 @<2> 0 Vd Rt 1 0 1 1 D @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (param1_2 << 2) + param2_2@ = uint8_t shift @@ (opc & 0b1000) == 0b1000@ @@ (opc & 0b1001) == 0b0001@ @@ (opc & 0b1011) == 0b0000@ shift,0,1,2,0xFF@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.\%d8 &l&l shift\ <Dd[x]>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VNML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 1 M 0 Vm VNMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 0 M 0 Vm VADD<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 1 M 0 Vm VSUB<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VDIV<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VFNM\(op ? "A" : "S")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 1 0 Vn Vd 1 0 1 sz N op M 0 Vm VFM\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 0 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set float mantissa = 16 + param2_4@ set float imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F32 <Sd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 1 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set double mantissa = 16 + param2_4@ set double imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F64 <Dd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 0 1 M 0 Vm VMOV<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 1 1 M 0 Vm VABS<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 0 1 M 0 Vm VNEG<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 1 1 M 0 Vm VSQRT<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 0 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F32.F16 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 1 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F16.F32 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 1 Vd 1 0 1 sz op 1 (0) 0 (0) (0) (0) (0) VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, #0.0
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
INVALIDATE <32>
-494
View File
@@ -1,494 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <elf.h>
#include <sys/mman.h>
#include "box86version.h"
#include "elfloader.h"
#include "debug.h"
#include "elfload_dump.h"
#include "elfloader_private.h"
#include "librarian.h"
#include "x86run.h"
#include "bridge.h"
#include "wrapper.h"
#include "box86context.h"
#include "library.h"
#include "x86emu.h"
void FreeElfHeader(elfheader_t** head)
{
if(!head || !*head)
return;
elfheader_t *h = *head;
free(h->name);
free(h->PHEntries);
free(h->SHEntries);
free(h->SHStrTab);
free(h->StrTab);
free(h->Dynamic);
free(h->DynStr);
free(h->SymTab);
free(h->DynSym);
FreeElfMemory(h);
free(h);
*head = NULL;
}
int CalcLoadAddr(elfheader_t* head)
{
head->memsz = 0;
head->paddr = head->vaddr = (uintptr_t)~0;
head->align = 1;
for (int i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD) {
if(head->paddr > head->PHEntries[i].p_paddr)
head->paddr = head->PHEntries[i].p_paddr;
if(head->vaddr > head->PHEntries[i].p_vaddr)
head->vaddr = head->PHEntries[i].p_vaddr;
}
if(head->vaddr==~0 || head->paddr==~0) {
printf_log(LOG_NONE, "Error: v/p Addr for Elf Load not set\n");
return 1;
}
head->stacksz = 1024*1024; //1M stack size default?
head->stackalign = 4; // default align for stack
for (int i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
uintptr_t phend = head->PHEntries[i].p_vaddr - head->vaddr + head->PHEntries[i].p_memsz;
if(phend > head->memsz)
head->memsz = phend;
if(head->PHEntries[i].p_align > head->align)
head->align = head->PHEntries[i].p_align;
}
if(head->PHEntries[i].p_type == PT_GNU_STACK) {
if(head->stacksz < head->PHEntries[i].p_memsz)
head->stacksz = head->PHEntries[i].p_memsz;
if(head->stackalign < head->PHEntries[i].p_align)
head->stackalign = head->PHEntries[i].p_align;
}
}
printf_log(LOG_DEBUG, "Elf Addr(v/p)=%p/%p Memsize=0x%x (align=0x%x)\n", (void*)head->vaddr, (void*)head->paddr, head->memsz, head->align);
printf_log(LOG_DEBUG, "Elf Stack Memsize=%u (align=%u)\n", head->stacksz, head->stackalign);
return 0;
}
const char* ElfName(elfheader_t* head)
{
return head->name;
}
int AllocElfMemory(elfheader_t* head)
{
#if 0
printf_log(LOG_DEBUG, "Allocating memory for Elf \"%s\"\n", head->name);
if (posix_memalign((void**)&head->memory, head->align, head->memsz)) {
printf_log(LOG_NONE, "Cannot allocate aligned memory (0x%x/0x%x) for elf \"%s\"\n", head->memsz, head->align, head->name);
return 1;
}
printf_log(LOG_DEBUG, "Address is %p\n", head->memory);
printf_log(LOG_DEBUG, "And setting memory access to PROT_READ | PROT_WRITE | PROT_EXEC\n");
if (mprotect(head->memory, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC)) {
printf_log(LOG_NONE, "Cannot protect memory for elf \"%s\"\n", head->name);
// memory protect error not fatal for now....
}
#else
printf_log(LOG_DEBUG, "Allocating 0x%x memory @%p for Elf \"%s\"\n", head->memsz, (void*)head->vaddr, head->name);
void* p = mmap((void*)head->vaddr, head->memsz
, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_ANONYMOUS | ((head->vaddr)?MAP_FIXED:0)
, -1, 0);
if(p==MAP_FAILED) {
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%x/0x%x) for elf \"%s\"\n", (void*)head->vaddr, head->memsz, head->align, head->name);
return 1;
}
head->memory = p;
memset(p, 0, head->memsz);
head->delta = (intptr_t)p - (intptr_t)head->vaddr;
printf_log(LOG_DEBUG, "Got %p (delta=%p)\n", p, (void*)head->delta);
#endif
return 0;
}
void FreeElfMemory(elfheader_t* head)
{
if(head->memory)
munmap((void*)head->memory, head->memsz);
}
int LoadElfMemory(FILE* f, elfheader_t* head)
{
for (int i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
Elf32_Phdr * e = &head->PHEntries[i];
char* dest = (char*)e->p_paddr + head->delta;
printf_log(LOG_DEBUG, "Loading block #%i @%p (0x%x/0x%x)\n", i, dest, e->p_filesz, e->p_memsz);
fseek(f, e->p_offset, SEEK_SET);
if(fread(dest, e->p_filesz, 1, f)!=1) {
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d\n", i);
return 1;
}
// zero'd difference between filesz and memsz
if(e->p_filesz != e->p_memsz)
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
}
}
return 0;
}
int RelocateElfREL(lib_t *maplib, elfheader_t* head, int cnt, Elf32_Rel *rel)
{
for (int i=0; i<cnt; ++i) {
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rel[i].r_info)];
const char* symname = SymName(head, sym);
uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
uintptr_t offs = 0;
uint32_t sz = 0;
uintptr_t end = 0;
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, 0);
uintptr_t globoffs, globend;
int t = ELF32_R_TYPE(rel[i].r_info);
switch(t) {
case R_386_NONE:
// can be ignored
printf_log(LOG_DEBUG, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
break;
case R_386_PC32:
offs = (*p) + (offs - (uintptr_t)p);
printf_log(LOG_DEBUG, "Apply R_386_PC32 @%p with sym=%s (%p -> %p)\n", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
*p += offs;
break;
case R_386_GLOB_DAT:
// Look for same symbol already loaded but not in self
if (GetGlobalSymbolStartEnd(maplib, symname, &globoffs, &globend, 1)) {
offs = globoffs;
end = globend;
}
if (!offs) {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p)\n", symname, p, *(void**)p);
// return -1;
} else {
printf_log(LOG_DEBUG, "Apply R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", p, (void*)(p?(*p):0), (void*)offs, symname);
*p = offs;
}
break;
case R_386_RELATIVE:
printf_log(LOG_DEBUG, "Apply R_386_RELATIVE @%p (%p -> %p)\n", p, *(void**)p, (void*)((*p)+head->delta));
*p += head->delta;
break;
case R_386_32:
if (!offs) {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 @%p (%p)\n", symname, p, *(void**)p);
// return -1;
} else {
printf_log(LOG_DEBUG, "Apply R_386_32 @%p with sym=%s (%p -> %p)\n", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
*p += offs;
}
break;
//case R_386_TLS_DTPMOD32:
// try to use _dl_next_tls_modid() ?
case R_386_TLS_DTPOFF32:
case R_386_JMP_SLOT:
if (!offs) {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
// return -1;
} else {
if(p) {
printf_log(LOG_DEBUG, "Apply R_386_JMP_SLOT @%p with sym=%s (%p -> %p)\n", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
break;
case R_386_COPY:
if(offs) {
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, 1); // get original copy if any
printf_log(LOG_DEBUG, "Apply R_386_COPY @%p with sym=%s, @%p size=%d (", p, symname, (void*)offs, sym->st_size);
memmove(p, (void*)offs, sym->st_size);
if(LOG_DEBUG<=box86_log) {
uint32_t*k = (uint32_t*)p;
for (int i=0; i<sym->st_size; i+=4, ++k)
printf_log(LOG_DEBUG, "%s0x%08X", i?" ":"", *k);
printf_log(LOG_DEBUG, ")\n");
}
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY @%p (%p)\n", symname, p, *(void**)p);
}
break;
default:
printf_log(LOG_INFO, "Warning, don't know of to handle rel #%d %s (%p)\n", i, DumpRelType(ELF32_R_TYPE(rel[i].r_info)), p);
}
}
return 0;
}
int RelocateElfRELA(lib_t *maplib, elfheader_t* head, int cnt, Elf32_Rela *rela)
{
for (int i=0; i<cnt; ++i) {
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rela[i].r_info)];
const char* symname = SymName(head, sym);
uint32_t *p = (uint32_t*)(rela[i].r_offset + head->delta);
uintptr_t offs = 0;
uint32_t sz = 0;
uintptr_t end = 0;
switch(ELF32_R_TYPE(rela[i].r_info)) {
case R_386_NONE:
case R_386_PC32:
// can be ignored
break;
case R_386_COPY:
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end,1);
if(offs) {
// add r_addend to p?
printf_log(LOG_DEBUG, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
memcpy(p, (void*)(offs+rela[i].r_addend), sym->st_size);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY @%p (%p)\n", symname, p, *(void**)p);
}
break;
default:
printf_log(LOG_INFO, "Warning, don't know of to handle rel #%d %s on %s\n", i, DumpRelType(ELF32_R_TYPE(rela[i].r_info)), symname);
}
}
return 0;
}
int RelocateElf(lib_t *maplib, elfheader_t* head)
{
if(head->rel) {
int cnt = head->relsz / head->relent;
DumpRelTable(head, cnt, (Elf32_Rel *)(head->rel + head->delta), "Rel");
printf_log(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name);
if(RelocateElfREL(maplib, head, cnt, (Elf32_Rel *)(head->rel + head->delta)))
return -1;
}
if(head->rela) {
int cnt = head->relasz / head->relaent;
DumpRelATable(head, cnt, (Elf32_Rela *)(head->rela + head->delta), "RelA");
printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
if(RelocateElfRELA(maplib, head, cnt, (Elf32_Rela *)(head->rela + head->delta)))
return -1;
}
return 0;
}
int RelocateElfPlt(box86context_t* context, lib_t *maplib, elfheader_t* head)
{
if(head->pltrel) {
int cnt = head->pltsz / head->pltent;
if(head->pltrel==DT_REL) {
DumpRelTable(head, cnt, (Elf32_Rel *)(head->jmprel + head->delta), "PLT");
printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name);
if(RelocateElfREL(maplib, head, cnt, (Elf32_Rel *)(head->jmprel + head->delta)))
return -1;
} else if(head->pltrel==DT_RELA) {
DumpRelATable(head, cnt, (Elf32_Rela *)(head->jmprel + head->delta), "PLT");
printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name);
if(RelocateElfRELA(maplib, head, cnt, (Elf32_Rela *)(head->jmprel + head->delta)))
return -1;
}
if(head->gotplt) {
if(pltResolver==~0) {
pltResolver = AddBridge(context->system, vFEpp, PltResolver); // should be vFEuu
}
*(uintptr_t*)(head->gotplt+head->delta+8) = pltResolver;
printf_log(LOG_DEBUG, "PLT Resolver injected at %p\n", (void*)(head->gotplt+head->delta+8));
}
}
return 0;
}
void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
{
if(*stacksz < elf->stacksz)
*stacksz = elf->stacksz;
if(*stackalign < elf->stackalign)
*stackalign = elf->stackalign;
}
Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
{
// TODO: create a hash on named to avoid this loop
for (int i=0; i<h->numSymTab; ++i) {
if(h->SymTab[i].st_info == 18) { // TODO: this "18" is probably defined somewhere
const char * symname = h->StrTab+h->SymTab[i].st_name;
if(strcmp(symname, name)==0) {
return h->SymTab+i;
}
}
}
return NULL;
}
uintptr_t GetFunctionAddress(elfheader_t* h, const char* name)
{
Elf32_Sym* sym = GetFunction(h, name);
if(sym) return sym->st_value;
return 0;
}
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
{
uintptr_t ep = h->entrypoint + h->delta;
printf_log(LOG_DEBUG, "Entry Point is %p\n", (void*)ep);
if(box86_log>=LOG_DUMP) {
printf_log(LOG_DUMP, "(short) Dump of Entry point\n");
int sz = 64;
uintptr_t lastbyte = GetLastByte(h);
if (ep + sz > lastbyte)
sz = lastbyte - ep;
DumpBinary((char*)ep, sz);
}
/*
// but instead of regular entrypoint, lets grab "main", it will be easier to manage I guess
uintptr_t m = FindSymbol(maplib, "main");
if(m) {
ep = m;
printf_log(LOG_DEBUG, "Using \"main\" as Entry Point @%p\n", ep);
if(box86_log>=LOG_DUMP) {
printf_log(LOG_DUMP, "(short) Dump of Entry point\n");
int sz = 64;
uintptr_t lastbyte = GetLastByte(h);
if (ep + sz > lastbyte)
sz = lastbyte - ep;
DumpBinary((char*)ep, sz);
}
}
*/
return ep;
}
uintptr_t GetLastByte(elfheader_t* h)
{
return (uintptr_t)h->memory + h->delta + h->memsz;
}
void AddGlobalsSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, elfheader_t* h)
{
// info == 161 => OBJECT UNIQUE
// info == 33 => OBJECT WEAK
printf_log(LOG_DUMP, "Will look for Symbol to add in SymTable(%d)\n", h->numSymTab);
for (int i=0; i<h->numSymTab; ++i) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
if(((h->SymTab[i].st_info & 2) || (h->SymTab[i].st_info == 17)
|| (h->SymTab[i].st_info == 161 && !FindGlobalSymbol(maplib, symname))
|| (h->SymTab[i].st_info == 33)
)
&& (h->SymTab[i].st_other==0) && (h->SymTab[i].st_shndx!=0)) {
if(!h->SymTab[i].st_value && FindGlobalSymbol(maplib, symname))
break;
uintptr_t offs = h->SymTab[i].st_value + h->delta;
uint32_t sz = h->SymTab[i].st_size;
printf_log(LOG_DUMP, "Adding Symbol \"%s\" with offset=%p sz=%d\n", symname, (void*)offs, sz);
AddSymbol(mapsymbols, symname, offs, sz);
}
}
printf_log(LOG_DUMP, "Will look for Symbol to add in DynSym (%d)\n", h->numDynSym);
for (int i=0; i<h->numDynSym; ++i) {
const char * symname = h->DynStr+h->DynSym[i].st_name;
if(((h->DynSym[i].st_info & 2) || (h->DynSym[i].st_info == 17)
|| (h->DynSym[i].st_info == 161 && !FindGlobalSymbol(maplib, symname))
|| (h->DynSym[i].st_info == 33)
)
&& (h->DynSym[i].st_other==0) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<62521)) {
if(!h->DynSym[i].st_value && FindGlobalSymbol(maplib, symname))
break;
uintptr_t offs = h->DynSym[i].st_value + h->delta;
uint32_t sz = h->DynSym[i].st_size;
printf_log(LOG_DUMP, "Adding Symbol \"%s\" with offset=%p sz=%d\n", symname, (void*)offs, sz);
AddSymbol(mapsymbols, symname, offs, sz);
}
}
}
/*
$ORIGIN – Provides the directory the object was loaded from. This token is typical
used for locating dependencies in unbundled packages. For more details of this
token expansion, see “Locating Associated Dependencies”
$OSNAME – Expands to the name of the operating system (see the uname(1) man
page description of the -s option). For more details of this token expansion, see
“System Specific Shared Objects”
$OSREL – Expands to the operating system release level (see the uname(1) man
page description of the -r option). For more details of this token expansion, see
“System Specific Shared Objects”
$PLATFORM – Expands to the processor type of the current machine (see the
uname(1) man page description of the -i option). For more details of this token
expansion, see “System Specific Shared Objects”
*/
int LoadNeededLib(elfheader_t* h, lib_t *maplib, box86context_t *box86, x86emu_t* emu)
{
DumpDynamicNeeded(h);
// reverse order on needed libs
for (int i=h->numDynamic-1; i>=0; --i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
// TODO: Add LD_LIBRARY_PATH and RPATH Handling
if(AddNeededLib(maplib, needed, box86, emu)) {
printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed);
return 1; //error...
}
}
return 0;
}
void RunElfInit(elfheader_t* h, x86emu_t *emu)
{
if(h->init_done || !h->initentry)
return;
uintptr_t p = h->initentry + h->delta;
box86context_t* context = GetEmuContext(emu);
if(context->deferedInit) {
if(context->deferedInitSz==context->deferedInitCap) {
context->deferedInitCap += 4;
context->deferedInitList = (elfheader_t**)realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
}
context->deferedInitList[context->deferedInitSz++] = h;
return;
}
printf_log(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
EmuCall(emu, p);
h->init_done = 1;
return;
}
void RunDeferedElfInit(x86emu_t *emu)
{
box86context_t* context = GetEmuContext(emu);
if(!context->deferedInit)
return;
context->deferedInit = 0;
if(!context->deferedInitList)
return;
for (int i=0; i<context->deferedInitSz; ++i)
RunElfInit(context->deferedInitList[i], emu);
free(context->deferedInitList);
context->deferedInitList = NULL;
context->deferedInitCap = context->deferedInitSz = 0;
}
void RunElfFini(elfheader_t* h, x86emu_t *emu)
{
if(h->fini_done || !h->finientry)
return;
uintptr_t p = h->finientry + h->delta;
printf_log(LOG_DEBUG, "Calling Fini for %s @%p\n", ElfName(h), (void*)p);
EmuCall(emu, p);
h->fini_done = 1;
return;
}
uintptr_t GetElfInit(elfheader_t* h)
{
return h->initentry + h->delta;
}
uintptr_t GetElfFini(elfheader_t* h)
{
return h->finientry + h->delta;
}
-33
View File
@@ -1,33 +0,0 @@
#ifndef __ELF_LOADER_H_
#define __ELF_LOADER_H_
#include <stdio.h>
typedef struct elfheader_s elfheader_t;
typedef struct lib_s lib_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct box86context_s box86context_t;
typedef struct x86emu_s x86emu_t;
void* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
void FreeElfHeader(elfheader_t** head);
const char* ElfName(elfheader_t* head);
// return 0 if OK
int CalcLoadAddr(elfheader_t* head);
int AllocElfMemory(elfheader_t* head);
void FreeElfMemory(elfheader_t* head);
int LoadElfMemory(FILE* f, elfheader_t* head);
int RelocateElf(lib_t *maplib, elfheader_t* head);
int RelocateElfPlt(box86context_t* context, lib_t *maplib, elfheader_t* head);
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddGlobalsSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, elfheader_t* h);
int LoadNeededLib(elfheader_t* h, lib_t *maplib, box86context_t* box86, x86emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
void RunElfInit(elfheader_t* h, x86emu_t *emu);
void RunElfFini(elfheader_t* h, x86emu_t *emu);
void RunDeferedElfInit(x86emu_t *emu);
#endif //__ELF_LOADER_H_
-271
View File
@@ -1,271 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <elf.h>
#include "box86version.h"
#include "elfloader.h"
#include "debug.h"
#include "elfload_dump.h"
#include "elfloader_private.h"
#ifndef PN_XNUM
#define PN_XNUM (0xffff)
#endif
int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t type)
{
if(type && (s->sh_type != type)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type);
return -1;
}
if (type==SHT_SYMTAB && s->sh_size%sizeof(Elf32_Sym)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
}
*SH = calloc(1, s->sh_size);
fseek(f, s->sh_offset ,SEEK_SET);
if(fread(*SH, s->sh_size, 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
return -1;
}
return 0;
}
int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name)
{
for (int i=0; i<n; ++i) {
if(s[i].sh_type!=SHT_NULL)
if(!strcmp(SHStrTab+s[i].sh_name, name))
return i;
}
return 0;
}
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
if(n)
LoadSH(f, s+n, what, name, type);
if(type==SHT_SYMTAB || type==SHT_DYNSYM) {
if(*what && num)
*num = s[n].sh_size / sizeof(Elf32_Sym);
} else if(type==SHT_DYNAMIC) {
if(*what && num)
*num = s[n].sh_size / sizeof(Elf32_Dyn);
}
}
void* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
{
Elf32_Ehdr header;
if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read ELF Header\n");
return NULL;
}
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
printf_log(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]);
return NULL;
}
if(header.e_ident[EI_CLASS]!=ELFCLASS32) {
printf_log(LOG_INFO, "Not an 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
return NULL;
}
if(header.e_ident[EI_DATA]!=ELFDATA2LSB) {
printf_log(LOG_INFO, "Not an LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
return NULL;
}
if(header.e_ident[EI_VERSION]!=EV_CURRENT) {
printf_log(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]);
return NULL;
}
if(header.e_ident[EI_OSABI]!=ELFOSABI_LINUX && header.e_ident[EI_OSABI]!=ELFOSABI_NONE && header.e_ident[EI_OSABI]!=ELFOSABI_SYSV) {
printf_log(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]);
return NULL;
}
if(header.e_type != ET_EXEC && header.e_type != ET_DYN) {
printf_log(LOG_INFO, "Not an Executable (%d)\n", header.e_type);
return NULL;
}
if(header.e_machine != EM_386) {
printf_log(LOG_INFO, "Not an i386 ELF (%d)\n", header.e_machine);
return NULL;
}
if(header.e_entry == 0) {
printf_log(LOG_INFO, "No entry point in ELF\n");
return NULL;
}
if(header.e_phentsize != sizeof(Elf32_Phdr)) {
printf_log(LOG_INFO, "Program Header Entry size incorrect (%d != %d)\n", header.e_phentsize, sizeof(Elf32_Phdr));
return NULL;
}
if(header.e_shentsize != sizeof(Elf32_Shdr)) {
printf_log(LOG_INFO, "Section Header Entry size incorrect (%d != %d)\n", header.e_shentsize, sizeof(Elf32_Shdr));
return NULL;
}
elfheader_t *h = calloc(1, sizeof(elfheader_t));
h->name = strdup(name);
h->entrypoint = header.e_entry;
h->numPHEntries = header.e_phnum;
h->numSHEntries = header.e_shnum;
h->SHIdx = header.e_shstrndx;
// special cases for nums
if(h->numSHEntries == 0) {
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
// read 1st section header and grab actual number from here
fseek(f, header.e_shoff, SEEK_SET);
Elf32_Shdr section;
if(fread(&section, sizeof(Elf32_Shdr), 1, f)!=1) {
free(h);
printf_log(LOG_INFO, "Cannot read Initial Section Header\n");
return NULL;
}
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
h->SHEntries = (Elf32_Shdr*)calloc(h->numSHEntries, sizeof(Elf32_Shdr));
fseek(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Section Header\n");
return NULL;
}
if(h->numPHEntries == PN_XNUM) {
printf_log(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
// read 1st section header and grab actual number from here
h->numPHEntries = h->SHEntries[0].sh_info;
}
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
h->PHEntries = (Elf32_Phdr*)calloc(h->numPHEntries, sizeof(Elf32_Phdr));
fseek(f, header.e_phoff ,SEEK_SET);
if(fread(h->PHEntries, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Program Header\n");
return NULL;
}
if(h->SHIdx == SHN_XINDEX) {
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
h->SHIdx = h->SHEntries[0].sh_link;
}
if(h->SHIdx > h->numSHEntries) {
printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
FreeElfHeader(&h);
return NULL;
}
// load Section table
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
FreeElfHeader(&h);
return NULL;
}
if(box86_log>=LOG_DUMP) DumpMainHeader(&header, h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
if(box86_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
if(box86_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
// grab DT_REL & DT_RELA stuffs
// also grab the DT_STRTAB string table
{
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag == DT_REL)
h->rel = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELSZ)
h->relsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELENT)
h->relent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELA)
h->rela = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELASZ)
h->relasz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELAENT)
h->relaent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTREL)
h->pltrel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
h->pltsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_JMPREL)
h->jmprel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_STRTAB)
h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr);
else if(h->Dynamic[i].d_tag == DT_STRSZ)
h->szDynStrTab = h->Dynamic[i].d_un.d_val;
}
if(h->rel) {
if(h->relent != sizeof(Elf32_Rel)) {
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%x)\n", h->relent, sizeof(Elf32_Rel));
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
}
if(h->rela) {
if(h->relaent != sizeof(Elf32_Rela)) {
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%x)\n", h->relaent, sizeof(Elf32_Rela));
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
}
if(h->jmprel) {
if(h->pltrel == DT_REL) {
h->pltent = sizeof(Elf32_Rel);
} else if(h->pltrel == DT_RELA) {
h->pltent = sizeof(Elf32_Rela);
} else {
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\n", h->pltsz, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
if((h->pltsz / h->pltent)*h->pltent != h->pltsz) {
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%d)\n", h->pltsz, h->pltent, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
}
if(h->DynStrTab && h->szDynStrTab) {
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
}
}
// look for PLT Offset
int ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got.plt");
if(ii) {
h->gotplt = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
if(ii) {
h->got = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The GOT Table is at address %p\n", (void*)h->got);
}
// look for .init entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
if(ii) {
h->initentry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry);
}
// look for .fini entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini");
if(ii) {
h->finientry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
if(box86_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
return h;
}
@@ -183,6 +183,7 @@ const char* DumpRelType(int t)
GO(R_386_GOTOFF);
GO(R_386_GOTPC);
GO(R_386_PC8);
GO(R_386_TLS_TPOFF);
GO(R_386_TLS_GD_32);
GO(R_386_TLS_DTPMOD32);
GO(R_386_TLS_DTPOFF32);
@@ -283,6 +284,22 @@ void DumpDynamicNeeded(elfheader_t *h)
}
}
void DumpDynamicRPath(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->DynStrTab) {
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_RPATH) {
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
}
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
}
}
void DumpRelTable(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name)
{
if(box86_log>=LOG_DUMP) {
+1155
View File
File diff suppressed because it is too large. Load diff
@@ -1,8 +1,18 @@
#ifndef __ELFLOADER_PRIVATE_H_
#define __ELFLOADER_PRIVATE_H_
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
#endif
typedef struct library_s library_t;
typedef struct needed_libs_s needed_libs_t;
#include <pthread.h>
struct elfheader_s {
char* name;
char* path; // Resolved path to file
int numPHEntries;
Elf32_Phdr *PHEntries;
int numSHEntries;
@@ -25,7 +35,11 @@ struct elfheader_s {
uintptr_t entrypoint;
uintptr_t initentry;
uintptr_t initarray;
int initarray_sz;
uintptr_t finientry;
uintptr_t finiarray;
int finiarray_sz;
uintptr_t rel;
int relsz;
@@ -38,7 +52,10 @@ struct elfheader_s {
int pltent;
uint32_t pltrel;
uintptr_t gotplt;
uintptr_t pltgot;
uintptr_t got;
uintptr_t text;
int textsz;
uintptr_t paddr;
uintptr_t vaddr;
@@ -46,11 +63,24 @@ struct elfheader_s {
uint32_t memsz;
uint32_t stacksz;
int stackalign;
uint32_t tlssize;
int tlsalign;
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
int init_done;
int fini_done;
char* memory; // char* and not void* to allow math on memory pointer
void** multiblock;
uintptr_t* multiblock_offs;
uint32_t* multiblock_size;
int multiblock_n;
#ifdef DYNAREC
dynablocklist_t *blocks;
#endif
library_t *lib;
needed_libs_t *neededlibs;
};
#define R_386_NONE 0
@@ -65,4 +95,6 @@ struct elfheader_s {
#define R_386_GOTOFF 9
#define R_386_GOTPC 10
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
#endif //__ELFLOADER_PRIVATE_H_
+303
View File
@@ -0,0 +1,303 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <elf.h>
#include "box86version.h"
#include "elfloader.h"
#include "debug.h"
#include "elfload_dump.h"
#include "elfloader_private.h"
#ifndef PN_XNUM
#define PN_XNUM (0xffff)
#endif
int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t type)
{
if(type && (s->sh_type != type)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type);
return -1;
}
if (type==SHT_SYMTAB && s->sh_size%sizeof(Elf32_Sym)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
}
*SH = calloc(1, s->sh_size);
fseeko64(f, s->sh_offset ,SEEK_SET);
if(fread(*SH, s->sh_size, 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
return -1;
}
return 0;
}
int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name)
{
for (int i=0; i<n; ++i) {
if(s[i].sh_type!=SHT_NULL)
if(!strcmp(SHStrTab+s[i].sh_name, name))
return i;
}
return 0;
}
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
if(n)
LoadSH(f, s+n, what, name, type);
if(type==SHT_SYMTAB || type==SHT_DYNSYM) {
if(*what && num)
*num = s[n].sh_size / sizeof(Elf32_Sym);
} else if(type==SHT_DYNAMIC) {
if(*what && num)
*num = s[n].sh_size / sizeof(Elf32_Dyn);
}
}
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
{
Elf32_Ehdr header;
if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read ELF Header\n");
return NULL;
}
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
printf_log(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]);
return NULL;
}
if(header.e_ident[EI_CLASS]!=ELFCLASS32) {
if(header.e_ident[EI_CLASS]==ELFCLASS64) {
printf_log(LOG_INFO, "This is a 64bits ELF! box86 can only run 32bits ELF!\n");
} else {
printf_log(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
}
return NULL;
}
if(header.e_ident[EI_DATA]!=ELFDATA2LSB) {
printf_log(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
return NULL;
}
if(header.e_ident[EI_VERSION]!=EV_CURRENT) {
printf_log(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]);
return NULL;
}
if(header.e_ident[EI_OSABI]!=ELFOSABI_LINUX && header.e_ident[EI_OSABI]!=ELFOSABI_NONE && header.e_ident[EI_OSABI]!=ELFOSABI_SYSV) {
printf_log(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]);
return NULL;
}
if(header.e_type != ET_EXEC && header.e_type != ET_DYN) {
printf_log(LOG_INFO, "Not an Executable (%d)\n", header.e_type);
return NULL;
}
if(header.e_machine != EM_386) {
printf_log(LOG_INFO, "Not an i386 ELF (%d)\n", header.e_machine);
return NULL;
}
if(header.e_entry == 0 && exec) {
printf_log(LOG_INFO, "No entry point in ELF\n");
return NULL;
}
if(header.e_phentsize != sizeof(Elf32_Phdr)) {
printf_log(LOG_INFO, "Program Header Entry size incorrect (%d != %d)\n", header.e_phentsize, sizeof(Elf32_Phdr));
return NULL;
}
if(header.e_shentsize != sizeof(Elf32_Shdr) && header.e_shentsize != 0) {
printf_log(LOG_INFO, "Section Header Entry size incorrect (%d != %d)\n", header.e_shentsize, sizeof(Elf32_Shdr));
return NULL;
}
elfheader_t *h = calloc(1, sizeof(elfheader_t));
h->name = strdup(name);
h->entrypoint = header.e_entry;
h->numPHEntries = header.e_phnum;
h->numSHEntries = header.e_shnum;
h->SHIdx = header.e_shstrndx;
if(header.e_shentsize!=0) {
// special cases for nums
if(h->numSHEntries == 0) {
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
// read 1st section header and grab actual number from here
fseeko64(f, header.e_shoff, SEEK_SET);
Elf32_Shdr section;
if(fread(&section, sizeof(Elf32_Shdr), 1, f)!=1) {
free(h);
printf_log(LOG_INFO, "Cannot read Initial Section Header\n");
return NULL;
}
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
h->SHEntries = (Elf32_Shdr*)calloc(h->numSHEntries, sizeof(Elf32_Shdr));
fseeko64(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Section Header\n");
return NULL;
}
if(h->numPHEntries == PN_XNUM) {
printf_log(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
// read 1st section header and grab actual number from here
h->numPHEntries = h->SHEntries[0].sh_info;
}
}
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
h->PHEntries = (Elf32_Phdr*)calloc(h->numPHEntries, sizeof(Elf32_Phdr));
fseeko64(f, header.e_phoff ,SEEK_SET);
if(fread(h->PHEntries, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Program Header\n");
return NULL;
}
if(header.e_shentsize!=0) {
if(h->SHIdx == SHN_XINDEX) {
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
h->SHIdx = h->SHEntries[0].sh_link;
}
if(h->SHIdx > h->numSHEntries) {
printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
FreeElfHeader(&h);
return NULL;
}
// load Section table
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
FreeElfHeader(&h);
return NULL;
}
if(box86_log>=LOG_DUMP) DumpMainHeader(&header, h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
if(box86_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
if(box86_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
// grab DT_REL & DT_RELA stuffs
// also grab the DT_STRTAB string table
{
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag == DT_REL)
h->rel = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELSZ)
h->relsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELENT)
h->relent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELA)
h->rela = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELASZ)
h->relasz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELAENT)
h->relaent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTGOT)
h->pltgot = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTREL)
h->pltrel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
h->pltsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_JMPREL)
h->jmprel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_STRTAB)
h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr);
else if(h->Dynamic[i].d_tag == DT_STRSZ)
h->szDynStrTab = h->Dynamic[i].d_un.d_val;
}
if(h->rel) {
if(h->relent != sizeof(Elf32_Rel)) {
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%x)\n", h->relent, sizeof(Elf32_Rel));
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
}
if(h->rela) {
if(h->relaent != sizeof(Elf32_Rela)) {
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%x)\n", h->relaent, sizeof(Elf32_Rela));
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
}
if(h->jmprel) {
if(h->pltrel == DT_REL) {
h->pltent = sizeof(Elf32_Rel);
} else if(h->pltrel == DT_RELA) {
h->pltent = sizeof(Elf32_Rela);
} else {
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\n", h->pltsz, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
if((h->pltsz / h->pltent)*h->pltent != h->pltsz) {
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%d)\n", h->pltsz, h->pltent, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
}
if(h->DynStrTab && h->szDynStrTab) {
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
}
}
// look for PLT Offset
int ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got.plt");
if(ii) {
h->gotplt = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
if(ii) {
h->got = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The GOT Table is at address %p\n", (void*)h->got);
}
// look for .init entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
if(ii) {
h->initentry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry);
}
// and .init_array
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init_array");
if(ii) {
h->initarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf32_Addr);
h->initarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .init_array is at address %p, and have %d elements\n", (void*)h->initarray, h->initarray_sz);
}
// look for .fini entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini");
if(ii) {
h->finientry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry);
}
// and .fini_array
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini_array");
if(ii) {
h->finiarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf32_Addr);
h->finiarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .fini_array is at address %p, and have %d elements\n", (void*)h->finiarray, h->finiarray_sz);
}
// grab .text for main code
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
if(ii) {
h->text = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->textsz = h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
if(box86_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
}
return h;
}
+93
View File
@@ -0,0 +1,93 @@
// ModRM utilities macros
#define getecommon(A, T) \
if(!(nextop&0xC0)) { \
if((nextop&7)==4) { \
uint8_t sib = F8; \
uintptr_t base = ((sib&0x7)==5)?(F32):(emu->regs[(sib&0x7)].dword[0]); \
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
A = (T*)base; \
} else if((nextop&7)==5) { \
A = (T*)(F32); \
} else { \
A = (T*)(emu->regs[nextop&7].dword[0]); \
} \
} else { \
uintptr_t base; \
if((nextop&7)==4) { \
uint8_t sib = F8; \
base = emu->regs[(sib&0x7)].dword[0]; \
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
} else { \
base = emu->regs[(nextop&0x7)].dword[0]; \
} \
base+=(nextop&0x80)?(F32S):(F8S); \
A = (T*)base; \
}
#define getecommono(A, T, O) \
if(!(nextop&0xC0)) { \
if((nextop&7)==4) { \
uint8_t sib = F8; \
uintptr_t base = ((sib&0x7)==5)?(F32):(emu->regs[(sib&0x7)].dword[0]); \
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
A = (T*)(base+O); \
} else if((nextop&7)==5) { \
A = (T*)(F32+O); \
} else { \
A = (T*)(emu->regs[nextop&7].dword[0]+O); \
} \
} else { \
uintptr_t base; \
if((nextop&7)==4) { \
uint8_t sib = F8; \
base = emu->regs[(sib&0x7)].dword[0]; \
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
} else { \
base = emu->regs[(nextop&0x7)].dword[0]; \
} \
base+=(nextop&0x80)?(F32S):(F8S); \
A = (T*)(base+O); \
}
#define geteb(A) \
if((nextop&0xC0)==0xC0) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommon(A, reg32_t)
#define getebo(A, O) \
if((nextop&0xC0)==0xC0) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommono(A, reg32_t, O)
#define geted(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon(A, reg32_t)
#define getedo(A, O) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommono(A, reg32_t, O)
#define getem(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->mmx[(nextop&7)]; \
} else getecommon(A, mmx_regs_t)
#define getex(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->xmm[(nextop&7)]; \
} else getecommon(A, sse_regs_t)
// Macros for ModR/M gets
#define GET_EB geteb(oped)
#define GET_ED geted(oped)
#define GET_ED_OFFS(o) getedo(oped, o)
#define GET_EB_OFFS(o) getebo(oped, o)
#define GET_EM getem(opem)
#define GET_EX getex(opex)
#define EB oped
#define ED oped
#define EM opem
#define EX opex
#define GB emu->regs[(nextop>>3)&3].byte[(nextop>>5)&0x1]
#define GD emu->regs[((nextop&0x38)>>3)]
#define GM emu->mmx[((nextop&0x38)>>3)]
#define GX emu->xmm[((nextop&0x38)>>3)]
// Alias
#define GET_EW GET_ED
#define EW ED
#define GW GD
+1298
View File
File diff suppressed because it is too large. Load diff
+136 -13
View File
@@ -25,11 +25,30 @@
GO(0x30, xor) /* XOR 0x31 ~> 0x35 */
//GO(0x38, cmp) /* CMP 0x39 ~> 0x3D */
#undef GO
_66_0x06: /* PUSH ES */
Push16(emu, emu->segs[_ES]);
NEXT;
_66_0x07: /* POP ES */
emu->segs[_ES] = Pop16(emu); // no check, no use....
emu->segs_clean[_ES] = 0;
NEXT;
_66_0x0F: /* 66 0f prefix */
#include "run660f.h"
_66_0x26: /* ES: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x2E: /* CS: */
// ignored
NEXT;
opcode = F8;
goto *opcodes66[opcode];
_66_0x36: /* SS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x39:
nextop = F8;
GET_EW;
@@ -66,17 +85,67 @@
tmp8u = opcode&7;
emu->regs[tmp8u].word[0] = dec16(emu, emu->regs[tmp8u].word[0]);
NEXT;
_66_0x50:
_66_0x51:
_66_0x52:
_66_0x53:
_66_0x54:
_66_0x55:
_66_0x56:
_66_0x57: /* PUSH Reg */
tmp8u = opcode&7;
Push16(emu, emu->regs[tmp8u].word[0]);
NEXT;
_66_0x58:
_66_0x59:
_66_0x5A:
_66_0x5B:
_66_0x5C:
_66_0x5D:
_66_0x5E:
_66_0x5F: /* POP Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].word[0] = Pop16(emu);
NEXT;
_66_0x60: /* PUSHA */
tmp16u = R_SP;
Push16(emu, R_AX);
Push16(emu, R_CX);
Push16(emu, R_DX);
Push16(emu, R_BX);
Push16(emu, tmp16u);
Push16(emu, R_BP);
Push16(emu, R_SI);
Push16(emu, R_DI);
NEXT;
_66_0x61: /* POPA */
R_DI = Pop16(emu);
R_SI = Pop16(emu);
R_BP = Pop16(emu);
R_ESP+=2; // POP ESP
R_BX = Pop16(emu);
R_DX = Pop16(emu);
R_CX = Pop16(emu);
R_AX = Pop16(emu);
NEXT;
_66_0x66:
goto _0x66; // 0x66 0x66 => can remove one 0x66
_66_0x68: /* PUSH u16 */
tmp16u = F16;
Push16(emu, tmp16u);
NEXT;
_66_0x69: /* IMUL Gw,Ew,Iw */
nextop = F8;
GET_EW;
tmp16u = F16;
GW.word[0] = imul16(emu, EW->word[0], tmp16u);
NEXT;
_66_0x6A: /* PUSH Ib (as signed word) */
tmp16s = F8S;
Push16(emu, (uint16_t)tmp16s);
NEXT;
_66_0x6B: /* IMUL Gw,Ew,Ib */
nextop = F8;
GET_EW;
@@ -131,26 +200,56 @@
GET_EW;
GW.word[0] = EW->word[0];
NEXT;
_66_0x8C: /* MOV Ew,Seg */
nextop = F8;
GET_EW;
EW->word[0] = emu->segs[(nextop&38)>>3];
NEXT;
_66_0x8E: /* MOV Seg,Ew */
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_clean[((nextop&0x38)>>3)] = 0;
NEXT;
_66_0x8F: /* POP Ew */
nextop = F8;
GET_EW;
EW->dword[0] = Pop16(emu);
EW->word[0] = Pop16(emu);
NEXT;
_66_0x90: /* NOP */
NEXT;
_66_0x92: /* XCHG DX,AX */
_66_0x91:
_66_0x92:
_66_0x93:
_66_0x94:
_66_0x95:
_66_0x96:
_66_0x97: /* XCHG reg,EAX */
tmp16u = R_AX;
R_AX = R_DX;
R_DX = tmp16u;
R_AX = emu->regs[opcode&7].word[0];
emu->regs[opcode&7].word[0] = tmp16u;
NEXT;
_66_0x98: /* CBW */
emu->regs[_AX].sword[0] = emu->regs[_AX].sbyte[0];
NEXT;
_66_0x99: /* CWD */
R_DX=(R_AX & 0x8000)?0xFFFF:0x0000;
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
NEXT;
_66_0x9C: /* PUSHFW */
CHECK_FLAGS(emu);
PackFlags(emu);
Push16(emu, (uint16_t)emu->packed_eflags.x32);
NEXT;
_66_0x9D: /* POPFW */
CHECK_FLAGS(emu);
PackFlags(emu);
emu->packed_eflags.x32 &=0xffff0000;
emu->packed_eflags.x32 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
UnpackFlags(emu);
NEXT;
_66_0xA1: /* MOV AX,Ow */
@@ -174,6 +273,11 @@
R_ESI += tmp8s;
cmp16(emu, tmp16u2, tmp16u);
NEXT;
_66_0xA9: /* TEST AX,Iw */
test16(emu, R_AX, F16);
NEXT;
_66_0xAB: /* STOSW */
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
*(uint16_t*)R_EDI = R_AX;
@@ -241,7 +345,7 @@
NEXT;
_66_0xD9:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
Run66D9(emu);
ip = R_EIP;
@@ -249,7 +353,7 @@
NEXT;
_66_0xDD:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
Run66DD(emu);
ip = R_EIP;
@@ -263,6 +367,14 @@
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp32u = R_ECX;
switch(nextop) {
case 0xA4: /* REP MOVSB */
while(tmp32u) {
--tmp32u;
*(uint8_t*)R_EDI = *(uint8_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
}
break;
case 0xA5: /* REP MOVSW */
while(tmp32u) {
--tmp32u;
@@ -272,6 +384,8 @@
}
break;
case 0xA7: /* REP(N)Z CMPSW */
tmp16u = 0;
tmp16u2 = 0;
while(tmp32u) {
--tmp32u;
tmp16u = *(uint16_t*)R_EDI;
@@ -298,6 +412,7 @@
}
break;
case 0xAF: /* REP(N)Z SCASW */
tmp16u = 0;
while(tmp32u) {
--tmp32u;
tmp16u = *(uint16_t*)R_EDI;
@@ -341,6 +456,14 @@
break;
}
NEXT;
_66_0xF8: /* CLC */
CHECK_FLAGS(emu);
CLEAR_FLAG(F_CF);
NEXT;
_66_0xF9: /* STC */
CHECK_FLAGS(emu);
SET_FLAG(F_CF);
NEXT;
_66_0xFF: /* GRP 5 Ew */
nextop = F8;
@@ -352,8 +475,11 @@
case 1: /* DEC Ed */
EW->word[0] = dec16(emu, EW->word[0]);
break;
case 6:
Push16(emu, EW->word[0]);
break;
default:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 66 %02X %02X\n", opcode, nextop);
emu->quit=1;
@@ -361,6 +487,3 @@
goto fini;
}
NEXT;
+335 -58
View File
@@ -101,7 +101,16 @@
GET_EX;
memcpy(EX, &GX, 16); // unaligned...
NEXT;
_6f_0x12: /* MOVLPD Gx, Eq */
nextop = F8;
GET_ED;
GX.q[0] = *(uint64_t*)ED;
NEXT;
_6f_0x13: /* MOVLPD Eq, Gx */
nextop = F8;
GET_ED;
*(uint64_t*)ED = GX.q[0];
NEXT;
_6f_0x14: /* UNPCKLPD Gx, Ex */
nextop = F8;
GET_EX;
@@ -150,12 +159,33 @@
_6f_0x2C: /* CVTTPD2PI Gm, Ex */
_6f_0x2D: /* CVTPD2PI Gm, Ex */
nextop = F8;
GET_EX;
GM.sd[0] = EX->d[0];
GM.sd[1] = EX->d[1];
NEXT;
_6f_0x2D: /* CVTPD2PI Gm, Ex */
nextop = F8;
GET_EX;
switch(emu->round) {
case ROUND_Nearest:
GM.sd[0] = floor(EX->d[0]+0.5);
GM.sd[1] = floor(EX->d[1]+0.5);
break;
case ROUND_Down:
GM.sd[0] = floor(EX->d[0]);
GM.sd[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GM.sd[0] = ceil(EX->d[0]);
GM.sd[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GM.sd[0] = EX->d[0];
GM.sd[1] = EX->d[1];
break;
}
NEXT;
_6f_0x2E: /* UCOMISD Gx, Ex */
// no special check...
_6f_0x2F: /* COMISD Gx, Ex */
@@ -171,6 +201,69 @@
} else {
SET_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
}
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
NEXT;
_6f_0x38: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x00: /* PSHUFB */
nextop = F8;
GET_EX;
eax1 = GX;
for (int i=0; i<15; ++i) {
if(EX->ub[i]&128)
GX.ub[i] = 0;
else
GX.ub[i] = eax1.ub[EX->ub[i]&15];
}
break;
case 0x04: /* PMADDUBSW Gx,Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
tmp32s = (int32_t)(GX.ub[i*2+0])*EX->ub[i*2+0] + (int32_t)(GX.ub[i*2+1])*EX->ub[i*2+1];
GX.sw[i] = (tmp32s>32767)?32767:tmp32s; // no negative value to test
}
break;
default:
goto _default;
}
NEXT;
_6f_0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F: // PALIGNR
nextop = F8;
GET_EX;
tmp8u = F8;
if(tmp8u>31)
{EX->q[0] = EX->q[1] = 0;}
else if(tmp8u>15) {
tmp8u=(tmp8u-16)*8;
if (tmp8u < 64) {
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
GX.q[1] = (EX->q[1] >> tmp8u);
} else {
GX.q[0] = EX->q[1] >> (tmp8u - 64);
GX.q[1] = 0;
}
} else {
tmp8u*=8;
if (tmp8u < 64) {
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
GX.q[1] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64-tmp8u));
} else {
tmp8u -= 64;
GX.q[0] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64 - tmp8u));
GX.q[1] = (EX->q[0] >> tmp8u) | (EX->q[1] >> (64 - tmp8u));
}
}
break;
default:
goto _default;
}
NEXT;
_6f_0x50: /* MOVMSKPD Gd, Ex */
@@ -290,36 +383,44 @@
GX.ud[2] = GX.ud[1];
GX.ud[1] = EX->ud[0];
NEXT;
_6f_0x63: /* PACKSSWB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
NEXT;
_6f_0x64: /* PCMPGTB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
GX.sb[i] = (GX.sb[i]>EX->sb[i])?0xFF:0x00;
GX.ub[i] = (GX.sb[i]>EX->sb[i])?0xFF:0x00;
NEXT;
_6f_0x65: /* PCMPGTW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.sw[i] = (GX.sw[i]>EX->sw[i])?0xFFFF:0x0000;
GX.uw[i] = (GX.sw[i]>EX->sw[i])?0xFFFF:0x0000;
NEXT;
_6f_0x66: /* PCMPGTD Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
GX.sd[i] = (GX.sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000;
GX.ud[i] = (GX.sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000;
NEXT;
_6f_0x67: /* PACKUSWB */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
for(int i=0; i<8; ++i)
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
for(int i=0; i<4; ++i)
GX.ub[4+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
for(int i=0; i<8; ++i)
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
NEXT;
_6f_0x68: /* PUNPCKHBW Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
for(int i=0; i<8; ++i)
GX.ub[2 * i] = GX.ub[i + 8];
for(int i=0; i<8; ++i)
@@ -328,6 +429,7 @@
_6f_0x69: /* PUNPCKHWD Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
for(int i=0; i<4; ++i)
GX.uw[2 * i] = GX.uw[i + 4];
for(int i=0; i<4; ++i)
@@ -336,6 +438,7 @@
_6f_0x6A: /* PUNPCKHDQ Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
GX.ud[0] = GX.ud[2];
GX.ud[2] = GX.ud[3];
GX.ud[1] = EX->ud[2];
@@ -344,6 +447,7 @@
_6f_0x6B: /* PACKSSDW Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
for(int i=0; i<4; ++i)
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
for(int i=0; i<4; ++i)
@@ -376,31 +480,26 @@
nextop = F8;
GET_EX;
tmp8u = F8;
if(&GX!=EX)
for (int i=0; i<4; ++i)
GX.ud[i] = EX->ud[(tmp8u>>(i*2))&3];
else {
for (int i=0; i<4; ++i)
eax1.ud[i] = EX->ud[(tmp8u>>(i*2))&3];
memcpy(&GX, &eax1, sizeof(eax1));
}
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
for (int i=0; i<4; ++i)
GX.ud[i] = EX->ud[(tmp8u>>(i*2))&3];
NEXT;
_6f_0x71: /* GRP */
nextop = F8;
GET_EX;
switch((nextop>>3)&7) {
case 2: /* PSRLW Gx, Ib */
case 2: /* PSRLW Ex, Ib */
tmp8u = F8;
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else
for (int i=0; i<8; ++i) EX->uw[i] >>= tmp8u;
break;
case 4: /* PSRAW Gx, Ib */
case 4: /* PSRAW Ex, Ib */
tmp8u = F8;
for (int i=0; i<8; ++i) EX->sw[i] >>= tmp8u;
break;
case 6: /* PSLLW Gx, Ib */
case 6: /* PSLLW Ex, Ib */
tmp8u = F8;
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
@@ -453,10 +552,14 @@
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else {
for (int i=tmp8u; i<16; ++i)
EX->ub[i-tmp8u] = EX->ub[i];
for (int i=16-tmp8u; i<16; ++i)
EX->ub[i] = 0;
tmp8u*=8;
if (tmp8u < 64) {
EX->q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
EX->q[1] = (EX->q[1] >> tmp8u);
} else {
EX->q[0] = EX->q[1] >> (tmp8u - 64);
EX->q[1] = 0;
}
}
break;
case 6: /* PSLLQ Ex, Ib */
@@ -471,10 +574,14 @@
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else {
for (int i=16-tmp8u; i>=0; --i)
EX->ub[i+tmp8u] = EX->ub[i];
for (int i=0; i<tmp8u; ++i)
EX->ub[i] = 0;
tmp8u*=8;
if (tmp8u < 64) {
EX->q[1] = (EX->q[1] << tmp8u) | (EX->q[0] >> (64 - tmp8u));
EX->q[0] = (EX->q[0] << tmp8u);
} else {
EX->q[1] = EX->q[0] << (tmp8u - 64);
EX->q[0] = 0;
}
}
break;
default:
@@ -582,6 +689,43 @@
GW.word[0] = EB->byte[0];
NEXT;
_6f_0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ew,Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
break;
case 6: /* BTR Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(ED))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
break;
default:
goto _default;
}
NEXT;
_6f_0xBB: /* BTC Ew,Gw */
CHECK_FLAGS(emu);
nextop = F8;
@@ -655,15 +799,15 @@
_6f_0xC4: /* PINSRW Gx,Ew,Ib */
nextop = F8;
GET_EW;
GET_ED;
tmp8u = F8;
GX.uw[tmp8u&7] = EW->word[0];
GX.uw[tmp8u&7] = ED->word[0]; // only low 16bits
NEXT;
_6f_0xC5: /* PEXTRW Gw,Ex,Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
GW.word[0] = EX->uw[tmp8u&7];
GD.dword[0] = EX->uw[tmp8u&7]; // 16bits extract, 0 extended
NEXT;
_6f_0xC6: /* SHUFPD Gx, Ex, Ib */
nextop = F8;
@@ -681,7 +825,7 @@
if(EX->q[0]>15)
{GX.q[0] = GX.q[1] = 0;}
else
{tmp8u=EX->q[0]; for (int i=0; i<8; ++i) GX.uw[i] >>= tmp8u;}
{tmp8u=EX->ub[0]; for (int i=0; i<8; ++i) GX.uw[i] >>= tmp8u;}
NEXT;
_6f_0xD2: /* PSRLD Gx, Ex */
nextop = F8;
@@ -689,7 +833,7 @@
if(EX->q[0]>31)
{GX.q[0] = GX.q[1] = 0;}
else
{tmp8u=EX->q[0]; for (int i=0; i<4; ++i) GX.ud[i] >>= tmp8u;}
{tmp8u=EX->ub[0]; for (int i=0; i<4; ++i) GX.ud[i] >>= tmp8u;}
NEXT;
_6f_0xD3: /* PSRLQ Gx, Ex */
nextop = F8;
@@ -697,15 +841,22 @@
if(EX->q[0]>63)
{GX.q[0] = GX.q[1] = 0;}
else
{tmp8u=EX->q[0]; for (int i=0; i<2; ++i) GX.q[i] >>= tmp8u;}
{tmp8u=EX->ub[0]; for (int i=0; i<2; ++i) GX.q[i] >>= tmp8u;}
NEXT;
_6f_0xD4: /* PADDQ Gx,Ex */
nextop = F8;
GET_EX;
GX.q[0] += EX->q[0];
GX.q[1] += EX->q[1];
GX.sq[0] += EX->sq[0];
GX.sq[1] += EX->sq[1];
NEXT;
_6f_0xD5: /* PMULLW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.sw[i] * EX->sw[i];
GX.sw[i] = tmp32s;
}
NEXT;
_6f_0xD6: /* MOVQ Ex,Gx */
nextop = F8;
GET_EX;
@@ -713,6 +864,30 @@
if((nextop&0xC0)==0xC0)
EX->q[1] = 0;
NEXT;
_6f_0xD7: /* PMOVMSKB Gd,Ex */
nextop = F8;
GET_EX;
GD.dword[0] = 0;
for (int i=0; i<16; ++i)
if(EX->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
_6f_0xD8: /* PSUBUSB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.ub[i] - EX->ub[i];
GX.ub[i] = (tmp16s<0)?0:((tmp16s>255)?255:tmp16s);
}
NEXT;
_6f_0xD9: /* PSUBUSW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.uw[i] - EX->uw[i];
GX.uw[i] = (tmp32s<0)?0:((tmp32s>0xffff)?0xffff:tmp32s);
}
NEXT;
_6f_0xDB: /* PAND Gx,Ex */
nextop = F8;
@@ -720,26 +895,58 @@
GX.q[0] &= EX->q[0];
GX.q[1] &= EX->q[1];
NEXT;
_6f_0xDC: /* PADDUSB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.ub[i] + EX->ub[i];
GX.ub[i] = (tmp16s>255)?255:tmp16s;
}
NEXT;
_6f_0xDE: /* PMAXUB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i)
if(EX->ub[i]>GX.ub[i]) GX.ub[i] = EX->ub[i];
NEXT;
_6f_0xDF: /* PANDN Gx,Ex */
nextop = F8;
GET_EX;
GX.q[0] = (~GX.q[0]) & EX->q[0];
GX.q[1] = (~GX.q[1]) & EX->q[1];
NEXT;
_6f_0xE0: /* PAVGB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i) GX.ub[i] = ((uint16_t)GX.ub[i] + EX->ub[i] + 1)>>1;
NEXT;
_6f_0xE1: /* PSRAW Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=EX->q[0];
tmp8u=(EX->q[0]>15)?16:EX->ub[0];
for (int i=0; i<8; ++i) GX.sw[i] >>= tmp8u;
NEXT;
_6f_0xE2: /* PSRAD Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=EX->q[0]; for (int i=0; i<4; ++i) GX.sd[i] >>= tmp8u;
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
for (int i=0; i<4; ++i) GX.sd[i] >>= tmp8u;
NEXT;
_6f_0xE3: /* PAVGW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) GX.uw[i] = ((uint16_t)GX.uw[i] + EX->uw[i] + 1)>>1;
NEXT;
_6f_0xE5: /* PMULHW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.sw[i] * EX->sw[i];
GX.uw[i] = (tmp32s>>16)&0xffff;
}
NEXT;
_6f_0xE6: /* CVTTPD2DQ Gx, Ex */
nextop = F8;
GET_EX;
@@ -747,7 +954,34 @@
GX.sd[1] = EX->d[1];
GX.q[1] = 0;
NEXT;
_6f_0xE7: /* MOVNTDQ Ex, Gx */
nextop = F8;
GET_EX;
EX->q[0] = GX.q[0];
EX->q[1] = GX.q[1];
NEXT;
_6f_0xE8: /* PSUBSB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.sb[i] - EX->sb[i];
GX.ub[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
}
NEXT;
_6f_0xE9: /* PSUBSW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.sw[i] - EX->sw[i];
GX.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
NEXT;
_6f_0xEA: /* PMINSW Gx,Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i)
GX.sw[i] = (GX.sw[i]<EX->sw[i])?GX.sw[i]:EX->sw[i];
NEXT;
_6f_0xEB: /* POR Gx,Ex */
nextop = F8;
GET_EX;
@@ -760,7 +994,7 @@
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = GX.sb[i] + EX->sb[i];
tmp16s = (int16_t)GX.sb[i] + EX->sb[i];
GX.sb[i] = (tmp16s>127)?127:((tmp16s<-128)?-128:tmp16s);
}
NEXT;
@@ -768,7 +1002,7 @@
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = GX.sw[i] + EX->sw[i];
tmp32s = (int32_t)GX.sw[i] + EX->sw[i];
GX.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
NEXT;
@@ -793,7 +1027,7 @@
if(EX->q[0]>15)
{GX.q[0] = GX.q[1] = 0;}
else
{tmp8u=EX->q[0]; for (int i=0; i<8; ++i) GX.uw[i] <<= tmp8u;}
{tmp8u=EX->ub[0]; for (int i=0; i<8; ++i) GX.uw[i] <<= tmp8u;}
NEXT;
_6f_0xF2: /* PSLLD Gx, Ex */
nextop = F8;
@@ -801,7 +1035,7 @@
if(EX->q[0]>31)
{GX.q[0] = GX.q[1] = 0;}
else
{tmp8u=EX->q[0]; for (int i=0; i<4; ++i) GX.ud[i] <<= tmp8u;}
{tmp8u=EX->ub[0]; for (int i=0; i<4; ++i) GX.ud[i] <<= tmp8u;}
NEXT;
_6f_0xF3: /* PSLLQ Gx, Ex */
nextop = F8;
@@ -817,35 +1051,78 @@
GX.q[1] = (uint64_t)EX->ud[2]*GX.ud[2];
GX.q[0] = (uint64_t)EX->ud[0]*GX.ud[0];
NEXT;
_6f_0xF5: /* PMADDWD Gx,Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sd[i] = (int32_t)(GX.sw[i*2+0])*EX->sw[i*2+0] + (int32_t)(GX.sw[i*2+1])*EX->sw[i*2+1];
NEXT;
_6f_0xF6: /* PSADBW Gx, Ex */
nextop = F8;
GET_EX;
tmp32u = 0;
for (int i=0; i<8; ++i)
tmp32u += (GX.ub[i]>EX->ub[i])?(GX.ub[i] - EX->ub[i]):(EX->ub[i] - GX.ub[i]);
GX.q[0] = tmp32u;
tmp32u = 0;
for (int i=8; i<16; ++i)
tmp32u += (GX.ub[i]>EX->ub[i])?(GX.ub[i] - EX->ub[i]):(EX->ub[i] - GX.ub[i]);
GX.q[1] = tmp32u;
NEXT;
_6f_0xF7: /* MASKMOVDQU Gx, Ex */
nextop = F8;
GET_EX;
opx2 = (sse_regs_t *)(R_EDI);
for (int i=0; i<16; ++i) {
if(EX->ub[i]&0x80)
opx2->ub[i] = GX.ub[i];
}
NEXT;
_6f_0xF8: /* PSUBB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
GX.ub[i] -= EX->ub[i];
NEXT;
_6f_0xF9: /* PSUBW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.uw[i] -= EX->uw[i];
NEXT;
_6f_0xFA: /* PSUBD Gx,Ex */
nextop = F8;
GET_EX;
GX.ud[0] -= EX->ud[0];
GX.ud[1] -= EX->ud[1];
GX.ud[2] -= EX->ud[2];
GX.ud[3] -= EX->ud[3];
GX.sd[0] -= EX->sd[0];
GX.sd[1] -= EX->sd[1];
GX.sd[2] -= EX->sd[2];
GX.sd[3] -= EX->sd[3];
NEXT;
_6f_0xFB: /* PSUBQ Gx,Ex */
nextop = F8;
GET_EX;
GX.q[0] -= EX->q[0];
GX.q[1] -= EX->q[1];
GX.sq[0] -= EX->sq[0];
GX.sq[1] -= EX->sq[1];
NEXT;
_6f_0xFC: /* PADDB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
GX.ub[i] += EX->ub[i];
GX.sb[i] += EX->sb[i];
NEXT;
_6f_0xFD: /* PADDW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.sw[i] += EX->sw[i];
NEXT;
_6f_0xFE: /* PADDD Gx,Ex */
nextop = F8;
GET_EX;
GX.ud[0] += EX->ud[0];
GX.ud[1] += EX->ud[1];
GX.ud[2] += EX->ud[2];
GX.ud[3] += EX->ud[3];
GX.sd[0] += EX->sd[0];
GX.sd[1] += EX->sd[1];
GX.sd[2] += EX->sd[2];
GX.sd[3] += EX->sd[3];
NEXT;
+83
View File
@@ -1,3 +1,5 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch(nextop) {
case 0xC0:
@@ -8,7 +10,11 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
#ifdef USE_FLOAT
ST0.f += ST(nextop&7).f;
#else
ST0.d += ST(nextop&7).d;
#endif
break;
case 0xC8:
case 0xC9:
@@ -18,7 +24,11 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
#ifdef USE_FLOAT
ST0.f *= ST(nextop&7).f;
#else
ST0.d *= ST(nextop&7).d;
#endif
break;
case 0xD0:
case 0xD1:
@@ -28,7 +38,11 @@
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
break;
case 0xD8:
case 0xD9:
@@ -38,7 +52,11 @@
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
fpu_do_pop(emu);
break;
case 0xE0:
@@ -49,7 +67,11 @@
case 0xE5:
case 0xE6:
case 0xE7: /* FSUB */
#ifdef USE_FLOAT
ST0.f -= ST(nextop&7).f;
#else
ST0.d -= ST(nextop&7).d;
#endif
break;
case 0xE8:
case 0xE9:
@@ -59,7 +81,11 @@
case 0xED:
case 0xEE:
case 0xEF: /* FSUBR */
#ifdef USE_FLOAT
ST0.f = ST(nextop&7).f - ST0.f;
#else
ST0.d = ST(nextop&7).d - ST0.d;
#endif
break;
case 0xF0:
case 0xF1:
@@ -69,7 +95,11 @@
case 0xF5:
case 0xF6:
case 0xF7: /* FDIV */
#ifdef USE_FLOAT
ST0.f /= ST(nextop&7).f;
#else
ST0.d /= ST(nextop&7).d;
#endif
break;
case 0xF8:
case 0xF9:
@@ -79,26 +109,46 @@
case 0xFD:
case 0xFE:
case 0xFF: /* FDIVR */
#ifdef USE_FLOAT
ST0.f = ST(nextop&7).f / ST0.f;
#else
ST0.d = ST(nextop&7).d / ST0.d;
#endif
break;
default:
switch((nextop>>3)&7) {
case 0: /* FADD ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f += *(float*)ED;
#else
ST0.d += *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f += f;
#else
ST0.d += f;
#endif
}
break;
case 1: /* FMUL ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f *= *(float*)ED;
#else
ST0.d *= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f *= f;
#else
ST0.d *= f;
#endif
}
break;
case 2: /* FCOM ST0, float */
@@ -123,40 +173,73 @@
case 4: /* FSUB ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f -= *(float*)ED;
#else
ST0.d -= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f -= f;
#else
ST0.d -= f;
#endif
}
break;
case 5: /* FSUBR ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f = *(float*)ED - ST0.f;
#else
ST0.d = *(float*)ED - ST0.d;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f = f - ST0.f;
#else
ST0.d = f - ST0.d;
#endif
}
break;
case 6: /* FDIV ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f /= *(float*)ED;
#else
ST0.d /= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f /= f;
#else
ST0.d /= f;
#endif
}
break;
case 7: /* FDIVR ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f = *(float*)ED / ST0.f;
#else
ST0.d = *(float*)ED / ST0.d;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f = f / ST0.f;
#else
ST0.d = f / ST0.d;
#endif
}
break;
default:
goto _default;
}
}
#pragma GCC diagnostic pop
+362
View File
@@ -0,0 +1,362 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch (nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7: /* FLD STx */
ll = ST(nextop&7).ll;
fpu_do_push(emu);
ST0.ll = ll;
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* FXCH STx */
ll = ST(nextop&7).ll;
ST(nextop&7).ll = ST0.ll;
ST0.ll = ll;
break;
case 0xD0: /* FNOP */
break;
case 0xE0: /* FCHS */
#ifdef USE_FLOAT
ST0.f = -ST0.f;
#else
ST0.d = -ST0.d;
#endif
break;
case 0xE1: /* FABS */
#ifdef USE_FLOAT
ST0.f = fabsf(ST0.f);
#else
ST0.d = fabs(ST0.d);
#endif
break;
case 0xE4: /* FTST */
fpu_ftst(emu);
break;
case 0xE5: /* FXAM */
fpu_fxam(emu);
break;
case 0xE8: /* FLD1 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = 1.0f;
#else
ST0.d = 1.0;
#endif
break;
case 0xE9: /* FLDL2T */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = L2T;
#else
ST0.d = L2T;
#endif
break;
case 0xEA: /* FLDL2E */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = L2E;
#else
ST0.d = L2E;
#endif
break;
case 0xEB: /* FLDPI */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = PI;
#else
ST0.d = PI;
#endif
break;
case 0xEC: /* FLDLG2 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = LG2;
#else
ST0.d = LG2;
#endif
break;
case 0xED: /* FLDLN2 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = LN2;
#else
ST0.d = LN2;
#endif
break;
case 0xEE: /* FLDZ */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = 0.0f;
#else
ST0.d = 0.0;
#endif
break;
case 0xF0: /* F2XM1 */
#ifdef USE_FLOAT
ST0.f = exp2f(ST0.f) - 1.0f;
#else
ST0.d = exp2(ST0.d) - 1.0;
#endif
break;
case 0xF1: /* FYL2X */
#ifdef USE_FLOAT
ST(1).f = log2f(ST0.f)*ST(1).f;
#else
ST(1).d = log2(ST0.d)*ST(1).d;
#endif
fpu_do_pop(emu);
break;
case 0xF2: /* FPTAN */
#ifdef USE_FLOAT
ST0.f = tanf(ST0.f);
fpu_do_push(emu);
ST0.f = 1.0f;
#else
ST0.d = tan(ST0.d);
fpu_do_push(emu);
ST0.d = 1.0;
#endif
emu->sw.f.F87_C2 = 0;
break;
case 0xF3: /* FPATAN */
#ifdef USE_FLOAT
ST1.f = atan2f(ST1.f, ST0.f);
#else
ST1.d = atan2(ST1.d, ST0.d);
#endif
fpu_do_pop(emu);
break;
case 0xF4: /* FXTRACT */
#ifdef USE_FLOAT
tmp32s = (ST0.ll&0x7f700000)>>23;
tmp32s -= 127;
ST0.f /= exp2f(tmp32s);
fpu_do_push(emu);
ST0.f = tmp32s;
#else
tmp32s = (ST0.ll&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST0.d /= exp2(tmp32s);
fpu_do_push(emu);
ST0.d = tmp32s;
#endif
break;
case 0xF8: /* FPREM */
#ifdef USE_FLOAT
ll = ST0.f / ST1.f;
ST0.f -= ST1.f * ll;
#else
ll = ST0.d / ST1.d;
ST0.d -= ST1.d * ll;
#endif
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (ll&1);
emu->sw.f.F87_C3 = ((ll>>1)&1);
emu->sw.f.F87_C1 = ((ll>>2)&1);
break;
case 0xF5: /* FPREM1 */
// get exponant(ST(0))-exponant(ST(1)) in temp32s
#ifdef USE_FLOAT
tmp32s = ((ST0.ll&0x7f700000)>>23) - ((ST1.ll&0x7f700000)>>23);
#else
tmp32s = ((ST0.ll&0x7ff0000000000000LL)>>52) - ((ST1.ll&0x7ff0000000000000LL)>>52);
#endif
if(tmp32s<64)
{
#ifdef USE_FLOAT
ll = (int64_t)round(ST0.f/ST1.f);
ST0.f = ST0.f - (ST1.f*ll);
#else
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
#endif
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
#ifdef USE_FLOAT
ll = (int64_t)(floor((ST0.f/ST1.f))/powf(2, tmp32s - 32));
ST0.f = ST0.f - ST1.f*ll*powf(2, 32);
#else
ll = (int64_t)(floor((ST0.d/ST1.d))/pow(2, tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*pow(2, tmp32s - 32);
#endif
emu->sw.f.F87_C2 = 1;
}
break;
case 0xF6: /* FDECSTP */
emu->top=(emu->top-1)&7; // this will probably break a few things
break;
case 0xF7: /* FINCSTP */
emu->top=(emu->top+1)&7; // this will probably break a few things
break;
case 0xF9: /* FYL2XP1 */
#ifdef USE_FLOAT
ST(1).f = log2f(ST0.f + 1.0f)*ST(1).f;
#else
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
#endif
fpu_do_pop(emu);
break;
case 0xFA: /* FSQRT */
#ifdef USE_FLOAT
ST0.f = sqrtf(ST0.f);
#else
ST0.d = sqrt(ST0.d);
#endif
break;
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
#ifdef USE_FLOAT
sincosf(ST1.f, &ST1.f, &ST0.f);
#else
sincos(ST1.d, &ST1.d, &ST0.d);
#endif
break;
case 0xFC: /* FRNDINT */
#ifdef USE_FLOAT
ST0.f = fpu_round(emu, ST0.f);
#else
ST0.d = fpu_round(emu, ST0.d);
#endif
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
#ifdef USE_FLOAT
ST0.f *= exp2f(truncf(ST1.f));
#else
ST0.d *= exp2(trunc(ST1.d));
#endif
break;
case 0xFE: /* FSIN */
#ifdef USE_FLOAT
ST0.f = sinf(ST0.f);
#else
ST0.d = sin(ST0.d);
#endif
break;
case 0xFF: /* FCOS */
#ifdef USE_FLOAT
ST0.f = cosf(ST0.f);
#else
ST0.d = cos(ST0.d);
#endif
break;
case 0xD1:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE2:
case 0xE3:
case 0xE6:
case 0xE7:
case 0xEF:
goto _default;
default:
switch((nextop>>3)&7) {
case 0: /* FLD ST0, Ed float */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.ll = ED->dword[0];
#else
if(!(((uintptr_t)ED)&3))
ST0.d = *(float*)ED;
else {
memcpy(&f, ED->dword, sizeof(float));
ST0.d = f;
}
#endif
break;
case 2: /* FST Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
*(float*)ED = ST0.f;
#else
if(!(((uintptr_t)ED)&3))
*(float*)ED = ST0.d;
else {
f = ST0.d;
memcpy(ED->dword, &f, sizeof(float));
}
#endif
break;
case 3: /* FSTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
ED->dword[0] = ST0.ll;
#else
if(!(((uintptr_t)ED)&3))
*(float*)ED = ST0.d;
else {
f = ST0.d;
memcpy(ED->dword, &f, sizeof(float));
}
#endif
fpu_do_pop(emu);
break;
case 4: /* FLDENV m */
// warning, incomplete
GET_ED;
fpu_loadenv(emu, (char*)ED, 0);
break;
case 5: /* FLDCW Ew */
GET_EW;
emu->cw = EW->word[0];
// do something with cw?
emu->round = (fpu_round_t)((emu->cw >> 10) & 3);
break;
case 6: /* FNSTENV m */
// warning, incomplete
GET_ED;
fpu_savenv(emu, (char*)ED, 0);
ED->dword[0] = emu->cw;
ED->dword[1] = emu->sw.x16;
// tagword: 2bits*8
ED->word[4] = 0;
for (int i=0; i<8; ++i)
ED->word[4] |= (emu->p_regs[i].tag)<<(i*2);
// intruction pointer: 48bits
// data (operand) pointer: 48bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
break;
case 7: /* FNSTCW Ew */
GET_EW;
EW->word[0] = emu->cw;
break;
default:
goto _default;
}
}
#pragma GCC diagnostic pop
+41 -2
View File
@@ -51,7 +51,11 @@
break;
case 0xE9: /* FUCOMPP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST1.f);
#else
fpu_fcom(emu, ST1.d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
@@ -72,25 +76,60 @@
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f += ED->sdword[0];
#else
ST0.d += ED->sdword[0];
#endif
break;
case 1: /* FIMUL ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f *= ED->sdword[0];
#else
ST0.d *= ED->sdword[0];
#endif
break;
case 2: /* FICOM ST0, Ed int */
GET_ED;
fpu_fcom(emu, ED->sdword[0]);
break;
case 3: /* FICOMP ST0, Ed int */
GET_ED;
fpu_fcom(emu, ED->sdword[0]);
fpu_do_pop(emu);
break;
case 4: /* FISUB ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f -= ED->sdword[0];
#else
ST0.d -= ED->sdword[0];
#endif
break;
case 5: /* FISUBR ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f = ED->sdword[0] - ST0.f;
#else
ST0.d = ED->sdword[0] - ST0.d;
#endif
break;
case 6: /* FIDIV ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f /= ED->sdword[0];
#else
ST0.d /= ED->sdword[0];
#endif
break;
case 7: /* FIDIVR ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f = ED->sdword[0] / ST0.f;
#else
ST0.d = ED->sdword[0] / ST0.d;
#endif
break;
default:
goto _default;
}
}
+241
View File
@@ -0,0 +1,241 @@
nextop = F8;
switch(nextop) {
case 0xC0: /* FCMOVNB ST(0), ST(i) */
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_CF))
ST0.ll = ST(nextop&7).ll;
break;
case 0xC8: /* FCMOVNE ST(0), ST(i) */
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_ZF))
ST0.ll = ST(nextop&7).ll;
break;
case 0xD0: /* FCMOVNBE ST(0), ST(i) */
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
CHECK_FLAGS(emu);
if(!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
ST0.ll = ST(nextop&7).ll;
break;
case 0xD8: /* FCMOVNU ST(0), ST(i) */
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_PF))
ST0.ll = ST(nextop&7).ll;
break;
case 0xE2: /* FNCLEX */
//Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE),
// the exception summary status flag (ES), the stack fault flag (SF), and the busy flag (B) in the FPU status word
emu->sw.f.F87_PE = 0;
emu->sw.f.F87_UE = 0;
emu->sw.f.F87_OE = 0;
emu->sw.f.F87_ZE = 0;
emu->sw.f.F87_DE = 0;
emu->sw.f.F87_IE = 0;
emu->sw.f.F87_ES = 0;
emu->sw.f.F87_SF = 0;
emu->sw.f.F87_B = 0;
break;
case 0xE3: /* FNINIT */
reset_fpu(emu);
break;
case 0xE8: /* FUCOMI ST0, STx */
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
break;
case 0xF0: /* FCOMI ST0, STx */
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d);
#endif
break;
case 0xE0:
case 0xE1:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
goto _default;
default:
switch((nextop>>3)&7) {
case 0: /* FILD ST0, Gd */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = ED->sdword[0];
#else
ST0.d = ED->sdword[0];
#endif
break;
case 1: /* FISTTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
tmp32s = ST0.f; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.f, (float)(int32_t)0x7fffffff))
tmp32s = 0x80000000;
#else
tmp32s = ST0.d; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
tmp32s = 0x80000000;
#endif
fpu_do_pop(emu);
ED->sdword[0] = tmp32s;
break;
case 2: /* FIST Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floorf(ST0.f);
break;
case ROUND_Up:
ED->sdword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floor(ST0.d);
break;
case ROUND_Up:
ED->sdword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.d;
break;
}
}
#endif
break;
case 3: /* FISTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floorf(ST0.f);
break;
case ROUND_Up:
ED->sdword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floor(ST0.d);
break;
case ROUND_Up:
ED->sdword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.d;
break;
}
}
#endif
fpu_do_pop(emu);
break;
case 5: /* FLD ST0, Gt */
GET_ED;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
#ifdef USE_FLOAT
LD2D(&STld(0), &d);
ST0.f = d;
#else
LD2D(&STld(0), &ST(0).d);
#endif
STld(0).ref = ST0.ll;
break;
case 7: /* FSTP tbyte */
GET_ED;
if(ST0.ll!=STld(0).ref)
#ifdef USE_FLOAT
{d = ST0.f; D2LD(&d, ED);}
#else
D2LD(&ST0.d, ED);
#endif
else
memcpy(ED, &STld(0).ld, 10);
fpu_do_pop(emu);
break;
default:
goto _default;
}
}
+90 -1
View File
@@ -1,3 +1,5 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch(nextop) {
case 0xC0:
@@ -8,7 +10,11 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
#ifdef USE_FLOAT
ST(nextop&7).f += ST0.f;
#else
ST(nextop&7).d += ST0.d;
#endif
break;
case 0xC8:
case 0xC9:
@@ -18,7 +24,11 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
#ifdef USE_FLOAT
ST(nextop&7).f *= ST0.f;
#else
ST(nextop&7).d *= ST0.d;
#endif
break;
case 0xD0:
case 0xD1:
@@ -28,7 +38,11 @@
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
fpu_fcom(emu, ST(nextop&7).d); // TODO: is this ok?
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
break;
case 0xD8:
case 0xD9:
@@ -38,7 +52,11 @@
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // TODO: is this ok?
#endif
fpu_do_pop(emu);
break;
case 0xE0:
@@ -49,7 +67,11 @@
case 0xE5:
case 0xE6:
case 0xE7: /* FSUBR */
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f -ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d -ST(nextop&7).d;
#endif
break;
case 0xE8:
case 0xE9:
@@ -59,7 +81,11 @@
case 0xED:
case 0xEE:
case 0xEF: /* FSUB */
#ifdef USE_FLOAT
ST(nextop&7).f -= ST0.f;
#else
ST(nextop&7).d -= ST0.d;
#endif
break;
case 0xF0:
case 0xF1:
@@ -69,7 +95,11 @@
case 0xF5:
case 0xF6:
case 0xF7: /* FDIVR */
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
#endif
break;
case 0xF8:
case 0xF9:
@@ -79,26 +109,48 @@
case 0xFD:
case 0xFE:
case 0xFF: /* FDIV */
#ifdef USE_FLOAT
ST(nextop&7).f /= ST0.f;
#else
ST(nextop&7).d /= ST0.d;
#endif
break;
default:
GET_ED;
switch((nextop>>3)&7) {
case 0: /* FADD ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f += *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f += d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d += *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.d += d;
}
#endif
break;
case 1: /* FMUL ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f *= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f *= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d *= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.d *= d;
}
#endif
break;
case 2: /* FCOM ST0, double */
if(!(((uintptr_t)ED)&7))
@@ -118,38 +170,75 @@
fpu_do_pop(emu);
break;
case 4: /* FSUB ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f -= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f -= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d -= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.d -= d;
}
#endif
break;
case 5: /* FSUBR ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f = *(double*)ED - ST0.f;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f = d - ST0.f;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED - ST0.d;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.d = d - ST0.d;
}
#endif
break;
case 6: /* FDIV ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f /= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f /= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d /= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.d /= d;
}
#endif
break;
case 7: /* FDIVR ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f = *(double*)ED / ST0.f;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f = d / ST0.f;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED / ST0.d;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.d = d / ST0.d;
}
#endif
break;
default:
goto _default;
}
}
#pragma GCC diagnostic pop
+49 -1
View File
@@ -9,7 +9,8 @@
case 0xC5:
case 0xC6:
case 0xC7:
break; // not handling Tag...
fpu_do_free(emu, nextop-0xC0);
break;
case 0xD0: /* FST ST0, STx */
case 0xD1:
@@ -40,7 +41,11 @@
case 0xE5:
case 0xE6:
case 0xE7:
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
break;
case 0xE8: /* FUCOMP ST0, STx */
case 0xE9:
@@ -50,7 +55,11 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
break;
@@ -85,15 +94,39 @@
case 0: /* FLD double */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
*(uint64_t*)&d = *(int64_t*)ED;
ST0.f = d;
#else
ST0.ll = *(int64_t*)ED;
#endif
break;
case 1: /* FISTTP ED qword */
GET_ED;
#ifdef USE_FLOAT
*(int64_t*)ED = ST0.f;
#else
*(int64_t*)ED = ST0.d;
#endif
fpu_do_pop(emu);
break;
case 2: /* FST double */
GET_ED;
#ifdef USE_FLOAT
d = ST0.f;
*(int64_t*)ED = *(uint64_t*)&d;
#else
*(int64_t*)ED = ST0.ll;
#endif
break;
case 3: /* FSTP double */
GET_ED;
#ifdef USE_FLOAT
d = ST0.f;
*(int64_t*)ED = *(uint64_t*)&d;
#else
*(int64_t*)ED = ST0.ll;
#endif
fpu_do_pop(emu);
break;
case 4: /* FRSTOR m108byte */
@@ -104,7 +137,12 @@
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
d = ST(i).f;
LD2D(p, &d);
#else
LD2D(p, &ST(i).d);
#endif
p+=10;
}
}
@@ -119,12 +157,22 @@
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
D2LD(&d, p);
ST(i).f = d;
#else
D2LD(&ST(i).d, p);
#endif
p+=10;
}
}
reset_fpu(emu);
break;
case 7: /* FNSTSW m2byte */
GET_ED;
emu->sw.f.F87_TOP = emu->top&7;
*(uint16_t*)ED = emu->sw.x16;
break;
default:
goto _default;
}
+68 -7
View File
@@ -1,7 +1,11 @@
nextop = F8;
switch (nextop) {
case 0xC1: /* FADDP ST1, ST0 */
#ifdef USE_FLOAT
ST(1).f += ST0.f;
#else
ST(1).d += ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC0: /* FADDP STx, ST0 */
@@ -11,11 +15,19 @@
case 0xC5:
case 0xC6:
case 0xC7:
#ifdef USE_FLOAT
ST(nextop&7).f += ST0.f;
#else
ST(nextop&7).d += ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC9: /* FMULP ST1, ST0 */
#ifdef USE_FLOAT
ST1.f *= ST0.f;
#else
ST1.d *= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC8: /* FMULP STx, ST0 */
@@ -25,11 +37,19 @@
case 0xCD:
case 0xCE:
case 0xCF:
#ifdef USE_FLOAT
ST(nextop&7).f *= ST0.f;
#else
ST(nextop&7).d *= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xD9: /* FCOMPP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST1.f);
#else
fpu_fcom(emu, ST1.d);
#endif
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
@@ -45,11 +65,19 @@
case 0xE5:
case 0xE6:
case 0xE7:
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f - ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d - ST(nextop&7).d;
#endif
fpu_do_pop(emu);
break;
case 0xE9: /* FSUBP ST1, ST0 */
#ifdef USE_FLOAT
ST1.f -= ST0.f;
#else
ST1.d -= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xE8: /* FSUBP STx, ST0 */
@@ -59,12 +87,13 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
ST(nextop&7).f -= ST0.f;
#else
ST(nextop&7).d -= ST0.d;
#endif
fpu_do_pop(emu);
break;
/*ST(1).d = ST0.d / ST(1).d;
fpu_do_pop(emu);
break;*/
case 0xF0: /* FDIVRP STx, ST0 */
case 0xF1: /* FDIVRP ST1, ST0 */
case 0xF2:
@@ -73,13 +102,13 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
#endif
fpu_do_pop(emu);
break;
/*d = ST0.d;
fpu_do_pop(emu);
ST0.d /= d;
break;*/
case 0xF8: /* FDIVP STx, ST0 */
case 0xF9: /* FDIVP ST1, ST0 */
case 0xFA:
@@ -88,7 +117,11 @@
case 0xFD:
case 0xFE:
case 0xFF:
#ifdef USE_FLOAT
ST(nextop&7).f /= ST0.f;
#else
ST(nextop&7).d /= ST0.d;
#endif
fpu_do_pop(emu);
break;
@@ -113,23 +146,51 @@
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f += EW->sword[0];
#else
ST0.d += EW->sword[0];
#endif
break;
case 1: /* FIMUL ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f *= EW->sword[0];
#else
ST0.d *= EW->sword[0];
#endif
break;
case 4: /* FISUB ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f -= EW->sword[0];
#else
ST0.d -= EW->sword[0];
#endif
break;
case 5: /* FISUBR ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f = EW->sword[0] - ST0.f;
#else
ST0.d = EW->sword[0] - ST0.d;
#endif
break;
case 6: /* FIDIV ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f /= EW->sword[0];
#else
ST0.d /= EW->sword[0];
#endif
break;
case 7: /* FIDIVR ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f = EW->sword[0] / ST0.f;
#else
ST0.d = EW->sword[0] / ST0.d;
#endif
break;
default:
goto _default;
+240
View File
@@ -0,0 +1,240 @@
nextop = F8;
switch (nextop) {
case 0xE0: /* FNSTSW AX */
emu->sw.f.F87_TOP = emu->top&7;
R_AX = emu->sw.x16;
break;
case 0xE8: /* FUCOMIP ST0, STx */
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
break;
case 0xF0: /* FCOMIP ST0, STx */
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d);
#endif
fpu_do_pop(emu);
break;
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
goto _default;
default:
switch((nextop>>3)&7) {
case 0: /* FILD ST0, Gw */
GET_EW;
tmp16s = EW->sword[0];
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = tmp16s;
#else
ST0.d = tmp16s;
#endif
break;
case 1: /* FISTTP Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
tmp16s = ST0.f;
#else
tmp16s = ST0.d;
#endif
EW->sword[0] = tmp16s;
fpu_do_pop(emu);
break;
case 2: /* FIST Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(int32_t)0x7fff))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
EW->sword[0] = floorf(ST0.f);
break;
case ROUND_Up:
EW->sword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
EW->sword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
EW->sword[0] = floor(ST0.d);
break;
case ROUND_Up:
EW->sword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
EW->sword[0] = ST0.d;
break;
}
}
#endif
break;
case 3: /* FISTP Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(int32_t)0x7fff))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
EW->sword[0] = floorf(ST0.f);
break;
case ROUND_Up:
EW->sword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
EW->sword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
EW->sword[0] = floor(ST0.d);
break;
case ROUND_Up:
EW->sword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
EW->sword[0] = ST0.d;
break;
}
}
#endif
fpu_do_pop(emu);
break;
case 4: /* FBLD ST0, tbytes */
GET_ED;
fpu_do_push(emu);
fpu_fbld(emu, (uint8_t*)ED);
break;
case 5: /* FILD ST0, Gq */
GET_ED;
tmp64s = *(int64_t*)ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = tmp64s;
#else
ST0.d = tmp64s;
#endif
STll(0).ll = tmp64s;
STll(0).ref = ST0.ll;
break;
case 6: /* FBSTP tbytes, ST0 */
GET_ED;
fpu_fbst(emu, (uint8_t*)ED);
fpu_do_pop(emu);
break;
case 7: /* FISTP i64 */
GET_ED;
if(STll(0).ref==ST(0).ll) {
*(int64_t*)ED = STll(0).ll;
} else {
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int64_t)0x7fffffffffffffffLL) || isless(ST0.f, (float)(int64_t)0x8000000000000000LL))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = (int64_t)ST0.f;
#else
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = (int64_t)ST0.d;
#endif
}
fpu_do_pop(emu);
break;
default:
goto _default;
}
}
+37 -2
View File
@@ -15,6 +15,11 @@
GET_EX;
EX->q[0] = GX.q[0];
break;
case 0x12: /* MOVDDUP Gx, Ex */
nextop = F8;
GET_EX;
GX.q[1] = GX.q[0] = EX->q[0];
break;
case 0x2A: /* CVTSI2SD Gx, Ed */
nextop = F8;
@@ -23,12 +28,28 @@
break;
case 0x2C: /* CVTTSD2SI Gd, Ex */
case 0x2D: /* CVTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
GD.sdword[0] = EX->d[0];
break;
case 0x2D: /* CVTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
switch(emu->round) {
case ROUND_Nearest:
GD.sdword[0] = floor(EX->d[0]+0.5);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->d[0];
break;
}
break;
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
GET_EX;
@@ -90,6 +111,20 @@
}
break;
case 0x7C: /* HADDPS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] += GX.f[1];
GX.f[1] = GX.f[2] + GX.f[3];
if(EX==&GX) {
GX.f[2] = GX.f[0];
GX.f[3] = GX.f[1];
} else {
GX.f[2] = EX->f[0] + EX->f[1];
GX.f[3] = EX->f[2] + EX->f[3];
}
break;
case 0xC2: /* CMPSD Gx, Ex, Ib */
nextop = F8;
GET_EX;
+56 -1
View File
@@ -15,6 +15,15 @@
GET_EX;
EX->ud[0] = GX.ud[0];
break;
case 0x1E: /* NOP / ENDBR32 / ENDBR64 */
nextop = F8;
GET_ED;
break;
case 0x1F: /* REP NOP */
nextop = F8;
GET_ED;
break;
case 0x2A: /* CVTSI2SS Gx, Ed */
nextop = F8;
@@ -23,17 +32,44 @@
break;
case 0x2C: /* CVTTSS2SI Gd, Ex */
case 0x2D: /* CVTSS2SI Gd, Ex */
nextop = F8;
GET_EX;
GD.sdword[0] = EX->f[0];
break;
case 0x2D: /* CVTSS2SI Gd, Ex */
nextop = F8;
GET_EX;
switch(emu->round) {
case ROUND_Nearest:
GD.sdword[0] = floor(EX->f[0]+0.5);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->f[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->f[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->f[0];
break;
}
break;
case 0x51: /* SQRTSS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] = sqrtf(EX->f[0]);
break;
case 0x52: /* RSQRTSS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] = 1.0f/sqrtf(EX->f[0]);
break;
case 0x53: /* RCPSS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] = 1.0f/EX->f[0];
break;
case 0x58: /* ADDSS Gx, Ex */
nextop = F8;
@@ -114,6 +150,25 @@
memcpy(EX, &GX, 16); // unaligned...
break;
case 0xBC: /* TZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp32u = ED->dword[0];
if(tmp32u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp32u&(1<<tmp8u))) ++tmp8u;
GD.dword[0] = tmp8u;
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CLEAR_FLAG(F_CF);
} else {
CLEAR_FLAG(F_ZF);
SET_FLAG(F_CF);
GD.dword[0] = 32;
}
break;
case 0xC2: /* CMPSS Gx, Ex, Ib */
nextop = F8;
GET_EX;
+466
View File
@@ -0,0 +1,466 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86emu_private.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "x86run.h"
#include "x86run_private.h"
#include "callback.h"
typedef struct cleanup_s {
void* f;
int arg;
void* a;
} cleanup_t;
static uint32_t x86emu_parity_tab[8] =
{
0x96696996,
0x69969669,
0x69969669,
0x96696996,
0x69969669,
0x96696996,
0x96696996,
0x69969669,
};
static uint8_t EndEmuMarker[] = {0xcc, 'S', 'C', 0, 0, 0, 0};
void PushExit(x86emu_t* emu)
{
Push(emu, (uint32_t)&EndEmuMarker);
}
void* GetExit()
{
return &EndEmuMarker;
}
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
emu->context = context;
// setup cpu helpers
for (int i=0; i<8; ++i)
emu->sbiidx[i] = &emu->regs[i];
emu->sbiidx[4] = &emu->zero;
emu->x86emu_parity_tab = x86emu_parity_tab;
emu->packed_eflags.x32 = 0x202; // default flags?
UnpackFlags(emu);
// own stack?
emu->stack2free = (ownstack)?(void*)stack:NULL;
emu->init_stack = (void*)stack;
emu->size_stack = stacksize;
// set default value
R_EIP = start;
R_ESP = (stack + stacksize) & ~7; // align stack start, always
// fake init of segments...
emu->segs[_CS] = 0x73;
emu->segs[_DS] = emu->segs[_ES] = emu->segs[_SS] = 0x7b;
emu->segs[_FS] = default_fs;
emu->segs[_GS] = 0x33;
// setup fpu regs
reset_fpu(emu);
}
EXPORTDYN
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
x86emu_t *emu = (x86emu_t*)calloc(1, sizeof(x86emu_t));
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
return emu;
}
x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
return emu;
}
EXPORTDYN
void SetupX86Emu(x86emu_t *emu)
{
printf_log(LOG_DEBUG, "Setup X86 Emu\n");
}
void SetTraceEmu(uintptr_t start, uintptr_t end)
{
if(my_context->zydis) {
if (end == 0) {
printf_log(LOG_INFO, "Setting trace\n");
} else {
if(end!=1) { // 0-1 is basically no trace, so don't printf it...
printf_log(LOG_INFO, "Setting trace only between %p and %p\n", (void*)start, (void*)end);
}
}
}
trace_start = start;
trace_end = end;
}
void AddCleanup(x86emu_t *emu, void *p)
{
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 0;
my_context->cleanups[my_context->clean_sz].a = NULL;
my_context->cleanups[my_context->clean_sz++].f = p;
}
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a)
{
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 1;
my_context->cleanups[my_context->clean_sz].a = a;
my_context->cleanups[my_context->clean_sz++].f = p;
}
void CallCleanup(x86emu_t *emu, void* p)
{
printf_log(LOG_DEBUG, "Calling atexit registered functions for %p mask\n", p);
for(int i=my_context->clean_sz-1; i>=0; --i) {
if(p==my_context->cleanups[i].f) {
printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
// now remove the cleanup
if(i!=my_context->clean_sz-1)
memmove(my_context->cleanups+i, my_context->cleanups+i+1, (my_context->clean_sz-i-1)*sizeof(cleanup_t));
--my_context->clean_sz;
}
}
}
void CallAllCleanup(x86emu_t *emu)
{
printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
for(int i=my_context->clean_sz-1; i>=0; --i) {
printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
}
my_context->clean_sz = 0;
}
static void internalFreeX86(x86emu_t* emu)
{
free(emu->stack2free);
}
EXPORTDYN
void FreeX86Emu(x86emu_t **emu)
{
if(!emu)
return;
printf_log(LOG_DEBUG, "Free a X86 Emu (%p)\n", *emu);
internalFreeX86(*emu);
free(*emu);
*emu = NULL;
}
void FreeX86EmuFromStack(x86emu_t **emu)
{
if(!emu)
return;
printf_log(LOG_DEBUG, "Free a X86 Emu from stack (%p)\n", *emu);
internalFreeX86(*emu);
}
void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
{
memcpy(newemu->regs, emu->regs, sizeof(emu->regs));
memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip));
memcpy(&newemu->packed_eflags, &emu->packed_eflags, sizeof(emu->packed_eflags));
memcpy(&newemu->flags, &emu->flags, sizeof(emu->flags));
newemu->old_ip = emu->old_ip;
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
memset(newemu->segs_clean, 0, sizeof(newemu->segs_clean));
memcpy(newemu->fpu, emu->fpu, sizeof(emu->fpu));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
newemu->cw = emu->cw;
newemu->cw_mask_all = emu->cw_mask_all;
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
newemu->top = emu->top;
newemu->fpu_stack = emu->fpu_stack;
memcpy(&newemu->round, &emu->round, sizeof(emu->round));
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
newemu->error = emu->error;
// adapt R_ESP to new stack frame
uintptr_t oldst = (uintptr_t)((emu->init_stack)?emu->init_stack:emu->context->stack);
uintptr_t newst = (uintptr_t)((newemu->init_stack)?newemu->init_stack:newemu->context->stack);
newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst);
}
box86context_t* GetEmuContext(x86emu_t* emu)
{
return emu->context;
}
uint32_t GetEAX(x86emu_t *emu)
{
return R_EAX;
}
uint64_t GetEDXEAX(x86emu_t *emu)
{
return ((uint64_t)R_EAX)|(((uint64_t)R_EDX)<<32);
}
void SetEAX(x86emu_t *emu, uint32_t v)
{
R_EAX = v;
}
void SetEBX(x86emu_t *emu, uint32_t v)
{
R_EBX = v;
}
void SetECX(x86emu_t *emu, uint32_t v)
{
R_ECX = v;
}
void SetEDX(x86emu_t *emu, uint32_t v)
{
R_EDX = v;
}
void SetEIP(x86emu_t *emu, uint32_t v)
{
R_EIP = v;
}
void SetESI(x86emu_t *emu, uint32_t v)
{
R_ESI = v;
}
void SetEDI(x86emu_t *emu, uint32_t v)
{
R_EDI = v;
}
void SetEBP(x86emu_t *emu, uint32_t v)
{
R_EBP = v;
}
void SetESP(x86emu_t *emu, uint32_t v)
{
R_ESP = v;
}
uint32_t GetESP(x86emu_t *emu)
{
return R_ESP;
}
void SetFS(x86emu_t *emu, uint16_t v)
{
emu->segs[_FS] = v;
}
uint16_t GetFS(x86emu_t *emu)
{
return emu->segs[_FS];
}
void ResetFlags(x86emu_t *emu)
{
emu->df = d_none;
}
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
{
static char buff[800];
char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
char tmp[80];
buff[0] = '\0';
if(trace_emm) {
// do emm reg is needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "mm%d:%016llx", i, emu->mmx[i].q);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
}
if(trace_xmm) {
// do xmm reg is needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "%d:%016llx%016llx", i, emu->xmm[i].q[1], emu->xmm[i].q[0]);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
}
// start with FPU regs...
if(emu->fpu_stack) {
for (int i=0; i<emu->fpu_stack; i++) {
#ifdef USE_FLOAT
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].f);
#else
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].d);
#endif
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
if(i==3) strcat(buff, "\n");
}
strcat(buff, "\n");
}
for (int i=_AX; i<=_DI; ++i) {
sprintf(tmp, "%s=%08x ", regname[i], emu->regs[i].dword[0]);
strcat(buff, tmp);
if (i==3) {
if(emu->df) {
strcat(buff, "FLAGS=??????\n");
} else {
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "-"
sprintf(tmp, "FLAGS=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
strcat(buff, tmp);
#undef FLAG_CHAR
}
}
}
sprintf(tmp, "EIP=%08x ", ip);
strcat(buff, tmp);
return buff;
}
void StopEmu(x86emu_t* emu, const char* reason)
{
emu->quit = 1;
printf_log(LOG_NONE, "%s", reason);
// dump stuff...
printf_log(LOG_NONE, "CPU Regs=%s\n", DumpCPURegs(emu, R_EIP));
// TODO: stack, memory/instruction around EIP, etc..
}
void UnimpOpcode(x86emu_t* emu)
{
R_EIP = emu->old_ip;
int tid = syscall(SYS_gettid);
printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode %02X %02X %02X %02X %02X %02X %02X %02X\n",
tid, (void*)emu->old_ip,
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7));
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
void EmuCall(x86emu_t* emu, uintptr_t addr)
{
uint32_t old_esp = R_ESP;
uint32_t old_ebx = R_EBX;
uint32_t old_edi = R_EDI;
uint32_t old_esi = R_ESI;
uint32_t old_ebp = R_EBP;
uint32_t old_eip = R_EIP;
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
Run(emu, 0);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
emu->longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
R_ESI = old_esi;
R_EBP = old_ebp;
R_ESP = old_esp;
R_EIP = old_eip; // and set back instruction pointer
}
}
#if defined(__ARM_ARCH)
#if (__ARM_ARCH >= 6)
static inline unsigned int arm_perf (void)
{
unsigned int value;
// Read CCNT Register
asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
return value;
}
static inline void init_perfcounters (int32_t do_reset, int32_t enable_divider)
{
// in general enable all counters (including cycle counter)
int32_t value = 1;
// peform reset:
if (do_reset)
{
value |= 2; // reset all counters to zero.
value |= 4; // reset cycle counter to zero.
}
if (enable_divider)
value |= 8; // enable "by 64" divider for CCNT.
value |= 16;
// program the performance-counter control-register:
asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(value));
// enable all counters:
asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n" :: "r"(0x8000000f));
// clear overflows:
asm volatile ("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
}
#endif
#endif
uint64_t ReadTSC(x86emu_t* emu)
{
// Read the TimeStamp Counter as 64bits.
// this is supposed to be the number of instrunctions executed since last reset
#if defined(__i386__)
uint64_t ret;
__asm__ volatile("rdtsc" : "=A"(ret));
return ret;
#if 0
#elif defined(__ARM_ARCH)
#if (__ARM_ARCH >= 6)
static int init = 1;
if(init) {
init_perfcounters(1, 1);
init = 0;
}
uint32_t perf = arm_perf();
if(perf) {
return ((uint64_t)perf)*64;
}
#endif
#endif
#endif
// fall back to gettime...
#ifndef NOGETCLOCK
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#endif
}
@@ -3,14 +3,25 @@
#include "regs.h"
typedef struct zydis_dec_s zydis_dec_t;
typedef struct box86context_s box86context_t;
typedef struct i386_ucontext_s i386_ucontext_t;
#define ERR_UNIMPL 1
#define ERR_DIVBY0 2
#define ERR_ILLEGAL 4
typedef struct cleanup_s cleanup_t;
#ifdef DYNAREC
#define CSTACK 32
#define CSTACKMASK 31
#endif
typedef struct forkpty_s {
void* amaster;
void* name;
void* termp;
void* winp;
void* f; // forkpty function
} forkpty_t;
typedef struct x86emu_s {
// cpu
@@ -18,51 +29,59 @@ typedef struct x86emu_s {
int flags[F_LAST];
x86flags_t packed_eflags;
uintptr_t old_ip;
// segments
uint32_t segs[6]; // only 32bits value?
// fpu
fpu_reg_t fpu[9];
fpu_ld_t fpu_ld[9]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[9]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[9];
uint16_t cw,cw_mask_all;
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
fpu_round_t round;
fpu_ld_t fpu_ld[9]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[9]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[9];
// mmx
mmx_regs_t mmx[8];
// sse
sse_regs_t xmm[8];
uint32_t mxcsr;
// cpu helpers
reg32_t zero;
reg32_t *sbiidx[8];
// defered flags
defered_flags_t df;
uint32_t op1;
uint32_t op2;
uint32_t res;
uint32_t *x86emu_parity_tab; // helper
#ifdef HAVE_TRACE
uintptr_t prev2_ip, prev_ip;
#endif
// segments
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
int segs_clean[6]; // are seg offset clean (1) or does they need to be re-computed (0)?
// emu control
int quit;
int error;
int fork; // quit because need to fork
// trace
zydis_dec_t *dec;
uintptr_t trace_start, trace_end;
// global stuffs, pointed with GS: segment
void *globals;
int *shared_global;
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
#ifdef DYNAREC
int cstacki; // current index
uint64_t cstack[CSTACK+1]; // pair of x86 address / native address for call/ret, using uint64_t for alignement, +1 for allignment
#endif
// parent context
box86context_t *context;
// atexit and fini functions
cleanup_t *cleanups;
int clean_sz;
int clean_cap;
// scratch stack, used for alignement of double and 64bits ints on arm
uint32_t *scratch;
// cpu helpers
reg32_t zero;
reg32_t *sbiidx[8];
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
uint32_t scratch[200];
// local stack, do be deleted when emu is freed
void* stack;
void* stack2free; // this is the stack to free (can be NULL)
void* init_stack; // initial stack (owned or not)
uint32_t size_stack; // stack size (owned or not)
i386_ucontext_t *uc_link; // to handle setcontext
} x86emu_t;
+265
View File
@@ -0,0 +1,265 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <pthread.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "wrapper.h"
#include "box86context.h"
#include "librarian.h"
#include <elf.h>
#include "elfloader.h"
#include "elfs/elfloader_private.h"
typedef int32_t (*iFpppp_t)(void*, void*, void*, void*);
x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
{
// execute atforks prepare functions, in reverse order
for (int i=my_context->atfork_sz-1; i>=0; --i)
if(my_context->atforks[i].prepare)
EmuCall(emu, my_context->atforks[i].prepare);
int v;
if(forktype==2) {
iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
v = forkpty(emu->forkpty_info->amaster, emu->forkpty_info->name, emu->forkpty_info->termp, emu->forkpty_info->winp);
emu->forkpty_info = NULL;
} else
v = fork();
if(v==EAGAIN || v==ENOMEM) {
// error...
} else if(v!=0) {
// execute atforks parent functions
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].parent)
EmuCall(emu, my_context->atforks[i].parent);
} else if(v==0) {
// execute atforks child functions
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].child)
EmuCall(emu, my_context->atforks[i].child);
}
R_EAX = v;
return emu;
}
extern int errno;
void x86Int3(x86emu_t* emu)
{
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
{
R_EIP += 2;
uint32_t addr = Fetch32(emu);
if(addr==0) {
//printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu);
emu->quit=1; // normal quit
} else {
RESET_FLAGS(emu);
wrapper_t w = (wrapper_t)addr;
addr = Fetch32(emu);
/* This party can be used to trace only 1 specific lib (but it is quite slow)
elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP));
int have_trace = 0;
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
pthread_mutex_lock(&emu->context->mutex_trace);
int tid = GetTID();
char buff[256] = "\0";
char buff2[64] = "\0";
char buff3[64] = "\0";
char *tmp;
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
} else
if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "glColor4f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
} else if(strstr(s, "glTexCoord2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex3f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
} else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "opendir")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
perr = 1;
} else if(strstr(s, "__open")==s || strcmp(s, "open")==0) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "fopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
} else if(!strcmp(s, "chdir")) {
pu32=*(uint32_t**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
} else if(strstr(s, "getenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
post = 2;
} else if(strstr(s, "pread")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
perr = 1;
} else if(strstr(s, "ioctl")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "statvfs64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "index")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "rindex")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "__xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "__lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "sem_timedwait")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
perr = 1;
} else if(strstr(s, "clock_gettime")==s || strstr(s, "__clock_gettime")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
post = 1;
pu32 = *(uint32_t**)(R_ESP+8);
} else if(strstr(s, "semop")==s) {
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/%d], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "mmap64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
perr = 1;
} else if(!strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 1;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "gtk_signal_connect_full")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
} else if(strstr(s, "strcmp")==s || strstr(s, "__strcmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strstr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strlen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "vsprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\"...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "snprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "sprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vfprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "sscanf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "XCreateWindow")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
} else if(strstr(s, "XLoadQueryFont")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "pthread_mutex_lock")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(!strcmp(s, "fmodf")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(!strcmp(s, "fmod")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
} else if(strstr(s, "SDL_GetWindowSurface")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "syscall")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
perr = 1;
} else {
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
}
printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
w(emu, addr); // some function never come back, so unlock the mutex first!
pthread_mutex_lock(&emu->context->mutex_trace);
if(post)
switch(post) {
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
break;
case 2: snprintf(buff2, 63, "(%s)", R_EAX?((char*)R_EAX):"nil");
break;
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
break;
#ifdef USE_FLOAT
case 4: snprintf(buff2, 63, " (%f)", ST0.f);
#else
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
#endif
break;
case 5: {
uint32_t* p = (uint32_t*)R_EAX;
if(p)
snprintf(buff2, 63, " size=%dx%d, pitch=%d, pixels=%p", p[2], p[3], p[4], p+5);
else
snprintf(buff2, 63, "NULL Surface");
}
break;
}
if(perr==1 && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==2 && R_EAX==0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
} else
w(emu, addr);
}
return;
}
printf_log(LOG_INFO, "Warning, ignoring unsupported Int 3 call\n");
//emu->quit = 1;
}
int GetTID()
{
return syscall(SYS_gettid);
}
+76 -264
View File
@@ -105,19 +105,7 @@
/*------------------------- Global Variables ------------------------------*/
static uint32_t x86emu_parity_tab[8] =
{
0x96696996,
0x69969669,
0x69969669,
0x96696996,
0x69969669,
0x96696996,
0x96696996,
0x69969669,
};
#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define PARITY(x) (((emu->x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
/*----------------------------- Implementation ----------------------------*/
@@ -223,8 +211,8 @@ Implements the ADC instruction and side effects.
****************************************************************************/
uint8_t adc8(x86emu_t *emu, uint8_t d, uint8_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t cc;
uint32_t res; /* all operands in native machine order */
uint32_t cc;
CHECK_FLAGS(emu);
@@ -251,8 +239,8 @@ Implements the ADC instruction and side effects.
****************************************************************************/
uint16_t adc16(x86emu_t *emu, uint16_t d, uint16_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t cc;
uint32_t res; /* all operands in native machine order */
uint32_t cc;
CHECK_FLAGS(emu);
@@ -279,10 +267,10 @@ Implements the ADC instruction and side effects.
****************************************************************************/
uint32_t adc32(x86emu_t *emu, uint32_t d, uint32_t s)
{
register uint32_t lo; /* all operands in native machine order */
register uint32_t hi;
register uint32_t res;
register uint32_t cc;
uint32_t lo; /* all operands in native machine order */
uint32_t hi;
uint32_t res;
uint32_t cc;
CHECK_FLAGS(emu);
@@ -297,7 +285,7 @@ uint32_t adc32(x86emu_t *emu, uint32_t d, uint32_t s)
hi = (lo >> 16) + (d >> 16) + (s >> 16);
CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
@@ -314,8 +302,8 @@ Implements the CMP instruction and side effects.
****************************************************************************/
uint8_t cmp8(x86emu_t *emu, uint8_t d, uint8_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
RESET_FLAGS(emu);
@@ -339,8 +327,8 @@ Implements the CMP instruction and side effects.
****************************************************************************/
uint16_t cmp16(x86emu_t *emu, uint16_t d, uint16_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
RESET_FLAGS(emu);
@@ -363,14 +351,14 @@ Implements the CMP instruction and side effects.
****************************************************************************/
uint32_t cmp32(x86emu_t *emu, uint32_t d, uint32_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
RESET_FLAGS(emu);
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
/* calculate the borrow chain. See note at top */
@@ -393,10 +381,11 @@ uint8_t daa8(x86emu_t *emu, uint8_t d)
res += 6;
SET_FLAG(F_AF);
}
if (res > 0x9F || ACCESS_FLAG(F_CF)) {
if (d > 0x99 || ACCESS_FLAG(F_CF)) {
res += 0x60;
SET_FLAG(F_CF);
}
} else
CLEAR_FLAG(F_CF);
CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
@@ -409,21 +398,24 @@ Implements the DAS instruction and side effects.
****************************************************************************/
uint8_t das8(x86emu_t *emu, uint8_t d)
{
uint32_t res = d;
CHECK_FLAGS(emu);
uint32_t newcf = 0;
if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
d -= 6;
res -= 6;
newcf = (d < 6);
SET_FLAG(F_AF);
} else
CLEAR_FLAG(F_AF);
if (d > 0x9F || ACCESS_FLAG(F_CF)) {
d -= 0x60;
SET_FLAG(F_CF);
} else
CLEAR_FLAG(F_CF);
CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
CONDITIONAL_SET_FLAG(d == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
return d;
if (d > 0x99 || ACCESS_FLAG(F_CF)) {
res -= 0x60;
newcf = 1;
}
CONDITIONAL_SET_FLAG(newcf, F_CF);
CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
return res;
}
/****************************************************************************
@@ -432,7 +424,7 @@ Implements the RCL instruction and side effects.
****************************************************************************/
uint8_t rcl8(x86emu_t *emu, uint8_t d, uint8_t s)
{
register unsigned int res, cnt, mask, cf;
unsigned int res, cnt, mask, cf;
CHECK_FLAGS(emu);
s = s&0x1f;
@@ -507,7 +499,7 @@ Implements the RCL instruction and side effects.
****************************************************************************/
uint16_t rcl16(x86emu_t *emu, uint16_t d, uint8_t s)
{
register unsigned int res, cnt, mask, cf;
unsigned int res, cnt, mask, cf;
CHECK_FLAGS(emu);
s = s&0x1f;
@@ -533,14 +525,14 @@ Implements the RCL instruction and side effects.
****************************************************************************/
uint32_t rcl32(x86emu_t *emu, uint32_t d, uint8_t s)
{
register uint32_t res, cnt, mask, cf;
uint32_t res, cnt, mask, cf;
CHECK_FLAGS(emu);
s = s&0x1f;
res = d;
if ((cnt = s % 33) != 0) {
cf = (d >> (32 - cnt)) & 0x1;
res = (d << cnt) & 0xffffffff;
res = (d << cnt);
mask = (1 << (cnt - 1)) - 1;
res |= (d >> (33 - cnt)) & mask;
if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
@@ -722,7 +714,7 @@ uint8_t rol8(x86emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -749,7 +741,7 @@ uint16_t rol16(x86emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -776,7 +768,7 @@ uint32_t rol32(x86emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -803,7 +795,7 @@ uint8_t ror8(x86emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -830,7 +822,7 @@ uint16_t ror16(x86emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -857,7 +849,7 @@ uint32_t ror32(x86emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -899,7 +891,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
CLEAR_FLAG(F_OF);
}
} else {
res = (fill << (cnt)) | (d >> (16 - cnt));
res = (fill << (cnt)) | (fill >> (16 - cnt));
if(s==16)
cf = d & 1;
else
@@ -928,7 +920,7 @@ uint32_t shld32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
res = (d << cnt) | (fill >> (32-cnt));
cf = d & (1 << (32 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
} else {
@@ -973,7 +965,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
}
} else {
cf = fill & (1 << (cnt - 1));
res = (fill >> cnt) | (d << (16 - cnt));
res = (fill >> cnt) | (fill << (16 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
@@ -1006,7 +998,7 @@ uint32_t shrd32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
cf = d & (1 << (cnt - 1));
res = (d >> cnt) | (fill << (32 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
} else {
@@ -1026,8 +1018,8 @@ Implements the SBB instruction and side effects.
****************************************************************************/
uint8_t sbb8(x86emu_t *emu, uint8_t d, uint8_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
@@ -1052,8 +1044,8 @@ Implements the SBB instruction and side effects.
****************************************************************************/
uint16_t sbb16(x86emu_t *emu, uint16_t d, uint16_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
@@ -1078,8 +1070,8 @@ Implements the SBB instruction and side effects.
****************************************************************************/
uint32_t sbb32(x86emu_t *emu, uint32_t d, uint32_t s)
{
register uint32_t res; /* all operands in native machine order */
register uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
@@ -1087,7 +1079,7 @@ uint32_t sbb32(x86emu_t *emu, uint32_t d, uint32_t s)
else
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
/* calculate the borrow chain. See note at top */
@@ -1104,7 +1096,7 @@ Implements the TEST instruction and side effects.
****************************************************************************/
void test8(x86emu_t *emu, uint8_t d, uint8_t s)
{
register uint32_t res; /* all operands in native machine order */
uint32_t res; /* all operands in native machine order */
RESET_FLAGS(emu);
res = d & s;
@@ -1123,7 +1115,7 @@ Implements the TEST instruction and side effects.
****************************************************************************/
void test16(x86emu_t *emu, uint16_t d, uint16_t s)
{
register uint32_t res; /* all operands in native machine order */
uint32_t res; /* all operands in native machine order */
RESET_FLAGS(emu);
res = d & s;
@@ -1142,7 +1134,7 @@ Implements the TEST instruction and side effects.
****************************************************************************/
void test32(x86emu_t *emu, uint32_t d, uint32_t s)
{
register uint32_t res; /* all operands in native machine order */
uint32_t res; /* all operands in native machine order */
RESET_FLAGS(emu);
res = d & s;
@@ -1155,196 +1147,13 @@ void test32(x86emu_t *emu, uint32_t d, uint32_t s)
CLEAR_FLAG(F_CF);
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul8(x86emu_t *emu, uint8_t s)
{
int16_t res = (int16_t)(int8_t)R_AL * (int8_t)s;
RESET_FLAGS(emu);
R_AX = res;
if (((R_AL & 0x80) == 0 && R_AH == 0x00) ||
((R_AL & 0x80) != 0 && R_AH == 0xFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul16_eax(x86emu_t *emu, uint16_t s)
{
int32_t res = (int32_t)(int16_t)R_AX * (int16_t)s;
RESET_FLAGS(emu);
R_AX = (uint16_t)res;
R_DX = (uint16_t)(res >> 16);
if (((R_AX & 0x8000) == 0 && R_DX == 0x00) ||
((R_AX & 0x8000) != 0 && R_DX == 0xFFFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
uint16_t imul16(x86emu_t *emu, uint16_t op1, uint16_t op2)
{
int32_t res = (int32_t)(int16_t)op1 * (int16_t)op2;
RESET_FLAGS(emu);
op1 = (uint16_t)res;
uint16_t tmp = (uint16_t)(res >> 16);
if (((op1 & 0x8000) == 0 && tmp == 0x00) ||
((op1 & 0x8000) != 0 && tmp == 0xFFFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
return op1;
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul32_direct(uint32_t *res_lo, uint32_t* res_hi,uint32_t d, uint32_t s)
{
int64_t res = (int64_t)(int32_t)d * (int32_t)s;
*res_lo = (uint32_t)res;
*res_hi = (uint32_t)(res >> 32);
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
uint32_t imul32(x86emu_t *emu, uint32_t op1, uint32_t op2)
{
uint32_t s;
uint32_t r;
RESET_FLAGS(emu);
imul32_direct(&r,&s,op1,op2);
if (((r & 0x80000000) == 0 && s == 0x00) ||
((r & 0x80000000) != 0 && s == 0xFFFFFFFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(r & 0xff), F_PF);
return r;
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
void imul32_eax(x86emu_t *emu, uint32_t s)
{
RESET_FLAGS(emu);
imul32_direct(&R_EAX,&R_EDX,R_EAX,s);
if (((R_EAX & 0x80000000) == 0 && R_EDX == 0x00) ||
((R_EAX & 0x80000000) != 0 && R_EDX == 0xFFFFFFFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
}
/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
void mul8(x86emu_t *emu, uint8_t s)
{
uint16_t res = (uint16_t)(R_AL) * s;
RESET_FLAGS(emu);
R_AX = res;
if (R_AH == 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
}
/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
void mul16(x86emu_t *emu, uint16_t s)
{
uint32_t res = (uint32_t)R_AX * s;
RESET_FLAGS(emu);
R_AX = (uint16_t)res;
R_DX = (uint16_t)(res >> 16);
if (R_DX == 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
}
/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
void mul32_eax(x86emu_t *emu, uint32_t s)
{
uint64_t res = (uint64_t)R_EAX * s;
RESET_FLAGS(emu);
R_EAX = (uint32_t)res;
R_EDX = (uint32_t)(res >> 32);
if (R_EDX == 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(R_AL & 0xff), F_PF);
}
/****************************************************************************
REMARKS:
Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv8(x86emu_t *emu, uint8_t s)
{
int32_t dvd, div, mod;
int32_t dvd, quot, mod;
RESET_FLAGS(emu);
dvd = (int16_t)R_AX;
@@ -1352,13 +1161,14 @@ void idiv8(x86emu_t *emu, uint8_t s)
INTR_RAISE_DIV0(emu);
return;
}
div = dvd / (int8_t)s;
mod = dvd % (int8_t)s;
if (abs(div) > 0x7f) {
div_t p = div(dvd, (int8_t)s);
quot = p.quot;
mod = p.rem;
if (abs(quot) > 0x7f) {
INTR_RAISE_DIV0(emu);
return;
}
R_AL = (int8_t) div;
R_AL = (int8_t) quot;
R_AH = (int8_t) mod;
}
@@ -1368,25 +1178,26 @@ Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv16(x86emu_t *emu, uint16_t s)
{
int32_t dvd, div, mod;
int32_t dvd, quot, mod;
dvd = (((int32_t)R_DX) << 16) | R_AX;
if (s == 0) {
INTR_RAISE_DIV0(emu);
return;
}
div = dvd / (int16_t)s;
mod = dvd % (int16_t)s;
if (abs(div) > 0x7fff) {
div_t p = div(dvd, (int16_t)s);
quot = p.quot;
mod = p.rem;
if (abs(quot) > 0x7fff) {
INTR_RAISE_DIV0(emu);
return;
}
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_SF);
CONDITIONAL_SET_FLAG(div == 0, F_ZF);
CONDITIONAL_SET_FLAG(quot == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_AX = (uint16_t)div;
R_AX = (uint16_t)quot;
R_DX = (uint16_t)mod;
}
@@ -1396,7 +1207,7 @@ Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv32(x86emu_t *emu, uint32_t s)
{
int64_t dvd, div, mod;
int64_t dvd, quot, mod;
RESET_FLAGS(emu);
dvd = (((int64_t)R_EDX) << 32) | R_EAX;
@@ -1404,9 +1215,10 @@ void idiv32(x86emu_t *emu, uint32_t s)
INTR_RAISE_DIV0(emu);
return;
}
div = dvd / (int32_t)s;
mod = dvd % (int32_t)s;
if (llabs(div) > 0x7fffffff) {
lldiv_t p = lldiv(dvd, (int32_t)s);
quot = p.quot;
mod = p.rem;
if (llabs(quot) > 0x7fffffff) {
INTR_RAISE_DIV0(emu);
return;
}
@@ -1416,7 +1228,7 @@ void idiv32(x86emu_t *emu, uint32_t s)
SET_FLAG(F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_EAX = (uint32_t)div;
R_EAX = (uint32_t)quot;
R_EDX = (uint32_t)mod;
}
+106 -15
View File
@@ -81,8 +81,6 @@ Implements the AND instruction and side effects.
****************************************************************************/
static inline uint32_t and32(x86emu_t *emu, uint32_t d, uint32_t s)
{
register uint32_t res; /* all operands in native machine order */
emu->res = d & s;
emu->df = d_and32;
@@ -161,6 +159,14 @@ Implements the INC instruction and side effects.
****************************************************************************/
static inline uint32_t inc32(x86emu_t *emu, uint32_t d)
{
if(emu->df == d_shr32) {
// workaround for some wine trickery
uint32_t cnt = emu->op2;
if (cnt > 0) {
uint32_t cc = emu->op1 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
emu->res = d + 1;
emu->op1 = d;
emu->df = d_inc32;
@@ -239,7 +245,7 @@ static inline uint32_t neg32(x86emu_t *emu, uint32_t s)
/****************************************************************************
REMARKS:
Implements the NOT instruction and side effects.
Implements the NOT instruction
****************************************************************************/
static inline uint8_t not8(x86emu_t *emu, uint8_t s)
{
@@ -248,7 +254,7 @@ static inline uint8_t not8(x86emu_t *emu, uint8_t s)
/****************************************************************************
REMARKS:
Implements the NOT instruction and side effects.
Implements the NOT instruction
****************************************************************************/
static inline uint16_t not16(x86emu_t *emu, uint16_t s)
{
@@ -257,7 +263,7 @@ static inline uint16_t not16(x86emu_t *emu, uint16_t s)
/****************************************************************************
REMARKS:
Implements the NOT instruction and side effects.
Implements the NOT instruction
****************************************************************************/
static inline uint32_t not32(x86emu_t *emu, uint32_t s)
{
@@ -503,15 +509,100 @@ static inline uint32_t xor32(x86emu_t *emu, uint32_t d, uint32_t s)
return emu->res;
}
void imul8 (x86emu_t *emu, uint8_t s);
void imul16_eax (x86emu_t *emu, uint16_t s);
uint16_t imul16 (x86emu_t *emu, uint16_t op1, uint16_t op2);
void imul32_eax (x86emu_t *emu, uint32_t s);
uint32_t imul32(x86emu_t *emu, uint32_t op1, uint32_t op2);
void imul32_direct(uint32_t *res_lo, uint32_t* res_hi, uint32_t d, uint32_t s);
void mul8 (x86emu_t *emu, uint8_t s);
void mul16 (x86emu_t *emu, uint16_t s);
void mul32_eax (x86emu_t *emu, uint32_t s);
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static inline void imul8(x86emu_t *emu, uint8_t s)
{
emu->df = d_imul8;
R_AX = emu->res = (int16_t)(int8_t)R_AL * (int8_t)s;
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static inline void imul16_eax(x86emu_t *emu, uint16_t s)
{
emu->df = d_imul16;
emu->res = (int32_t)(int16_t)R_AX * (int16_t)s;
R_AX = (uint16_t)emu->res;
R_DX = (uint16_t)(emu->res >> 16);
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static inline uint16_t imul16(x86emu_t *emu, uint16_t op1, uint16_t op2)
{
emu->df = d_imul16;
emu->res = (int32_t)(int16_t)op1 * (int16_t)op2;
return (uint16_t)emu->res;
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static inline void imul32_direct(uint32_t *res_lo, uint32_t* res_hi,uint32_t d, uint32_t s)
{
int64_t res = (int64_t)(int32_t)d * (int32_t)s;
*res_lo = (uint32_t)res;
*res_hi = (uint32_t)(res >> 32);
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static inline uint32_t imul32(x86emu_t *emu, uint32_t op1, uint32_t op2)
{
emu->df = d_imul32;
imul32_direct(&emu->res,&emu->op1,op1,op2);
return emu->res;
}
/****************************************************************************
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static inline void imul32_eax(x86emu_t *emu, uint32_t s)
{
emu->df = d_imul32;
imul32_direct(&R_EAX,&R_EDX,R_EAX,s);
emu->res = R_EAX;
emu->op1 = R_EDX;
}
/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
static inline void mul8(x86emu_t *emu, uint8_t s)
{
emu->df = d_mul8;
R_AX = emu->res = (uint16_t)(R_AL) * s;
}
/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
static inline void mul16(x86emu_t *emu, uint16_t s)
{
emu->df = d_mul16;
emu->res = (uint32_t)R_AX * s;
R_AX = (uint16_t)emu->res;
R_DX = (uint16_t)(emu->res >> 16);
}
/****************************************************************************
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
static inline void mul32_eax(x86emu_t *emu, uint32_t s)
{
emu->df = d_mul32;
uint64_t res = (uint64_t)R_EAX * s;
emu->res = R_EAX = (uint32_t)res;
emu->op1 = R_EDX = (uint32_t)(res >> 32);
}
void idiv8 (x86emu_t *emu, uint8_t s);
void idiv16 (x86emu_t *emu, uint16_t s);
void idiv32 (x86emu_t *emu, uint32_t s);
@@ -519,4 +610,4 @@ void div8 (x86emu_t *emu, uint8_t s);
void div16 (x86emu_t *emu, uint16_t s);
void div32 (x86emu_t *emu, uint32_t s);
#endif //__X86PRIMOP_H_
#endif //__X86PRIMOP_H_
+1573
View File
File diff suppressed because it is too large. Load diff
+805
View File
@@ -0,0 +1,805 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#define F8 *(uint8_t*)(ip++)
#define F8S *(int8_t*)(ip++)
#define F16 *(uint16_t*)(ip+=2, ip-2)
#define F16S *(int16_t*)(ip+=2, ip-2)
#define F32 *(uint32_t*)(ip+=4, ip-4)
#define F32S *(int32_t*)(ip+=4, ip-4)
#define PK(a) *(uint8_t*)(ip+a)
#include "modrm.h"
void Run6766(x86emu_t *emu)
{
uintptr_t ip = R_EIP+2; //skip 67 66
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *op1, *op2;
switch(opcode) {
case 0x8D: /* LEA Gw,Ew */
nextop = F8;
op1=GetEw16(emu, nextop);
op2=GetG(emu, nextop);
op2->word[0] = (uint16_t)(uintptr_t)op1;
break;
default:
ip-=2; //unfetch
UnimpOpcode(emu);
}
R_EIP = ip;
}
void Run67(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1; //skip 67
uint8_t opcode = F8;
int8_t tmp8s;
int32_t tmp32s;
switch(opcode) {
case 0x66: /* MoooRE opcodes */
Run6766(emu);
break;
case 0x6C: /* INSB */
*(int8_t*)(R_DI+GetESBaseEmu(emu)) = 0; // faking port read, using actual segment ES, just in case
if(ACCESS_FLAG(F_DF))
R_DI-=1;
else
R_DI+=1;
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX && !ACCESS_FLAG(F_ZF))
R_EIP += tmp8s;
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX && ACCESS_FLAG(F_ZF))
R_EIP += tmp8s;
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX)
R_EIP += tmp8s;
break;
case 0xE3: /* JCXZ */
tmp8s = F8S;
if(!R_CX)
R_EIP += tmp8s;
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_EIP);
R_EIP += tmp32s;
break;
default:
UnimpOpcode(emu);
}
R_EIP = ip;
}
void RunLock(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1;
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u, tmp32u2;
int32_t tmp32s;
pthread_mutex_lock(&emu->context->mutex_lock);
switch(opcode) {
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GET_EB; \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
break; \
case B+1: \
nextop = F8; \
GET_ED; \
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
break; \
case B+2: \
nextop = F8; \
GET_EB; \
GB = OP##8(emu, GB, EB->byte[0]); \
break; \
case B+3: \
nextop = F8; \
GET_ED; \
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
break; \
case B+4: \
R_AL = OP##8(emu, R_AL, F8); \
break; \
case B+5: \
R_EAX = OP##32(emu, R_EAX, F32); \
break;
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x0f:
opcode = F8;
switch (opcode) {
case 0xB0: /* CMPXCHG Eb,Gb */
CHECK_FLAGS(emu);
nextop = F8;
GET_EB;
cmp8(emu, R_AL, EB->byte[0]);
if(ACCESS_FLAG(F_ZF)) {
EB->byte[0] = GB;
} else {
R_AL = EB->byte[0];
}
break;
case 0xB1: /* CMPXCHG Ed,Gd */
nextop = F8;
GET_ED;
cmp32(emu, R_EAX, ED->dword[0]);
if(ACCESS_FLAG(F_ZF)) {
ED->dword[0] = GD.dword[0];
} else {
R_EAX = ED->dword[0];
}
break;
case 0xB3: /* BTR Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ed,Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
break;
default:
ip -= 3; //unfetch
break;
}
break;
case 0xBB: /* BTC Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
break;
case 0xC0: /* XADD Gb,Eb */
nextop = F8;
GET_EB;
tmp8u = add8(emu, EB->byte[0], GB);
GB = EB->byte[0];
EB->byte[0] = tmp8u;
break;
case 0xC1: /* XADD Gd,Ed */
nextop = F8;
GET_ED;
tmp32u = add32(emu, ED->dword[0], GD.dword[0]);
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
break;
case 0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
break;
default:
// trigger invalid lock?
ip -= 2; // unfetch
break;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GET_ED;
if(opcode==0x83) {
tmp32s = F8S;
tmp32u = (uint32_t)tmp32s;
} else
tmp32u = F32;
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
break;
case 0x86: /* XCHG Eb,Gb */
nextop = F8;
GET_EB;
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
break;
case 0x87: /* XCHG Ed,Gd */
nextop = F8;
GET_ED;
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
ED->dword[0] = inc32(emu, ED->dword[0]);
break;
case 1: /* DEC Ed */
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0x%02X 0x%02X\n", opcode, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
break;
}
break;
default:
//UnimpOpcode(emu);
// should trigger invalid unlock ?
ip--; // "unfetch" to use normal instruction
}
R_EIP = ip;
pthread_mutex_unlock(&emu->context->mutex_lock);
}
void RunGS(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1;
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
uintptr_t tlsdata = GetGSBaseEmu(emu);
switch(opcode) {
case 0x01: /* ADD GS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = add32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x03: /* ADD Gd, GS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = add32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x11: /* ADC GS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
case 0x2B: /* SUB Gd, GS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x33: /* XOR Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x64: /* FS: */
// so just ignore that GS: prefix then
--ip; // put FS back
break;
case 0x69: /* IMUL Gd,Ed,Id */
nextop = F8;
GET_ED_OFFS(tlsdata);
tmp32u = F32;
GD.dword[0] = imul32(emu, ED->dword[0], tmp32u);
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7A:
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F:
// just ignore the prefix
--ip;
break;
case 0x80: /* GRP Eb,Ib */
case 0x82: // 0x82 and 0x80 are the same opcodes it seems?
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = F8;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GET_ED_OFFS(tlsdata);
if(opcode==0x83) {
tmp32s = F8S;
tmp32u = (uint32_t)tmp32s;
} else
tmp32u = F32;
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
break;
case 0x89: /* MOV Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8A: /* MOV Gb,GS:Eb */
nextop = F8;
GET_EB_OFFS(tlsdata);
GB = EB->byte[0];
break;
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0xA1: /* MOV EAX,Ov */
tmp32s = F32S;
R_EAX = *(uint32_t*)((tlsdata) + tmp32s);
break;
case 0xA2: /* MOV Ob,AL */
tmp32s = F32S;
*(uint8_t*)((tlsdata) + tmp32s) = R_AL;
break;
case 0xA3: /* MOV Od,EAX */
tmp32s = F32S;
*(uint32_t*)((tlsdata) + tmp32s) = R_EAX;
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = F8/* & 0x1f*/; // masking done in each functions
switch((nextop>>3)&7) {
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
case 4:
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0xC6: /* MOV Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
EB->byte[0] = F8;
break;
case 0xC7: /* MOV Ed,Id */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = F32;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
switch((nextop>>3)&7) {
case 0: /* INC Ed */
ED->dword[0] = inc32(emu, ED->dword[0]);
break;
case 1: /* DEC Ed */
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
Push(emu, R_EIP);
R_EIP = ED->dword[0]; // should get value in temp var. in case ED use ESP?
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
} else {
Push16(emu, R_CS);
Push(emu, R_EIP);
R_EIP = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 4: /* JMP NEAR Ed */
R_EIP = ED->dword[0];
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
} else {
R_EIP = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 6: /* Push Ed */
Push(emu, ED->dword[0]);
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
}
break;
default:
ip--;
UnimpOpcode(emu);
}
R_EIP = ip;
}
void RunFS(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1;
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
int16_t tmp16s;
uintptr_t tlsdata = GetFSBaseEmu(emu);
switch(opcode) {
case 0x33: /* XOR Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x3B: /* CMP GD, FS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x54: /* PUSH ESP */
tmp32u = R_ESP;
R_ESP -= 4;
*((uint32_t*)(R_ESP+tlsdata)) = tmp32u; //Push(emu, tmp32u);
break;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x55:
case 0x56:
case 0x57: /* PUSH Reg */
tmp8u = opcode&7;
*((uint32_t*)(R_ESP+tlsdata)) = emu->regs[tmp8u].dword[0]; //Push(emu, emu->regs[tmp8u].dword[0]);
break;
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C: /* POP ESP */
case 0x5D:
case 0x5E:
case 0x5F: /* POP Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].dword[0] = *((uint32_t*)(R_ESP+tlsdata)); // Pop(emu);
R_ESP += 4;
break;
case 0x67:
opcode = F8;
switch(opcode) {
case 0x89: /* MOV ED16,Gd */
nextop = F8;
oped=GetEw16off(emu, nextop, tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8B: /* MOV Gd,Ed16 */
nextop = F8;
oped=GetEw16off(emu, nextop, tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0xA1: /* MOV EAX,Ov16 */
tmp16s = F16S;
R_EAX = *(uint32_t*)((tlsdata) + tmp16s);
break;
case 0xA3: /* MOV Ov16,EAX */
tmp16s = F16S;
*(uint32_t*)((tlsdata) + tmp16s) = R_EAX;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
switch((nextop>>3)&7) {
case 6: /* Push Ed */
oped=GetEw16off(emu, nextop, tlsdata);
Push(emu, ED->dword[0]);
break;
default:
ip-=2;
UnimpOpcode(emu);
}
break;
default:
ip-=2;
UnimpOpcode(emu);
}
break;
case 0x69: /* IMUL Gd,Ed,Id */
nextop = F8;
GET_ED_OFFS(tlsdata);
tmp32u = F32;
GD.dword[0] = imul32(emu, ED->dword[0], tmp32u);
break;
case 0x80: /* GRP Eb,Ib */
case 0x82: // 0x82 and 0x80 are the same opcodes it seems?
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = F8;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GET_ED_OFFS(tlsdata);
if(opcode==0x83) {
tmp32s = F8S;
tmp32u = (uint32_t)tmp32s;
} else
tmp32u = F32;
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
break;
case 0x89: /* MOV Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8F: /* POP Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0xA1: /* MOV EAX,Ov */
tmp32s = F32S;
R_EAX = *(uint32_t*)((tlsdata) + tmp32s);
break;
case 0xA2: /* MOV Ob,AL */
tmp32s = F32S;
*(uint8_t*)((tlsdata) + tmp32s) = R_AL;
break;
case 0xA3: /* MOV Od,EAX */
tmp32s = F32S;
*(uint32_t*)((tlsdata) + tmp32s) = R_EAX;
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = F8/* & 0x1f*/; // masking done in each functions
switch((nextop>>3)&7) {
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
case 4:
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0xC6: /* MOV Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
EB->byte[0] = F8;
break;
case 0xC7: /* MOV Ed,Id */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = F32;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
switch((nextop>>3)&7) {
case 0: /* INC Ed */
ED->dword[0] = inc32(emu, ED->dword[0]);
break;
case 1: /* DEC Ed */
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
Push(emu, R_EIP);
R_EIP = ED->dword[0]; // should get value in temp var. in case ED use ESP?
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
} else {
Push16(emu, R_CS);
Push(emu, R_EIP);
R_EIP = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 4: /* JMP NEAR Ed */
R_EIP = ED->dword[0];
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
} else {
R_EIP = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 6: /* Push Ed */
Push(emu, ED->dword[0]);
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
ip-=2;
emu->quit=1;
emu->error |= ERR_ILLEGAL;
}
break;
default:
ip--;
UnimpOpcode(emu);
}
R_EIP = ip;
}
+369 -48
View File
@@ -4,61 +4,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_TRACE
#include <unistd.h>
#include <sys/syscall.h>
#endif
#include "debug.h"
#include "stack.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86run_private.h"
#include "x86emu_private.h"
#include "box86context.h"
#include "x86run.h"
#include "librarian.h"
#include "elfloader.h"
#ifdef HAVE_TRACE
#include "x86trace.h"
#endif
#include "x86tls.h"
static uint32_t x86emu_parity_tab[8] =
{
0x96696996,
0x69969669,
0x69969669,
0x96696996,
0x69969669,
0x96696996,
0x96696996,
0x69969669,
};
#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define PARITY(x) (((emu->x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
//TODO: register rtld_fini
//TODO: register fini
// let's cheat and set all args...
Push(emu, (uint32_t)my_context->envv);
Push(emu, (uint32_t)my_context->argv);
Push(emu, (uint32_t)my_context->argc);
if(init) {
PushExit(emu);
R_EIP=(uint32_t)*init;
printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
Run(emu);
DynaRun(emu);
if(emu->error) // any error, don't bother with more
return 0;
emu->quit = 0;
}
// let's cheat and set all args...
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
// call main and finish
Push(emu, (uint32_t)emu->context->envv);
Push(emu, (uint32_t)emu->context->argv);
Push(emu, (uint32_t)emu->context->argc);
PushExit(emu);
R_EIP=(uint32_t)main;
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", emu->context->argc, emu->context->argv, emu->context->envv, main);
#ifdef DYNAREC
DynaRun(emu);
#endif
return 0;
}
const char* GetNativeName(void* p)
{
static char unknown[10] = "???";
const char *ret = GetNameOffset(my_context->maplib, p);
if(ret)
return ret;
static char buff[500] = {0};
Dl_info info;
if(dladdr(p, &info)==0)
strcpy(buff, "???");
return unknown;
else {
if(info.dli_sname) {
strcpy(buff, info.dli_sname);
@@ -66,18 +72,11 @@ const char* GetNativeName(void* p)
strcat(buff, " ("); strcat(buff, info.dli_fname); strcat(buff, ")");
}
} else
strcpy(buff, "unknown");
return unknown;
}
return buff;
}
uintptr_t pltResolver = ~0;
void PltResolver(x86emu_t* emu, uint32_t id, uintptr_t ofs)
{
printf_log(LOG_INFO, "PltResolver: Ofs=%p, Id=%d (IP=%p)", (void*)ofs, id, *(void**)(R_ESP));
emu->quit=1;
}
void UpdateFlags(x86emu_t *emu)
{
uint32_t cc;
@@ -111,7 +110,7 @@ void UpdateFlags(x86emu_t *emu)
lo = (emu->op2 & 0xFFFF) + (emu->op1 & 0xFFFF);
hi = (lo >> 16) + (emu->op2 >> 16) + (emu->op1 >> 16);
CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
@@ -124,7 +123,7 @@ void UpdateFlags(x86emu_t *emu)
CLEAR_FLAG(F_AF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res), F_PF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
break;
case d_and16:
CLEAR_FLAG(F_OF);
@@ -160,7 +159,7 @@ void UpdateFlags(x86emu_t *emu)
break;
case d_dec32:
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
@@ -183,20 +182,91 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_inc32:
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (1 & emu->op1) | ((~emu->res) & (1 | emu->op1));
CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_imul8:
lo = emu->res & 0xff;
hi = (emu->res>>8)&0xff;
if (((lo & 0x80) == 0 && hi == 0x00) ||
((lo & 0x80) != 0 && hi == 0xFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
break;
case d_imul16:
lo = (uint16_t)emu->res;
hi = (uint16_t)(emu->res >> 16);
if (((lo & 0x8000) == 0 && hi == 0x00) ||
((lo & 0x8000) != 0 && hi == 0xFFFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
break;
case d_imul32:
if (((emu->res & 0x80000000) == 0 && emu->op1 == 0x00) ||
((emu->res & 0x80000000) != 0 && emu->op1 == 0xFFFFFFFF)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
break;
case d_mul8:
lo = emu->res & 0xff;
hi = (emu->res>>8)&0xff;
if (hi == 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
break;
case d_mul16:
lo = (uint16_t)emu->res;
hi = (uint16_t)(emu->res >> 16);
if (hi == 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
break;
case d_mul32:
if (emu->op1 == 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
} else {
SET_FLAG(F_CF);
SET_FLAG(F_OF);
}
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
break;
case d_or8:
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_AF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res), F_PF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
break;
case d_or16:
CLEAR_FLAG(F_OF);
@@ -218,7 +288,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res), F_PF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = emu->res | emu->op1;
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -234,7 +304,7 @@ void UpdateFlags(x86emu_t *emu)
break;
case d_neg32:
CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = emu->res | emu->op1;
@@ -291,7 +361,7 @@ void UpdateFlags(x86emu_t *emu)
if (emu->op2 > 0) {
cc = emu->op1 & (1 << (32 - emu->op2));
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
}
@@ -402,7 +472,7 @@ void UpdateFlags(x86emu_t *emu)
if (cnt > 0) {
cc = emu->op1 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
}
@@ -430,7 +500,7 @@ void UpdateFlags(x86emu_t *emu)
break;
case d_sub32:
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
@@ -441,7 +511,7 @@ void UpdateFlags(x86emu_t *emu)
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res), F_PF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_AF);
break;
@@ -461,6 +531,155 @@ void UpdateFlags(x86emu_t *emu)
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_AF);
break;
case d_cmp8:
CLEAR_FLAG(F_CF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_cmp16:
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_cmp32:
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_tst8:
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
break;
case d_tst16:
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
break;
case d_tst32:
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
break;
case d_adc8:
CONDITIONAL_SET_FLAG(emu->res & 0x100, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_adc16:
CONDITIONAL_SET_FLAG(emu->res & 0x10000, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_adc32:
if(emu->res == (emu->op1+emu->op2)) {
lo = (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
} else {
lo = 1 + (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
}
hi = (lo >> 16) + (emu->op1 >> 16) + (emu->op2 >> 16);
CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op2 & emu->op1) | ((~emu->res) & (emu->op2 | emu->op1));
CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_sbb8:
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_sbb16:
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_sbb32:
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_rol8:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 7)) & 1, F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
break;
case d_rol16:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 15)) & 1, F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
break;
case d_rol32:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 31)) & 1, F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
break;
case d_ror8:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & (1 << 7), F_CF);
break;
case d_ror16:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & (1 << 15), F_CF);
break;
case d_ror32:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & (1 << 31), F_CF);
break;
case d_unknown:
printf_log(LOG_NONE, "Box86: %p trying to evaluate Unknown defered Flags\n", (void*)R_EIP);
break;
}
RESET_FLAGS(emu);
}
@@ -469,12 +688,13 @@ void UpdateFlags(x86emu_t *emu)
void PackFlags(x86emu_t* emu)
{
#define GO(A) emu->packed_eflags.f.F__##A = emu->flags[F_##A];
#define GOC(A, C) emu->packed_eflags.f.F__##A = C;
GO(CF);
GO(res1);
GOC(res1, 1);
GO(PF);
GO(res2);
GOC(res2, 0);
GO(AF);
GO(res3);
GOC(res3, 0);
GO(ZF);
GO(SF);
GO(TF);
@@ -483,7 +703,7 @@ void PackFlags(x86emu_t* emu)
GO(OF);
GO(IOPL);
GO(NT);
GO(dummy);
GOC(dummy, 0);
GO(RF);
GO(VM);
GO(AC);
@@ -491,16 +711,18 @@ void PackFlags(x86emu_t* emu)
GO(VIP);
GO(ID);
#undef GO
#undef GOC
}
void UnpackFlags(x86emu_t* emu)
{
#define GO(A) emu->flags[F_##A] = emu->packed_eflags.f.F__##A;
#define GOC(A, C) emu->flags[F_##A] = C;
GO(CF);
GO(res1);
GOC(res1, 1);
GO(PF);
GO(res2);
GOC(res2, 0);
GO(AF);
GO(res3);
GOC(res3, 0);
GO(ZF);
GO(SF);
GO(TF);
@@ -509,7 +731,7 @@ void UnpackFlags(x86emu_t* emu)
GO(OF);
GO(IOPL);
GO(NT);
GO(dummy);
GOC(dummy, 0);
GO(RF);
GO(VM);
GO(AC);
@@ -517,4 +739,103 @@ void UnpackFlags(x86emu_t* emu)
GO(VIP);
GO(ID);
#undef GO
#undef GOC
}
uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg)
{
if(!emu->segs_clean[seg] || seg==_GS) {
emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
emu->segs_clean[seg] = 1;
}
return emu->segs_offs[seg];
}
const char* getAddrFunctionName(uintptr_t addr)
{
static char ret[1000];
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
if(addr==start)
sprintf(ret, "%s/%s", ElfName(FindElfAddress(my_context, addr)), symbname);
else
sprintf(ret, "%s/%s + %d", ElfName(FindElfAddress(my_context, addr)), symbname, addr - start);
} else
sprintf(ret, "???");
return ret;
}
void printFunctionAddr(uintptr_t nextaddr, const char* text)
{
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
if(nextaddr==start)
printf_log(LOG_NONE, " (%s%s/%s)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname);
else
printf_log(LOG_NONE, " (%s%s/%s + %d)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname, nextaddr - start);
}
}
#ifdef HAVE_TRACE
extern uint64_t start_cnt;
#define PK(a) (*(uint8_t*)(ip+a))
#define PK32(a) (*(int32_t*)((uint8_t*)(ip+a)))
void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
{
if(start_cnt) --start_cnt;
if(!start_cnt && my_context->dec && (
(trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) ) {
pthread_mutex_lock(&my_context->mutex_trace);
int tid = syscall(SYS_gettid);
#ifdef DYNAREC
if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
my_context->trace_tid = tid;
my_context->trace_dynarec = dynarec;
}
#else
if(my_context->trace_tid != tid) {
printf_log(LOG_NONE, "Thread %04d|\n", tid);
my_context->trace_tid = tid;
}
#endif
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
uint32_t a = *(uint32_t*)(ip+3);
if(a==0) {
printf_log(LOG_NONE, "%p: Exit x86emu\n", (void*)ip);
} else {
printf_log(LOG_NONE, "%p: Native call to %p => %s\n", (void*)ip, (void*)a, GetNativeName(*(void**)(ip+7)));
}
} else {
printf_log(LOG_NONE, "%s", DecodeX86Trace(my_context->dec, ip));
uint8_t peek = PK(0);
if(peek==0xC3 || peek==0xC2) {
printf_log(LOG_NONE, " => %p", *(void**)(R_ESP));
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
} else if(peek==0x55) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_ESP));
printFunctionAddr(ip, "here: ");
} else if(peek==0xE8) { // Call
uintptr_t nextaddr = ip + 5 + PK32(1);
printFunctionAddr(nextaddr, "=> ");
} else if(peek==0xFF) {
if(PK(1)==0x25) {
uintptr_t nextaddr = ip + 6 + PK32(2);
printFunctionAddr(nextaddr, "=> ");
}
}
printf_log(LOG_NONE, "\n");
}
pthread_mutex_unlock(&my_context->mutex_trace);
}
}
#endif
@@ -6,42 +6,42 @@
#include "x86emu_private.h"
typedef struct x86emu_s x86emu_t;
inline uint8_t Fetch8(x86emu_t *emu) {return *(uint8_t*)(R_EIP++);}
inline int8_t Fetch8s(x86emu_t *emu) {return *(int8_t*)(R_EIP++);}
inline uint16_t Fetch16(x86emu_t *emu)
static inline uint8_t Fetch8(x86emu_t *emu) {return *(uint8_t*)(R_EIP++);}
static inline int8_t Fetch8s(x86emu_t *emu) {return *(int8_t*)(R_EIP++);}
static inline uint16_t Fetch16(x86emu_t *emu)
{
uint16_t val = *(uint16_t*)R_EIP;
R_EIP+=2;
return val;
}
inline int16_t Fetch16s(x86emu_t *emu)
static inline int16_t Fetch16s(x86emu_t *emu)
{
int16_t val = *(int16_t*)R_EIP;
R_EIP+=2;
return val;
}
inline uint32_t Fetch32(x86emu_t *emu)
static inline uint32_t Fetch32(x86emu_t *emu)
{
uint32_t val = *(uint32_t*)R_EIP;
R_EIP+=4;
return val;
}
inline int32_t Fetch32s(x86emu_t *emu)
static inline int32_t Fetch32s(x86emu_t *emu)
{
int32_t val = *(int32_t*)R_EIP;
R_EIP+=4;
return val;
}
inline uint8_t Peek(x86emu_t *emu, int offset){return *(uint8_t*)(R_EIP + offset);}
static inline uint8_t Peek(x86emu_t *emu, int offset){return *(uint8_t*)(R_EIP + offset);}
inline uint32_t Pop(x86emu_t *emu)
static inline uint32_t Pop(x86emu_t *emu)
{
uint32_t* st = ((uint32_t*)(R_ESP));
R_ESP += 4;
return *st;
}
inline void Push(x86emu_t *emu, uint32_t v)
static inline void Push(x86emu_t *emu, uint32_t v)
{
R_ESP -= 4;
*((uint32_t*)R_ESP) = v;
@@ -122,6 +122,33 @@ static inline reg32_t* GetEw16(x86emu_t *emu, uint32_t v)
}
}
static inline reg32_t* GetEw16off(x86emu_t *emu, uint32_t v, uintptr_t offset)
{
uint32_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)];
} else {
uint32_t base = 0;
switch(m&7) {
case 0: base = R_BX+R_SI; break;
case 1: base = R_BX+R_DI; break;
case 2: base = R_BP+R_SI; break;
case 3: base = R_BP+R_DI; break;
case 4: base = R_SI; break;
case 5: base = R_DI; break;
case 6: base = R_BP; break;
case 7: base = R_BX; break;
}
switch((m>>6)&3) {
case 0: if(m==6) base = Fetch16(emu); break;
case 1: base += Fetch8s(emu); break;
case 2: base += Fetch16s(emu); break;
// case 3 is C0..C7, already dealt with
}
return (reg32_t*)(base+offset);
}
}
static inline mmx_regs_t* GetEm(x86emu_t *emu, uint32_t v)
{
uint32_t m = v&0xC7; // filter Ed
@@ -172,15 +199,26 @@ void Run0F(x86emu_t *emu);
void Run660F(x86emu_t *emu);
void Run66D9(x86emu_t *emu); // x87
void Run6766(x86emu_t *emu);
void RunGS(x86emu_t *emu);
void RunFS(x86emu_t *emu);
void RunLock(x86emu_t *emu);
void x86Syscall(x86emu_t *emu);
void x86Int3(x86emu_t* emu);
x86emu_t* x86emu_fork(x86emu_t* e);
x86emu_t* x86emu_fork(x86emu_t* e, int forktype);
void PackFlags(x86emu_t* emu);
void UnpackFlags(x86emu_t* emu);
uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg);
#define GetGSBaseEmu(emu) GetSegmentBaseEmu(emu, _GS)
#define GetFSBaseEmu(emu) GetSegmentBaseEmu(emu, _FS)
#define GetESBaseEmu(emu) GetSegmentBaseEmu(emu, _ES)
const char* GetNativeName(void* p);
#ifdef HAVE_TRACE
void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec);
#endif
#endif //__X86RUN_PRIVATE_H_
+668
View File
@@ -0,0 +1,668 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h> /* For SYS_xxx definitions */
#include <unistd.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <asm/stat.h>
#include <errno.h>
#include <sched.h>
#include <sys/wait.h>
#include <sys/utsname.h>
#ifndef __NR_socketcall
#include <linux/net.h>
#include <sys/socket.h>
#endif
#include <sys/resource.h>
#include <poll.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "myalign.h"
#include "box86context.h"
#include "callback.h"
#include "signals.h"
#include "x86tls.h"
#ifndef __NR_socketcall
#ifndef SYS_RECVMMSG
#define SYS_RECVMMSG 19
#endif
#ifndef SYS_SENDMMSG
#define SYS_SENDMMSG 20
#endif
int32_t my_accept4(x86emu_t* emu, int32_t fd, void* a, void* l, int32_t flags); // not always present, so used wrapped version
#ifdef SYS_RECVMMSG
int32_t my_recvmmsg(x86emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, uint32_t flags, void* timeout);
int32_t my___sendmmsg(x86emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, uint32_t flags);
#endif
#endif
typedef struct x86_sigaction_s x86_sigaction_t;
int32_t my_getrandom(x86emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
int of_convert(int flag);
int32_t my_open(x86emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
#ifndef NOALIGN
int my_epoll_create(x86emu_t* emu, int size);
int my_epoll_create1(x86emu_t* emu, int flags);
int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void* event);
int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
#endif
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
#define O_NONBLOCK 04000
#endif
#undef fcntl
int fcntl(int fd, int cmd, ... /* arg */ );
// Syscall table for x86 can be found here: http://shell-storm.org/shellcode/files/syscalls.html
typedef struct scwrap_s {
int x86s;
int nats;
int nbpars;
} scwrap_t;
scwrap_t syscallwrap[] = {
{ 2, __NR_fork, 1 }, // should wrap this one, because of the struct pt_regs (the only arg)?
//{ 3, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
//{ 4, __NR_write, 3 }, // same
//{ 5, __NR_open, 3 }, // flags need transformation
//{ 6, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
#ifdef __NR_waitpid
{ 7, __NR_waitpid, 3 },
#endif
{ 10, __NR_unlink, 1 },
{ 12, __NR_chdir, 1 },
#ifdef __NR_time
{ 13, __NR_time, 1 },
#endif
{ 15, __NR_chmod, 2 },
{ 19, __NR_lseek, 3 },
{ 20, __NR_getpid, 0 },
{ 24, __NR_getuid, 0 },
{ 33, __NR_access, 2 },
{ 37, __NR_kill, 2 },
{ 38, __NR_rename, 2 },
{ 39, __NR_mkdir, 2 },
{ 40, __NR_rmdir, 1 },
{ 41, __NR_dup, 1 },
{ 42, __NR_pipe, 1 },
{ 45, __NR_brk, 1 },
{ 47, __NR_getgid, 0 },
{ 49, __NR_geteuid, 0 },
{ 50, __NR_getegid, 0 },
{ 54, __NR_ioctl, 3 }, // should be wrapped to allow SA_RESTART handling by libc, but syscall is only 3 arguments, ioctl can be 5
//{ 55, __NR_fcntl, 3 }, // wrapped to allow filter of F_SETFD
{ 60, __NR_umask, 1 },
{ 63, __NR_dup2, 2 },
{ 64, __NR_getppid, 0 },
{ 66, __NR_setsid, 0 },
{ 75, __NR_setrlimit, 2 },
#ifdef __NR_getrlimit
{ 76, __NR_getrlimit, 2 },
#endif
{ 77, __NR_getrusage, 2 },
{ 78, __NR_gettimeofday, 2 },
{ 83, __NR_symlink, 2 },
#ifdef __NR_select
{ 82, __NR_select, 5 },
#endif
{ 85, __NR_readlink, 3 },
{ 91, __NR_munmap, 2 },
{ 94, __NR_fchmod, 2 },
{ 99, __NR_statfs, 2 },
#ifdef __NR_socketcall
{ 102, __NR_socketcall, 2 },
#endif
{ 104, __NR_setitimer, 3 },
{ 105, __NR_getitimer, 2 },
#ifdef __NR_newstat
{ 106, __NR_newstat, 2 },
#else
{ 106, __NR_stat, 2 },
#endif
#ifdef __NR_newlstat
{ 107, __NR_newlstat, 2 },
#else
{ 107, __NR_lstat, 2 },
#endif
#ifdef __NR_newfstat
{ 108, __NR_newfstat, 2 },
#else
{ 108, __NR_fstat, 2 },
#endif
#ifdef __NR_olduname
{ 109, __NR_olduname, 1 },
#endif
#ifdef __NR_iopl
{ 110, __NR_iopl, 1 },
#endif
{ 114, __NR_wait4, 4 }, //TODO: check struct rusage alignment
#ifdef __NR_ipc
{ 117, __NR_ipc, 6 },
#endif
//{ 119, __NR_sigreturn, 0},
//{ 120, __NR_clone, 5 }, // need works
//{ 122, __NR_uname, 1 },
//{ 123, __NR_modify_ldt },
{ 125, __NR_mprotect, 3 },
{ 136, __NR_personality, 1 },
{ 140, __NR__llseek, 5 },
{ 141, __NR_getdents, 3 },
{ 142, __NR__newselect, 5 },
{ 143, __NR_flock, 2 },
{ 144, __NR_msync, 3 },
{ 145, __NR_readv, 3 },
{ 146, __NR_writev, 3 },
{ 148, __NR_fdatasync, 1 },
{ 149, __NR__sysctl, 1 }, // need wrapping?
{ 156, __NR_sched_setscheduler, 3 },
{ 157, __NR_sched_getscheduler, 1 },
{ 158, __NR_sched_yield, 0 },
{ 162, __NR_nanosleep, 2 },
{ 164, __NR_setresuid, 3 },
//{ 168, __NR_poll, 3 }, // wrapped to allow SA_RESTART wrapping by libc
{ 172, __NR_prctl, 5 },
//{ 173, __NR_rt_sigreturn, 0 },
{ 175, __NR_rt_sigprocmask, 4 },
{ 179, __NR_rt_sigsuspend, 2 },
{ 183, __NR_getcwd, 2 },
{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something?
{ 191, __NR_ugetrlimit, 2 },
{ 192, __NR_mmap2, 6},
//{ 195, __NR_stat64, 2 }, // need proprer wrap because of structure size change
//{ 196, __NR_lstat64, 2 }, // need proprer wrap because of structure size change
//{ 197, __NR_fstat64, 2 }, // need proprer wrap because of structure size change
{ 199, __NR_getuid32, 0 },
{ 200, __NR_getgid32, 0 },
{ 201, __NR_geteuid32, 0 },
{ 202, __NR_getegid32, 0 },
{ 208, __NR_setresuid32, 3 },
{ 220, __NR_getdents64, 3 },
//{ 221, __NR_fcntl64, 3 },
{ 224, __NR_gettid, 0 },
{ 240, __NR_futex, 6 },
{ 252, __NR_exit_group, 1 },
#ifdef NOALIGN
{ 254, __NR_epoll_create, 1 },
{ 255, __NR_epoll_ctl, 4 },
{ 256, __NR_epoll_wait, 4 },
#endif
{ 265, __NR_clock_gettime, 2 },
{ 266, __NR_clock_getres, 2 },
//{ 270, __NR_tgkill, 3 },
{ 271, __NR_utimes, 2 },
{ 311, __NR_set_robust_list, 2 },
{ 312, __NR_get_robust_list, 4 },
#ifdef NOALIGN
{ 329, __NR_epoll_create1, 1 },
#endif
#ifdef __NR_getrandom
{ 355, __NR_getrandom, 3 },
#endif
};
struct mmap_arg_struct {
unsigned long addr;
unsigned long len;
unsigned long prot;
unsigned long flags;
unsigned long fd;
unsigned long offset;
};
#undef st_atime
#undef st_ctime
#undef st_mtime
struct x86_pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
int xfs;
int xgs;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
#ifndef __NR_olduname
struct oldold_utsname {
char sysname[9];
char nodename[9];
char release[9];
char version[9];
char machine[9];
};
#endif
struct old_utsname {
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
};
struct i386_user_desc {
unsigned int entry_number;
unsigned long base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
};
int clone_fn(void* arg)
{
x86emu_t *emu = (x86emu_t*)arg;
R_EAX = 0;
DynaRun(emu);
int ret = R_EAX;
FreeX86Emu(&emu);
return ret;
}
void EXPORT x86Syscall(x86emu_t *emu)
{
RESET_FLAGS(emu);
uint32_t s = R_EAX;
printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p", (void*)R_EIP, s, s, (void*)R_EBX, (void*)R_ECX, (void*)R_EDX, (void*)R_ESI, (void*)R_EDI);
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
for (int i=0; i<cnt; i++) {
if(syscallwrap[i].x86s == s) {
int sc = syscallwrap[i].nats;
switch(syscallwrap[i].nbpars) {
case 0: *(int32_t*)&R_EAX = syscall(sc); break;
case 1: *(int32_t*)&R_EAX = syscall(sc, R_EBX); break;
case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break;
case 3: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break;
case 4: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break;
case 5: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break;
case 6: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break;
default:
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars);
emu->quit = 1;
return;
}
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
return;
}
}
switch (s) {
case 1: // sys_exit
emu->quit = 1;
emu->exit = 1;
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the program now
break;
case 3: // sys_read
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
break;
case 4: // sys_write
R_EAX = (uint32_t)write((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
break;
case 5: // sys_open
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_EBX, of_convert(R_ECX), R_EDX);};
//R_EAX = (uint32_t)open((void*)R_EBX, of_convert(R_ECX), R_EDX);
R_EAX = (uint32_t)my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
break;
case 6: // sys_close
R_EAX = (uint32_t)close((int)R_EBX);
break;
#ifndef __NR_waitpid
case 7: //sys_waitpid
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, (int)R_EDX);
break;
#endif
case 11: // sys_execve
{
char* prog = (char*)R_EBX;
char** argv = (char**)R_ECX;
char** envv = (char**)R_EDX;
printf_log(LOG_DUMP, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
R_EAX = execve((const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
}
break;
#ifndef __NR_time
case 13: // sys_time (it's deprecated and remove on ARM EABI it seems)
R_EAX = time(NULL);
break;
#endif
case 54: // sys_ioctl
R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
break;
case 55: // sys_fcntl
if(R_ECX==4) {
// filter out O_NONBLOCK so old stacally linked games that access X11 don't get EAGAIN error sometimes
int tmp = of_convert((int)R_EDX)&(~O_NONBLOCK);
if(R_EDX==0xFFFFF7FF) {
// special case for ~O_NONBLOCK...
int flags = fcntl(R_EBX, 3);
tmp = flags&~O_NONBLOCK;
}
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, tmp);
} else
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX);
break;
#ifndef __NR_getrlimit
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
break;
#endif
#ifndef __NR_select
case 82: // select
R_EAX = select(R_EBX, (fd_set*)R_ECX, (fd_set*)R_EDX, (fd_set*)R_ESI, (struct timeval*)R_EDI);
break;
#endif
case 90: // old_mmap
{
struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX;
R_EAX = (uintptr_t)mmap((void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
}
break;
#ifndef __NR_socketcall
case 102: {
unsigned long *args = (unsigned long *)R_ECX;
// need to do all call "by hand"
switch(R_EBX) {
case SYS_SOCKET: R_EAX = socket(args[0], args[1], args[2]); break;
case SYS_BIND: R_EAX = bind(args[0], (void*)args[1], args[2]); break;
case SYS_CONNECT: R_EAX = connect(args[0], (void*)args[1], args[2]); break;
case SYS_LISTEN: R_EAX = listen(args[0], args[1]); break;
case SYS_ACCEPT: R_EAX = accept(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_GETSOCKNAME: R_EAX = getsockname(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_GETPEERNAME: R_EAX = getpeername(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_SOCKETPAIR: R_EAX = socketpair(args[0], args[1], args[2], (int*)args[3]); break;
case SYS_SEND: R_EAX = send(args[0], (void*)args[1], args[2], args[3]); break;
case SYS_RECV: R_EAX = recv(args[0], (void*)args[1], args[2], args[3]); break;
case SYS_SENDTO: R_EAX = sendto(args[0], (void*)args[1], args[2], args[3], (void*)args[4], args[5]); break;
case SYS_RECVFROM: R_EAX = recvfrom(args[0], (void*)args[1], args[2], args[3], (void*)args[4], (void*)args[5]); break;
case SYS_SHUTDOWN: R_EAX = shutdown(args[0], args[1]); break;
case SYS_SETSOCKOPT: R_EAX = setsockopt(args[0], args[1], args[2], (void*)args[3], args[4]); break;
case SYS_GETSOCKOPT: R_EAX = getsockopt(args[0], args[1], args[2], (void*)args[3], (void*)args[4]); break;
case SYS_SENDMSG: R_EAX = sendmsg(args[0], (void*)args[1], args[2]); break;
case SYS_RECVMSG: R_EAX = recvmsg(args[0], (void*)args[1], args[2]); break;
case SYS_ACCEPT4: R_EAX = my_accept4(emu, args[0], (void*)args[1], (void*)args[2], args[3]); break;
#ifdef SYS_RECVMMSG
case SYS_RECVMMSG: R_EAX = my_recvmmsg(emu, args[0], (void*)args[1], args[2], args[3], (void*)args[4]); break;
case SYS_SENDMMSG: R_EAX = my___sendmmsg(emu, args[0], (void*)args[1], args[2], args[3]); break;
#endif
default:
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", R_EBX);
R_EAX = -1;
}
}
break;
#endif
#ifndef __NR_olduname
case 109: // olduname
{
struct utsname un;
R_EAX = uname(&un);
if(!R_EAX) {
struct oldold_utsname *old = (struct oldold_utsname*)R_EBX;
memcpy(old->sysname, un.sysname, 9);
memcpy(old->nodename, un.nodename, 9);
memcpy(old->release, un.release, 9);
memcpy(old->version, un.version, 9);
strcpy(old->machine, "i686");
}
}
break;
#endif
#ifndef __NR_iopl
case 110: // iopl
R_EAX = 0; // only on x86, so return 0...
break;
#endif
case 119: // sys_sigreturn
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
break;
case 120: // clone
{
//struct x86_pt_regs *regs = (struct x86_pt_regs *)R_EDI;
// lets duplicate the emu
void* stack_base = (void*)R_ECX;
int stack_size = 0;
if(!R_ECX) {
// allocate a new stack...
stack_size = 1024*1024;
stack_base = malloc(stack_size); // why not 1M... (normal operation do copy on write, simpler to just copy)
// copy value from old stack to new stack
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base-size_to_copy, (void*)R_ESP, size_to_copy);
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
SetESP(newemu, (uintptr_t)stack_base);
// setup registers
/*if(regs) {
SetEAX(newemu, regs->eax);
SetEBX(newemu, regs->ebx);
SetECX(newemu, regs->ecx);
SetEDX(newemu, regs->edx);
SetEDI(newemu, regs->edi);
SetESI(newemu, regs->esi);
SetEBP(newemu, regs->ebp);
SetESP(newemu, (uintptr_t)stack_base - size_to_copy);
}
SetESP(newemu, (uintptr_t)stack_base - size_to_copy);*/
void* mystack = (R_EBX&CLONE_VM)?malloc(1024*1024):NULL; // stack for own process... memory leak, but no practical way to remove it
int ret = clone(clone_fn, (void*)((R_EBX&CLONE_VM)?((uintptr_t)mystack+1024*1024):0), R_EBX, newemu, R_ESI, R_EDI, R_EBP);
//int r = syscall(__NR_clone, R_EBX, (R_EBX&CLONE_VM)?((uintptr_t)mystack):0, R_EDX, R_ESI, NULL); // cannot use that syscall in C: how to setup the stack?!
R_EAX = ret;
}
break;
case 122: // uname
{
struct utsname un;
R_EAX = uname(&un);
if(!R_EAX) {
struct old_utsname *old = (struct old_utsname*)R_EBX;
memcpy(old->sysname, un.sysname, 65);
memcpy(old->nodename, un.nodename, 65);
memcpy(old->release, un.release, 65);
memcpy(old->version, un.version, 65);
strcpy(old->machine, "i686");
}
}
break;
case 123: // SYS_modify_ldt
R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX);
break;
case 168: // sys_poll
R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX);
break;
case 173: // sys_rt_sigreturn
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
break;
case 174: // sys_rt_sigaction
//printf_log(LOG_NONE, "Warning, Ignoring sys_rt_sigaction(0x%02X, %p, %p)\n", R_EBX, (void*)R_ECX, (void*)R_EDX);
R_EAX = my_syscall_sigaction(emu, R_EBX, (void*)R_ECX, (void*)R_EDX, R_ESI);
break;
case 190: // vfork
{
int r = vfork();
R_EAX = r;
}
break;
case 195: // stat64
{
struct stat64 st;
unsigned int r = syscall(__NR_stat64, R_EBX, &st);
UnalignStat64(&st, (void*)R_ECX);
R_EAX = r;
}
break;
case 196: // lstat64
{
struct stat64 st;
unsigned int r = syscall(__NR_lstat64, R_EBX, &st);
UnalignStat64(&st, (void*)R_ECX);
R_EAX = r;
}
break;
case 197: // fstat64
{
struct stat64 st;
unsigned int r = syscall(__NR_fstat64, R_EBX, &st);
UnalignStat64(&st, (void*)R_ECX);
R_EAX = r;
}
break;
case 221: // sys_fcntl64
if(R_ECX==4) {
int tmp = of_convert((int)R_EDX);
R_EAX = (uint32_t)fcntl((int)R_EBX, R_ECX, tmp);
} else
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX);
break;
case 243: // set_thread_area
R_EAX = my_set_thread_area((thread_area_t*)R_EBX);
break;
#ifndef NOALIGN
case 254: // epoll_create
R_EAX = my_epoll_create(emu, (int)R_EBX);
break;
case 255: // epoll_ctl
R_EAX = my_epoll_ctl(emu, (int)R_EBX, (int)R_ECX, (int)R_EDX, (void*)R_ESI);
break;
case 256: // epoll_wait
R_EAX = my_epoll_wait(emu, (int)R_EBX, (void*)R_ECX, (int)R_EDX, (int)R_ESI);
break;
#endif
case 270: // tgkill
R_EAX = syscall(__NR_tgkill, R_EBX, R_ECX, R_EDX);
break;
#ifndef NOALIGN
case 329: // epoll_create1
R_EAX = my_epoll_create1(emu, of_convert(R_EBX));
break;
#endif
#ifndef __NR_getrandom
case 355: // getrandom
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
break;
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
emu->quit = 1;
emu->error |= ERR_UNIMPL;
return;
}
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
}
#define stack(n) (R_ESP+4+n)
#define i32(n) *(int32_t*)stack(n)
#define u32(n) *(uint32_t*)stack(n)
#define p(n) *(void**)stack(n)
uint32_t EXPORT my_syscall(x86emu_t *emu)
{
uint32_t s = u32(0);
printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
for (int i=0; i<cnt; i++) {
if(syscallwrap[i].x86s == s) {
int sc = syscallwrap[i].nats;
switch(syscallwrap[i].nbpars) {
case 0: return syscall(sc);
case 1: return syscall(sc, u32(4));
case 2: return syscall(sc, u32(4), u32(8));
case 3: return syscall(sc, u32(4), u32(8), u32(12));
case 4: return syscall(sc, u32(4), u32(8), u32(12), u32(16));
case 5: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20));
case 6: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20), u32(24));
default:
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars);
emu->quit = 1;
return 0;
}
}
}
switch (s) {
case 1: // __NR_exit
emu->quit = 1;
return u32(4); // faking the syscall here, we don't want to really terminate the program now
case 3: // sys_read
return (uint32_t)read(i32(4), p(8), u32(12));
case 4: // sys_write
return (uint32_t)write(i32(4), p(8), u32(12));
case 5: // sys_open
return my_open(emu, p(4), of_convert(u32(8)), u32(12));
case 6: // sys_close
return (uint32_t)close(i32(4));
case 123: // SYS_modify_ldt
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
case 174: // sys_rt_sigaction
return (uint32_t)my_sigaction(emu, i32(4), (x86_sigaction_t*)p(8), (x86_sigaction_t*)p(12));
case 243: // set_thread_area
return my_set_thread_area((thread_area_t*)p(4));
#ifndef NOALIGN
case 254: // epoll_create
return my_epoll_create(emu, i32(4));
case 255: // epoll_ctl
return my_epoll_ctl(emu, i32(4), i32(8), i32(12), p(16));
case 256: // epoll_wait
return my_epoll_wait(emu, i32(4), p(8), i32(12), i32(16));
#endif
case 270: //_NR_tgkill
/*if(!u32(12))*/ {
//printf("tgkill(%u, %u, %u) => ", u32(4), u32(8), u32(12));
uint32_t ret = (uint32_t)syscall(__NR_tgkill, u32(4), u32(8), u32(12));
//printf("%u (errno=%d)\n", ret, (ret==(uint32_t)-1)?errno:0);
return ret;
}/* else {
printf_log(LOG_INFO, "Warning: ignoring libc Syscall tgkill (%u, %u, %u)\n", u32(4), u32(8), u32(12));
}*/
return 0;
#ifndef NOALIGN
case 329: // epoll_create1
return my_epoll_create1(emu, of_convert(i32(4)));
#endif
#ifndef __NR_getrandom
case 355: // getrandom
return (uint32_t)my_getrandom(emu, p(4), u32(8), u32(12));
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
emu->quit = 1;
emu->error |= ERR_UNIMPL;
}
return 0;
}
+209
View File
@@ -0,0 +1,209 @@
// Handling of TLS calls, include x86 specifi set_thread_area
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86context.h"
#include "x86emu.h"
#include "x86tls.h"
#include "elfloader.h"
typedef struct thread_area_s
{
int entry_number;
uintptr_t base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
} thread_area_t;
static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
static void thread_key_alloc0() {
pthread_key_create(&my_context->segtls[0].key, NULL);
}
static void thread_key_alloc1() {
pthread_key_create(&my_context->segtls[1].key, NULL);
}
static void thread_key_alloc2() {
pthread_key_create(&my_context->segtls[2].key, NULL);
}
uint32_t my_set_thread_area(thread_area_t* td)
{
printf_log(LOG_DEBUG, "set_thread_area(%p[%d/base=%p/limit=%u/32bits:%u/%u/%u...])\n", td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only);
int isempty = 0;
// first, check if the "user_desc", here td, is "empty"
if(td->read_exec_only==1 && td->seg_not_present==1)
if( !td->base_addr
&& !td->limit
&& !td->seg_32bit
&& !td->contents
&& !td->limit_in_pages
&& !td->useable)
isempty = 1;
int idx = td->entry_number;
if(idx==-1) {
// find a free one
for (int i=0; i<3 && idx==-1; ++i)
if(!my_context->segtls[i].present)
idx=i;
if(idx==-1) {
errno = ESRCH;
return (uint32_t)-1;
}
idx+=7;
td->entry_number = idx;
}
if(isempty && (td->entry_number<7 || td->entry_number>7+2)) {
errno = EINVAL;
return (uint32_t)-1;
}
if(isempty) {
memset(&my_context->segtls[td->entry_number-7], 0, sizeof(base_segment_t));
return 0;
}
if((idx<7 || idx>7+2)) {
errno = EINVAL;
return (uint32_t)-1;
}
my_context->segtls[idx-7].base = td->base_addr;
my_context->segtls[idx-7].limit = td->limit;
my_context->segtls[idx-7].present = 1;
switch (idx-7) {
case 0: pthread_once(&thread_key_once0, thread_key_alloc0); break;
case 1: pthread_once(&thread_key_once1, thread_key_alloc1); break;
case 2: pthread_once(&thread_key_once2, thread_key_alloc2); break;
}
pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
return 0;
}
uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
{
printf_log(/*LOG_DEBUG*/LOG_INFO, "modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
if(!td) {
errno = EFAULT;
return (uint32_t)-1;
}
if(op!=0x11) {
errno = ENOSYS;
return (uint32_t)-1;
}
if(!td->seg_32bit) {
// not handling 16bits segments for now
errno = EINVAL;
return (uint32_t)-1;
}
int idx = td->entry_number - 7;
if(idx<0 || idx>2) {
errno = EINVAL;
return (uint32_t)-1;
}
/*
my_context->segtls[idx].base = td->base_addr;
my_context->segtls[idx].limit = td->limit;
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
*/
return 0;
}
#define POS_TLS 0x50
static tlsdatasize_t* setupTLSData(box86context_t* context)
{
// Setup the GS segment:
int dtsize = context->elfsize*8;
void *ptr = (char*)malloc(context->tlssize+4+POS_TLS+dtsize);
memcpy(ptr, context->tlsdata, context->tlssize);
tlsdatasize_t *data = (tlsdatasize_t*)calloc(1, sizeof(tlsdatasize_t));
data->tlsdata = ptr;
data->tlssize = context->tlssize;
pthread_setspecific(context->tlskey, data);
// copy canary...
memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize); // set to 0 remining bytes
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, 4); // put canary in place
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, 4);
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
memcpy((void*)(tlsptr+0x4), &dtp, 4);
if(dtsize) {
for (int i=0; i<context->elfsize; ++i) {
// set pointer
dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8), &dtp, 4);
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8+4), &i, 4); // index
}
}
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, 4); // address of vsyscall
return data;
}
void* fillTLSData(box86context_t *context)
{
pthread_mutex_lock(&context->mutex_lock);
tlsdatasize_t *data = setupTLSData(context);
pthread_mutex_unlock(&context->mutex_lock);
return data;
}
void* resizeTLSData(box86context_t *context, void* oldptr)
{
pthread_mutex_lock(&context->mutex_lock);
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
tlsdatasize_t *data = setupTLSData(context);
// copy the relevent old part, in case something changed
memcpy((void*)((uintptr_t)data->tlsdata+(context->tlssize-oldata->tlssize)), oldata->tlsdata, oldata->tlssize);
// all done, update new size, free old pointer and exit
pthread_mutex_unlock(&context->mutex_lock);
free_tlsdatasize(oldptr);
return data;
}
static void* GetSeg33Base()
{
tlsdatasize_t* ptr;
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) == NULL) {
ptr = (tlsdatasize_t*)fillTLSData(my_context);
}
if(ptr->tlssize != my_context->tlssize)
ptr = (tlsdatasize_t*)resizeTLSData(my_context, ptr);
return ptr->tlsdata+ptr->tlssize;
}
void* GetSegmentBase(uint32_t desc)
{
if(!desc) {
printf_log(LOG_NONE, "Warning, accessing segment NULL\n");
return NULL;
}
int base = desc>>3;
if(base==0xe || base==0xf)
return NULL; // regular value...
if(base==0x6)
return GetSeg33Base();
if(base>6 && base<10 && my_context->segtls[base-7].present) {
void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
return ptr;
}
printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc);
return NULL;
}
Loaded 100 of 425 files, more files were not shown because too many files have changed in this diff. Show more