mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 10:10:25 -10:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8153391dd7 | ||
|
|
2420f9ffdd | ||
|
|
b9fd1c6213 | ||
|
|
b5e6f92547 | ||
|
|
d2c391406e | ||
|
|
db1df82696 | ||
|
|
67380e2c00 | ||
|
|
b956b29f66 |
No files matched your search
@@ -19,7 +19,6 @@ on:
|
||||
- RPI4ARM64
|
||||
- SD845
|
||||
- TEGRAX1
|
||||
- ARM64
|
||||
build_type:
|
||||
description: 'Build type'
|
||||
required: true
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, ARM64]
|
||||
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845]
|
||||
type: [Release, Trace]
|
||||
os: [ubuntu-latest]
|
||||
include:
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
+7
-19
@@ -14,13 +14,11 @@ option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
|
||||
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
|
||||
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
|
||||
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
|
||||
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
|
||||
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
|
||||
option(RV64 "Set to ON if targeting an RISC-V RV64GC based device" ${RV64})
|
||||
option(PPC64LE "Set to ON if targeting an PowerPC 64 LE based device" ${PPC64LE})
|
||||
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
|
||||
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
|
||||
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
|
||||
@@ -48,13 +46,13 @@ if(PPC64LE)
|
||||
set(RV64_DYNAREC OFF CACHE BOOL "")
|
||||
set(PAGE16K OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR LX2160A OR M1 OR ARM64)
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A OR M1)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
set(RV64_DYNAREC OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR LX2160A)
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A)
|
||||
set(PAGE16K OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3588)
|
||||
@@ -139,17 +137,13 @@ elseif(TEGRAX1)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
|
||||
elseif(PHYTIUM)
|
||||
add_definitions(-DPHYTIUM)
|
||||
add_definitions(-DPHYSIUM)
|
||||
add_definitions(-pipe -march=armv8.1-a+crc+simd+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+crc+simd+crypto+aes")
|
||||
elseif(SD845)
|
||||
add_definitions(-DSD845)
|
||||
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
|
||||
elseif(SD888)
|
||||
add_definitions(-DSD888)
|
||||
add_definitions(-pipe -march=armv8.4-a+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.4-a+crypto")
|
||||
elseif(M1)
|
||||
add_definitions(-DM1)
|
||||
add_definitions(-pipe -march=armv8.5-a+simd+crypto)
|
||||
@@ -170,9 +164,6 @@ elseif(LX2160A)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto")
|
||||
elseif(SW64)
|
||||
add_definitions(-DSW64)
|
||||
elseif(ARM64)
|
||||
#add_definitions(-pipe -march=native)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+simd")
|
||||
elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
endif()
|
||||
@@ -318,7 +309,6 @@ set(INTERPRETER
|
||||
"${BOX64_ROOT}/src/emu/x64run66f0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67_32.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6764_32.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67660f.c"
|
||||
@@ -343,7 +333,6 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatomic.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcap.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairogobject.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
|
||||
@@ -370,7 +359,6 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgmp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgobject2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgomp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgstapp.c"
|
||||
@@ -751,10 +739,10 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "riscv64" _riscv64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "riscv64" _riscv64)
|
||||
|
||||
if(_x86_64 OR _aarch64)
|
||||
add_definitions(-DCONFIG_64BIT)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
|
||||
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
|
||||
|
||||
     
|
||||
|
||||
@@ -86,22 +86,23 @@ GTK libraries are now wrapped on box64, both gtk2 and gtk3.
|
||||
Notes about Steam
|
||||
----
|
||||
|
||||
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, and that steamwebhelper process is now mendatory, even on the "small mode". And that process will eat lots of memory. So machine with less the 6Gb of RAM will need a swapfile tp use Steam.
|
||||
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, but like most stuff using libcef/chromium, it's not working correctly on box64 for now.
|
||||
So, no Steam for now on box64.
|
||||
|
||||
----
|
||||
|
||||
Notes about Wine
|
||||
----
|
||||
|
||||
Wine64 is supported on box64. Proton too. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
|
||||
Note that the new 32bits PE in 64bits process that the Wine time in currently implementing in Wine 7.+ is now supported, but the support is quite young so there might be some residual issues.
|
||||
Wine64 is supported on box64. Proton should also work. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
|
||||
Note that the new 32bits PE in 64bits process that the Wine time in currently implementing in Wine 7.+ is not yet supported. I tested Wine 7.5 64bits and it worked, but more recent version will probably just not work yet.
|
||||
|
||||
----
|
||||
|
||||
Notes about Vulkan
|
||||
----
|
||||
|
||||
Box64 wraps Vulkan libraries, but note that it as mostly been tested with a AMD RX550 card and on the Freedreno driver, so some extensions may be missing depending on your graphics card.
|
||||
Box64 wraps Vulkan libraries, but note that it as only been tested with a RX550 card, so some extensions may be missing depending on your graphics card.
|
||||
|
||||
----
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ Linux 上用户空间的 x86_64 应用模拟器(支持运行原生库)
|
||||
----
|
||||

|
||||
|
||||
[English](docs/README.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md)
|
||||
[English](docs/README.md)
|
||||
|
||||
Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux 程序(比如游戏),注意主机系统需要是 64 位小端。
|
||||
|
||||
|
||||
-119
@@ -1,119 +0,0 @@
|
||||

|
||||
|
||||
Емулятор простіра користувача x86_64 із родзинкою
|
||||
|
||||
[Дивитись журнал змін](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box64/issues/new)
|
||||
|
||||
     
|
||||
|
||||
----
|
||||
|
||||
Box64 дозволяє запускати x86_64 Linux програми (наприклад, ігри) на системах Linux відмінних від x86_64, наприклад ARM (хост-система має мати 64-розрядний порядок редагування).
|
||||
|
||||
Ви можете знайти багато відео про Box64 в YouTube каналах [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) або [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
|
||||
|
||||
Оскільки Box64 використовує рідні версії деяких «системних» бібліотек, таких як libc, libm, SDL і OpenGL, його легко інтегрувати та використовувати з більшістю програм, а продуктивність у багатьох випадках може бути напрочуд високою. Подивіться на цей стендовий аналіз для прикладу [тут](https://box86.org/index.php/2021/06/game-performances/).
|
||||
|
||||
Box64 інтегрується з DynaRec (динамічний рекомпілятор) для платформ ARM64 і RV64 забезпечуючи підвищення швидкості в 5-10 разів, ніж використання лише інтерпретатора. Деякі високорівневі відомості про те, як працює DynaRec, можна знайти [тут](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
|
||||
|
||||
Деякі внутрішні коди операцій x64 використовують частини «Бібліотеки емулятора Realmode X86», дивіться [x64primop.c](src/emu/x64primop.c) для детальної інформації про авторські права.
|
||||
|
||||
<img src="docs/img/Box64Icon.png" width="96" height="96">
|
||||
|
||||
Логотип і піктограма зроблені @grayduck, дякую!
|
||||
|
||||
----
|
||||
|
||||
Використання
|
||||
----
|
||||
|
||||
Є кілька змінних середовища для керування поведінкою Box64.
|
||||
|
||||
Дивіться [тут](docs/USAGE.md) для перегляду всіх змінних середовища та того, що вони роблять.
|
||||
|
||||
Примітка: Dynarec від Box64 використовує механізм із захистом пам’яті та обробником сигналу помилки сегментів для обробки JIT коду. Простіше кажучи, якщо ви хочете використовувати GDB для налагодження запущеної програми, яка використовує JIT-код (наприклад, mono/Unity3D), ви все одно матимете багато «звичайних» помилок сегментів. Пропонується використовувати щось на зразок `handle SIGSEGV nostop` в GDB, щоб не зупинятися на кожній помилці сегмента, і, можливо, поставити точку зупину всередині `my_memprotectionhandler` в `signals.c`, якщо ви хочете перехопити помилки сегментів.
|
||||
|
||||
----
|
||||
Компіляція/Встановлення
|
||||
----
|
||||
> Інструкцію зі складання Box64 можна знайти [тут](docs/COMPILE.md).\
|
||||
> Інструкцію з встановлення Wine для Box64 можна знайти [тут](docs/X64WINE.md).
|
||||
|
||||
----
|
||||
|
||||
Історія версій/Журнал змін
|
||||
----
|
||||
|
||||
Історія версій доступна [тут](docs/CHANGELOG.md).
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо 32 бітних платформ
|
||||
----
|
||||
Оскільки Box64 працює шляхом прямого перекладу викликів функцій з x86_64 на хост-систему, хост-система (та, на якій працює Box64) повинна мати 64-розрядні бібліотеки. Box64 не містить 64-біт <-> 32-біт перекладу.
|
||||
|
||||
Також розумійте що Box64 запускатиме лише 64-розрядні двійкові Linux файли. Для 32-розрядних двійкових файлів вам потрібен Box86 (з усіма хитрощами з мультиархітектурною системою або корінними правами). Зауважте, що багато інсталяторів (на основі mojo) повертаються до "x86" при виявленні ОС ARM64, і тому намагатимуться використовувати Box86 для налаштування, навіть якщо існує версія x86_64. Ви можете зламати свій шлях за допомогою фальшивого "uname", який повертає "x86_64", коли аргумент "-m"
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо конфігурації Box64
|
||||
----
|
||||
|
||||
Обидва файли мають однаковий синтаксис і в основному є файлами ini. Розділ у квадратних дужках визначає назву процесу, а решта — встановлють змінну середовища. Подивіться [використання](USAGE.md), щоб дізнатися, які параметри можна завдати. Box64 поставляється з файлом за замовчуванням, який слід встановити для кращої стабільності. Файл знаходиться в `system/box64.box64rc` і має бути встановлен в `/etc/box64.box64rc`. Якщо з певних причин ви не хочете встановлювати цей файл у `/etc`, принаймні скопіюйте його в `~/.box64rc` або гра може не працювати належним чином. Зауважте, що пріоритетом є: `~/.bashrc` > `/etc/box64.box64rc` > командний рядок
|
||||
Таким чином, ваші налаштування в `~/.bashrc` можуть замінити налаштування з вашого командного рядка...
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо емуляції ігор Unity
|
||||
----
|
||||
|
||||
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
|
||||
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо програм GTK
|
||||
----
|
||||
|
||||
Бібліотеки GTK2 і GTK3 тепер використовуються в Box64.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Steam
|
||||
----
|
||||
|
||||
Зауважте, що Steam є гібридом 32-біт / 64-біт. Вам ПОТРІБЕН box86, щоб запустити Steam, оскільки клієнта є 32-розрядною двійковою програмою. Він також використовує 64-розрядні двійкові файли локального сервера, і цей процес steamwebhelper тепер є обов’язковим навіть у «малому режимі». І цей процес з’їсть багато оперативної пам’яті, таким чином машині з 6 Гб оперативної пам’яті знадобиться файл підкачки для використання Steam.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Wine
|
||||
----
|
||||
|
||||
Wine64 підтримується Box64, Proton теж. Майте на увазі, що 64-розрядний Wine також містить 32-розрядні компоненти щоб мати можливість запускати 32-розрядні програми Windows. Для 32-розрядних програм потрібен Box86, і вони не працюватимуть без нього. У системі, де присутні і працюють Box64, і Box86, 64-розрядне встановлення Wine може запускати як 32-розрядні, так і 64-розрядні програми Windows (просто використовуйте `wine` і `wine64` відповідно).
|
||||
Зауважте, що новий 32-бітний PE в 64-бітному процесі, який Wine зараз реалізує у Wine 7+ тепер підтримується, але підтримка є досить молодою тому можуть виникнути деякі проблеми.
|
||||
|
||||
----
|
||||
|
||||
Примітки щодо Vulkan
|
||||
----
|
||||
|
||||
Box64 використовує бібліотеки Vulkan, але зауважте що він тестувався з картою AMD Radeon RX550 і драйвером Freedreno, тому деякі розширення можуть бути відсутні залежно від вашої відеокарти.
|
||||
|
||||
----
|
||||
|
||||
Останнє слово
|
||||
----
|
||||
|
||||
Я хочу подякувати всім, хто зробив внесок у розвиток box64.
|
||||
Є багато способів зробити внесок: внесок коду, фінансовий внесок, апаратне забезпечення та реклама!
|
||||
Отже, без особливого порядку, я хочу подякувати:
|
||||
* За основний внесок у код: rajdakin, mogery
|
||||
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* За апаратне забезпечення та міграцію LoongArch: [xiaoji](https://www.linuxgame.cn/), команда розробників Deepin Beijing
|
||||
* За основний внесок у код RV64 Dynarec: ksco, xctan
|
||||
* За внесок у апаратне забезпечення: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
|
||||
* За безперервну рекламу Box64: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/Команда [TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
|
||||
І я також дякую багатьом іншим людям, які хоч раз брали участь у цьому проекті.
|
||||
|
||||
(Якщо ви використовуєте Box64 у своєму проекті, будь ласка, не забудьте згадати про це!)
|
||||
@@ -1,28 +1,3 @@
|
||||
v0.2.4
|
||||
======
|
||||
* Added Dynarec for RISC-V
|
||||
* Added partial 32 bits support (WoW64 works)
|
||||
* Changed cpuid to display box64
|
||||
* Fixed steam, again
|
||||
* Improved hacked version for overridden malloc/free functions
|
||||
* More wrapped libs
|
||||
* More wrapped functions and syscalls
|
||||
* Reduced memory footprint
|
||||
* Added support for the BIND_NOW flags in ELF files
|
||||
* Added RTLD_NOLOAD support
|
||||
* Fixed some typos and general cleanup, again
|
||||
* Added a cosimulation mode (to compare the behaviour of the dynarec with the interpreter)
|
||||
* Added FASTNAN/FASTROUND handling for more opcodes
|
||||
* Better float/double/long double handling
|
||||
* Better dlopen/dlclose handling
|
||||
* More games in the rc file
|
||||
* Added BOX64_DYNAREC_MISSING to show only missing opcode, independantly of the log level
|
||||
* Added BOX64_RESERVE_HIGH to reserve addresses above 47bits
|
||||
* Improved multitreading support
|
||||
* Ukrainian translation of the README
|
||||
=> Dynarec now support RISC-V, large speedup on RISC-V 64, were games are now playable (like Stardew Valley on a Vision Five 2)
|
||||
=> Improved compatibility with more fixes in elf handling, more wrapped libs and functiond, more fixed opcodes and refined profile
|
||||
|
||||
v0.2.2
|
||||
======
|
||||
* Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work.
|
||||
|
||||
Regular → Executable
+1
-8
@@ -7,7 +7,7 @@ You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to i
|
||||
```
|
||||
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
|
||||
wget -qO- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box64-debs-archive-keyring.gpg
|
||||
sudo apt update && sudo apt install box64-arm64 -y
|
||||
sudo apt update && sudo apt install box64-generic-arm -y
|
||||
```
|
||||
|
||||
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
|
||||
@@ -111,13 +111,6 @@ Using a 64bit OS:
|
||||
-D PHYTIUM=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for a generic ARM64 machine
|
||||
|
||||
Using a 64bit OS:
|
||||
```
|
||||
-D ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
#### for M1
|
||||
|
||||
Only test on Asahi for now, using the default "16K page" kernel
|
||||
|
||||
Regular → Executable
+5
@@ -212,6 +212,11 @@ Dynarec print the missing opcodes
|
||||
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
|
||||
* 1 : Will print the missing opcodes
|
||||
|
||||
#### BOX64_DYNAREC_AGE *
|
||||
Dynarec will check if black can be freed when that atteins a certain age (in dynablock creation count)
|
||||
* 0 : do not age dynablocks (don't try to free old one)
|
||||
* XXXX: try to free block that are at least XXXX old (default 10240)
|
||||
|
||||
#### BOX64_SSE_FLUSHTO0 *
|
||||
Handling of SSE Flush to 0 flags
|
||||
* 0 : Just track the flag (Default)
|
||||
|
||||
Regular → Executable
File mode changed.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Regular → Executable
File mode changed.
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
+1
-26
@@ -824,10 +824,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
allowed_regs : str = "cCwWiuIUlLp"
|
||||
allowed_fpr : str = "fd"
|
||||
|
||||
# Detect functions which return in an x87 register
|
||||
retx87_wraps: Dict[ClausesStr, List[FunctionType]] = {}
|
||||
return_x87: str = "DK"
|
||||
|
||||
# Sanity checks
|
||||
forbidden_simple: str = "EDKVOSNMHPAxX"
|
||||
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(allowed_conv.values))
|
||||
@@ -835,7 +831,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
assert(all(c not in allowed_simply + allowed_regs for c in allowed_fpr))
|
||||
assert(all(c not in allowed_simply + allowed_regs + allowed_fpr for c in forbidden_simple))
|
||||
assert(all(c in allowed_simply + allowed_regs + allowed_fpr + forbidden_simple for c in allowed_conv.values))
|
||||
assert(all(c in allowed_conv.values for c in return_x87))
|
||||
|
||||
def check_simple(v: FunctionType) -> Optional[int]:
|
||||
regs_count: int = 0
|
||||
@@ -872,15 +867,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
simple_wraps[k] = tmp
|
||||
simple_idxs = sorted(simple_wraps.keys(), key=lambda x: Clauses(x).splitdef())
|
||||
|
||||
def check_return_x87(v: FunctionType) -> bool:
|
||||
return v[0] in return_x87
|
||||
|
||||
for k in gbls:
|
||||
tmp = [v for v in gbls[k] if check_return_x87(v)]
|
||||
if tmp:
|
||||
retx87_wraps[k] = tmp
|
||||
retx87_idxs = sorted(retx87_wraps.keys(), key=lambda x: Clauses(x).splitdef())
|
||||
|
||||
# Now the files rebuilding part
|
||||
# File headers and guards
|
||||
files_header = {
|
||||
@@ -1395,17 +1381,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
file.write("#endif\n")
|
||||
file.write("\treturn 0;\n}\n")
|
||||
|
||||
# Write the isRetX87Wrapper function
|
||||
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
|
||||
for k in retx87_idxs:
|
||||
if k != str(Clauses()):
|
||||
file.write("#if " + k + "\n")
|
||||
for vf in retx87_wraps[k]:
|
||||
file.write("\tif (fun == &" + vf + ") return 1;\n")
|
||||
if k != str(Clauses()):
|
||||
file.write("#endif\n")
|
||||
file.write("\treturn 0;\n}\n")
|
||||
|
||||
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# Rewrite the wrapper.h file:
|
||||
@@ -1479,6 +1454,6 @@ if __name__ == '__main__':
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.18") != 0:
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.17") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
Regular → Executable
File mode changed.
Regular → Executable
-4
@@ -259,8 +259,6 @@ box64context_t *NewBox64Context(int argc)
|
||||
context->segtls[4].present = 1;
|
||||
context->segtls[4].is32bits = 1;
|
||||
|
||||
context->globdata = NewMapSymbols();
|
||||
|
||||
initAllHelpers(context);
|
||||
|
||||
return context;
|
||||
@@ -355,8 +353,6 @@ void FreeBox64Context(box64context_t** context)
|
||||
if(ctx->emu_sig)
|
||||
FreeX64Emu(&ctx->emu_sig);
|
||||
|
||||
FreeMapSymbols(&ctx->globdata);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifdef DYNAREC
|
||||
|
||||
Regular → Executable
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 2
|
||||
#define BOX64_REVISION 4
|
||||
#define BOX64_REVISION 3
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
+84
-4
@@ -73,6 +73,7 @@ typedef struct memprot_s
|
||||
uint8_t* prot;
|
||||
uint8_t* hot;
|
||||
} memprot_t;
|
||||
//#define TRACE_MEMSTAT
|
||||
#ifdef TRACE_MEMSTAT
|
||||
static uint64_t memprot_allocated = 0, memprot_max_allocated = 0;
|
||||
#endif
|
||||
@@ -481,6 +482,7 @@ void customFree(void* p)
|
||||
#define NCHUNK 64
|
||||
typedef struct mmaplist_s {
|
||||
blocklist_t chunks[NCHUNK];
|
||||
size_t minage[NCHUNK];
|
||||
mmaplist_t* next;
|
||||
} mmaplist_t;
|
||||
|
||||
@@ -522,11 +524,13 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
|
||||
#ifdef TRACE_MEMSTAT
|
||||
static uint64_t dynarec_allocated = 0;
|
||||
#endif
|
||||
uintptr_t AllocDynarecMap(size_t size)
|
||||
uintptr_t AllocDynarecMap(size_t size, size_t age)
|
||||
{
|
||||
if(!size)
|
||||
return 0;
|
||||
|
||||
static int current = 0;
|
||||
|
||||
size = roundSize(size);
|
||||
|
||||
mmaplist_t* list = mmaplist;
|
||||
@@ -534,8 +538,32 @@ uintptr_t AllocDynarecMap(size_t size)
|
||||
list = mmaplist = (mmaplist_t*)box_calloc(1, sizeof(mmaplist_t));
|
||||
// check if there is space in current open ones
|
||||
int i = 0;
|
||||
int current_i = 0;
|
||||
uintptr_t sz = size + 2*sizeof(blockmark_t);
|
||||
while(1) {
|
||||
size_t newage = 0;
|
||||
if(box64_dynarec_age && current==current_i && (!list->minage[i] || list->minage[i]<=age)) {
|
||||
//check age of blocks for cleaning
|
||||
blockmark_t* sub = (blockmark_t*)list->chunks[i].block;
|
||||
uintptr_t end = (uintptr_t)list->chunks[i].block+list->chunks[i].size-sizeof(blockmark_t);
|
||||
while(sub && (uintptr_t)sub<end) {
|
||||
blockmark_t* n = NEXT_BLOCK(sub);
|
||||
dynablock_t* db = NULL;
|
||||
if(n->next.fill)
|
||||
db = *(dynablock_t**)((uintptr_t)n+sizeof(blockmark_t));
|
||||
if(db) {
|
||||
size_t new_age = AgeDynablock(db, age);
|
||||
if(!new_age) // db has been removed
|
||||
n = sub; // go back 1 step
|
||||
else if(new_age<newage || !newage)
|
||||
newage = new_age;
|
||||
}
|
||||
sub = n;
|
||||
}
|
||||
list->minage[i] = newage;
|
||||
}
|
||||
if(current==current_i)
|
||||
current++;
|
||||
if(list->chunks[i].maxfree>=size) {
|
||||
// looks free, try to alloc!
|
||||
size_t rsize = 0;
|
||||
@@ -551,6 +579,8 @@ uintptr_t AllocDynarecMap(size_t size)
|
||||
}
|
||||
// check if new
|
||||
if(!list->chunks[i].size) {
|
||||
if(current_i+1==current)
|
||||
current = 0;
|
||||
// alloc a new block, aversized or not, we are at the end of the list
|
||||
size_t allocsize = (sz>MMAPSIZE)?sz:MMAPSIZE;
|
||||
// allign sz with pagesize
|
||||
@@ -576,6 +606,7 @@ uintptr_t AllocDynarecMap(size_t size)
|
||||
list->chunks[i].block = p;
|
||||
list->chunks[i].first = p;
|
||||
list->chunks[i].size = allocsize;
|
||||
list->minage[i] = age + box64_dynarec_age;
|
||||
// setup marks
|
||||
blockmark_t* m = (blockmark_t*)p;
|
||||
m->prev.x32 = 0;
|
||||
@@ -594,6 +625,7 @@ uintptr_t AllocDynarecMap(size_t size)
|
||||
}
|
||||
// next chunk...
|
||||
++i;
|
||||
++current_i;
|
||||
if(i==NCHUNK) {
|
||||
i = 0;
|
||||
if(!list->next)
|
||||
@@ -656,6 +688,51 @@ static uintptr_t getDBSize(uintptr_t addr, size_t maxsize, dynablock_t** db)
|
||||
return (addr&~JMPTABLE_MASK0)+idx0+1;
|
||||
}
|
||||
|
||||
void freeJmpTable(uintptr_t addr)
|
||||
{
|
||||
uintptr_t idx3, idx2, idx1, idx0;
|
||||
idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
|
||||
idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
|
||||
idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
|
||||
idx0 = (((uintptr_t)addr) )&JMPTABLE_MASK0;
|
||||
if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
|
||||
return;
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
return;
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
return;
|
||||
}
|
||||
uintptr_t* tbl0 = box64_jmptbl3[idx3][idx2][idx1];
|
||||
for(int i=0; i<1<<JMPTABL_SHIFT0; ++i)
|
||||
if(tbl0[i]!=(uintptr_t)native_next)
|
||||
return;
|
||||
box64_jmptbl3[idx3][idx2][idx1] = box64_jmptbldefault0;
|
||||
box_free(tbl0);
|
||||
#ifdef TRACE_MEMSTAT
|
||||
jmptbl_allocated -= (1<<JMPTABL_SHIFT0)*sizeof(uintptr_t);
|
||||
#endif
|
||||
uintptr_t** tbl1 = box64_jmptbl3[idx3][idx2];
|
||||
for(int i=0; i<1<<JMPTABL_SHIFT1; ++i)
|
||||
if(tbl1[i]!=box64_jmptbldefault0)
|
||||
return;
|
||||
box64_jmptbl3[idx3][idx2] = box64_jmptbldefault1;
|
||||
box_free(tbl1);
|
||||
#ifdef TRACE_MEMSTAT
|
||||
jmptbl_allocated -= (1<<JMPTABL_SHIFT1)*sizeof(uintptr_t*);
|
||||
#endif
|
||||
uintptr_t*** tbl2 = box64_jmptbl3[idx3];
|
||||
for(int i=0; i<1<<JMPTABL_SHIFT2; ++i)
|
||||
if(tbl2[i]!=box64_jmptbldefault1)
|
||||
return;
|
||||
box64_jmptbl3[idx3] = box64_jmptbldefault2;
|
||||
box_free(tbl2);
|
||||
#ifdef TRACE_MEMSTAT
|
||||
jmptbl_allocated -= (1<<JMPTABL_SHIFT2)*sizeof(uintptr_t**);
|
||||
#endif
|
||||
}
|
||||
|
||||
// each dynmap is 64k of size
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size)
|
||||
@@ -670,14 +747,18 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?"destroy":"mark");
|
||||
dynablock_t* db = NULL;
|
||||
uintptr_t end = addr+size;
|
||||
uintptr_t old_addr = 0;
|
||||
while (start_addr<end) {
|
||||
start_addr = getDBSize(start_addr, end-start_addr, &db);
|
||||
old_addr = getDBSize(start_addr, end-start_addr, &db);
|
||||
if(db) {
|
||||
if(destroy)
|
||||
FreeRangeDynablock(db, addr, size);
|
||||
else
|
||||
MarkRangeDynablock(db, addr, size);
|
||||
}
|
||||
/*if(destroy && start_addr && ((start_addr&~JMPTABLE_MASK0)!=(old_addr&~JMPTABLE_MASK0)))
|
||||
freeJmpTable(start_addr);*/ // cannot free jmpTable as some dynablock might rely on direct address (for fixed IP jmp/call)
|
||||
start_addr = old_addr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1463,7 +1544,7 @@ void init_custommem_helper(box64context_t* ctx)
|
||||
memprot[i].prot = memprot_default;
|
||||
init_mutexes();
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec) {
|
||||
if(box64_dynarec)
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT3); ++i)
|
||||
box64_jmptbl3[i] = box64_jmptbldefault2;
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT2); ++i)
|
||||
@@ -1472,7 +1553,6 @@ void init_custommem_helper(box64context_t* ctx)
|
||||
box64_jmptbldefault1[i] = box64_jmptbldefault0;
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT0); ++i)
|
||||
box64_jmptbldefault0[i] = (uintptr_t)native_next;
|
||||
}
|
||||
lockaddress = kh_init(lockaddress);
|
||||
#endif
|
||||
pthread_atfork(NULL, NULL, atfork_child_custommem);
|
||||
|
||||
Regular → Executable
+11
-42
@@ -363,9 +363,6 @@
|
||||
#define POP2_32(reg1, reg2) LDPw_S7_postindex(reg1, reg2, xRSP, 8)
|
||||
#define PUSH2_32(reg1, reg2) STPw_S7_preindex(reg2, reg1, xRSP, -8)
|
||||
|
||||
#define POP1_16(reg) LDRH_S9_postindex(reg, xRSP, 2)
|
||||
#define PUSH1_16(reg) STRH_S9_preindex(reg, xRSP, -2)
|
||||
|
||||
#define POP1z(reg) if(rex.is32bits) {POP1_32(reg);} else {POP1(reg);}
|
||||
#define PUSH1z(reg) if(rex.is32bits) {PUSH1_32(reg);} else {PUSH1(reg);}
|
||||
#define POP2z(reg1, reg2) if(rex.is32bits) {POP2_32(reg1, reg2);} else {POP2(reg1, reg2);}
|
||||
@@ -490,9 +487,9 @@
|
||||
#define CSNEGx(Rd, Rn, Rm, cond) EMIT(CSNEG_gen(1, Rm, cond, Rn, Rd))
|
||||
#define CSNEGw(Rd, Rn, Rm, cond) EMIT(CSNEG_gen(0, Rm, cond, Rn, Rd))
|
||||
#define CSNEGxw(Rd, Rn, Rm, cond) EMIT(CSNEG_gen(rex.w, Rm, cond, Rn, Rd))
|
||||
#define CNEGx(Rd, Rn, cond) CSNEGx(Rn, Rn, Rd, invCond(cond))
|
||||
#define CNEGw(Rd, Rn, cond) CSNEGw(Rn, Rn, Rd, invCond(cond))
|
||||
#define CNEGxw(Rd, Rn, cond) CSNEGxw(Rn, Rn, Rd, invCond(cond))
|
||||
#define CNEGx(Rd, Rn, cond) CSNEGx(Rn, Rn, Rn, invCond(cond))
|
||||
#define CNEGw(Rd, Rn, cond) CSNEGw(Rn, Rn, Rn, invCond(cond))
|
||||
#define CNEGxw(Rd, Rn, cond) CSNEGxw(Rn, Rn, Rn, invCond(cond))
|
||||
|
||||
// AND / ORR
|
||||
#define LOGIC_gen(sf, opc, N, immr, imms, Rn, Rd) ((sf)<<31 | (opc)<<29 | 0b100100<<23 | (N)<<22 | (immr)<<16 | (imms)<<10 | (Rn)<<5 | Rd)
|
||||
@@ -537,15 +534,6 @@
|
||||
#define EORx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b10, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define EORw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b10, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define EORxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define EONx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define EONw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define EONxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define EONx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EONw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EONxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EONx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b10, 0b01, 1, Rm, lsr, Rn, Rd))
|
||||
#define EONw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b10, 0b01, 1, Rm, lsr, Rn, Rd))
|
||||
#define EONxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b01, 1, Rm, lsr, Rn, Rd))
|
||||
#define MOVx_REG(Rd, Rm) ORRx_REG(Rd, xZR, Rm)
|
||||
#define MOVw_REG(Rd, Rm) ORRw_REG(Rd, xZR, Rm)
|
||||
#define MOVxw_REG(Rd, Rm) ORRxw_REG(Rd, xZR, Rm)
|
||||
@@ -572,12 +560,6 @@
|
||||
#define BICx_REG BICx
|
||||
#define BICw_REG BICw
|
||||
#define BICxw_REG BICxw
|
||||
#define BICx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICx_REG_LSR(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b00, 0b01, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICw_REG_LSR(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b00, 0b01, 1, Rm, lsl, Rn, Rd))
|
||||
#define BICxw_REG_LSR(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b01, 1, Rm, lsl, Rn, Rd))
|
||||
#define TSTx_REG(Rn, Rm) ANDSx_REG(xZR, Rn, Rm)
|
||||
#define TSTw_REG(Rn, Rm) ANDSw_REG(wZR, Rn, Rm)
|
||||
#define TSTxw_REG(Rn, Rm) ANDSxw_REG(xZR, Rn, Rm)
|
||||
@@ -968,10 +950,6 @@
|
||||
#define VSUB_16(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define VSUB_32(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
|
||||
#define ADDSUB_scalar(U, size, Rm, Rn, Rd) (01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10000<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define ADD_64(Vd, Vn, Vm) EMIT(ADDSUB_scalar(0, 0b11, Vm, Vn, Vd))
|
||||
#define SUB_64(Vd, Vn, Vm) EMIT(ADDSUB_scalar(1, 0b11, Vm, Vn, Vd))
|
||||
|
||||
#define NEGABS_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define NEG_8(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b00, Vn, Vd))
|
||||
#define NEG_16(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b01, Vn, Vd))
|
||||
@@ -1446,23 +1424,14 @@
|
||||
#define VUZP1Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 0, Rn, Rt))
|
||||
#define VUZP2Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 1, Rn, Rt))
|
||||
|
||||
#define DUP_element(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VDUP_8(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUPQ_8(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUP_16(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUPQ_16(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUP_32(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_32(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_64(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<4|0b1000), Vn, Vd))
|
||||
|
||||
#define DUP_general(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 0b11<<10 | (Rn)<<5 | (Rd))
|
||||
#define VDUPB(Vd, Wn) EMIT(DUP_general(0, 0b1, Wn, Vd))
|
||||
#define VDUPQB(Vd, Wn) EMIT(DUP_general(1, 0b1, Wn, Vd))
|
||||
#define VDUPH(Vd, Wn) EMIT(DUP_general(0, 0b10, Wn, Vd))
|
||||
#define VDUPQH(Vd, Wn) EMIT(DUP_general(1, 0b10, Wn, Vd))
|
||||
#define VDUPS(Vd, Wn) EMIT(DUP_general(0, 0b100, Wn, Vd))
|
||||
#define VDUPQS(Vd, Wn) EMIT(DUP_general(1, 0b100, Wn, Vd))
|
||||
#define VDUPQD(Vd, Xn) EMIT(DUP_general(1, 0b1000, Xn, Vd))
|
||||
#define DUP_gen(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VDUP_8(Vd, Vn, idx) EMIT(DUP_gen(0, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUPQ_8(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<1|1), Vn, Vd))
|
||||
#define VDUP_16(Vd, Vn, idx) EMIT(DUP_gen(0, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUPQ_16(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<2|0b10), Vn, Vd))
|
||||
#define VDUP_32(Vd, Vn, idx) EMIT(DUP_gen(0, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_32(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<3|0b100), Vn, Vd))
|
||||
#define VDUPQ_64(Vd, Vn, idx) EMIT(DUP_gen(1, ((idx)<<4|0b1000), Vn, Vd))
|
||||
|
||||
// TBL
|
||||
#define TBL_gen(Q, Rm, len, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (Rm)<<16 | (len)<<13 | (op)<<12 | (Rn)<<5 | (Rd))
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+13
-13
@@ -27,46 +27,46 @@ extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
|
||||
// STLXRD of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
|
||||
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uintptr_t arm64_lock_xchg_dd(void* p, uintptr_t val);
|
||||
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_d(void* p, uint32_t val);
|
||||
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_h(void* p, uint32_t val);
|
||||
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_b(void* p, uint32_t val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern uint32_t arm64_lock_storeifnull_d(void*p, uint32_t val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern void* arm64_lock_storeifnull(void*p, void* val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifref(void*p, void* val, void* ref);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t arm64_lock_storeifref_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t arm64_lock_storeifref2_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// decrement atomically the byte at [p] (but only if p not 0)
|
||||
// decrement atomicaly the byte at [p] (but only if p not 0)
|
||||
extern void arm64_lock_decifnot0b(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_storeb(void*p, uint8_t b);
|
||||
|
||||
// increment atomically the int at [p] only if it was 0. Return the old value of [p]
|
||||
// increment atomicaly the int at [p] only if it was 0. Return the old value of [p]
|
||||
extern int arm64_lock_incif0(void*p);
|
||||
|
||||
// decrement atomically the int at [p] (but only if p not 0)
|
||||
// decrement atomicaly the int at [p] (but only if p not 0)
|
||||
extern int arm64_lock_decifnot0(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_store(void*p, uint32_t v);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
#endif //__ARM64_LOCK__H__
|
||||
Regular → Executable
File mode changed.
Regular → Executable
+3
-26
@@ -1107,19 +1107,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "FSQRT %c%d, %c%d", s, Rd, s, Rn);
|
||||
return buff;
|
||||
}
|
||||
// FPRINTX
|
||||
if(isMask(opcode, "0Q1011100f100001100110nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
char d = sf?'D':'S';
|
||||
int n = (a.Q && !sf)?4:2;
|
||||
snprintf(buff, sizeof(buff), "VFRINTX %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
|
||||
return buff;
|
||||
}
|
||||
if (isMask(opcode, "00011110ff100111010000nnnnnddddd", &a)) {
|
||||
char s = (sf==0)?'S':((sf==1)?'D':'?');
|
||||
snprintf(buff, sizeof(buff), "FRINTX %c%d, %c%d", s, Rd, s, Rn);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// FRINTI
|
||||
if(isMask(opcode, "0Q1011101f100001100110nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
@@ -1499,7 +1487,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
|
||||
// DUP
|
||||
if(isMask(opcode, "0Q001110000iiiii000001nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "2D", "??"};
|
||||
const char* Z[] = {"B", "H", "S", "D"};
|
||||
int sz = 3;
|
||||
if((imm&0b0001)==0b0001) sz=0;
|
||||
@@ -1511,18 +1499,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "DUP V%d.%s, V%d.%s[%d]", Rd, Vd, Rn, Vn, sh);
|
||||
return buff;
|
||||
}
|
||||
|
||||
if(isMask(opcode, "0Q001110000iiiii000011nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
int sz = 3;
|
||||
if((imm&0b0001)==0b0001) sz=0;
|
||||
else if((imm&0b0011)==0b0010) sz=1;
|
||||
else if((imm&0b0111)==0b0100) sz=2;
|
||||
const char* Vd = Y[(sz<<1)|a.Q];
|
||||
snprintf(buff, sizeof(buff), "DUP V%d.%s, X%d", Rd, Vd, Rn);
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
// AES
|
||||
if(isMask(opcode, "0100111000101000010f10nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "AES%c V%d.16B, V%d.16B", sf?'D':'E', Rd, Rn);
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
+31
-75
@@ -25,7 +25,6 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
int isRetX87Wrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
@@ -526,19 +525,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x3F:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("AAS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization AAS\n");
|
||||
READFLAGS(X_AF);
|
||||
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
|
||||
UXTHw(x1, xRAX);
|
||||
CALL_(aas16, x1, 0);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
@@ -679,16 +665,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x62:
|
||||
if(rex.is32bits) {
|
||||
// BOUND here
|
||||
DEFAULT;
|
||||
} else {
|
||||
INST_NAME("BOUND Gd, Ed");
|
||||
nextop = F8;
|
||||
FAKEED(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x63:
|
||||
if(rex.is32bits) {
|
||||
// ARPL here
|
||||
@@ -1030,7 +1007,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
GETED(0);
|
||||
emit_test32(dyn, ninst, rex, ed, gd, x3, x5, x6);
|
||||
emit_test32(dyn, ninst, rex, ed, gd, x3, x5);
|
||||
break;
|
||||
case 0x86:
|
||||
INST_NAME("(LOCK)XCHG Eb, Gb");
|
||||
@@ -1324,7 +1301,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
else
|
||||
u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
SMREAD();
|
||||
LDRB_U12(x2, x1, 0);
|
||||
BFIx(xRAX, x2, 0, 8);
|
||||
break;
|
||||
@@ -1335,7 +1311,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
else
|
||||
u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
SMREAD();
|
||||
LDRxw_U12(xRAX, x1, 0);
|
||||
break;
|
||||
case 0xA2:
|
||||
@@ -1501,7 +1476,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
|
||||
emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4);
|
||||
break;
|
||||
case 0xAA:
|
||||
if(rep) {
|
||||
@@ -1547,42 +1522,26 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ADDx_REG(xRDI, xRDI, x3);
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
if(rep) {
|
||||
INST_NAME("REP LODSB");
|
||||
} else {
|
||||
INST_NAME("LODSB");
|
||||
}
|
||||
GETDIR(x1, 1);
|
||||
if(rep) {
|
||||
CBZx_NEXT(xRCX);
|
||||
MARK;
|
||||
}
|
||||
LDRB_U12(x2, xRSI, 0);
|
||||
ADDx_REG(xRSI, xRSI, x1);
|
||||
if(rep) {
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK(xRCX);
|
||||
}
|
||||
BFIx(xRAX, x2, 0, 8);
|
||||
break;
|
||||
|
||||
case 0xAD:
|
||||
if(rep) {
|
||||
INST_NAME("REP LODSD");
|
||||
} else {
|
||||
INST_NAME("LODSD");
|
||||
}
|
||||
GETDIR(x1, rex.w?8:4);
|
||||
if(rep) {
|
||||
CBZx_NEXT(xRCX);
|
||||
MARK;
|
||||
}
|
||||
LDRxw_U12(xRAX, xRSI, 0);
|
||||
ADDx_REG(xRSI, xRSI, x1);
|
||||
if(rep) {
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK(xRCX);
|
||||
BFIw(x2, xFlags, F_DF, 1);
|
||||
if(rex.w) {
|
||||
MOV32w(x1, 8);
|
||||
} else {
|
||||
MOV32w(x1, 4);
|
||||
}
|
||||
EORxw_REG_LSL(x1, x1, x2, rex.w?63:31);
|
||||
if(rep) {
|
||||
MULxw(x1, x1, xRCX);
|
||||
EORw_REG(xRCX, xRCX, xRCX);
|
||||
}
|
||||
ADDx_REG(xRSI, xRSI, x1);
|
||||
break;
|
||||
case 0xAE:
|
||||
switch(rep) {
|
||||
@@ -1942,9 +1901,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
x87_forget(dyn, ninst, x3, x4, 0);
|
||||
sse_purge07cache(dyn, ninst, x3);
|
||||
tmp = isSimpleWrapper(*(wrapper_t*)(addr));
|
||||
if(isRetX87Wrapper(*(wrapper_t*)(addr)))
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
|
||||
if((box64_log<2 && !cycle_log) && tmp) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(addr+8), tmp);
|
||||
@@ -1985,15 +1941,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xCD:
|
||||
u8 = F8;
|
||||
if(box64_wine && (u8==0x2D || u8==0x2C || u8==0x29)) {
|
||||
INST_NAME("INT 29/2c/2d");
|
||||
if(box64_wine && u8==0x2D) {
|
||||
INST_NAME("INT 2D");
|
||||
// lets do nothing
|
||||
MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n");
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
MOV32w(x1, u8);
|
||||
CALL(native_int, -1);
|
||||
LOAD_XEMU_CALL(xRIP);
|
||||
MESSAGE(LOG_INFO, "INT 2D Windows anti-debug hack\n");
|
||||
} else if (u8==0x80) {
|
||||
INST_NAME("32bits SYSCALL");
|
||||
NOTEST(x1);
|
||||
@@ -2010,6 +1961,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK;
|
||||
LOAD_XEMU_REM();
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
} else if(box64_wine && u8==0x29) {
|
||||
INST_NAME("INT 0x29");
|
||||
// __fastfail ignored!
|
||||
MOV32w(x1, 1);
|
||||
STRw_U12(x1, xEmu, offsetof(x64emu_t, quit));
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
} else {
|
||||
INST_NAME("INT n");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
@@ -2379,7 +2338,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBz_U12(xRCX, xRCX, 1);
|
||||
TBNZ_NEXT(xFlags, F_ZF);
|
||||
TBNZ_NEXT(xFlags, 1<<F_ZF);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE1:
|
||||
@@ -2387,7 +2346,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBz_U12(xRCX, xRCX, 1);
|
||||
TBZ_NEXT(xFlags, F_ZF);
|
||||
TBZ_NEXT(xFlags, 1<<F_ZF);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE2:
|
||||
@@ -2433,13 +2392,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SKIPTEST(x1); // disable test as this hack dos 2 instructions for 1
|
||||
// calling a native function
|
||||
sse_purge07cache(dyn, ninst, x3);
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall) {
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall)
|
||||
tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2));
|
||||
} else
|
||||
else
|
||||
tmp=0;
|
||||
if(dyn->insts[ninst].natcall && isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall && tmp) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
|
||||
@@ -2648,7 +2604,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEDH(x1, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
|
||||
Regular → Executable
+16
-108
@@ -30,8 +30,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t eb1, eb2, gb1, gb2;
|
||||
uint8_t wback, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
int32_t i32, i32_;
|
||||
int cacheupd = 0;
|
||||
int v0, v1;
|
||||
@@ -42,12 +42,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
int64_t j64;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(gb1);
|
||||
MAYUSE(gb2);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(d0);
|
||||
@@ -1107,7 +1104,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRx(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDxw(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1155,7 +1152,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRx(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDxw(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1321,7 +1318,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRx(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDxw(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1334,14 +1331,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
LSRxw_REG(x4, ed, x2);
|
||||
if(rex.w) {
|
||||
ANDx_mask(x4, x4, 1, 0, 0); //mask=1
|
||||
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
|
||||
} else {
|
||||
ANDw_mask(x4, x4, 0, 0); //mask=1
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLxw_REG(x4, x4, x2);
|
||||
BICxw_REG(ed, ed, x4);
|
||||
EORxw_REG(x4, ed, x4);
|
||||
CSELxw(ed, ed, x4, cEQ);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
@@ -1420,7 +1418,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
TBNZ_MARK3(xFlags, 0); // bit already set, jump to next instruction
|
||||
MOV32w(x4, 1);
|
||||
ORRxw_REG_LSL(ed, ed, x4, u8);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STxw(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
@@ -1445,7 +1443,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
TBZ_MARK3(xFlags, 0); // bit already clear, jump to next instruction
|
||||
MOV32w(x4, 1);
|
||||
BICxw_REG_LSL(ed, ed, x4, u8);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STxw(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
@@ -1492,7 +1490,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRx(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDxw(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1582,29 +1580,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDSHxw(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xC0:
|
||||
INST_NAME("XADD Gb, Eb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x1);
|
||||
GETEB(x2, 0);
|
||||
gd = x2; ed = x1; // swap gd/ed
|
||||
emit_add8(dyn, ninst, x1, x2, x4, x5);
|
||||
GBBACK; // gb gets x2 (old ed)
|
||||
EBBACK; // eb gets x1 (sum)
|
||||
break;
|
||||
case 0xC1:
|
||||
INST_NAME("XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETED(0);
|
||||
MOVxw_REG(x3, ed);
|
||||
MOVxw_REG(ed, gd);
|
||||
MOVxw_REG(gd, x3);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x4, x5);
|
||||
WBACK;
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPS Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -1725,56 +1701,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
gd = xRAX+(opcode&7)+(rex.b<<3);
|
||||
REVxw(gd, gd);
|
||||
break;
|
||||
case 0xD1:
|
||||
INST_NAME("PSRLW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
if(MODREG) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
}
|
||||
else {
|
||||
q0 = d1;
|
||||
}
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VMOVBto(x1, d1, 0);
|
||||
MOVZw(x2, 16);
|
||||
SUBSw_REG(x2, x2, x1);
|
||||
B_MARK(cGT);
|
||||
VMOVQDfrom(d0, 0, xZR);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
VDUPQS(q1, x2);
|
||||
UXTL_16(q0, d0);
|
||||
USHLQ_32(q0, q0, q1);
|
||||
VUZP2Q_16(q0, q0, q0);
|
||||
VMOVeD(d0, 0, q0, 0);
|
||||
break;
|
||||
case 0xD2:
|
||||
INST_NAME("PSRLD Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
if(MODREG) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
}
|
||||
else {
|
||||
q0 = d1;
|
||||
}
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VMOVBto(x1, d1, 0);
|
||||
MOVZw(x2, 32);
|
||||
SUBSw_REG(x2, x2, x1);
|
||||
B_MARK(cGT);
|
||||
VMOVQDfrom(d0, 0, xZR);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
VDUPQD(q1, x2);
|
||||
UXTL_32(q0, d0);
|
||||
USHLQ_64(q0, q0, q1);
|
||||
VUZP2Q_32(q0, q0, q0);
|
||||
VMOVeD(d0, 0, q0, 0);
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
INST_NAME("PSRLQ Gm,Em");
|
||||
nextop = F8;
|
||||
@@ -1787,13 +1714,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
NEG_64(q0, d1);
|
||||
USHL_R_64(d0, d0, q0);
|
||||
break;
|
||||
case 0xD4:
|
||||
INST_NAME("PADDQ Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(q0, 0);
|
||||
ADD_64(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xD5:
|
||||
INST_NAME("PMULLW Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -1987,13 +1908,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_32(v0, v0); // 2*q1 in 32bits now
|
||||
SSHL_32(d0, d0, v0);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("PMULUDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
VUMULL_32(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0xF5:
|
||||
INST_NAME("PMADDWD Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -2046,13 +1961,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEM(v1, 0);
|
||||
VADD_8(v0, v0, v1);
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("PSUBQ Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
SUB_64(v0, v0, v1);
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("PADDW Gm, Em");
|
||||
nextop = F8;
|
||||
|
||||
@@ -884,7 +884,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEDO(x6, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
|
||||
Regular → Executable
+26
-106
@@ -319,78 +319,35 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_dec16(dyn, ninst, x1, x2, x3);
|
||||
BFIw(gd, x1, 0, 16);
|
||||
break;
|
||||
case 0x50:
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
case 0x54:
|
||||
case 0x55:
|
||||
case 0x56:
|
||||
case 0x57:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSH reg");
|
||||
gd = xRAX+(opcode&0x07);
|
||||
if (gd == xRSP) {
|
||||
MOVw_REG(x1, xRSP);
|
||||
PUSH1_16(x1);
|
||||
} else {
|
||||
PUSH1_16(gd);
|
||||
}
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
case 0x5B:
|
||||
case 0x5C:
|
||||
case 0x5D:
|
||||
case 0x5E:
|
||||
case 0x5F:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("POP reg");
|
||||
gd = xRAX+(opcode&0x07);
|
||||
POP1_16(x1);
|
||||
BFIw(gd, x1, 0, 16);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSHA 16bits (32bits)");
|
||||
INST_NAME("PUSHA 16 (32bits)");
|
||||
MOVw_REG(x1, xRSP);
|
||||
PUSH1_16(xRAX);
|
||||
PUSH1_16(xRCX);
|
||||
PUSH1_16(xRDX);
|
||||
PUSH1_16(xRBX);
|
||||
PUSH1_16(x1);
|
||||
PUSH1_16(xRBP);
|
||||
PUSH1_16(xRSI);
|
||||
PUSH1_16(xRDI);
|
||||
STRH_S9_preindex(xRAX, xRSP, -2);
|
||||
STRH_S9_preindex(xRCX, xRSP, -2);
|
||||
STRH_S9_preindex(xRDX, xRSP, -2);
|
||||
STRH_S9_preindex(xRBX, xRSP, -2);
|
||||
STRH_S9_preindex(x1, xRSP, -2);
|
||||
STRH_S9_preindex(xRBP, xRSP, -2);
|
||||
STRH_S9_preindex(xRSI, xRSP, -2);
|
||||
STRH_S9_preindex(xRDI, xRSP, -2);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x61:
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("POPA 16bits (32bits)");
|
||||
POP1_16(x1);
|
||||
BFIw(xRDI, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRSI, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRBP, x1, 0, 16);
|
||||
POP1_16(x1); // RSP ignored
|
||||
POP1_16(x1);
|
||||
BFIw(xRBX, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRDX, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRCX, x1, 0, 16);
|
||||
POP1_16(x1);
|
||||
BFIw(xRAX, x1, 0, 16);
|
||||
INST_NAME("POPA 16 (32bits)");
|
||||
MOVw_REG(x1, xRSP);
|
||||
LDRH_S9_postindex(xRDI, xRSP, 2);
|
||||
LDRH_S9_postindex(xRSI, xRSP, 2);
|
||||
LDRH_S9_postindex(xRBP, xRSP, 2);
|
||||
LDRH_S9_postindex(x1, xRSP, 2);
|
||||
LDRH_S9_postindex(xRBX, xRSP, 2);
|
||||
LDRH_S9_postindex(xRDX, xRSP, 2);
|
||||
LDRH_S9_postindex(xRCX, xRSP, 2);
|
||||
LDRH_S9_postindex(xRAX, xRSP, 2);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -632,30 +589,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x98:
|
||||
INST_NAME("CBW");
|
||||
SXTBw(x1, xRAX);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0x9C:
|
||||
INST_NAME("PUSHF");
|
||||
READFLAGS(X_ALL);
|
||||
PUSH1_16(xFlags);
|
||||
break;
|
||||
case 0x9D:
|
||||
INST_NAME("POPF");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
POP1_16(x1); // probably not usefull...
|
||||
BFIw(xFlags, x1, 0, 16);
|
||||
MOV32w(x1, 0x3F7FD7);
|
||||
ANDw_REG(xFlags, xFlags, x1);
|
||||
ORRw_mask(xFlags, xFlags, 0b011111, 0); //mask=0x00000002
|
||||
SET_DFNONE(x1);
|
||||
if(box64_wine) { // should this be done all the time?
|
||||
TBZ_NEXT(xFlags, F_TF);
|
||||
MOV64x(x1, addr);
|
||||
STORE_XEMU_CALL(x1);
|
||||
CALL(native_singlestep, -1);
|
||||
BFCw(xFlags, F_TF, 1);
|
||||
}
|
||||
BFIw(xRAX, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
@@ -665,7 +599,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
else
|
||||
u64 = F64;
|
||||
MOV64z(x1, u64);
|
||||
SMREAD();
|
||||
LDRH_U12(x2, x1, 0);
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
break;
|
||||
@@ -786,23 +719,20 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CBZx_NEXT(xRCX);
|
||||
TBNZ_MARK2(xFlags, F_DF);
|
||||
MARK; // Part with DF==0
|
||||
LDRH_S9_postindex(x2, xRSI, 2);
|
||||
LDRH_S9_postindex(xRAX, xRSI, 2);
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK(xRCX);
|
||||
B_MARK3_nocond;
|
||||
B_NEXT_nocond;
|
||||
MARK2; // Part with DF==1
|
||||
LDRH_S9_postindex(x2, xRSI, -2);
|
||||
LDRH_S9_postindex(xRAX, xRSI, -2);
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK2(xRCX);
|
||||
MARK3;
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
// done
|
||||
} else {
|
||||
INST_NAME("LODSW");
|
||||
INST_NAME("STOSW");
|
||||
GETDIR(x3, 2);
|
||||
LDRH_U12(x2, xRSI, 0);
|
||||
LDRH_U12(xRAX, xRSI, 0);
|
||||
ADDx_REG(xRSI, xRSI, x3);
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1164,16 +1094,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_dec16(dyn, ninst, x1, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
case 6: // Push Ew
|
||||
if(rex.is32bits) {
|
||||
INST_NAME("PUSH Ew");
|
||||
GETEW(x1, 0);
|
||||
PUSH1_16(ed);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
Regular → Executable
+9
-40
@@ -747,37 +747,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xF0:
|
||||
INST_NAME("MOVBE Gw, Ew");
|
||||
nextop=F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
REV16x(x1, ed);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
LDH(x1, ed, fixedaddress);
|
||||
REV16x(x1, x1);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("MOVBE Ew, Gw");
|
||||
nextop=F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
REV16x(x1, gd);
|
||||
BFIx(ed, x1, 0, 16);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
REV16x(x1, gd);
|
||||
STH(x1, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -1786,7 +1756,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXx(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
|
||||
LDH(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1827,10 +1797,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXx(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDH(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
@@ -1840,7 +1809,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
B_NEXT(cNE);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
ORRx_REG(ed, ed, x1);
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
@@ -1890,7 +1859,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXx(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDH(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
@@ -1903,7 +1872,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
B_NEXT(cEQ);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
BICx_REG(ed, ed, x1);
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STH(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
@@ -1970,7 +1939,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
TBNZ_MARK3(xFlags, 0); // bit already set, jump to next instruction
|
||||
MOV32w(x4, 1);
|
||||
ORRxw_REG_LSL(ed, ed, x4, u8);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
EWBACK(x1);
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1984,7 +1953,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
|
||||
TBZ_MARK3(xFlags, 0); // bit already clear, jump to next instruction
|
||||
MOV32w(x4, 1);
|
||||
BICxw_REG_LSL(ed, ed, x4, u8);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
EWBACK(x1);
|
||||
MARK3;
|
||||
break;
|
||||
@@ -2016,7 +1985,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXx(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDH(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
|
||||
@@ -152,28 +152,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x5);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
emit_adc16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
|
||||
Regular → Executable
+1
-37
@@ -166,28 +166,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
opcode=F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("MOVUPS Ex,Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VST128(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
@@ -230,20 +208,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VLD64(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("MOVDQU Gx,Ex");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
GETGX_empty(v0);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
GETGX_empty(v0);
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLD128(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -990,7 +954,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETED32H(x1, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
|
||||
@@ -184,8 +184,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
DEFAULT;
|
||||
break;
|
||||
return 0;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+12
-5
@@ -265,8 +265,8 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
|
||||
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX_PENDOR0 {
|
||||
@@ -292,11 +292,18 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s3, s4, s5);
|
||||
ANDw_mask(s3, s3, 0b011011, 0b000010); // 0xE0
|
||||
LSRw(s3, s3, 5);
|
||||
MOV64x(s4, (uintptr_t)GetParityTab());
|
||||
LDRw_REG_LSL2(s4, s4, s3);
|
||||
ANDw_mask(s3, s1, 0, 0b000100); // 0x1f
|
||||
LSRw_REG(s4, s4, s3);
|
||||
MVNx_REG(s4, s4);
|
||||
BFIw(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
|
||||
// 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, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
@@ -327,7 +334,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch
|
||||
// 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, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
|
||||
@@ -173,7 +173,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLxw_REG(x4, x4, x2);
|
||||
ORRxw_REG(ed, ed, x4);
|
||||
EORxw_REG(x4, ed, x4);
|
||||
CSELxw(ed, ed, x4, cNE);
|
||||
} else {
|
||||
// Will fetch only 1 byte, to avoid alignment issue
|
||||
if(rex.w) {
|
||||
@@ -190,11 +191,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
LSRw_REG(x4, ed, x2);
|
||||
ANDw_mask(x4, x4, 0, 0); //mask=1
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLw_REG(x4, x4, x2);
|
||||
ORRw_REG(ed, ed, x4);
|
||||
EORw_REG(x4, ed, x4);
|
||||
CSELw(ed, ed, x4, cNE);
|
||||
STLXRB(x4, ed, wback);
|
||||
CBNZw_MARKLOCK(x4);
|
||||
SMDMB();
|
||||
@@ -320,14 +322,15 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
LSRxw_REG(x4, ed, x2);
|
||||
if(rex.w) {
|
||||
ANDx_mask(x4, x4, 1, 0, 0); //mask=1
|
||||
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
|
||||
} else {
|
||||
ANDw_mask(x4, x4, 0, 0); //mask=1
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLxw_REG(x4, x4, x2);
|
||||
BICxw_REG(ed, ed, x4);
|
||||
EORxw_REG(x4, ed, x4);
|
||||
CSELxw(ed, ed, x4, cEQ);
|
||||
} else {
|
||||
// Will fetch only 1 byte, to avoid alignment issue
|
||||
if(rex.w) {
|
||||
@@ -337,18 +340,19 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
ASRx(x1, gd, 3); // r1 = (gd>>3)
|
||||
ASRxw(x1, gd, 3); // r1 = (gd>>3)
|
||||
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
LSRw_REG(x4, ed, x2);
|
||||
ANDw_mask(x4, x4, 0, 0); //mask=1
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLw_REG(x4, x4, x2);
|
||||
ORRw_REG(ed, ed, x4);
|
||||
EORw_REG(x4, ed, x4);
|
||||
CSELw(ed, ed, x4, cEQ);
|
||||
STLXRB(x4, ed, wback);
|
||||
CBNZw_MARKLOCK(x4);
|
||||
SMDMB();
|
||||
@@ -436,55 +440,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x10:
|
||||
INST_NAME("LOCK ADC Eb, Gb");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(rex.rex) {
|
||||
wback = xRAX + (nextop&7) + (rex.b<<3);
|
||||
wb2 = 0;
|
||||
} else {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xRAX+(wback&3);
|
||||
}
|
||||
UBFXw(x1, wback, wb2*8, 8);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x5);
|
||||
BFIx(wback, x1, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x5);
|
||||
STLXRB(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ed, Gd");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
emit_adc32(dyn, ninst, rex, x1, gd, x4, x5);
|
||||
STLXRxw(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("LOCK AND Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+1
-1
@@ -36,7 +36,7 @@ void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// Combine and propagate if needed (pass 1 only)
|
||||
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
|
||||
|
||||
// FPU Cache transformation (for loops) // Specific, need to be written by backend
|
||||
// FPU Cache transformation (for loops) // Specific, need to be written par backend
|
||||
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
|
||||
|
||||
// Undo the changes of a neoncache to get the status before the instruction
|
||||
|
||||
Regular → Executable
+30
-6
@@ -477,8 +477,8 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
int64_t offset = 0;
|
||||
int absmin = 0;
|
||||
if(s) absmin = -absmax;
|
||||
if(!n && (m&7)==6) {
|
||||
offset = F16S;
|
||||
if(!n && m==6) {
|
||||
offset = F16;
|
||||
MOVZw(ret, offset);
|
||||
} else {
|
||||
switch(n) {
|
||||
@@ -544,6 +544,16 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void exit_block(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
ADR_S20(x5, (intptr_t)dyn->enter - (uintptr_t)dyn->block);
|
||||
LDAXRw(x4, x5);
|
||||
SUBw_U12(x4, x4, 1);
|
||||
STLXRw(x3, x4, x5);
|
||||
CBNZw(x3, 4-4*4);
|
||||
}
|
||||
#define EXIT_SIZE (4*5)
|
||||
|
||||
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
|
||||
@@ -559,6 +569,8 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
NOTEST(x2);
|
||||
TABLE64(x2, (uintptr_t)arm64_epilog);
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BR(x2);
|
||||
}
|
||||
|
||||
@@ -599,6 +611,8 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
//MOVx(x3, 15); no access to PC reg
|
||||
#endif
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BLR(x2); // save LR...
|
||||
}
|
||||
|
||||
@@ -612,10 +626,12 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
|
||||
if(box64_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
LDPx_S7_offset(x2, x6, xSP, 0);
|
||||
CBZx(x6, 5*4);
|
||||
CBZx(x6, 5*4+(box64_dynarec_age?EXIT_SIZE:0));
|
||||
ADDx_U12(xSP, xSP, 16);
|
||||
SUBx_REG(x6, x6, xRIP); // is it the right address?
|
||||
CBNZx(x6, 2*4);
|
||||
CBNZx(x6, 2*4+(box64_dynarec_age?EXIT_SIZE:0));
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BLR(x2);
|
||||
// not the correct return address, regular jump
|
||||
}
|
||||
@@ -630,6 +646,8 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BLR(x2); // save LR
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -650,10 +668,12 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
|
||||
if(box64_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
LDPx_S7_offset(x2, x6, xSP, 0);
|
||||
CBZx(x6, 5*4);
|
||||
CBZx(x6, 5*4+(box64_dynarec_age?EXIT_SIZE:0));
|
||||
ADDx_U12(xSP, xSP, 16);
|
||||
SUBx_REG(x6, x6, xRIP); // is it the right address?
|
||||
CBNZx(x6, 2*4);
|
||||
CBNZx(x6, 2*4+(box64_dynarec_age?EXIT_SIZE:0));
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BLR(x2);
|
||||
// not the correct return address, regular jump
|
||||
}
|
||||
@@ -668,6 +688,8 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BLR(x2); // save LR
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -712,6 +734,8 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
|
||||
// Ret....
|
||||
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BR(x2);
|
||||
CLEARIP();
|
||||
}
|
||||
|
||||
Regular → Executable
+9
-9
@@ -34,12 +34,12 @@
|
||||
|
||||
// Strong mem emulation helpers
|
||||
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
|
||||
// Sequence of Write will trigger a DMB on "last" write if strongmem is 1
|
||||
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
|
||||
// Opcode will read
|
||||
#define SMREAD() if(!dyn->smread && box64_dynarec_strongmem>1) {SMDMB();}
|
||||
// Opcode will read with option forced lock
|
||||
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box64_dynarec_strongmem>1)) {SMDMB();}
|
||||
// Opcode might read (depend on nextop)
|
||||
// Opcode migh read (depend on nextop)
|
||||
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
|
||||
// Opcode has wrote
|
||||
#define SMWRITE() dyn->smwrite=1
|
||||
@@ -47,7 +47,7 @@
|
||||
#define SMWRITE2() if(box64_dynarec_strongmem>1) dyn->smwrite=1
|
||||
// Opcode has wrote with option forced lock
|
||||
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
|
||||
// Opcode might have wrote (depend on nextop)
|
||||
// Opcode migh have wrote (depend on nextop)
|
||||
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
|
||||
// Start of sequence
|
||||
#define SMSTART() SMEND()
|
||||
@@ -360,18 +360,18 @@
|
||||
gb2 = 0; \
|
||||
} else { \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
gb2 = ((gd&4)<<1); \
|
||||
gb2 = ((gd&4)>>2); \
|
||||
gb1 = xRAX+(gd&3); \
|
||||
} \
|
||||
gd = i; \
|
||||
UBFXx(gd, gb1, gb2, 8);
|
||||
//GETSGB sign extend GB, will use i for gd
|
||||
UBFXx(gd, gb1, gb2*8, 8);
|
||||
//GETSGB signe extend GB, will use i for gd
|
||||
#define GETSGB(i) if(rex.rex) { \
|
||||
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
gb2 = 0; \
|
||||
} else { \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
gb2 = ((gd&4)<<1); \
|
||||
gb2 = ((gd&4)>>2); \
|
||||
gb1 = xRAX+(gd&3); \
|
||||
} \
|
||||
gd = i; \
|
||||
@@ -1035,7 +1035,7 @@ 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, rex_t rex, int s1, int s3, int s4);
|
||||
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
|
||||
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
@@ -1100,7 +1100,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
// x87 helper
|
||||
// cache of the local stack counter, to avoid update at every call
|
||||
// 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, int s1, int t);
|
||||
|
||||
@@ -8,4 +8,17 @@ void CreateJmpNext(void* addr, void* next)
|
||||
uint32_t* block = (uint32_t*)addr;
|
||||
LDRx_literal(x2, (intptr_t)next - (intptr_t)addr);
|
||||
BR(x2);
|
||||
}
|
||||
|
||||
int CreateEnter(void* addr, void* enter)
|
||||
{
|
||||
if(enter) {
|
||||
uint32_t* block = (uint32_t*)addr;
|
||||
ADR_S20(x2, (intptr_t)enter - (intptr_t)addr);
|
||||
LDAXRw(x1, x2);
|
||||
ADDw_U12(x1, x1, 1);
|
||||
STLXRw(x3, x1, x2);
|
||||
CBNZw(x3, 4-4*4);
|
||||
}
|
||||
return 4*5;
|
||||
}
|
||||
Regular → Executable
+2
@@ -5,6 +5,8 @@
|
||||
dyn->insts[ninst].x64.addr = addr; \
|
||||
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
|
||||
|
||||
#define ENTER()
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
|
||||
#define READFLAGS(A) \
|
||||
|
||||
Regular → Executable
+1
@@ -1,5 +1,6 @@
|
||||
#define INIT
|
||||
#define FINI
|
||||
#define ENTER()
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A)
|
||||
#define NEW_INST \
|
||||
|
||||
Regular → Executable
+1
-1
@@ -4,7 +4,7 @@
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>(dyn->insts[ninst].size/4))?dyn->insts[ninst].x64.size:(dyn->insts[ninst].size/4))/15; \
|
||||
}
|
||||
|
||||
#define ENTER() dyn->block_prolog = CreateEnter(NULL, NULL)
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->native_size+=4;}while(0)
|
||||
#define NEW_INST \
|
||||
|
||||
Regular → Executable
+1
@@ -3,6 +3,7 @@
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x64.size, dyn->insts[ninst].size/4); \
|
||||
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
|
||||
#define ENTER() dyn->block += CreateEnter(dyn->block, dyn->enter)
|
||||
#define EMIT(A) \
|
||||
do{ \
|
||||
if(box64_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
|
||||
|
||||
Regular → Executable
+9
-6
@@ -77,8 +77,8 @@ typedef struct instruction_arm64_s {
|
||||
uintptr_t natcall;
|
||||
int retn;
|
||||
int barrier_maybe;
|
||||
flagcache_t f_exit; // flags status at end of instruction
|
||||
neoncache_t n; // neoncache at end of instruction (but before poping)
|
||||
flagcache_t f_exit; // flags status at end of intruction
|
||||
neoncache_t n; // neoncache at end of intruction (but before poping)
|
||||
flagcache_t f_entry; // flags status before the instruction begin
|
||||
} instruction_arm64_t;
|
||||
|
||||
@@ -87,12 +87,13 @@ typedef struct dynarec_arm_s {
|
||||
int32_t size;
|
||||
int32_t cap;
|
||||
uintptr_t start; // start of the block
|
||||
uint32_t isize; // size in bytes of x64 instructions included
|
||||
uint32_t isize; // size in byte of x64 instructions included
|
||||
uint32_t block_prolog; // size in byte of block prolog (not part of 1st instruction)
|
||||
void* block; // memory pointer where next instruction is emitted
|
||||
uintptr_t native_start; // start of the arm code
|
||||
size_t native_size; // size of emitted arm code
|
||||
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state) TODO: move to a cache something
|
||||
uint64_t* table64; // table of 64bits values
|
||||
uint64_t* table64; // table of 64bits value
|
||||
int table64size;// size of table (will be appended at end of executable code)
|
||||
int table64cap;
|
||||
uintptr_t tablestart;
|
||||
@@ -106,7 +107,7 @@ typedef struct dynarec_arm_s {
|
||||
dynablock_t* dynablock;
|
||||
instsize_t* instsize;
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
@@ -115,6 +116,7 @@ typedef struct dynarec_arm_s {
|
||||
uint8_t doublepush;
|
||||
uint8_t doublepop;
|
||||
uint8_t always_test;
|
||||
int* enter;
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
@@ -122,9 +124,10 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
int CreateEnter(void* addr, void* enter);
|
||||
|
||||
#define GO_TRACE(A, B) \
|
||||
GETIP(addr); \
|
||||
|
||||
Regular → Executable
+49
-6
@@ -90,6 +90,43 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
}
|
||||
}
|
||||
|
||||
size_t AgeDynablock(dynablock_t* db, size_t age)
|
||||
{
|
||||
if(db) {
|
||||
dynarec_log(LOG_DEBUG, "AgeDynablock %p %p-%p, age=%zu, db:age/romove=%zu/%d\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, age, db->age, db->try_remove);
|
||||
if(db->age>age || !db->done || db->gone)
|
||||
return db->age;
|
||||
dynablock_t* actual = getDB((uintptr_t)db->x64_addr);
|
||||
if(actual != db) {
|
||||
printf_log(LOG_INFO, "Warning, AgeDynablock with a rogue db %p instead of %p for %p\n", db, actual, db->x64_addr);
|
||||
return age + box64_dynarec_age;
|
||||
}
|
||||
int need_test = getNeedTest((uintptr_t)db->x64_addr);
|
||||
if(db->try_remove) {
|
||||
if(need_test && !*db->active_count) {
|
||||
db = InvalidDynablock(db, 0);
|
||||
FreeInvalidDynablock(db, 0);
|
||||
return 0;
|
||||
} else {
|
||||
db->try_remove = 0;
|
||||
db->age = age + box64_dynarec_age; // re-arm the wait
|
||||
}
|
||||
} else {
|
||||
if(need_test || (getProtection((uintptr_t)db->x64_addr)&PROT_NOPROT) || db->always_test || !db->active_count || *db->active_count) {
|
||||
// don't mess with this kind of dynablock...
|
||||
db->age = age+box64_dynarec_age*2;
|
||||
} else if(setJumpTableIfRef64(db->x64_addr, db->jmpnext, db->block)) {
|
||||
dynarec_log(LOG_DEBUG, "Marking block %p at %p for later removal\n", db, db->x64_addr);
|
||||
db->age = age+box64_dynarec_age;
|
||||
db->try_remove = 1;
|
||||
} else {
|
||||
db->age = age+box64_dynarec_age*2; // failed to swap, try again later
|
||||
}
|
||||
}
|
||||
return db->age;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void MarkDynablock(dynablock_t* db)
|
||||
@@ -109,6 +146,8 @@ void MarkDynablock(dynablock_t* db)
|
||||
else
|
||||
db->previous = old;
|
||||
}
|
||||
} else {
|
||||
db->try_remove = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,7 +216,7 @@ void cancelFillBlock()
|
||||
{
|
||||
longjmp(&dynarec_jmpbuf, 1);
|
||||
}
|
||||
|
||||
extern size_t box64_counter;
|
||||
/*
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
@@ -187,8 +226,10 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(hasAlternate((void*)addr))
|
||||
return NULL;
|
||||
dynablock_t* block = getDB(addr);
|
||||
if(block || !create)
|
||||
if(block || !create) {
|
||||
if(block) block->age = box64_counter+box64_dynarec_age;
|
||||
return block;
|
||||
}
|
||||
|
||||
if(need_lock) {
|
||||
if(box64_dynarec_wait) {
|
||||
@@ -209,7 +250,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
// fill the block
|
||||
block->x64_addr = (void*)addr;
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, canceling\n", (void*)addr);
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
FreeDynablock(block, 0);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
@@ -250,7 +291,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
|
||||
if(db && db->done && db->block && getNeedTest(addr)) {
|
||||
if(db->always_test)
|
||||
sched_yield(); // just calm down...
|
||||
if(AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
|
||||
if(!db->try_remove && AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
|
||||
emu->test.test = 0;
|
||||
if(box64_dynarec_fastpage) {
|
||||
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
|
||||
@@ -289,7 +330,8 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
|
||||
// fill back jumptable
|
||||
if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
|
||||
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
|
||||
}
|
||||
} else
|
||||
db->try_remove = 0;
|
||||
}
|
||||
if(!need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
@@ -327,7 +369,8 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr,
|
||||
// fill back jumptable
|
||||
if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
|
||||
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
|
||||
}
|
||||
} else
|
||||
db->try_remove = 0;
|
||||
}
|
||||
if(!need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
Regular → Executable
+5
-2
@@ -10,17 +10,20 @@ typedef struct dynablock_s {
|
||||
void* block; // block-sizeof(void*) == self
|
||||
void* actual_block; // the actual start of the block (so block-sizeof(void*))
|
||||
struct dynablock_s* previous; // a previous block that might need to be freed
|
||||
int size;
|
||||
void* x64_addr;
|
||||
uintptr_t x64_size;
|
||||
int size;
|
||||
uint32_t hash;
|
||||
uint8_t done;
|
||||
uint8_t gone;
|
||||
uint8_t always_test;
|
||||
uint8_t dirty; // if need to be tested as soon as it's created
|
||||
int isize;
|
||||
instsize_t* instsize;
|
||||
void* jmpnext; // a branch jmpnext code when block is marked
|
||||
size_t age; //age of the block
|
||||
int try_remove; // block marked as try removed
|
||||
int isize;
|
||||
uint32_t* active_count; // is this block currently being executed, or NULL if not tracked
|
||||
} dynablock_t;
|
||||
|
||||
#endif //__DYNABLOCK_PRIVATE_H_
|
||||
Regular → Executable
+99
-48
@@ -73,65 +73,114 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Disable "clobbered" warnings
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclobbered"
|
||||
#endif
|
||||
void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
{
|
||||
uint64_t old_rsp = R_RSP;
|
||||
uint64_t old_rbx = R_RBX;
|
||||
uint64_t old_rdi = R_RDI;
|
||||
uint64_t old_rsi = R_RSI;
|
||||
uint64_t old_rbp = R_RBP;
|
||||
uint64_t old_rip = R_RIP;
|
||||
PushExit(emu);
|
||||
R_RIP = addr;
|
||||
emu->df = d_none;
|
||||
DynaRun(emu);
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
|
||||
if(emu->flags.quitonlongjmp==1)
|
||||
emu->flags.longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
R_RSI = old_rsi;
|
||||
R_RBP = old_rbp;
|
||||
R_RSP = old_rsp;
|
||||
R_RIP = old_rip; // and set back instruction pointer
|
||||
}
|
||||
}
|
||||
|
||||
void DynaRun(x64emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
struct __jmp_buf_tag jmpbuf[1] = {0};
|
||||
int skip = 0;
|
||||
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
|
||||
emu->flags.jmpbuf_ready = 0;
|
||||
emu->jmpbuf = jmpbuf;
|
||||
|
||||
while(!(emu->quit)) {
|
||||
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
|
||||
emu->jmpbuf = jmpbuf;
|
||||
emu->flags.jmpbuf_ready = 1;
|
||||
if((skip=sigsetjmp(emu->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x64test_check(emu, R_RIP);
|
||||
if((skip = sigsetjmp(emu->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", emu->segs[_FS]);
|
||||
addr = R_RIP; // not sure if it should still be inside DynaCall!
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x64test_check(emu, R_RIP);
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!box64_dynarec)
|
||||
#endif
|
||||
EmuCall(emu, addr);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
uint64_t old_rsp = R_RSP;
|
||||
uint64_t old_rbx = R_RBX;
|
||||
uint64_t old_rdi = R_RDI;
|
||||
uint64_t old_rsi = R_RSI;
|
||||
uint64_t old_rbp = R_RBP;
|
||||
uint64_t old_rip = R_RIP;
|
||||
PushExit(emu);
|
||||
R_RIP = addr;
|
||||
emu->df = d_none;
|
||||
while(!emu->quit) {
|
||||
int is32bits = (emu->segs[_CS]==0x23);
|
||||
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
|
||||
if(!block || !block->block || !block->done) {
|
||||
skip = 0;
|
||||
// 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, "%04d|Calling Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
|
||||
if(box64_dynarec_test)
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
Run(emu, 1);
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->hash, emu);
|
||||
CHECK_FLAGS(emu);
|
||||
// block is here, let's run it!
|
||||
native_prolog(emu, block->block);
|
||||
}
|
||||
if(emu->fork) {
|
||||
int forktype = emu->fork;
|
||||
emu->quit = 0;
|
||||
emu->fork = 0;
|
||||
emu = x64emu_fork(emu, forktype);
|
||||
}
|
||||
}
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->flags.need_jmpbuf = 0;
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
R_RSI = old_rsi;
|
||||
R_RBP = old_rbp;
|
||||
R_RSP = old_rsp;
|
||||
R_RIP = old_rip; // and set back instruction pointer
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// clear the setjmp
|
||||
emu->jmpbuf = old_jmpbuf;
|
||||
}
|
||||
|
||||
int DynaRun(x64emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
struct __jmp_buf_tag jmpbuf[1] = {0};
|
||||
int skip = 0;
|
||||
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
|
||||
emu->jmpbuf = jmpbuf;
|
||||
|
||||
if((skip=sigsetjmp(emu->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x64test_check(emu, R_RIP);
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
if(!box64_dynarec)
|
||||
if(!box64_dynarec)
|
||||
#endif
|
||||
Run(emu, 0);
|
||||
return Run(emu, 0);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
else {
|
||||
while(!emu->quit) {
|
||||
int is32bits = (emu->segs[_CS]==0x23);
|
||||
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
|
||||
if(!block || !block->block || !block->done) {
|
||||
@@ -154,10 +203,12 @@ void DynaRun(x64emu_t* emu)
|
||||
emu = x64emu_fork(emu, forktype);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->quit = 0;
|
||||
}
|
||||
// clear the setjmp
|
||||
emu->jmpbuf = old_jmpbuf;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+39
-32
@@ -23,6 +23,8 @@
|
||||
#include "dynarec_arch.h"
|
||||
#include "dynarec_next.h"
|
||||
|
||||
size_t box64_counter = 0;
|
||||
|
||||
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
|
||||
uint8_t *ip = (uint8_t*)inst->addr;
|
||||
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
|
||||
@@ -78,7 +80,7 @@ void add_next(dynarec_native_t *dyn, uintptr_t addr) {
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
|
||||
// get closest, but no addresses before
|
||||
// get closest, but no addresses befores
|
||||
uintptr_t best = 0;
|
||||
int i = 0;
|
||||
while((i<dyn->next_sz) && (best!=addr)) {
|
||||
@@ -124,8 +126,8 @@ int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return size of next instruction, -1 is unknown
|
||||
// not all instructions are setup
|
||||
// return size of next instuciton, -1 is unknown
|
||||
// not all instrction are setup
|
||||
int next_instruction(dynarec_native_t *dyn, uintptr_t addr)
|
||||
{
|
||||
uint8_t opcode = PK(0);
|
||||
@@ -293,7 +295,7 @@ int Table64(dynarec_native_t *dyn, uint64_t val, int pass)
|
||||
static void fillPredecessors(dynarec_native_t* dyn)
|
||||
{
|
||||
int pred_sz = 1; // to be safe
|
||||
// compute total size of predecessor to allocate the array
|
||||
// compute total size of predecessor to alocate the array
|
||||
// first compute the jumps
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
if(dyn->insts[i].x64.jmp && (dyn->insts[i].x64.jmp_insts!=-1)) {
|
||||
@@ -301,13 +303,6 @@ static void fillPredecessors(dynarec_native_t* dyn)
|
||||
dyn->insts[dyn->insts[i].x64.jmp_insts].pred_sz++;
|
||||
}
|
||||
}
|
||||
// remove "has_next" from orphan branch
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(!dyn->insts[i].x64.has_next) {
|
||||
if(dyn->insts[i+1].x64.has_next && !dyn->insts[i+1].pred_sz)
|
||||
dyn->insts[i+1].x64.has_next = 0;
|
||||
}
|
||||
}
|
||||
// second the "has_next"
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(dyn->insts[i].x64.has_next) {
|
||||
@@ -335,7 +330,7 @@ static void fillPredecessors(dynarec_native_t* dyn)
|
||||
}
|
||||
}
|
||||
|
||||
// updateNeed goes backward, from last instruction to top
|
||||
// updateNeed goes backward, from last intruction to top
|
||||
static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
|
||||
while (ninst>=0) {
|
||||
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
|
||||
@@ -375,9 +370,9 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
|
||||
else
|
||||
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
|
||||
}
|
||||
--ninst;
|
||||
if(!ok)
|
||||
return ninst;
|
||||
return ninst - 1;
|
||||
--ninst;
|
||||
}
|
||||
return ninst;
|
||||
}
|
||||
@@ -414,10 +409,10 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
block->isize = 0;
|
||||
block->done = 0;
|
||||
size_t sz = 4*sizeof(void*);
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* actual_p = (void*)AllocDynarecMap(sz, box64_counter);
|
||||
void* p = actual_p + sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", block, sz);
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
@@ -425,6 +420,7 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
block->actual_block = actual_p;
|
||||
block->block = p;
|
||||
block->jmpnext = p;
|
||||
block->age = box64_counter + box64_dynarec_age;
|
||||
*(dynablock_t**)actual_p = block;
|
||||
*(void**)(p+2*sizeof(void*)) = native_epilog;
|
||||
CreateJmpNext(block->jmpnext, p+2*sizeof(void*));
|
||||
@@ -444,11 +440,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
B+8 .. B+15 : 2 Native code for jmpnext (or jmp epilog in case of empty block)
|
||||
B+16 .. B+23 : jmpnext (or jmp_epilog) address
|
||||
B+24 .. B+31 : empty (in case an architecture needs more than 2 opcodes)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction length on x64 and native side)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction lenght on x64 and native side)
|
||||
|
||||
*/
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
|
||||
@@ -456,7 +452,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(current_helper) {
|
||||
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock at %p as another one is going on\n", (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
// protect the 1st page
|
||||
@@ -468,6 +464,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 128;
|
||||
++box64_counter;
|
||||
helper.insts = (instruction_native_t*)dynaCalloc(helper.cap, sizeof(instruction_native_t));
|
||||
// pass 0, addresses, x64 jump addresses, overall size of the block
|
||||
uintptr_t end = native_pass0(&helper, addr, alternate, is32bits);
|
||||
@@ -520,7 +517,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
while (pos>=0)
|
||||
pos = updateNeed(&helper, pos, 0);
|
||||
|
||||
// pass 1, float optimizations, first pass for flags
|
||||
// pass 1, float optimisations, first pass for flags
|
||||
native_pass1(&helper, addr, alternate, is32bits);
|
||||
|
||||
// pass 2, instruction size
|
||||
@@ -528,22 +525,29 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
// keep size of instructions for signal handling
|
||||
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
|
||||
insts_rsize = (insts_rsize+7)&~7; // round the size...
|
||||
size_t native_size = (helper.native_size+7)&~7; // round the size...
|
||||
size_t native_size = (helper.native_size+helper.block_prolog+7)&~7; // round the size...
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize;
|
||||
// dynablock_t* block (arm insts) table64 jmpnext code instsize
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
size_t sz = sizeof(void*) // dynablock_t*
|
||||
+ native_size // block (arm insts)
|
||||
+ helper.table64size*sizeof(uint64_t) // table64
|
||||
+ 4*sizeof(void*) // jmpnext code
|
||||
+ (box64_dynarec_age?sizeof(void*):0) // enter_count
|
||||
+ insts_rsize; // instsize
|
||||
|
||||
void* actual_p = (void*)AllocDynarecMap(sz, box64_counter);
|
||||
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
|
||||
void* tablestart = p + native_size;
|
||||
void* next = tablestart + helper.table64size*sizeof(uint64_t);
|
||||
void* instsize = next + 4*sizeof(void*);
|
||||
void* instsize = next + 4*sizeof(void*) + (box64_dynarec_age?sizeof(void*):0);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", block, sz);
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
helper.block = p;
|
||||
block->actual_block = actual_p;
|
||||
block->active_count = box64_dynarec_age?(next + 4*sizeof(void*)):NULL;
|
||||
block->age = box64_counter + box64_dynarec_age;
|
||||
helper.native_start = (uintptr_t)p;
|
||||
helper.tablestart = (uintptr_t)tablestart;
|
||||
helper.jmp_next = (uintptr_t)next+sizeof(void*);
|
||||
@@ -552,6 +556,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
helper.table64cap = helper.table64size;
|
||||
dynaFree(helper.table64);
|
||||
helper.table64 = (uint64_t*)helper.tablestart;
|
||||
helper.enter = block->active_count;
|
||||
// pass 3, emit (log emit native opcode)
|
||||
if(box64_dynarec_dump) {
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u %s bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize, is32bits?"x86":"x64");
|
||||
@@ -568,7 +573,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
// keep size of instructions for signal handling
|
||||
block->instsize = instsize;
|
||||
// ok, free the helper now
|
||||
dynaFree(helper.insts);
|
||||
instruction_native_t* pass2_insts = helper.insts;
|
||||
helper.insts = NULL;
|
||||
helper.table64 = NULL;
|
||||
helper.instsize = NULL;
|
||||
@@ -588,7 +593,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
// all done...
|
||||
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// Check if something changed, to abort if it is
|
||||
// Check if something changed, to abbort if it as
|
||||
if((block->hash != hash)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
|
||||
AddHotPage(addr);
|
||||
@@ -599,19 +604,21 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
|
||||
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
|
||||
for(int i=0; i<helper.size; ++i) {
|
||||
for(int i=0; i<helper.size-1; ++i) {
|
||||
printf_log(LOG_NONE, "%p:", dump);
|
||||
for(; dump<(uint8_t*)helper.insts[i+1].x64.addr; ++dump)
|
||||
for(; dump<(uint8_t*)pass2_insts[i+1].x64.addr; ++dump)
|
||||
printf_log(LOG_NONE, " %02X", *dump);
|
||||
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
|
||||
printf_log(LOG_NONE, "\t%d -> %d\n", pass2_insts[i].size2, pass2_insts[i].size);
|
||||
}
|
||||
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
dynaFree(pass2_insts);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
dynaFree(pass2_insts);
|
||||
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
|
||||
printf_log(LOG_NONE, "BOX64: Warning, insts_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
|
||||
printf_log(LOG_NONE, "BOX64: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x64_addr, block->x64_size);
|
||||
|
||||
@@ -138,7 +138,7 @@ void native_fistp64(x64emu_t* emu, int64_t* ed)
|
||||
|
||||
void native_fistt64(x64emu_t* emu, int64_t* ed)
|
||||
{
|
||||
// used of memcpy to avoid alignments issues
|
||||
// used of memcpy to avoid aligments issues
|
||||
int64_t tmp = ST0.d;
|
||||
memcpy(ed, &tmp, sizeof(tmp));
|
||||
}
|
||||
@@ -163,12 +163,6 @@ void native_priv(x64emu_t* emu)
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
}
|
||||
|
||||
void native_int(x64emu_t* emu, int num)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_interruption(emu, num, (void*)R_RIP);
|
||||
}
|
||||
|
||||
void native_singlestep(x64emu_t* emu)
|
||||
{
|
||||
emit_signal(emu, SIGTRAP, (void*)R_RIP, 1);
|
||||
|
||||
@@ -46,7 +46,6 @@ void native_clflush(x64emu_t* emu, void* p);
|
||||
void native_ud(x64emu_t* emu);
|
||||
void native_priv(x64emu_t* emu);
|
||||
void native_singlestep(x64emu_t* emu);
|
||||
void native_int(x64emu_t* emu, int num);
|
||||
|
||||
// Caches transformation (for loops) // Specific, need to be written par backend
|
||||
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
|
||||
|
||||
Regular → Executable
+14
-28
@@ -47,9 +47,12 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
ARCH_INIT();
|
||||
int reset_n = -1;
|
||||
dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz))?0:ip; // RIP is always set at start of block unless there is a predecessor!
|
||||
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with box64_dynarec_bigblock==2, else it needs 3
|
||||
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3
|
||||
// ok, go now
|
||||
INIT;
|
||||
if(box64_dynarec_age) {
|
||||
ENTER();
|
||||
}
|
||||
while(ok) {
|
||||
ip = addr;
|
||||
if (reset_n!=-1) {
|
||||
@@ -74,7 +77,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
}
|
||||
reset_n = -1;
|
||||
} else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
|
||||
dyn->last_ip = 0; // reset IP if some jump are coming here
|
||||
dyn->last_ip = 0; // reset IP if some jump are comming here
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
NEW_INST;
|
||||
if(!ninst) {
|
||||
@@ -166,7 +169,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if((dyn->insts[ii].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
|
||||
reset_n = -2; // hack to say Barrier!
|
||||
else {
|
||||
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are available
|
||||
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are availble
|
||||
if(reset_n==-1) {
|
||||
reset_n = -2;
|
||||
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
|
||||
@@ -183,7 +186,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
ok = 1; // in case it was 0
|
||||
} else if ((dyn->forward_to < addr) || ok<=0) {
|
||||
} else if ((dyn->forward_to < addr) || !ok) {
|
||||
// something when wrong! rollback
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
ok = 0;
|
||||
@@ -214,19 +217,12 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
|
||||
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
|
||||
if(!((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)next))) {
|
||||
if(dyn->forward) {
|
||||
if(next<dyn->forward_to)
|
||||
dyn->forward_to = next;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
} else {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,16 +238,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
dyn->insts[ninst].x64.need_after |= X_PEND;
|
||||
++ninst;
|
||||
}
|
||||
if(dyn->forward) {
|
||||
// stopping too soon
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst+1;
|
||||
addr = dyn->forward;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++ninst;
|
||||
@@ -296,7 +282,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(need_epilog) {
|
||||
NOTEST(x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknown instruction
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
|
||||
}
|
||||
FINI;
|
||||
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
@@ -25,6 +25,8 @@
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t opcode;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
@@ -167,16 +169,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x10:
|
||||
INST_NAME("ADC Eb, Gb");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEB(x1, 0);
|
||||
GETGB(x2);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x5, x3);
|
||||
EBBACK(x5, 0);
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ed, Gd");
|
||||
READFLAGS(X_CF);
|
||||
@@ -187,43 +180,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
|
||||
WBACK;
|
||||
break;
|
||||
case 0x12:
|
||||
INST_NAME("ADC Gb, Eb");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEB(x2, 0);
|
||||
GETGB(x1);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x3, x5);
|
||||
GBBACK(x5);
|
||||
break;
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gd, Ed");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETED(0);
|
||||
emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
|
||||
break;
|
||||
case 0x14:
|
||||
INST_NAME("ADC AL, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
u8 = F8;
|
||||
ANDI(x1, xRAX, 0xff);
|
||||
emit_adc8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
|
||||
ANDI(xRAX, xRAX, -256);
|
||||
OR(xRAX, xRAX, x1);
|
||||
break;
|
||||
case 0x15:
|
||||
INST_NAME("ADC EAX, Id");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i64 = F32S;
|
||||
MOV64xw(x1, i64);
|
||||
emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6);
|
||||
break;
|
||||
|
||||
case 0x18:
|
||||
INST_NAME("SBB Eb, Gb");
|
||||
READFLAGS(X_CF);
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "dynarec_rv64_functions.h"
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "dynarec_rv64_helper.h"
|
||||
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
int isRetX87Wrapper(wrapper_t fun);
|
||||
|
||||
uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
@@ -308,9 +307,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
// disabling isSimpleWrapper because all signed value less than 64bits needs to be sign extended
|
||||
// and return value needs to be cleanned up
|
||||
tmp = 0;//isSimpleWrapper(*(wrapper_t*)(addr));
|
||||
if(isRetX87Wrapper(*(wrapper_t*)(addr)))
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
|
||||
if(tmp<0 || tmp>1)
|
||||
tmp=0; //TODO: removed when FP is in place
|
||||
if((box64_log<2 && !cycle_log) && tmp) {
|
||||
@@ -621,58 +617,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
case 0xDF:
|
||||
addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
#define GO(Z) \
|
||||
BARRIER(BARRIER_MAYBE); \
|
||||
JUMP(addr+i8, 1); \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
|
||||
CHECK_CACHE()) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
|
||||
if(Z) {BNE(xRCX, xZR, i32);} else {BEQ(xRCX, xZR, i32);}; \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
B(i32); \
|
||||
} \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
if(Z) {BEQ(xRCX, xZR, i32);} else {BNE(xRCX, xZR, i32);}; \
|
||||
}
|
||||
case 0xE0:
|
||||
INST_NAME("LOOPNZ");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBNZ_NEXT(x1);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("LOOPZ");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBZ_NEXT(x1);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("LOOP");
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("JECXZ");
|
||||
i8 = F8S;
|
||||
GO(1);
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("CALL Id");
|
||||
@@ -713,9 +657,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
tmp=0; // float paramters not ready!
|
||||
} else
|
||||
tmp=0;
|
||||
if(dyn->insts[ninst].natcall && isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall && tmp) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
|
||||
|
||||
@@ -316,134 +316,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
SRLI(xRDX, x3, 32);
|
||||
AND(xRAX, x3, 32); // wipe upper part
|
||||
break;
|
||||
case 0x38:
|
||||
//SSE3
|
||||
nextop=F8;
|
||||
switch(nextop) {
|
||||
case 0xF0:
|
||||
INST_NAME("MOVBE Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
LDxw(gd, ed, fixedaddress);
|
||||
if (rv64_zbb) {
|
||||
REV8(gd, gd);
|
||||
if (!rex.w) {
|
||||
SRLI(gd, gd, 32);
|
||||
}
|
||||
} else {
|
||||
if (rex.w) {
|
||||
MOV_U12(x2, 0xff);
|
||||
SLLI(x1, gd, 56);
|
||||
SRLI(x3, gd, 56);
|
||||
SRLI(x4, gd, 40);
|
||||
SLLI(x2, x2, 8);
|
||||
AND(x4, x4, x2);
|
||||
OR(x1, x1, x3);
|
||||
OR(x1, x1, x4);
|
||||
SLLI(x3, gd, 40);
|
||||
SLLI(x4, x2, 40);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
|
||||
SRLI(x3, gd, 24);
|
||||
SLLI(x4, x2, 8);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
SLLI(x3, gd, 24);
|
||||
SLLI(x4, x2, 32);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
|
||||
SRLI(x3, gd, 8);
|
||||
SLLI(x4, x2, 16);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
SLLI(x3, gd, 8);
|
||||
SLLI(x4, x2, 24);
|
||||
AND(x3, x3, x4);
|
||||
OR(gd, x1, x3);
|
||||
} else {
|
||||
MOV_U12(x2, 0xff);
|
||||
SLLIW(x2, x2, 8);
|
||||
SLLIW(x1, gd, 24);
|
||||
SRLIW(x3, gd, 24);
|
||||
SRLIW(x4, gd, 8);
|
||||
AND(x4, x4, x2);
|
||||
OR(x1, x1, x3);
|
||||
OR(x1, x1, x4);
|
||||
SLLIW(gd, gd, 8);
|
||||
LUI(x2, 0xff0);
|
||||
AND(gd, gd, x2);
|
||||
OR(gd, gd, x1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("MOVBE Ed, Gd");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
if (rv64_zbb) {
|
||||
REV8(x1, gd);
|
||||
if (!rex.w) {
|
||||
SRLI(x1, x1, 32);
|
||||
}
|
||||
} else {
|
||||
if (rex.w) {
|
||||
MOV_U12(x2, 0xff);
|
||||
SLLI(x1, gd, 56);
|
||||
SRLI(x3, gd, 56);
|
||||
SRLI(x4, gd, 40);
|
||||
SLLI(x2, x2, 8);
|
||||
AND(x4, x4, x2);
|
||||
OR(x1, x1, x3);
|
||||
OR(x1, x1, x4);
|
||||
SLLI(x3, gd, 40);
|
||||
SLLI(x4, x2, 40);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
|
||||
SRLI(x3, gd, 24);
|
||||
SLLI(x4, x2, 8);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
SLLI(x3, gd, 24);
|
||||
SLLI(x4, x2, 32);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
|
||||
SRLI(x3, gd, 8);
|
||||
SLLI(x4, x2, 16);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
SLLI(x3, gd, 8);
|
||||
SLLI(x4, x2, 24);
|
||||
AND(x3, x3, x4);
|
||||
OR(x1, x1, x3);
|
||||
} else {
|
||||
MOV_U12(x2, 0xff);
|
||||
SLLIW(x2, x2, 8);
|
||||
SLLIW(x1, gd, 24);
|
||||
SRLIW(x3, gd, 24);
|
||||
SRLIW(x4, gd, 8);
|
||||
AND(x4, x4, x2);
|
||||
OR(x1, x1, x3);
|
||||
OR(x1, x1, x4);
|
||||
SLLIW(x3, gd, 8);
|
||||
LUI(x2, 0xff0);
|
||||
AND(x3, x3, x2);
|
||||
OR(x1, x1, x3);
|
||||
}
|
||||
}
|
||||
SDxw(x1, wback, fixedaddress);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(GETFLAGS, NO, YES, F) \
|
||||
READFLAGS(F); \
|
||||
|
||||
@@ -117,43 +117,6 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
case 0x0F:
|
||||
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
emit_adc16(dyn, ninst, x1, x2, x4, x3, x5);
|
||||
EWBACK;
|
||||
break;
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
emit_adc16(dyn, ninst, x1, x2, x4, x3, x5);
|
||||
GWBACK;
|
||||
break;
|
||||
case 0x15:
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
SRLI(x6, xMASK, 16);
|
||||
AND(x1, xRAX, x6);
|
||||
MOV32w(x2, i16);
|
||||
emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
if (rv64_zbb) {
|
||||
ANDN(xRAX, xRAX, x6);
|
||||
} else {
|
||||
NOT(x6, x6);
|
||||
AND(xRAX, xRAX, x6);
|
||||
}
|
||||
OR(xRAX, xRAX, x1);
|
||||
break;
|
||||
case 0x19:
|
||||
INST_NAME("SBB Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
@@ -464,67 +427,6 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
GETGW(x2);
|
||||
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
break;
|
||||
case 0x87:
|
||||
INST_NAME("(LOCK)XCHG Ew, Gw");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
GETGD;
|
||||
GETED(0);
|
||||
ADDI(x1, gd, 0);
|
||||
LUI(x3, 0xffff0);
|
||||
AND(gd, gd, x3);
|
||||
ZEXTH(x4, ed);
|
||||
OR(gd, gd, x4);
|
||||
AND(ed, ed, x3);
|
||||
ZEXTH(x4, x1);
|
||||
OR(ed, ed, x4);
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
SMDMB();
|
||||
|
||||
ANDI(x3, ed, 1);
|
||||
BNEZ_MARK(x3);
|
||||
|
||||
ANDI(x3, ed, 0b10);
|
||||
LUI(x5, 0xffff0);
|
||||
ZEXTH(x6, gd);
|
||||
BNEZ_MARK3(x3);
|
||||
|
||||
MARKLOCK;
|
||||
LR_W(x1, ed, 1, 0);
|
||||
AND(x3, x1, x5);
|
||||
OR(x3, x3, x6);
|
||||
SC_W(x3, x3, ed, 0, 1);
|
||||
BNEZ_MARKLOCK(x3);
|
||||
ZEXTH(x1, x1);
|
||||
B_MARK2_nocond;
|
||||
|
||||
MARK3;
|
||||
NOT(x5, x5);
|
||||
SLLI(x5, x5, 16);
|
||||
SLLI(x6, x6, 16);
|
||||
NOT(x5, x5);
|
||||
LR_W(x1, ed, 1, 0);
|
||||
AND(x3, x1, x5);
|
||||
OR(x3, x3, x6);
|
||||
SC_W(x3, x3, ed, 0, 1);
|
||||
BNEZ(x3, -4 * 4);
|
||||
SRLI(x1, x1, 16);
|
||||
ZEXTH(x1, x1);
|
||||
B_MARK2_nocond;
|
||||
|
||||
MARK;
|
||||
LHU(x1, ed, 0);
|
||||
SH(gd, ed, 0);
|
||||
|
||||
MARK2;
|
||||
SMDMB();
|
||||
LUI(x5, 0xffff0);
|
||||
AND(gd, gd, x5);
|
||||
OR(gd, gd, x1);
|
||||
}
|
||||
break;
|
||||
case 0x89:
|
||||
INST_NAME("MOV Ew, Gw");
|
||||
nextop = F8;
|
||||
|
||||
@@ -411,7 +411,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
AND(x4, x4, x6);
|
||||
OR(x3, x3, x4);
|
||||
BNEZ(x3, 8);
|
||||
ORI(xFlags, xFlags, 1<<F_CF);
|
||||
ORI(xFlags, xFlags, 1<<F_ZF);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -715,44 +715,6 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETEX(x2, 0);
|
||||
SSE_LOOP_Q(x3, x4, XOR(x3, x3, x4));
|
||||
break;
|
||||
case 0xF0:
|
||||
INST_NAME("MOVBE Gw, Ew");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 1);
|
||||
LHU(x1, ed, fixedaddress);
|
||||
if (rv64_zbb) {
|
||||
REV8(x1, x1);
|
||||
SRLI(x1, x1, 48);
|
||||
} else {
|
||||
ANDI(x2, x1, 0xff);
|
||||
SLLI(x2, x2, 8);
|
||||
SRLI(x1, x1, 8);
|
||||
OR(x1, x1, x2);
|
||||
}
|
||||
LUI(x2, 0xffff0);
|
||||
AND(gd, gd, x2);
|
||||
OR(gd, gd, x1);
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("MOVBE Ew, Gw");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 0, 1);
|
||||
if (rv64_zbb) {
|
||||
REV8(x1, gd);
|
||||
SRLI(x1, x1, 48);
|
||||
} else {
|
||||
ANDI(x1, gd, 0xff);
|
||||
SLLI(x1, x1, 8);
|
||||
SRLI(x2, gd, 8);
|
||||
ANDI(x2, x2, 0xff);
|
||||
OR(x1, x1, x2);
|
||||
}
|
||||
SH(x1, wback, fixedaddress);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -37,35 +37,6 @@ uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETREX();
|
||||
|
||||
switch(opcode) {
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ew, Gw");
|
||||
nextop = F8;
|
||||
GETGD; // don't need GETGW here
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
ADDI(ed, gd, 0);
|
||||
} else {
|
||||
if(ed!=gd) {
|
||||
LUI(x1, 0xffff0);
|
||||
AND(gd, gd, x1);
|
||||
ZEXTH(x1, ed);
|
||||
OR(gd, gd, x1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
|
||||
ADD(x4, ed, x4);
|
||||
if(rex.w) {
|
||||
SD(gd, x4, fixedaddress);
|
||||
} else {
|
||||
SH(gd, x4, fixedaddress);
|
||||
}
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ed");
|
||||
nextop=F8;
|
||||
@@ -98,6 +69,7 @@ uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "rv64_emitter.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
@@ -49,71 +48,6 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETREX();
|
||||
|
||||
switch(opcode) {
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x6, 0xFFFF);
|
||||
AND(x2, ed, x6);
|
||||
emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
if (rv64_zbb) {
|
||||
ANDN(ed, ed, x6);
|
||||
} else {
|
||||
NOT(x6, x6);
|
||||
AND(ed, ed, x6);
|
||||
}
|
||||
OR(ed, ed, x2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
ANDI(x3, wback, 0b10);
|
||||
MOV32w(x4, 0xffff); // x4 = mask
|
||||
BNEZ_MARK(x3);
|
||||
// lower 16bits
|
||||
MARKLOCK;
|
||||
LR_W(x5, wback, 1, 1);
|
||||
AND(x6, x5, x4); // x6 = Ed.h[0]
|
||||
SRLIW(x5, x5, 16);
|
||||
SLLIW(x5, x5, 16); // x5 = clear Ed.h[0]
|
||||
ADDW(x2, x1, x6); // x2 = Gw + Ew
|
||||
ANDI(x9, xFlags, 1 << F_CF);
|
||||
ADDW(x2, x2, x9); // x2 = adc
|
||||
AND(x2, x2, x4);
|
||||
OR(x5, x5, x2);
|
||||
SC_W(x2, x5, wback, 1, 1);
|
||||
BNEZ_MARKLOCK(x2);
|
||||
B_MARK3_nocond;
|
||||
MARK;
|
||||
// upper 16bits
|
||||
SLLIW(x3, x4, 16); // x3 = mask
|
||||
SUBI(wback, wback, 2); // aligning address
|
||||
SLLI(x1, x1, 16); // x1 = extended Gw
|
||||
MARK2;
|
||||
LR_W(x6, wback, 1, 1); // x6 = Ed
|
||||
AND(x5, x6, x3); // x5 = Ed.h[1] << 16
|
||||
ADDW(x5,x5, x1);
|
||||
ANDI(x9, xFlags, 1 << F_CF);
|
||||
SLLIW(x9, x9, 16);
|
||||
ADDW(x5, x5, x9); // x5 = adc << 16
|
||||
AND(x9, x6, x4); // x9 = Ed.h[0]
|
||||
OR(x5, x5, x9);
|
||||
SC_W(x9, x5, wback, 1, 1);
|
||||
BNEZ_MARK2(x9);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
SRLIW(x6, x6, 16);
|
||||
SRLIW(x1, x1, 16);
|
||||
}
|
||||
MARK3;
|
||||
IFX(X_ALL|X_PEND) {
|
||||
emit_adc16(dyn, ninst, x1, x6, x3, x4, x5);
|
||||
}
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
|
||||
@@ -567,63 +567,6 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
}
|
||||
break;
|
||||
#define GO(Z) \
|
||||
BARRIER(BARRIER_MAYBE); \
|
||||
JUMP(addr+i8, 1); \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
|
||||
CHECK_CACHE()) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
|
||||
if(Z) {BNE(x1, xZR, i32);} else {BEQ(x1, xZR, i32);}; \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
B(i32); \
|
||||
} \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
|
||||
if(Z) {BEQ(x1, xZR, i32);} else {BNE(x1, xZR, i32);}; \
|
||||
}
|
||||
case 0xE0:
|
||||
INST_NAME("LOOPNZ (32bits)");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBNZ_NEXT(x1);
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("LOOPZ (32bits)");
|
||||
READFLAGS(X_ZF);
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
ANDI(x1, xFlags, 1 << F_ZF);
|
||||
CBZ_NEXT(x1);
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("LOOP (32bits)");
|
||||
i8 = F8S;
|
||||
SUBI(xRCX, xRCX, 1);
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(0);
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("JECXZ (32bits)");
|
||||
i8 = F8S;
|
||||
AND(x1, xRCX, xMASK);
|
||||
GO(1);
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -339,101 +339,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x10:
|
||||
INST_NAME("LOCK ADC Eb, Gb");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(rex.rex) {
|
||||
wback = xRAX + (nextop&7) + (rex.b<<3);
|
||||
wb2 = 0;
|
||||
} else {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xRAX+(wback&3);
|
||||
}
|
||||
SRLIW(x1, wback, wb2*8);
|
||||
ANDI(x1, x1, 0xFF);
|
||||
emit_adc8(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
SLLI(x1, x1, wb2*8);
|
||||
MOV_U12(x3, 0xFF);
|
||||
SLLI(x3, x3, wb2*8);
|
||||
NOT(x3, x3);
|
||||
AND(wback, wback, x3);
|
||||
OR(wback, wback, x1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
ANDI(x3, wback, 0b11);
|
||||
BNEZ_MARK(x3);
|
||||
MARKLOCK;
|
||||
LR_W(x5, wback, 1, 1);
|
||||
ANDI(x4, x5, 0xff); // x4 = Ed.b[0]
|
||||
ANDI(x5, x5, -256); // x5 = clear Ed.b[0]
|
||||
ADDW(x6, x4, x2);
|
||||
ANDI(x9, xFlags, 1 << F_CF);
|
||||
ADDW(x6, x6, x9); // x6 = adc
|
||||
ANDI(x6, x6, 0xff);
|
||||
OR(x5, x5, x6);
|
||||
SC_W(x9, x5, wback, 1, 1);
|
||||
BNEZ_MARKLOCK(x9);
|
||||
B_MARK3_nocond;
|
||||
MARK;
|
||||
SLLI(x3, x3, 3);
|
||||
MOV_U12(x4, 0xff);
|
||||
ANDI(wback, wback, ~3); // aligning address
|
||||
SLLI(x4, x4, x3); // x4 = byte mask
|
||||
NOT(x5, x4); // x5 = ~mask
|
||||
SLL(x2, x2, x3); // x2 = extented Gb
|
||||
MARK2;
|
||||
LR_W(x6, wback, 1, 1); // x6 = Ed
|
||||
AND(x9, x6, x4); // x9 = extended Ed.b[dest]
|
||||
AND(x6, x6, x5); // x6 = clear Ed.b[dest]
|
||||
ADDW(x5, x9, x2);
|
||||
ANDI(x4, xFlags, 1 << F_CF);
|
||||
SLL(x4, x4, x3); // extented
|
||||
ADDW(x5, x5, x4); // x5 = adc
|
||||
OR(x5, x5, x6);
|
||||
SC_W(x4, x5, wback, 1, 1);
|
||||
BNEZ_MARK2(x4);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
SRLI(x2, x2, x3); // Gb
|
||||
SRLI(x4, x9, x3); // Eb
|
||||
}
|
||||
MARK3;
|
||||
IFX(X_ALL|X_PEND) {
|
||||
emit_adc8(dyn, ninst, x4, x2, x3, x5, x6);
|
||||
}
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ed, Gd");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LRxw(x1, wback, 1, 1);
|
||||
ADDxw(x3, x1, gd);
|
||||
ANDI(x4, xFlags, 1 << F_CF);
|
||||
ADDxw(x3, x3, x4);
|
||||
SCxw(x4, x3, wback, 1, 1);
|
||||
BNEZ_MARKLOCK(x4);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
emit_adc32(dyn, ninst, rex, x1, gd, x3, x4, x5, x6);
|
||||
}
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x21:
|
||||
INST_NAME("LOCK AND Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -476,9 +381,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x66:
|
||||
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
|
||||
@@ -474,6 +474,15 @@ uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void exit_block(dynarec_rv64_t* dyn, int ninst)
|
||||
{
|
||||
uintptr_t diff = (intptr_t)dyn->enter - (uintptr_t)dyn->block;
|
||||
ADDI(x4, xZR, -1);
|
||||
AUIPC(x5, SPLIT20(diff));
|
||||
ADDI(x5, x5, SPLIT12(diff));
|
||||
AMOADD_W(xZR, x4, x5, 1, 1);
|
||||
}
|
||||
|
||||
void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
|
||||
@@ -488,6 +497,8 @@ void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
}
|
||||
TABLE64(x2, (uintptr_t)rv64_epilog);
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BR(x2);
|
||||
}
|
||||
|
||||
@@ -505,6 +516,8 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
}
|
||||
TABLE64(x2, (uintptr_t)rv64_epilog_fast);
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BR(x2);
|
||||
}
|
||||
|
||||
@@ -560,6 +573,8 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
//MOVx(x3, 15); no access to PC reg
|
||||
#endif
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
JALR(x2); // save LR...
|
||||
}
|
||||
|
||||
@@ -607,6 +622,8 @@ void ret_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex)
|
||||
}
|
||||
if(rv64_zba) SH3ADD(x3, x2, x3); else {SLLI(x2, x2, 3); ADD(x3, x3, x2);}
|
||||
LD(x2, x3, 0);
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
JALR(x2); // save LR
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -661,6 +678,8 @@ void retn_to_epilog(dynarec_rv64_t* dyn, int ninst, rex_t rex, int n)
|
||||
}
|
||||
if(rv64_zba) SH3ADD(x3, x2, x3); else {SLLI(x2, x2, 3); ADD(x3, x3, x2);}
|
||||
LD(x2, x3, 0);
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
JALR(x2); // save LR
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -704,6 +723,8 @@ void iret_to_epilog(dynarec_rv64_t* dyn, int ninst, int is64bits)
|
||||
// Ret....
|
||||
MOV64x(x2, (uintptr_t)rv64_epilog); // epilog on purpose, CS might have changed!
|
||||
SMEND();
|
||||
if(box64_dynarec_age)
|
||||
exit_block(dyn, ninst);
|
||||
BR(x2);
|
||||
CLEARIP();
|
||||
}
|
||||
|
||||
@@ -16,4 +16,17 @@ void CreateJmpNext(void* addr, void* next)
|
||||
LR_D(x2, x2, 1, 1);
|
||||
#endif
|
||||
BR(x2);
|
||||
}
|
||||
|
||||
void CreateEnter(void* addr, void* enter)
|
||||
{
|
||||
if(enter) {
|
||||
uint32_t* block = (uint32_t*)addr;
|
||||
uintptr_t diff = (intptr_t)enter - (intptr_t)addr;
|
||||
ADDI(x1, xZR, 1);
|
||||
AUIPC(x2, SPLIT20(diff));
|
||||
ADDI(x2, x2, SPLIT12(diff));
|
||||
AMOADD_W(x3, x1, x2, 1, 1);
|
||||
}
|
||||
return 4*4;
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
dyn->insts[ninst].x64.addr = addr; \
|
||||
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
|
||||
|
||||
#define ENTER()
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
|
||||
#define READFLAGS(A) \
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#define INIT
|
||||
#define FINI
|
||||
#define ENTER()
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A)
|
||||
#define NEW_INST \
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>(dyn->insts[ninst].size/4))?dyn->insts[ninst].x64.size:(dyn->insts[ninst].size/4))/15; \
|
||||
}
|
||||
|
||||
#define ENTER() dyn->block_prolog = CreateEnter(NULL, NULL)
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A) do {dyn->insts[ninst].size+=4; dyn->native_size+=4;}while(0)
|
||||
#define NEW_INST \
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x64.size, dyn->insts[ninst].size/4); \
|
||||
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
|
||||
#define ENTER() dyn->block += CreateEnter(dyn->block, dyn->enter)
|
||||
#define EMIT(A) \
|
||||
do { \
|
||||
if(box64_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)A); \
|
||||
@@ -10,7 +11,6 @@
|
||||
dyn->block += 4; dyn->native_size += 4; \
|
||||
dyn->insts[ninst].size2 += 4; \
|
||||
}while(0)
|
||||
|
||||
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
|
||||
#define NEW_INST \
|
||||
if(box64_dynarec_dump) print_newinst(dyn, ninst); \
|
||||
|
||||
@@ -99,6 +99,7 @@ typedef struct dynarec_rv64_s {
|
||||
uintptr_t start; // start of the block
|
||||
uint32_t isize; // size in byte of x64 instructions included
|
||||
void* block; // memory pointer where next instruction is emitted
|
||||
uint32_t block_prolog; // size in byte of block prolog (not part of 1st instruction)
|
||||
uintptr_t native_start; // start of the arm code
|
||||
size_t native_size; // size of emitted arm code
|
||||
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state) TODO: move to a cache something
|
||||
@@ -123,6 +124,7 @@ typedef struct dynarec_rv64_s {
|
||||
int32_t forward_size; // size at the forward point
|
||||
int forward_ninst; // ninst at the forward point
|
||||
uint8_t always_test;
|
||||
int* enter;
|
||||
} dynarec_rv64_t;
|
||||
|
||||
// convert idx (0..24) to reg index (10..31 0..1)
|
||||
@@ -135,9 +137,10 @@ uintptr_t get_closest_next(dynarec_rv64_t *dyn, uintptr_t addr);
|
||||
int is_nops(dynarec_rv64_t *dyn, uintptr_t addr, int n);
|
||||
int is_instructions(dynarec_rv64_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
int Table64(dynarec_rv64_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
int Table64(dynarec_rv64_t *dyn, uint64_t val, int pass); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
int CreateEnter(void* addr, void* enter);
|
||||
|
||||
#define GO_TRACE(A, B) \
|
||||
GETIP(addr); \
|
||||
|
||||
@@ -128,7 +128,6 @@ f28–31 ft8–11 FP temporaries Caller
|
||||
// RV32I
|
||||
// put imm20 in the [31:12] bits of rd, zero [11:0] and sign extend bits31
|
||||
#define LUI(rd, imm20) EMIT(U_type((imm20)<<12, rd, 0b0110111))
|
||||
|
||||
// put PC+imm20 in rd
|
||||
#define AUIPC(rd, imm20) EMIT(U_type((imm20)<<12, rd, 0b0010111))
|
||||
|
||||
@@ -382,6 +381,7 @@ f28–31 ft8–11 FP temporaries Caller
|
||||
#define SC_W(rd, rs2, rs1, aq, rl) EMIT(R_type(AQ_RL(0b00011, aq, rl), rs2, rs1, 0b010, rd, 0b0101111))
|
||||
|
||||
#define AMOSWAP_W(rd, rs2, rs1, aq, rl) EMIT(R_type(AQ_RL(0b00001, aq, rl), rs2, rs1, 0b010, rd, 0b0101111))
|
||||
#define AMOADD_W(rd, rs2, rs1, aq, rl) EMIT(R_type(AQ_RL(0b00000, aq, rl), rs2, rs1, 0b010, rd, 0b0101111))
|
||||
|
||||
// RV64A
|
||||
#define LR_D(rd, rs1, aq, rl) EMIT(R_type(AQ_RL(0b00010, aq, rl), 0, rs1, 0b011, rd, 0b0101111))
|
||||
|
||||
@@ -2,49 +2,49 @@
|
||||
#define __RV64_LOCK__H__
|
||||
#include <stdint.h>
|
||||
|
||||
// Atomically store val at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
|
||||
// Atomicaly store val at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
|
||||
extern int rv64_lock_cas_d(void* p, int32_t ref, int32_t val);
|
||||
|
||||
// Atomically store val at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
|
||||
// Atomicaly store val at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
|
||||
extern int rv64_lock_cas_dd(void* p, int64_t ref, int64_t val);
|
||||
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uintptr_t rv64_lock_xchg_dd(void* p, uintptr_t val);
|
||||
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uint32_t rv64_lock_xchg_d(void* p, uint32_t val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern uint32_t rv64_lock_storeifnull_d(void*p, uint32_t val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern void* rv64_lock_storeifnull(void*p, void* val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* rv64_lock_storeifref(void*p, void* val, void* ref);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t rv64_lock_storeifref_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t rv64_lock_storeifref2_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// decrement atomically the byte at [p] (but only if p not 0)
|
||||
// decrement atomicaly the byte at [p] (but only if p not 0)
|
||||
extern void rv64_lock_decifnot0b(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void rv64_lock_storeb(void*p, uint8_t b);
|
||||
|
||||
// increment atomically the int at [p] only if it was 0. Return the old value of [p]
|
||||
// increment atomicaly the int at [p] only if it was 0. Return the old value of [p]
|
||||
extern int rv64_lock_incif0(void*p);
|
||||
|
||||
// decrement atomically the int at [p] (but only if p not 0)
|
||||
// decrement atomicaly the int at [p] (but only if p not 0)
|
||||
extern int rv64_lock_decifnot0(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void rv64_lock_store(void*p, uint32_t v);
|
||||
|
||||
// (mostly) Atomically store val1 and val2 at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
|
||||
// (mostly) Atomicaly store val1 and val2 at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
|
||||
extern int rv64_lock_cas_dq(void* p, uint64_t ref, uint64_t val1, uint64_t val2);
|
||||
|
||||
// Not defined in assembler but in dynarec_rv64_functions
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
+21
-69
@@ -311,10 +311,8 @@ void FreeElfMemory(elfheader_t* head)
|
||||
for(int i=0; i<head->multiblock_n; ++i) {
|
||||
#ifdef DYNAREC
|
||||
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
|
||||
if(box64_dynarec) {
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
|
||||
freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
|
||||
}
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
|
||||
freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
|
||||
#endif
|
||||
munmap(head->multiblock[i], head->multiblock_size[i]);
|
||||
}
|
||||
@@ -376,23 +374,6 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
|
||||
{
|
||||
if(!verneeded || !head)
|
||||
return 1;
|
||||
if(!head->VerDef || !verneeded->VerNeed)
|
||||
return 1;
|
||||
int cnt = GetNeededVersionCnt(verneeded, libname);
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
const char* vername = GetNeededVersionString(verneeded, libname, i);
|
||||
if(vername && !GetVersionIndice(head, vername)) {
|
||||
printf_log(/*LOG_DEBUG*/LOG_INFO, "Discarding %s for missing version %s\n", head->path, vername);
|
||||
return 0; // missing version
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
|
||||
{
|
||||
(void)context;
|
||||
@@ -490,20 +471,11 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
end = offs + sym->st_size;
|
||||
}*/
|
||||
// so weak symbol are the one left
|
||||
if(bind==STB_WEAK) {
|
||||
if(!offs && !end) {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
} else {
|
||||
if(!offs && !end) {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
if(!offs && !end) {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
uintptr_t globoffs, globend;
|
||||
@@ -531,8 +503,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
if(sym->st_size && offs) {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname);
|
||||
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(my_context->globdata, symname, offs + head->delta, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname);
|
||||
}
|
||||
@@ -557,7 +528,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
uintptr_t old_offs = offs;
|
||||
uintptr_t old_end = end;
|
||||
offs = 0;
|
||||
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
|
||||
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
|
||||
if(offs==0) {
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver); // get original copy if any
|
||||
if(!offs && local_maplib)
|
||||
@@ -701,24 +672,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
end = offs + sym->st_size;
|
||||
}*/
|
||||
// so weak symbol are the one left
|
||||
if(bind==STB_WEAK) {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
old_bind = bind;
|
||||
@@ -752,7 +712,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
globoffs = offs;
|
||||
globend = end;
|
||||
offs = end = 0;
|
||||
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
|
||||
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
|
||||
if(!offs && local_maplib)
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
|
||||
if(!offs)
|
||||
@@ -777,8 +737,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
|
||||
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
|
||||
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername);
|
||||
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
|
||||
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
|
||||
@@ -1242,7 +1201,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64c
|
||||
h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, local, bindnow, h->needed, h, box64, emu)) {
|
||||
if(AddNeededLib(maplib, local, bindnow, h->needed, box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading one of needed lib\n");
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
@@ -1287,7 +1246,6 @@ void MarkElfInitDone(elfheader_t* h)
|
||||
if(h)
|
||||
h->init_done = 1;
|
||||
}
|
||||
void startMallocHook();
|
||||
void RunElfInitPltResolver(elfheader_t* h, x64emu_t *emu)
|
||||
{
|
||||
if(!h || h->init_done)
|
||||
@@ -1302,20 +1260,17 @@ void RunElfInitPltResolver(elfheader_t* h, x64emu_t *emu)
|
||||
}
|
||||
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunSafeFunction(p, 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
RunSafeFunction(my_context, p, 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
// and check init array now
|
||||
Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
|
||||
for (size_t i=0; i<h->initarray_sz; ++i) {
|
||||
if(addr[i]) {
|
||||
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunSafeFunction((uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
RunSafeFunction(my_context, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
}
|
||||
}
|
||||
|
||||
if(h->malloc_hook_2)
|
||||
startMallocHook();
|
||||
|
||||
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
|
||||
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
return;
|
||||
@@ -1360,9 +1315,6 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
|
||||
}
|
||||
}
|
||||
|
||||
if(h->malloc_hook_2)
|
||||
startMallocHook();
|
||||
|
||||
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
|
||||
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
return;
|
||||
@@ -1635,7 +1587,7 @@ static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)
|
||||
return 0; \
|
||||
if(!a->dlpi_name[0]) /*don't send informations about box64 itself*/ \
|
||||
return 0; \
|
||||
return (int)RunFunction(my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
|
||||
return (int)RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
|
||||
Regular → Executable
-1
@@ -87,7 +87,6 @@ struct elfheader_s {
|
||||
int init_done;
|
||||
int fini_done;
|
||||
int refcnt; // ref count for the elf
|
||||
int malloc_hook_2; // this elf hook malloc, hacking it
|
||||
|
||||
char* memory; // char* and not void* to allow math on memory pointer
|
||||
void** multiblock;
|
||||
|
||||
Regular → Executable
+12
-40
@@ -416,6 +416,18 @@ int GetVersionIndice(elfheader_t* h, const char* vername)
|
||||
{
|
||||
if(!vername)
|
||||
return 0;
|
||||
if(h->VerNeed) {
|
||||
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(!strcmp(h->DynStr+aux->vna_name, vername))
|
||||
return aux->vna_other;
|
||||
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
}
|
||||
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
}
|
||||
if(h->VerDef) {
|
||||
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
|
||||
while(def) {
|
||||
@@ -426,44 +438,4 @@ int GetVersionIndice(elfheader_t* h, const char* vername)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
|
||||
{
|
||||
if(!libname)
|
||||
return 0;
|
||||
if(h->VerNeed) {
|
||||
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
char *filename = h->DynStr + ver->vn_file;
|
||||
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
if(!strcmp(filename, libname))
|
||||
return ver->vn_cnt;
|
||||
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
|
||||
{
|
||||
if(!libname)
|
||||
return 0;
|
||||
if(h->VerNeed) {
|
||||
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
char *filename = h->DynStr + ver->vn_file;
|
||||
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
if(!strcmp(filename, libname)) {
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(j==idx)
|
||||
return h->DynStr+aux->vna_name;
|
||||
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
}
|
||||
return NULL; // idx out of bound, return NULL...
|
||||
}
|
||||
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -34,7 +34,6 @@
|
||||
#define GETEW(D) oped=TestEw(test, &addr, rex, nextop, D)
|
||||
#define GETEW32(D) oped=TestEw32O(test, &addr, rex, nextop, D, 0)
|
||||
#define GETEW_OFFS(D, O) oped=TestEdO(test, &addr, rex, nextop, D, O)
|
||||
#define GETEW_OFFS_16(O) oped=TestEw16off(test, &addr, rex, nextop, O)
|
||||
#define GETGW opgd=GetGw(test->emu, &addr, rex, nextop)
|
||||
#define GETEX(D) opex=TestEx(test, &addr, rex, nextop, D)
|
||||
#define GETEX32(D) opex=TestEx32O(test, &addr, rex, nextop, D, 0)
|
||||
@@ -59,7 +58,6 @@
|
||||
#define GETEW(D) oped=GetEw(emu, &addr, rex, nextop, D)
|
||||
#define GETEW32(D) oped=GetEw32O(emu, &addr, rex, nextop, D, 0)
|
||||
#define GETEW_OFFS(D, O) oped=GetEdO(emu, &addr, rex, nextop, D, O)
|
||||
#define GETEW_OFFS_16(O) oped=GetEw16off(emu, &addr, rex, nextop, O)
|
||||
#define GETGW opgd=GetGw(emu, &addr, rex, nextop)
|
||||
#define GETEX(D) opex=GetEx(emu, &addr, rex, nextop, D)
|
||||
#define GETEX32(D) opex=GetEx32O(emu, &addr, rex, nextop, D, 0)
|
||||
|
||||
Regular → Executable
+3
-3
@@ -567,9 +567,9 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
|
||||
Run(emu, 0);
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
|
||||
if(emu->flags.quitonlongjmp==1)
|
||||
emu->flags.longjmp = 0; // don't change anything because of the longjmp
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
|
||||
Regular → Executable
+6
-12
@@ -36,14 +36,6 @@ typedef struct x64test_s {
|
||||
uint8_t mem[16];
|
||||
} x64test_t;
|
||||
|
||||
typedef struct emu_flags_s {
|
||||
uint32_t need_jmpbuf:1; // need a new jmpbuff for signal handling
|
||||
uint32_t quitonlongjmp:2; // quit if longjmp is called
|
||||
uint32_t quitonexit:2; // quit if exit/_exit is called
|
||||
uint32_t longjmp:1; // if quit because of longjmp
|
||||
uint32_t jmpbuf_ready:1; // the jmpbuf in the emu is ok and don't need refresh
|
||||
} emu_flags_t;
|
||||
|
||||
typedef struct x64emu_s {
|
||||
// cpu
|
||||
reg64_t regs[16];
|
||||
@@ -56,7 +48,7 @@ typedef struct x64emu_s {
|
||||
mmx87_regs_t mmx[8];
|
||||
x87control_t cw;
|
||||
x87flags_t sw;
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separately
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separatly
|
||||
int fpu_stack;
|
||||
mmxcontrol_t mxcsr;
|
||||
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
|
||||
@@ -91,14 +83,16 @@ typedef struct x64emu_s {
|
||||
int quit;
|
||||
int error;
|
||||
int fork; // quit because need to fork
|
||||
int exit;
|
||||
forkpty_t* forkpty_info;
|
||||
emu_flags_t flags;
|
||||
int exit;
|
||||
int quitonlongjmp; // quit if longjmp is called
|
||||
int quitonexit; // quit if exit/_exit is called
|
||||
int longjmp; // if quit because of longjmp
|
||||
x64test_t test; // used for dynarec testing
|
||||
#ifdef HAVE_TRACE
|
||||
sse_regs_t old_xmm[16];
|
||||
#endif
|
||||
// scratch stack, used for alignment of double and 64bits ints on arm. 200 elements should be enough
|
||||
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
|
||||
uint64_t scratch[200];
|
||||
// local stack, do be deleted when emu is freed
|
||||
void* stack2free; // this is the stack to free (can be NULL)
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+19
-91
@@ -227,34 +227,11 @@ x64emurun:
|
||||
emu->segs_serial[_DS] = 0;
|
||||
break;
|
||||
|
||||
case 0x27: /* DAA */
|
||||
if(rex.is32bits) {
|
||||
R_AL = daa8(emu, R_AL);
|
||||
} else {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
case 0x2F: /* DAS */
|
||||
if(rex.is32bits) {
|
||||
R_AL = das8(emu, R_AL);
|
||||
} else {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
case 0x2E: /* segments are ignored */
|
||||
case 0x26:
|
||||
case 0x36: /* SS: (ignored) */
|
||||
break;
|
||||
case 0x37: /* AAA */
|
||||
if(rex.is32bits) {
|
||||
R_AX = aaa16(emu, R_AX);
|
||||
} else {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
@@ -294,15 +271,6 @@ x64emurun:
|
||||
else
|
||||
cmp32(emu, R_EAX, F32);
|
||||
break;
|
||||
|
||||
case 0x3F: /* AAS */
|
||||
if(rex.is32bits) {
|
||||
R_AX = aas16(emu, R_AX);
|
||||
} else {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
@@ -393,14 +361,7 @@ x64emurun:
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
case 0x62: /* BOUND Gd, Ed */
|
||||
if(rex.is32bits) {
|
||||
FAKEED(0);
|
||||
} else {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x63: /* MOVSXD Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -698,12 +659,12 @@ x64emurun:
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if(!MODREG)
|
||||
pthread_mutex_lock(&my_context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
if(!MODREG)
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
@@ -732,7 +693,7 @@ x64emurun:
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(!MODREG)
|
||||
pthread_mutex_lock(&my_context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
if(rex.w) {
|
||||
tmp64u = GD->q[0];
|
||||
GD->q[0] = ED->q[0];
|
||||
@@ -746,7 +707,7 @@ x64emurun:
|
||||
ED->dword[0] = tmp32u;
|
||||
}
|
||||
if(!MODREG)
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0x88: /* MOV Eb,Gb */
|
||||
@@ -1354,32 +1315,7 @@ x64emurun:
|
||||
addr = rex.is32bits?Pop32(emu):Pop64(emu);
|
||||
STEP2
|
||||
break;
|
||||
case 0xC4: /* LES Gd,Ed */
|
||||
if(rex.is32bits) {
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
emu->segs[_ES] = *(__uint16_t*)(((char*)ED)+4);
|
||||
emu->segs_serial[_ES] = 0;
|
||||
GD->dword[0] = *(uint32_t*)ED;
|
||||
} else {
|
||||
// AVX not supported yet
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
}
|
||||
break;
|
||||
case 0xC5: /* LDS Gd,Ed */
|
||||
if(rex.is32bits) {
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
emu->segs[_DS] = *(__uint16_t*)(((char*)ED)+4);
|
||||
emu->segs_serial[_DS] = 0;
|
||||
GD->dword[0] = *(uint32_t*)ED;
|
||||
} else {
|
||||
// AVX not supported yet
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC6: /* MOV Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB(1);
|
||||
@@ -1442,14 +1378,12 @@ x64emurun:
|
||||
if(box64_wine && tmp8u==0x2D) {
|
||||
// lets ignore the INT 2D
|
||||
printf_log(LOG_DEBUG, "INT 2D called\n");
|
||||
emit_interruption(emu, 0x2d, (void*)R_RIP);
|
||||
} else if(box64_wine && tmp8u==0x2c) {
|
||||
printf_log(LOG_DEBUG, "INT 2c called\n");
|
||||
emit_interruption(emu, 0x2c, (void*)R_RIP);
|
||||
} else if(box64_wine && tmp8u==0x29) {
|
||||
// INT 29 is __fastfail
|
||||
printf_log(LOG_DEBUG, "INT 29 called => __fastfail(0x%x)\n", R_ECX);
|
||||
emit_interruption(emu, 0x29, (void*)R_RIP);
|
||||
emu->quit = 1;
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
} else if (tmp8u==0x80) {
|
||||
// 32bits syscall
|
||||
#ifndef TEST_INTERPRETER
|
||||
@@ -1536,15 +1470,6 @@ x64emurun:
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD6: /* SALC */
|
||||
if(rex.is32bits) {
|
||||
CHECK_FLAGS(emu);
|
||||
R_AL = ACCESS_FLAG(F_CF)?0xff:0x00;
|
||||
} else {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
};
|
||||
break;
|
||||
case 0xD7: /* XLAT */
|
||||
R_AL = *(uint8_t*)(R_RBX + R_AL);
|
||||
break;
|
||||
@@ -1946,8 +1871,9 @@ x64emurun:
|
||||
case 3: /* CALL FAR Ed */
|
||||
GETET(0);
|
||||
if(MODREG) {
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: (%02X %02X %02X %02X) %02X %02X %02X %02X\n", (void*)R_RIP, PK(-6), PK(-5), PK(-4), PK(-3), opcode, nextop, PK(0), PK(1));
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
} else {
|
||||
if(rex.is32bits || !rex.w) {
|
||||
@@ -1976,8 +1902,9 @@ x64emurun:
|
||||
case 5: /* JMP FAR Ed */
|
||||
GETET(0);
|
||||
if(MODREG) {
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: (%02X %02X %02X %02X) %02X %02X %02X %02X\n", (void*)R_RIP, PK(-6), PK(-5), PK(-4), PK(-3), opcode, nextop, PK(0), PK(1));
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
} else {
|
||||
if(rex.is32bits || !rex.w) {
|
||||
@@ -2002,8 +1929,9 @@ x64emurun:
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X\n", (void*)R_RIP, PK(-6), PK(-5), PK(-4), PK(-3), opcode, nextop, PK(0), PK(1), PK(2), PK(3));
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
}
|
||||
break;
|
||||
|
||||
+4
-45
@@ -813,19 +813,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
, EB->byte[0]=0;
|
||||
,
|
||||
) /* 0x90 -> 0x9F SETxx Eb */
|
||||
case 0xA0: /* PUSH FS */
|
||||
if(rex.is32bits)
|
||||
Push32(emu, emu->segs[_FS]);
|
||||
else
|
||||
Push64(emu, emu->segs[_FS]);
|
||||
break;
|
||||
case 0xA1: /* POP FS */
|
||||
if(rex.is32bits)
|
||||
emu->segs[_FS] = Pop32(emu);
|
||||
else
|
||||
emu->segs[_FS] = Pop64(emu);
|
||||
emu->segs_serial[_FS] = 0;
|
||||
break;
|
||||
|
||||
case 0xA2: /* CPUID */
|
||||
tmp32u = R_EAX;
|
||||
my_cpuid(emu, tmp32u);
|
||||
@@ -881,20 +869,6 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA8: /* PUSH GS */
|
||||
if(rex.is32bits)
|
||||
Push32(emu, emu->segs[_GS]);
|
||||
else
|
||||
Push64(emu, emu->segs[_GS]);
|
||||
break;
|
||||
case 0xA9: /* POP GS */
|
||||
if(rex.is32bits)
|
||||
emu->segs[_GS] = Pop32(emu);
|
||||
else
|
||||
emu->segs[_GS] = Pop64(emu);
|
||||
emu->segs_serial[_FS] = 0;
|
||||
break;
|
||||
|
||||
case 0xAB: /* BTS Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
@@ -1464,12 +1438,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETGM;
|
||||
GM->q = (EM->q > 63) ? 0L : (GM->q >> EM->q);
|
||||
break;
|
||||
case 0xD4: /* PADDQ Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
GM->sq += EM->sq;
|
||||
break;
|
||||
|
||||
case 0xD5: /* PMULLW Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
@@ -1708,12 +1677,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETGM;
|
||||
GM->q = (EM->q > 63) ? 0L : (GM->q << EM->ub[0]);
|
||||
break;
|
||||
case 0xF4: /* PMULUDQ Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
GM->q = (uint64_t)GM->ud[0] * (uint64_t)EM->ud[0];
|
||||
break;
|
||||
|
||||
case 0xF5: /* PMADDWD Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
@@ -1756,12 +1720,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
for(int i=0; i<2; ++i)
|
||||
GM->ud[i] -= EM->ud[i];
|
||||
break;
|
||||
case 0xFB: /* PSUBQ Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
GM->sq -= EM->sq;
|
||||
break;
|
||||
|
||||
case 0xFC: /* PADDB Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
|
||||
@@ -326,11 +326,6 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
|
||||
case 0x66:
|
||||
return Run6664(emu, rex, seg, addr);
|
||||
case 0x67:
|
||||
if(rex.is32bits)
|
||||
return Run6764_32(emu, rex, seg, seg, addr);
|
||||
else
|
||||
return 0;
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
|
||||
+25
-62
@@ -166,33 +166,7 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].word[0] = dec16(emu, emu->regs[tmp8u].word[0]);
|
||||
break;
|
||||
case 0x50:
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
case 0x55:
|
||||
case 0x56:
|
||||
case 0x57: /* PUSH Reg */
|
||||
if(rex.is32bits) {
|
||||
tmp8u = opcode&7;
|
||||
Push16(emu, emu->regs[tmp8u].word[0]);
|
||||
} else
|
||||
return 0;
|
||||
break;
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
case 0x5B:
|
||||
case 0x5C: /* POP ESP */
|
||||
case 0x5D:
|
||||
case 0x5E:
|
||||
case 0x5F: /* POP Reg */
|
||||
if(rex.is32bits) {
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].word[0] = Pop16(emu);
|
||||
} else
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 0x60: /* PUSHA */
|
||||
if(rex.is32bits) {
|
||||
tmp16u = R_SP;
|
||||
@@ -364,26 +338,27 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
GD->word[0] = (uint16_t)tmp64u;
|
||||
break;
|
||||
|
||||
case 0x90: /* NOP or XCHG R8d, AX*/
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97: /* XCHG reg,AX */
|
||||
tmp8u = _AX+(opcode&7)+(rex.b<<3);
|
||||
if(tmp8u!=_AX) {
|
||||
if(rex.w) {
|
||||
tmp64u = R_RAX;
|
||||
R_RAX = emu->regs[tmp8u].q[0];
|
||||
emu->regs[tmp8u].q[0] = tmp64u;
|
||||
} else {
|
||||
tmp16u = R_AX;
|
||||
R_AX = emu->regs[tmp8u].word[0];
|
||||
emu->regs[tmp8u].word[0] = tmp16u;
|
||||
case 0x90: /* NOP or XCHG R8d, AX*/
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97: /* XCHG reg,AX */
|
||||
tmp8u = _AX+(opcode&7)+(rex.b<<3);
|
||||
if(tmp8u!=_AX) {
|
||||
if(rex.w) {
|
||||
tmp64u = R_RAX;
|
||||
R_RAX = emu->regs[tmp8u].q[0];
|
||||
emu->regs[tmp8u].q[0] = tmp64u;
|
||||
} else {
|
||||
tmp16u = R_AX;
|
||||
R_AX = emu->regs[tmp8u].word[0];
|
||||
emu->regs[tmp8u].word[0] = tmp16u;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x98: /* CBW */
|
||||
@@ -393,16 +368,6 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
|
||||
break;
|
||||
|
||||
case 0x9C: /* PUSHFW */
|
||||
CHECK_FLAGS(emu);
|
||||
Push16(emu, (uint16_t)emu->eflags.x64);
|
||||
break;
|
||||
case 0x9D: /* POPFW */
|
||||
CHECK_FLAGS(emu);
|
||||
emu->eflags.x64 &=0xffff0000;
|
||||
emu->eflags.x64 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
|
||||
break;
|
||||
|
||||
case 0xA1: /* MOV EAX,Od */
|
||||
if(rex.is32bits) {
|
||||
R_AX = *(uint16_t*)(uintptr_t)F32;
|
||||
@@ -824,6 +789,7 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
case 0xFF: /* GRP 5 Ew */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
EW->word[0] = inc16(emu, EW->word[0]);
|
||||
@@ -841,12 +807,9 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
}
|
||||
addr = tmp64u;
|
||||
break;
|
||||
case 6: /* Push Ew */
|
||||
if(rex.is32bits) {
|
||||
Push16(emu, EW->word[0]);
|
||||
} else
|
||||
return 0;
|
||||
break;
|
||||
/*case 6:
|
||||
Push16(emu, EW->word[0]);
|
||||
break;*/
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: 66 %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
|
||||
emu->quit=1;
|
||||
|
||||
+1
-12
@@ -788,18 +788,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GX->q[0] ^= EX->q[0];
|
||||
GX->q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xF0: /* MOVBE Gw, Ew */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->uw[0] = __builtin_bswap16(EX->uw[0]);
|
||||
break;
|
||||
case 0xF1: /* MOVBE Ew, Gw */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
EX->uw[0] = __builtin_bswap16(GX->uw[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+16
-16
@@ -79,14 +79,14 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&my_context->mutex_lock);
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp16(emu, R_AX, EW->word[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
EW->word[0] = GW->word[0];
|
||||
} else {
|
||||
R_AX = EW->word[0];
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -110,11 +110,11 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
}
|
||||
GD->word[0] = tmp16u;
|
||||
#else
|
||||
pthread_mutex_lock(&my_context->mutex_lock);
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp16u = add16(emu, ED->word[0], GD->word[0]);
|
||||
GD->word[0] = ED->word[0];
|
||||
ED->word[0] = tmp16u;
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -148,22 +148,22 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8; \
|
||||
GETEW(0); \
|
||||
GETGW; \
|
||||
pthread_mutex_lock(&my_context->mutex_lock); \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); \
|
||||
EW->word[0] = OP##16(emu, EW->word[0], GW->word[0]); \
|
||||
pthread_mutex_unlock(&my_context->mutex_lock); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock); \
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GETEW(0); \
|
||||
GETGW; \
|
||||
pthread_mutex_lock(&my_context->mutex_lock); \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); \
|
||||
GW->word[0] = OP##16(emu, GW->word[0], EW->word[0]); \
|
||||
pthread_mutex_unlock(&my_context->mutex_lock); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock); \
|
||||
break; \
|
||||
case B+5: \
|
||||
pthread_mutex_lock(&my_context->mutex_lock); \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); \
|
||||
R_AX = OP##16(emu, R_AX, F16); \
|
||||
pthread_mutex_unlock(&my_context->mutex_lock); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock); \
|
||||
break;
|
||||
#endif
|
||||
GO(0x00, add) /* ADD 0x00 -> 0x05 */
|
||||
@@ -205,7 +205,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 7: cmp16(emu, ED->word[0], tmp16u); break;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&my_context->mutex_lock);
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->word[0] = add16(emu, ED->word[0], tmp16u); break;
|
||||
case 1: ED->word[0] = or16(emu, ED->word[0], tmp16u); break;
|
||||
@@ -216,7 +216,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp16u); break;
|
||||
case 7: cmp16(emu, ED->word[0], tmp16u); break;
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -241,9 +241,9 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
} while(native_lock_write_h(ED, inc16(emu, tmp16u)));
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&my_context->mutex_lock);
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->word[0] = inc16(emu, ED->word[0]);
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
@@ -252,9 +252,9 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp16u = native_lock_read_h(ED);
|
||||
} while(native_lock_write_h(ED, dec16(emu, tmp16u)));
|
||||
#else
|
||||
pthread_mutex_lock(&my_context->mutex_lock);
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->word[0] = dec16(emu, ED->word[0]);
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
||||
+3
-7
@@ -39,15 +39,11 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
if(rex.is32bits)
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test67_32(test, rex, rep, addr);
|
||||
#else
|
||||
return Run67_32(emu, rex, rep, addr);
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
if(rex.is32bits)
|
||||
return Run67_32(emu, rex, rep, addr);
|
||||
|
||||
while(opcode==0x67)
|
||||
opcode = F8;
|
||||
|
||||
|
||||
@@ -51,19 +51,6 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 0: /* MOVUPS Ex,Gx */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
EX->u128 = GX->u128;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2E:
|
||||
// same for now
|
||||
case 0x2F:
|
||||
@@ -97,12 +84,6 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
GETGM;
|
||||
GM->q = EM->q;
|
||||
break;
|
||||
case 2: /* MOVDQU Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
memcpy(GX, EX, 16); // unaligned...
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loaded 100 of 1051 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user