mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-08 10:10:14 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5368285be0 | ||
|
|
096ff18ee8 | ||
|
|
2cde569916 | ||
|
|
f0afcb2e62 | ||
|
|
5b606a785d | ||
|
|
6bfa4a390c | ||
|
|
1b91e9d614 | ||
|
|
bff458d636 | ||
|
|
8814b73eb3 | ||
|
|
d116855eb8 | ||
|
|
5dd4a31f17 | ||
|
|
a32bf25289 | ||
|
|
eac21c4f59 | ||
|
|
f4f5cb2e80 | ||
|
|
f559a75353 | ||
|
|
aff26ce1c0 | ||
|
|
49717bf706 | ||
|
|
283eecadd6 | ||
|
|
9069f56a9d | ||
|
|
422c095ebf | ||
|
|
8373bee595 | ||
|
|
a474c66e26 | ||
|
|
b933efedd1 | ||
|
|
8719e9a857 | ||
|
|
2995c5312e | ||
|
|
0bed0d5b9c | ||
|
|
4e4d4515d0 | ||
|
|
6b46117211 | ||
|
|
679dbafc9e | ||
|
|
f6415a746c | ||
|
|
b5623128b2 | ||
|
|
cdcf85bdfa | ||
|
|
41f301c3c4 | ||
|
|
2641c5b274 | ||
|
|
9f4c37104a | ||
|
|
428d59a1b0 | ||
|
|
f3532ccb99 | ||
|
|
64f7ff5880 | ||
|
|
79fd8562bf | ||
|
|
b2aab80ef0 | ||
|
|
cb9698a5b0 | ||
|
|
3c0ac75fc7 | ||
|
|
00c7e88da0 | ||
|
|
e26d7981b0 | ||
|
|
2d184211bf | ||
|
|
1d7072bf86 | ||
|
|
33401074e7 | ||
|
|
35fcd0b269 | ||
|
|
6ce9ba83df | ||
|
|
0ee881cf0d | ||
|
|
9bf5db778b | ||
|
|
bcdeff5217 | ||
|
|
4a7c16c336 | ||
|
|
fa4b5fe75a | ||
|
|
7cf983f765 | ||
|
|
102e0a8ab3 | ||
|
|
754d7fc8a6 | ||
|
|
79d355668f | ||
|
|
189cd84c41 | ||
|
|
a5b13f592b | ||
|
|
987c87595a | ||
|
|
dc26964fd2 | ||
|
|
5a94979c69 | ||
|
|
028f700093 | ||
|
|
e782ffc98d | ||
|
|
6675da0661 | ||
|
|
ba965fce28 | ||
|
|
aeca17a36f | ||
|
|
0e64848623 | ||
|
|
52bf1907c5 | ||
|
|
40a2e18034 | ||
|
|
535db78525 | ||
|
|
aee4ee9430 | ||
|
|
20fd7e5b23 | ||
|
|
1cf3dd1cb1 | ||
|
|
a9a88c2f6e | ||
|
|
1b8dd6fa19 | ||
|
|
cffafe8b65 | ||
|
|
1d2752a0be | ||
|
|
6151667c84 | ||
|
|
d87c72298f | ||
|
|
2e1b3d23dc | ||
|
|
1955c22501 | ||
|
|
6378359fd8 | ||
|
|
fe83210938 | ||
|
|
aae0a76d2b | ||
|
|
34d7177768 | ||
|
|
28131360b2 | ||
|
|
7e0f3af5a0 | ||
|
|
cb6c9e8ceb | ||
|
|
b30a071783 | ||
|
|
0e8ab73e49 | ||
|
|
7475e7f68d | ||
|
|
25902550fa | ||
|
|
883b7bf054 | ||
|
|
b3077791b2 | ||
|
|
46fbe2a9a8 | ||
|
|
d5fab7c7b1 | ||
|
|
860a404cb1 | ||
|
|
0fa9c01549 | ||
|
|
b34652d862 | ||
|
|
fcd7578b9a | ||
|
|
f5e0c61d12 | ||
|
|
92d2d2c638 | ||
|
|
79a1dc0564 | ||
|
|
a22c0d3343 | ||
|
|
46114235f9 | ||
|
|
2bb62e419d | ||
|
|
ac6f71b188 | ||
|
|
a438985c8c | ||
|
|
9f310e6be2 | ||
|
|
edfb61a452 | ||
|
|
3b30a559b6 | ||
|
|
497d4dc804 | ||
|
|
631856ae54 | ||
|
|
8b887c7714 | ||
|
|
852f6af362 | ||
|
|
cd6cb2352f | ||
|
|
5bc7a1bf4f | ||
|
|
844566a78a | ||
|
|
2320c0de77 | ||
|
|
6afddae6d8 | ||
|
|
5de22d4ce1 | ||
|
|
3162ae83b4 | ||
|
|
e5bcae6e43 | ||
|
|
a110b60a2a | ||
|
|
9190a20ca1 | ||
|
|
7a7f746782 | ||
|
|
6c148b77a1 | ||
|
|
e30eae7652 | ||
|
|
811ffe83f8 | ||
|
|
ae8d61c3a3 | ||
|
|
0e54aaf70f | ||
|
|
4498f216a0 | ||
|
|
3b4a1e6861 | ||
|
|
83a9f96f20 | ||
|
|
dad2601f0d | ||
|
|
fb79a9eb22 | ||
|
|
5fded645fb | ||
|
|
84f16804bb | ||
|
|
e6969267e9 | ||
|
|
1655a98997 | ||
|
|
4444bd2286 | ||
|
|
fe402954f8 | ||
|
|
9ae3543879 | ||
|
|
e88fa9ab45 | ||
|
|
c707150666 | ||
|
|
c2e5f60526 | ||
|
|
395629f678 | ||
|
|
f77b80899d | ||
|
|
5720619bd2 | ||
|
|
e33ac88379 | ||
|
|
96c9bf168e | ||
|
|
3711622f66 | ||
|
|
a3cd9f7de7 | ||
|
|
389927dc1d | ||
|
|
ff63fa7437 | ||
|
|
b480d6856b | ||
|
|
76786e9e43 | ||
|
|
aa9ff80137 | ||
|
|
2e60a6b6e7 | ||
|
|
f24684f478 | ||
|
|
f43a507e91 | ||
|
|
25f7283af9 | ||
|
|
ea29d3f6df | ||
|
|
1592f9246b | ||
|
|
b481c25ee5 | ||
|
|
e6fa77b3c0 | ||
|
|
3da5f56257 | ||
|
|
d97dfa768a | ||
|
|
1d671b104b | ||
|
|
d7cb28a66b | ||
|
|
d153456653 | ||
|
|
ad77202a05 | ||
|
|
20ffd3681e | ||
|
|
d66c1f4510 | ||
|
|
fcdd6f7947 | ||
|
|
1b54190c15 | ||
|
|
7550203dc9 | ||
|
|
380e9fa09e | ||
|
|
c04aeec3e5 | ||
|
|
b758d842c4 | ||
|
|
ff9da0c850 | ||
|
|
87681ffcaa | ||
|
|
47c33cd5a9 | ||
|
|
ea9e9da829 | ||
|
|
0ffcfcb0c0 | ||
|
|
132d2dc3fc | ||
|
|
de61c33093 | ||
|
|
38b12c9773 | ||
|
|
2734536fa7 | ||
|
|
d4e7852598 | ||
|
|
fd3da6af08 | ||
|
|
de3ec8e7af | ||
|
|
2256560985 | ||
|
|
342ee45558 | ||
|
|
c207597409 | ||
|
|
2f5198eb9f | ||
|
|
96fb201246 | ||
|
|
ff36508548 | ||
|
|
02612749c8 | ||
|
|
7648cd9a56 | ||
|
|
95feb02d97 | ||
|
|
36a49e135e | ||
|
|
8fe7b90daa | ||
|
|
238103a5e0 | ||
|
|
72e0d80af9 | ||
|
|
21b61f07da | ||
|
|
1d67fb050c | ||
|
|
40eaacc33b | ||
|
|
4b47e699f5 | ||
|
|
d845f048ea | ||
|
|
e70dc0af56 | ||
|
|
3c3c64f3c7 | ||
|
|
87a9ce334a | ||
|
|
ace58063e4 | ||
|
|
33ef14cd5d | ||
|
|
4f6196b330 | ||
|
|
fbe1ff93e9 | ||
|
|
b2581fccaa | ||
|
|
056e29c9a8 | ||
|
|
0bf409fc10 | ||
|
|
6d2a3883ac | ||
|
|
d7dcb56105 | ||
|
|
a62a9f6c75 | ||
|
|
b4c32dd56b | ||
|
|
3a323abc9a | ||
|
|
1fefd5c82c | ||
|
|
e470a28bda | ||
|
|
435f1c2a16 | ||
|
|
e9f72c1e33 | ||
|
|
f8d8c6c7a4 | ||
|
|
0c7022a756 | ||
|
|
7254e5558b | ||
|
|
17cdb30ab1 | ||
|
|
db743b1226 | ||
|
|
e9cc8d43a9 | ||
|
|
4dd9bf74d9 | ||
|
|
722909a9cf | ||
|
|
13287a114c | ||
|
|
1a6659d577 | ||
|
|
3a7cc57fde | ||
|
|
c093f18d20 | ||
|
|
f2ebd77ace | ||
|
|
ad55a85b89 | ||
|
|
779e0bdc50 | ||
|
|
80c4d80952 | ||
|
|
42e54c0241 | ||
|
|
b393356b4b | ||
|
|
f65555c810 | ||
|
|
174bf29f28 | ||
|
|
1776027e63 | ||
|
|
4018df12cd | ||
|
|
c400cd5f61 | ||
|
|
4710c4777e | ||
|
|
a872136418 | ||
|
|
da15c9619a | ||
|
|
a67b510cae | ||
|
|
c84d1a827e | ||
|
|
0e2cac5505 | ||
|
|
aa4f39a51b | ||
|
|
3c0b7830de | ||
|
|
25f43108fe | ||
|
|
da64e491bb | ||
|
|
23fe11278c | ||
|
|
f27361bf17 | ||
|
|
91e0120780 | ||
|
|
e4f2af21c3 | ||
|
|
2edb0ed1e3 | ||
|
|
e317c61084 | ||
|
|
5506dbbc77 | ||
|
|
2ed175ee3b | ||
|
|
2a2631075e | ||
|
|
406226bd2b | ||
|
|
6f105f0720 | ||
|
|
e30430be48 | ||
|
|
3a52af11bd | ||
|
|
c73b427d42 | ||
|
|
85f5a619ab | ||
|
|
a6d94027db | ||
|
|
45a3044a61 | ||
|
|
d25b3a307e | ||
|
|
d5e3bc9ceb | ||
|
|
cd8f2997ca | ||
|
|
df65e97491 | ||
|
|
abbb60a4fa | ||
|
|
ff05035bc0 | ||
|
|
71d9d78ed5 | ||
|
|
d8b2e96552 | ||
|
|
c974ce057e | ||
|
|
ddbe50c5ef | ||
|
|
2aaf87bbcf | ||
|
|
8c74fde404 | ||
|
|
dbe5afeaba | ||
|
|
9bf035539b | ||
|
|
5cb73d58cd | ||
|
|
1e3eba1b5b | ||
|
|
87af935494 | ||
|
|
86cc204693 | ||
|
|
d1e6d744ae | ||
|
|
cea3dcea67 | ||
|
|
72a896a95a | ||
|
|
9ca0c429bf | ||
|
|
681e06ce73 | ||
|
|
3a3e393d20 | ||
|
|
6b86cb7d1e | ||
|
|
4a772f1bb6 | ||
|
|
d8309595cf | ||
|
|
6000f4f25c | ||
|
|
3cabeb4f27 | ||
|
|
53b525d758 | ||
|
|
06ebc4cb03 | ||
|
|
25245e2a46 | ||
|
|
4d8adae071 | ||
|
|
d65216df76 | ||
|
|
155c4ba1f9 | ||
|
|
f6ff832e51 | ||
|
|
0b4045ffb1 | ||
|
|
677d9feb87 | ||
|
|
043ac1fdab | ||
|
|
dacd75ca7e | ||
|
|
3e5352f79c | ||
|
|
2f56a667f3 | ||
|
|
cefa19ec6a | ||
|
|
ab2ab88581 | ||
|
|
a5c28c6020 | ||
|
|
ac3ddc134e | ||
|
|
86659b40bd | ||
|
|
fd7c7e356c | ||
|
|
10c4e0323a | ||
|
|
53a647af56 | ||
|
|
026185da74 | ||
|
|
951a85d3b7 | ||
|
|
d6db825ec3 | ||
|
|
d9ab158b97 | ||
|
|
f9305d58e8 | ||
|
|
8da827d06f | ||
|
|
4ee29a6d57 | ||
|
|
e060e060af | ||
|
|
81a63edcbc | ||
|
|
8b1ca1330f | ||
|
|
7bc1a6d7c7 | ||
|
|
9e24a71225 | ||
|
|
8d89e7efdb | ||
|
|
4ca4e84878 | ||
|
|
9461f7d24e | ||
|
|
e29ba9e43e | ||
|
|
a875a16c92 | ||
|
|
de92a8a41b | ||
|
|
d719809440 | ||
|
|
656e7552b5 | ||
|
|
9715a2fef6 | ||
|
|
268166b20a | ||
|
|
f03fb651c2 | ||
|
|
6b05e42582 | ||
|
|
0d42b42459 | ||
|
|
2159d407ee | ||
|
|
2b9645e3a6 | ||
|
|
5d0d1e4eb2 | ||
|
|
0d82e52aa6 | ||
|
|
28cfc17bb6 | ||
|
|
5c8d387c27 | ||
|
|
213f51c14b | ||
|
|
d2e5f715a9 |
No files matched your search
@@ -0,0 +1,88 @@
|
||||
### Auto build Box86 and release its binary with Github Action
|
||||
name: Build and Release Box86
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
push:
|
||||
paths:
|
||||
- "**/*.c"
|
||||
- "**/*.h"
|
||||
- "**/*.S"
|
||||
- "**/*.py"
|
||||
- "CMakeList.txt"
|
||||
- "**/*.yml"
|
||||
pull_request:
|
||||
types: [assigned, opened, synchronize, reopened]
|
||||
paths:
|
||||
- "**/*.c"
|
||||
- "**/*.h"
|
||||
- "**/*.S"
|
||||
- "**/*.py"
|
||||
- "CMakeList.txt"
|
||||
- "**/*.yml"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM]
|
||||
type: [Release, Trace]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout Box86 Repository"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Environment preparation"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
|
||||
if [[ ${{ matrix.platform }} != 'I386' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
|
||||
echo "BOX86_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
|
||||
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
|
||||
else
|
||||
if [[ ${{ matrix.platform }} == 'I386' ]]; then
|
||||
echo "BOX86_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
|
||||
echo "BOX86_COMPILER=/bin/i686-linux-gnu-gcc-10" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git libc6-dev-i386-amd64-cross gcc-10-i686-linux-gnu cmake make python3
|
||||
ls /bin/*gcc*
|
||||
else
|
||||
echo BOX86_PLATFORM_MARCRO="-DARM_DYNAREC=ON -DCMAKE_C_FLAGS=-marm" >> $GITHUB_ENV
|
||||
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ${{ matrix.type }} == 'Release' ]]; then
|
||||
echo BOX86_BUILD_TYPE=Release >> $GITHUB_ENV
|
||||
echo BOX86_HAVE_TRACE=0 >> $GITHUB_ENV
|
||||
else
|
||||
echo BOX86_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
|
||||
echo BOX86_HAVE_TRACE=1 >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: "Display Build info"
|
||||
run: |
|
||||
echo "CMake Platform Macro: ${{ env.BOX86_PLATFORM_MARCRO }}"
|
||||
echo "CMake C Compiler: ${{ env.BOX86_COMPILER }}"
|
||||
echo "Build type: ${{ env.BOX86_BUILD_TYPE }}"
|
||||
echo "Trace Enabled: ${{ env.BOX86_HAVE_TRACE }}"
|
||||
|
||||
- name: "Build Box86"
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }} ${{ env.BOX86_PLATFORM_MARCRO }} -DCMAKE_BUILD_TYPE=${{ env.BOX86_BUILD_TYPE }} -DHAVE_TRACE=${{ env.BOX86_HAVE_TRACE }} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
|
||||
make -j$(nproc) VERBOSE=1
|
||||
|
||||
- name: "Upload Artifact"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: box86-${{ matrix.platform }}-${{ matrix.type }}
|
||||
path: build/box86
|
||||
|
||||
|
||||
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
language: c
|
||||
arch:
|
||||
- arm64-graviton2
|
||||
- amd64
|
||||
os: linux
|
||||
dist: focal
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python3
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
#Build steps
|
||||
before_script:
|
||||
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then sudo dpkg --add-architecture armhf ; else sudo dpkg --add-architecture i386 ; fi
|
||||
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then sudo apt-get -y install gcc-arm-linux-gnueabihf ; else sudo apt-get -y install gcc-multilib libc6-dev:i386 libgcc1:i386 ; fi
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; else CFLAGS="-m32" cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; fi
|
||||
|
||||
script:
|
||||
- make
|
||||
- if [ "$TRAVIS_CPU_ARCH" != "arm64" ]; then ctest --output-on-failure ; fi
|
||||
+119
-34
@@ -6,17 +6,22 @@ option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
|
||||
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
|
||||
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
|
||||
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
|
||||
option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
|
||||
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
|
||||
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
|
||||
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
|
||||
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
|
||||
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
|
||||
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
|
||||
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
|
||||
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
|
||||
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 Box86" ${NO_LOADAADR})
|
||||
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR RK3399 OR RPI4ARM64)
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -46,7 +51,7 @@ else()
|
||||
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
|
||||
endif()
|
||||
|
||||
if(RK3399 OR RPI4ARM64)
|
||||
if(RK3399 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
|
||||
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
|
||||
@@ -66,50 +71,65 @@ endif()
|
||||
if(PANDORA)
|
||||
add_definitions(-DPANDORA)
|
||||
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
|
||||
endif()
|
||||
if(GAMESHELL)
|
||||
add_definitions(-DGAMEHELL)
|
||||
elseif(GAMESHELL)
|
||||
add_definitions(-DGAMESHELL)
|
||||
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
|
||||
endif()
|
||||
if(PYRA)
|
||||
elseif(PYRA)
|
||||
add_definitions(-DPYRA)
|
||||
add_definitions(-mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -marm)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard")
|
||||
endif()
|
||||
if(RPI2)
|
||||
elseif(RPI2)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI2)
|
||||
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
|
||||
endif()
|
||||
if(RPI3)
|
||||
elseif(RPI3)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI3)
|
||||
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
endif()
|
||||
if(RPI4)
|
||||
elseif(RPI4)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI4)
|
||||
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
endif()
|
||||
if(RPI4ARM64)
|
||||
elseif(RPI4ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
endif()
|
||||
if(ODROID)
|
||||
elseif(ODROID)
|
||||
add_definitions(-DODROID)
|
||||
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
|
||||
endif()
|
||||
if(RK3399)
|
||||
elseif(RK3288)
|
||||
add_definitions(-DRK3288)
|
||||
add_definitions(-mcpu=cortex-a17 -mfpu=neon -mfloat-abi=hard -marm)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a17 -mfpu=neon -mfloat-abi=hard")
|
||||
elseif(SD845)
|
||||
add_definitions(-DSD845)
|
||||
add_definitions(-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(A64)
|
||||
add_definitions(-DA64)
|
||||
add_definitions(-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(GOA_CLONE)
|
||||
add_definitions(-DGOA_CLONE)
|
||||
add_definitions(-marm -mcpu=cortex-a35 -mfpu=neon-vfpv3 -march=armv8-a+crc+simd+crypto -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a35 -mfpu=neon-vfpv3 -march=armv8-a+crc+simd+crypto -mfloat-abi=hard")
|
||||
elseif(RK3399)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(PHYTIUM)
|
||||
add_definitions(-DPHYTIUM)
|
||||
add_definitions(-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(ARM_DYNAREC)
|
||||
#if DYNAREC is selected alone, without any arch
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
|
||||
endif()
|
||||
|
||||
if(POWER9)
|
||||
@@ -123,7 +143,7 @@ endif()
|
||||
if(BOX86LIB)
|
||||
set(BOX86 box86)
|
||||
elseif(HAVE_TRACE)
|
||||
set(BOX86 box86t)
|
||||
set(BOX86 box86)
|
||||
else()
|
||||
set(BOX86 box86)
|
||||
endif()
|
||||
@@ -216,6 +236,9 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/elfs/elfload_dump.c"
|
||||
"${BOX86_ROOT}/src/librarian/library.c"
|
||||
"${BOX86_ROOT}/src/librarian/librarian.c"
|
||||
"${BOX86_ROOT}/src/librarian/dictionnary.c"
|
||||
"${BOX86_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX86_ROOT}/src/emu/x86emu.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66.c"
|
||||
@@ -332,6 +355,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibformw.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibpanel.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses6.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
|
||||
@@ -343,6 +367,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgmodule2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgobject2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedglib2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgconf2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer010.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
|
||||
@@ -376,8 +401,22 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibtiff.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedcrashhandler.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibv4l2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappednspr4.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedsmime3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappednssutil3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappednss3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedplds4.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedplc4.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedssl3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedsecret1.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedtbbmalloc.c"
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
if(ANDROID)
|
||||
list(APPEND WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedandroidshmem.c"
|
||||
)
|
||||
else()
|
||||
list(APPEND WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
|
||||
@@ -387,7 +426,7 @@ endif()
|
||||
|
||||
# If BOX86_ROOT contains a ".c", the build breaks...
|
||||
string(REPLACE ".c" "_private.h" MODROOT ${BOX86_ROOT})
|
||||
set(WRAPPEDS_HEAD "")
|
||||
set(WRAPPEDS_HEAD "${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9_genvate.h")
|
||||
foreach(A ${WRAPPEDS})
|
||||
string(REPLACE ".c" "_private.h" C ${A})
|
||||
string(REPLACE "${MODROOT}" "${BOX86_ROOT}" B ${C})
|
||||
@@ -556,6 +595,8 @@ endif()
|
||||
|
||||
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}" "armhf" _armhf)
|
||||
|
||||
if(NOT _x86 AND NOT _x86_64)
|
||||
install(TARGETS ${BOX86}
|
||||
@@ -577,6 +618,36 @@ if(NOT TARGET uninstall)
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif()
|
||||
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
|
||||
set(CPACK_PACKAGE_CONTACT "[email protected]")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Box86 - Linux Userspace x86 Emulator with a twist")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
|
||||
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MAJOR\\s*")
|
||||
string(REGEX REPLACE "BOX86_MAJOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX86_MAJOR ${TEMP_STRING})
|
||||
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MINOR\\s*")
|
||||
string(REGEX REPLACE "BOX86_MINOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX86_MINOR ${TEMP_STRING})
|
||||
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_REVISION\\s*")
|
||||
string(REGEX REPLACE "BOX86_REVISION" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX86_REVISION ${TEMP_STRING})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX86_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${BOX86_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${BOX86_REVISION})
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
|
||||
if(_aarch64 OR _armhf)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
|
||||
elseif(_x86_64 OR _x86)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
|
||||
else()
|
||||
#probably wrong...
|
||||
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
||||
endif()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
INCLUDE(CPack)
|
||||
|
||||
add_test(NAME bootSyscall COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
|
||||
@@ -647,16 +718,30 @@ add_test(NAME conditionalThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAK
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
# WIP
|
||||
#add_test(NAME linkingIndirectNoversion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile.txt
|
||||
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
|
||||
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
#
|
||||
#add_test(NAME linkingIndirectVersion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
|
||||
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
|
||||
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
add_test(NAME linkingIndirectNoversion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME linkingIndirectVersion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME ucomiss COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test19 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref19.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
|
||||
foreach(file ${extension_tests})
|
||||
|
||||
File renamed without changes.
@@ -1,3 +1,25 @@
|
||||
v0.2.4
|
||||
======
|
||||
* Some work on Dynarec to limit the number of mutex use, and also allow smaller block to be built (for JIT'd programs)
|
||||
* Introduce BOX86_DYNAREC_STRONGMEM, like with box64 (not found any program that needs that yet)
|
||||
* More vulkan wrapped function (so dkvk works, at least with RX550)
|
||||
* Reworked Elfloader part, with better handling of versionned symbols
|
||||
* Improve speed for x87 code (by avoiding many float<->double conversion)
|
||||
* Improve speed of the custom allocator used by dynarec and Hash (speedup loading)
|
||||
* Added a detection of box64 in uname call, to expose an x86_64 system instead of i386 one
|
||||
* Added a fix for linking box86 on system using glibc 2.34+
|
||||
* A few more wrapped libs
|
||||
* More ARM hardware option in CMake (Phytium, SD845)
|
||||
* Changed a bit struture of Dynarec, switching some operations from Pass1 to Pass0
|
||||
* Small fixes to elfloader
|
||||
* Some fixes and improvments on wrapped libs (mainly gtk2, gtk3 and d3dadpter)
|
||||
* Better VSyscall implementation
|
||||
* Fixed the "Alternate" handling (address shadowing on x86 side)
|
||||
* A few opcodes border case fixes
|
||||
* Improved wrapper helpers (from rajdakin)
|
||||
* Added a mecanism to cancel a Dynarec block construction if it triggers a segfault (instead of a crash)
|
||||
* Improvment to the handling of longjmp inside signal handlers
|
||||
|
||||
v0.2.2
|
||||
======
|
||||
* Reworked some elfloader relocation mecanism
|
||||
|
||||
+46
-7
@@ -20,30 +20,64 @@ Compiling
|
||||
git clone https://github.com/ptitSeb/box86
|
||||
cd box86
|
||||
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j4
|
||||
make
|
||||
sudo make install
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
Note that you can use `make -j2` or more to speed up 1st build, but beware of the memory requirement if you go to high.
|
||||
|
||||
_For Pi4. Change to RPI2 or RPI3 for other models. Change to RPI4ARM64 for compiling on arm64. (armhf multiarch or chroot required alongside armhf gcc. Install it with 'sudo apt install gcc-arm-linux-gnueabihf'.)_
|
||||
#### for Raspberry Pi on 64bits OS
|
||||
|
||||
_For Pi4. Change to RPI2 or RPI3 for other models. Change `-DRPI4=1` to `-DRPI4ARM64=1` for compiling on arm64. (armhf multiarch or chroot required alongside armhf gcc. Install it with 'sudo apt install gcc-arm-linux-gnueabihf'.)_
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box86
|
||||
cd box86
|
||||
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j2
|
||||
sudo make install
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for ODROID
|
||||
|
||||
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
#### for RK3399
|
||||
|
||||
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Tinker Board (1/1S) or RK3288
|
||||
|
||||
`mkdir build; cd build; cmake .. -DRK3288=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
#### for Allwinner A64
|
||||
|
||||
`mkdir build; cd build; cmake .. -DA64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
As most Allwinner A64 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Snapdragon 845
|
||||
|
||||
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most Snapdragon 845 device run AARCH64 OS, in most cases you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Phytium
|
||||
|
||||
`mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian/ubuntu, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Other ARM Linux platforms
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
#### for x86 Linux
|
||||
|
||||
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
`mkdir build; cd build; cmake .. -DCMAKE_C_FLAGS="-m32" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
#### use ccmake
|
||||
|
||||
@@ -65,7 +99,7 @@ To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` b
|
||||
|
||||
*to have ARM Dynarec*
|
||||
|
||||
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
|
||||
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode). Note that compiling with `ARM_DYNAREC` but without hardware profile is not advise. If you get error building that "target CPU does not support ARM mode", then try to pick hardware profile (like ODROID for armv7 or PI4 for armv8). Also, if you are using a 64bits with armhf multiarch, it's much easier to pick one of the hardware profile like `RPI4ARM64`, `RK3399`, `PHYTIUM` or `SD845`.
|
||||
|
||||
*not building from a git clone*
|
||||
|
||||
@@ -79,3 +113,8 @@ A few tests are included.
|
||||
They can be launched with `ctest`
|
||||
They are very basic and don't test much for now.
|
||||
|
||||
----
|
||||
|
||||
Note about devices with Tegra X1 and newer.
|
||||
|
||||
Nvidia don't provide armhf libraries for their GPU drivers at this moment so there is no special variable to compile it for them as it would be missleading for many people. If you still want to use it wihout GPU acceleration, building it with RPI4 configuration should work just fine. As instalation of Mesa can break Nvidia driver, safest option is usage of chroot.
|
||||
+28
-16
@@ -3,6 +3,8 @@
|
||||

|
||||
Linux Userspace x86 Emulator with a twist
|
||||
|
||||
[](https://app.travis-ci.com/ptitSeb/box86)
|
||||
|
||||
----
|
||||
|
||||
Compiling/Installation
|
||||
@@ -14,11 +16,11 @@ Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems,
|
||||
|
||||
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environnement).
|
||||
|
||||
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in some cases.
|
||||
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
|
||||
|
||||
Most x86 Games need OpenGL, so on ARM platforms an solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
|
||||
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
|
||||
|
||||
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter.
|
||||
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](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/).
|
||||
|
||||
Many games already work without much tweaking, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine. (there's a long list, among them are UNDERTALE, A Risk of Rain, and Cook Serve Delicious)
|
||||
|
||||
@@ -31,7 +33,7 @@ Here's 6 videos, the first 2 videos are videos of "Airline Tycoon Deluxe" and "
|
||||
|
||||
[](https://www.youtube.com/watch?v=bLt0hMoFDLk) [](https://www.youtube.com/watch?v=MM7kWYts7IA) [](https://www.youtube.com/watch?v=8hr71S029Hg) [](https://www.youtube.com/watch?v=B4YN37z3-ws) [](https://www.youtube.com/watch?v=xk8Q30mxqPg) [](https://www.youtube.com/watch?v=_QMRMVvYrqU)
|
||||
|
||||
You can find many more Box86 video on Youtube in the [Pi Labs Channel](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman Channel](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
|
||||
You can find many more Box86 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
|
||||
|
||||
Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list/issues
|
||||
|
||||
@@ -43,13 +45,6 @@ Note that this project is not to be mistaken with [86box](https://github.com/86B
|
||||
|
||||
----
|
||||
|
||||
Discord
|
||||
----
|
||||
|
||||
If you want to discuss (or have any problems) about box86, feel free to join the [Pi Labs Discord Server](https://discord.gg/Fh8sjmu)!
|
||||
|
||||
----
|
||||
|
||||
Usage
|
||||
----
|
||||
|
||||
@@ -73,11 +68,11 @@ Notes about 64-bit platforms
|
||||
|
||||
Because Box86 works by directly translating function calls from x86 to host system, the host system (the one Box86 is running on) needs to have 32-bit libraries. Box86 doesn't include any 32-bit <-> 64-bit translation. So basically, to run Box86 on, for example, an ARM64 platform, you will need to build Box86 for ARM 32-bit, and also need to have a chroot with 32-bit libraries.
|
||||
|
||||
Also note that, even if, on day, there is a Box86_64, this one will only be able to run x86_64 binaries on 64-bit platforms. You will still need Box86 (and a 32-bit chroot) to run x86 binaries (in fact, the same is the case on actual x86_64 Linux).
|
||||
If you look at a 64bits version of box86, look at [Box64](https://github.com/ptitSeb/box64): this one is able to run x86_64 binaries on 64-bit platforms. But note that you still need Box86 (and a 32-bit chroot) to run x86 binaries (as it also happens on actual x86_64 Linux that need x86 libs and binary on multiarch to run).
|
||||
|
||||
----
|
||||
|
||||
A note about Unity game emulation
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with the new "protected memory" mechanism implemented it should be running with correct performance now.
|
||||
@@ -104,11 +99,28 @@ Steam for Windows installs fine but doesn't work yet.
|
||||
Notes about Wine
|
||||
----
|
||||
|
||||
Wine is now partly supported. Wine integrated program all runs, and some windows programs and games now runs fine. Don't forget most Windows games use Direct3D, this may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
|
||||
Wine is now supported. Wine integrated program all runs, and many windows programs and games also runs fine. Don't forget most Windows games use Direct3D, this may require a complete OpenGL driver and a as high profile as possible (and gl4es with ES2 backend have issue with Wine for now).
|
||||
Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those models use a default OS that have a kernel with a 2/2 Split (meaning 2G of space for user program, and 2G of space for the Kernel). This is not compatible with Wine programs that needs to access memory > 2Gb address. So you'll need to reconfigure your kernel for a 3G/1G split.
|
||||
|
||||
----
|
||||
|
||||
Final words
|
||||
Notes about Vulkan
|
||||
----
|
||||
|
||||
(If you use Box86 in your project, please don't forget to mention Box86!)
|
||||
Box86 already wrap vulikan. If your system has a 32bits vulkan driver, box86 will use it when needed. Note that vulkan wrapping has not been tested much, due to the limited vulkan support on the hardware I currently own. Profile 1.0 and 1.1, whith some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardxware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
|
||||
|
||||
----
|
||||
Final word
|
||||
----
|
||||
|
||||
I want to thank everyone who has contributed to box86 developpement.
|
||||
There are many ways to contribute: code, financial, hardware and advertisement!
|
||||
So, in no particular order, I want to thank:
|
||||
* For their major code contribution: rajdakin, icecream95, M-HT
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000
|
||||
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
|
||||
* For their continous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
And I also thank the many other people who participated even once in the project.
|
||||
|
||||
(If you use Box86 in your project, please don't forget to mention it!)
|
||||
+18
-1
@@ -9,7 +9,12 @@ Controls the Verbosity level of the logs
|
||||
* 0: NONE : No message (except some fatal error). (Default.)
|
||||
* 1: INFO : Show some minimum log (Example: librairies not found)
|
||||
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
|
||||
* 3: DUMP : All DEBUG plus DUMP of all ELF Info.
|
||||
* 3: DUMP : All DEBUG plus DUMP of all ELF Info (so same as `BOX86_LOG=2 BOX86_DUMP=1`)
|
||||
|
||||
#### BOX86_DUMP
|
||||
Controls the Dump of elf content
|
||||
* 0: No dump of elf information (Default)
|
||||
* 1: Dump elf sections and relocations and other information (also active if using `BOX86_LOG=3`)
|
||||
|
||||
#### BOX86_NOBANNER
|
||||
Disables Box86 printing its version and build
|
||||
@@ -31,6 +36,7 @@ Enables/Disables the logging of `dlsym` errors.
|
||||
#### BOX86_TRACE_FILE
|
||||
Send all log and trace to a file instead of `stdout`
|
||||
Also, if name contains `%pid` then this is replaced by the actual PID of box86 instance
|
||||
Use `stderr` to use this instead of default `stdout`
|
||||
|
||||
#### BOX86_TRACE
|
||||
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
|
||||
@@ -109,6 +115,17 @@ Enables/Disables trace for generated code.
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
|
||||
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
|
||||
|
||||
#### BOX86_DYNAREC_BIGBLOCK
|
||||
Enables/Disables Box86's Dynarec building BigBlock.
|
||||
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 1 : Build Dynarec block as big as possible (Default.)
|
||||
|
||||
#### BOX86_DYNAREC_STRONGMEM
|
||||
Enable/Disable simulation of Strong Memory model
|
||||
* 0 : Don't try anything special (Default.)
|
||||
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
|
||||
|
||||
#### BOX86_LIBGL
|
||||
* libXXXX set the name for libGL (defaults to libGL.so.1).
|
||||
* /PATH/TO/libGLXXX : Sets the name and path for libGL
|
||||
|
||||
+48
-54
@@ -1,14 +1,14 @@
|
||||
# Installing Wine (and winetricks)
|
||||
_TwisterOS users: Wine, winetricks, and Box86 are already installed in TwisterOS. You do not have to install anything._
|
||||
|
||||
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 already has a 3G/1G split kernel and works with Wine, but **the Pi 3B+ and earlier models have a 2G/2G kernel and require a custom-compiled 3G/1G kernel to get Wine working.**_
|
||||
|
||||
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (x64 is not yet implemented).
|
||||
See installation steps below (in the [Examples](#examples) section).
|
||||
|
||||
_TwisterOS users, take note: Wine, winetricks, and Box86 are pre-installed in TwisterOS. TwisterOS users do not have to install anything._
|
||||
Box86 needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many of Wine's core Linux i386 libraries (.so files) so that their calls are interpretable by your ARM devices other armhf Linux system libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
|
||||
|
||||
Box86 actually needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many Windows and Wine i386 libraries (`.so` or `.dll` files) so that they will work with your ARM device's libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
|
||||
|
||||
Installation files for Wine can be found in the [WineHQ repository](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/), the [TwisterOS FAQ](https://twisteros.com/faq.html) page, or the [PlayOnLinux website repository](https://www.playonlinux.com/wine/). Box86 requires the "i386" (x86) versions of Wine install files (even though we are installing it on an ARM processor). Box86 "wraps" many of Wine's core Linux i386 libraries so that their calls are interpretable by Linux ARM libraries. Below are examples of how to install Wine from each of those places.
|
||||
|
||||
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 has a 3G/1G split kernel, but **the Pi 3 and earlier models have a 2G/2G kernel by default and will need you to install a custom-compiled 3G/1G kernel to get Wine to work.**
|
||||
Installation files for Wine can be found in the [WineHQ repository](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/), the [TwisterOS FAQ](https://twisteros.com/faq.html) page, or the [PlayOnLinux website repository](https://www.playonlinux.com/wine/). Box86 requires the "i386" (x86) version of Wine even though we are installing it on an ARM processor.
|
||||
|
||||
## Overview
|
||||
The general procedure for installing Wine for Box86 is to...
|
||||
@@ -20,10 +20,40 @@ The general procedure for installing Wine for Box86 is to...
|
||||
- Download winetricks (which is simply a very complicated bash script), make it executable, then copy it to `/usr/local/bin`.
|
||||
|
||||
## Examples
|
||||
_These examples were all tested on Raspberry Pi 4. Note the similarities between the different install methods._
|
||||
### Installing Wine for Box86 on Raspberry Pi OS from Twister OS FAQ .tgz files
|
||||
_Links from the [TwisterOS FAQ](https://twisteros.com/faq.html)_
|
||||
|
||||
### Installing wine-devel, wine-stable, or wine-staging for Raspberry Pi OS Buster from WineHQ deb files
|
||||
This installs Wine v5.13 (which is the version of Wine that comes pre-installed in TwisterOS). When submitting bug reports, other Box86 users may assume you are using this version of Wine unless you specify otherwise.
|
||||
```
|
||||
# Backup any old wine installations
|
||||
sudo mv ~/wine ~/wine-old
|
||||
sudo mv ~/.wine ~/.wine-old
|
||||
sudo mv /usr/local/bin/wine /usr/local/bin/wine-old
|
||||
sudo mv /usr/local/bin/wineboot /usr/local/bin/wineboot-old
|
||||
sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old
|
||||
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old
|
||||
|
||||
# Download, extract wine, and install wine (last I checked, the Twister OS FAQ page had Wine 5.13-devel)
|
||||
wget https://twisteros.com/wine.tgz -O ~/wine.tgz
|
||||
tar -xzvf ~/wine.tgz
|
||||
rm ~/wine.tgz # clean up
|
||||
|
||||
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
|
||||
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
|
||||
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
|
||||
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
|
||||
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
|
||||
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
|
||||
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
|
||||
|
||||
# Boot wine (make fresh wineprefix in ~/.wine )
|
||||
wine wineboot
|
||||
```
|
||||
|
||||
### Installing Wine for Box86 on Raspberry Pi OS Buster from WineHQ .deb files
|
||||
_Links from the [WineHQ repo](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/)_
|
||||
|
||||
This install method allows you to install different versions of Wine. You may install any version and any branch of Wine that you wish (wine-devel, wine-stable, or wine-staging).
|
||||
```
|
||||
# Backup any old wine installations
|
||||
sudo mv ~/wine ~/wine-old
|
||||
@@ -66,53 +96,19 @@ rm -rf libfaudio # clean up
|
||||
wine wineboot
|
||||
```
|
||||
|
||||
### Installing Wine for Raspberry Pi OS from the Twister OS FAQ page
|
||||
_Links from the [TwisterOS FAQ](https://twisteros.com/faq.html)_
|
||||
```
|
||||
# Backup any old wine installations
|
||||
sudo mv ~/wine ~/wine-old
|
||||
sudo mv ~/.wine ~/.wine-old
|
||||
sudo mv /usr/local/bin/wine /usr/local/bin/wine-old
|
||||
sudo mv /usr/local/bin/wineboot /usr/local/bin/wineboot-old
|
||||
sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old
|
||||
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old
|
||||
|
||||
# Download, extract wine, and install wine (last I checked, the Twister OS FAQ page had Wine 5.13-devel)
|
||||
wget https://twisteros.com/wine.tgz -O ~/wine.tgz
|
||||
tar -xzvf ~/wine.tgz
|
||||
rm ~/wine.tgz # clean up
|
||||
|
||||
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
|
||||
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
|
||||
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
|
||||
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
|
||||
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
|
||||
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
|
||||
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
|
||||
|
||||
# Boot wine (make fresh wineprefix in ~/.wine )
|
||||
wine wineboot
|
||||
```
|
||||
## Installing winetricks
|
||||
Winetricks is a script which makes it easier to install & configure any desired Windows core system software packages which may be dependencies for certain Windows programs.
|
||||
Winetricks is a bash script which makes it easier to install & configure any desired Windows core system software packages which may be dependencies for certain Windows programs. You can either install it with `apt`, or manually using the steps below.
|
||||
|
||||
```
|
||||
# Backup old winetricks
|
||||
sudo mv /usr/local/bin/winetricks /usr/local/bin/winetricks-old
|
||||
|
||||
# Download
|
||||
cd ~/Downloads
|
||||
wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
|
||||
|
||||
# Install
|
||||
sudo chmod +x winetricks
|
||||
sudo mv winetricks /usr/local/bin/
|
||||
|
||||
# winetricks needs this installed
|
||||
sudo apt-get install cabextract -y
|
||||
sudo apt-get install cabextract -y # winetricks needs this installed
|
||||
sudo mv /usr/local/bin/winetricks /usr/local/bin/winetricks-old # Backup old winetricks
|
||||
cd ~/Downloads && wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks # Download
|
||||
sudo chmod +x winetricks && sudo mv winetricks /usr/local/bin/ # Install
|
||||
```
|
||||
|
||||
If you have a desktop menu itm for wintricks, you may need to edit it to add the nobanner env var. Do so by edition `/usr/share/applications/winetricks.desktop` with your favorite text editor (not that you'll need `sudo` to save the file) and change from `Exec=winetricks --gui` to `Exec=env BOX86_NOBANNER=1 winetricks --gui`
|
||||
Whenever we run winetricks, we must tell Box86 to supress its info banner, otherwise winetricks will crash. Box86's info banner can be suppressed using the `BOX86_NOBANNER=1` environment variable before invoking winetricks (example: `BOX86_NOBANNER=1 winetricks`).
|
||||
|
||||
If `apt` installed a desktop menu shortcut for winetricks (or if you make your own desktop shortcut for winetricks) then you may need to edit that shortcut to include Box86's BOX86_NOBANNER=1 env var. With your favorite text editor, edit `/usr/share/applications/winetricks.desktop` and change `Exec=winetricks --gui` to `Exec=env BOX86_NOBANNER=1 winetricks --gui`.
|
||||
|
||||
## Example commands
|
||||
Here is an example of how we should run a winetricks command with box86:
|
||||
@@ -126,13 +122,11 @@ For a list of all the different Windows packages & libraries that winetricks can
|
||||
## Other notes
|
||||
|
||||
### Wineprefixes (and Wine initialization)
|
||||
The first time Wine is run (`wine wineboot`), it will create a fresh wineprefix for you (by default, located in the hidden folder `~/.wine`). Think of a wineprefix as Wine's virtual 'harddrive' where it installs software and saves settings. Wineprefixes are portable and deletable.
|
||||
When you first run or boot Wine (`wine wineboot`), Wine will create a new user environment within which to install Windows software. This user environment is called a "wineprefix" (or "wine bottle") and is located (by default) in `~/.wine` (note that Linux folders with a `.` in front of them are "hidden" folders). Think of a wineprefix as Wine's virtual 'harddrive' where it installs software and saves settings. Wineprefixes are portable and deletable. For more Wine documentation, see [WineHQ](https://www.winehq.org/documentation).
|
||||
|
||||
If you at any point corrupt something inside your default wineprefix, you can start "fresh" by deleting your `~/.wine` directory (with the `rm -rf ~/.wine` command) and boot wine again to create a new default wineprefix.
|
||||
|
||||
### Transplanting wineprefixes (side-loading)
|
||||
When you first run or boot Wine (`wine wineboot`), Wine will create a new user environment within which to install Windows software. This user environment is called a "wineprefix" (or "wine bottle") and is located (by default) in `~/.wine` (note that Linux folders with a `.` in front of them are "hidden" folders). For more Wine documentation, see [WineHQ](https://www.winehq.org/documentation).
|
||||
|
||||
If software isn't installing in Wine with Box86, but is installing for you in Wine on a regular x86 Linux computer, you can copy a wineprefix from your x86 Linux computer to the device you're running Box86 on. This is most easily done by tarring the `~/.wine` folder on your x86 Linux computer (`tar -cvf winebottle.tar ~/.wine`), transferring the tar file to your device, then un-tarring the tar file (`tar -xf winebottle.tar`) on your device running Box86 & Wine. Tarring the wineprefix preserves any symlinks that are inside it.
|
||||
|
||||
### Swapping out different versions of Wine
|
||||
@@ -140,4 +134,4 @@ Some versions of Wine work better with certain software. It is best to install a
|
||||
|
||||
Your entire Wine installation can reside within a single folder on your Linux computer. TwisterOS assumes that your Wine installation is located inside the `~/wine/` directory. The actual directory where you put your `wine` folder doesn't matter as long as you have symlinks within the `/usr/local/bin/` directory which point to the `wine` folder so that Linux can find Wine when you type `wine` into the terminal).
|
||||
|
||||
You can change which version of Wine you are running simply by renaming your old `wine` and `.wine` folders to something else, then putting a new `wine` folder (containing your new version of Wine) in its place. Running `wine wineboot` again will make a fresh wineprefix with your new version of Wine. You can check which version of Wine you're running with the `wine --version` command.
|
||||
You can change which version of Wine you are running simply by renaming your old `wine` and `.wine` folders to something else, then putting a new `wine` folder (containing your new version of Wine) in its place. Running `wine wineboot` again will migrate a wineprefix from an older version of Wine to be usable by the newer version of Wine you just installed. You can check which version of Wine you're running with the `wine --version` command.
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-arm-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -9,8 +9,8 @@ url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${_pkgname%-arm-git}-git" "${_pkgname%-arm-git}")
|
||||
conflicts=("${pkgname%-git}" "${_pkgname%-arm-git}-git" "${_pkgname%-arm-git}")
|
||||
provides=("${pkgname%-git}" "${pkgname%-arm-git}-git" "${pkgname%-arm-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-arm-git}-git" "${pkgname%-arm-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-gameshell-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-odroid-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -9,8 +9,8 @@ url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${_pkgname%-odroid-git}-git" "${_pkgname%-odroid-git}")
|
||||
conflicts=("${pkgname%-git}" "${_pkgname%-odroid-git}-git" "${_pkgname%-odroid-git}")
|
||||
provides=("${pkgname%-git}" "${pkgname%-odroid-git}-git" "${pkgname%-odroid-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-odroid-git}-git" "${pkgname%-odroid-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-pandora-git
|
||||
_pkgname=box86-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -1,8 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-pyra-git
|
||||
_pkgname=box86-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -1,8 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rpi-git
|
||||
_pkgname=box86-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -10,8 +9,8 @@ url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%--rpi-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%--rpi-git}")
|
||||
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
|
||||
@@ -1,8 +1,7 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rk3399-git
|
||||
_pkgname=box86-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -34,6 +33,12 @@ build() {
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}/build"
|
||||
cd "$srcdir/${pkgname%-arm-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier <[email protected]>
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-x86-git
|
||||
_pkgname=box86-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgver=3494.bedacef
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('i386')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-x86-git}")
|
||||
conflicts=("${pkgname%-x86-git}")
|
||||
provides=("${pkgname%-git}" "${pkgname%-x86-git}-git" "${pkgname%-x86-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-x86-git}-git" "${pkgname%-x86-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
@@ -19,3 +19,6 @@ This might give you some advantages like those:
|
||||
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
|
||||
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
|
||||
- your `box86` installation is recognized as a package (where it wasn't when installing with `make install`).
|
||||
|
||||
|
||||
### Note: You can use [makedeb](https://github.com/makedeb/makedeb) (or) [pkgbuild2spec](https://github.com/prozum/pkgbuild2spec) to compile box86 to .deb or .rpm installer files.
|
||||
+286
-278
@@ -621,7 +621,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
skiprbr = False
|
||||
if idx % 2:
|
||||
if text == "c":
|
||||
if variables["cond"] != -1:
|
||||
if variables["cond"] >= 0:
|
||||
append("%s")
|
||||
printf_args = printf_args + ", cond"
|
||||
elif text == "Rd":
|
||||
@@ -1675,297 +1675,305 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
|
||||
# Now the files rebuilding part
|
||||
# File header and guard
|
||||
header = """/*****************************************************************
|
||||
* File automatically generated by rebuild_printer.py (v{version})
|
||||
*****************************************************************/
|
||||
"""
|
||||
files_header = {
|
||||
"arm_printer.c": """#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arm_printer.h"
|
||||
|
||||
// conditions
|
||||
#define cEQ (0b0000<<28)
|
||||
#define cNE (0b0001<<28)
|
||||
#define cCS (0b0010<<28)
|
||||
#define cCC (0b0011<<28)
|
||||
#define cMI (0b0100<<28)
|
||||
#define cPL (0b0101<<28)
|
||||
#define cVS (0b0110<<28)
|
||||
#define cVC (0b0111<<28)
|
||||
#define cHI (0b1000<<28)
|
||||
#define cLS (0b1001<<28)
|
||||
#define cGE (0b1010<<28)
|
||||
#define cLT (0b1011<<28)
|
||||
#define cGT (0b1100<<28)
|
||||
#define cLE (0b1101<<28)
|
||||
#define c__ (0b1110<<28) // means all
|
||||
|
||||
static const char* conds[16] = {
|
||||
"EQ", "NE", "CS", "CC",
|
||||
"MI", "PL", "VS", "VC",
|
||||
"HI", "LS", "GE", "LT",
|
||||
"GT", "LE", "", "##"
|
||||
};
|
||||
|
||||
static const char* regname[16] = {
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
"r5", "r6", "r7", "r8", "r9",
|
||||
"r10", "r11", "r12", "SP", "LR", "PC"
|
||||
};
|
||||
|
||||
// Single precision are V_:_
|
||||
// Double and quad precision are _:V_
|
||||
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
|
||||
static const char* vecname[96] = {
|
||||
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
|
||||
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
|
||||
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
|
||||
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
|
||||
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
|
||||
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
|
||||
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
|
||||
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
|
||||
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
|
||||
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
|
||||
};
|
||||
|
||||
static const char* dts[16] = {
|
||||
"S8", "S16", "S32", "S64",
|
||||
"U8", "U16", "U32", "U64",
|
||||
"I8", "I16", "I32", "I64",
|
||||
"F8", "F16", "F32", "F64"
|
||||
};
|
||||
|
||||
static const char* shift_type[4] = {
|
||||
"lsl ", "lsr ", "asr ", "ror "
|
||||
};
|
||||
|
||||
const char* print_shift(int shift, int comma) {
|
||||
static __thread char ret[20];
|
||||
ret[0] = '\\0';
|
||||
|
||||
int sh_op = (shift >> 1) & 3;
|
||||
if(shift & 1) {
|
||||
int rs = shift >> 4;
|
||||
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
|
||||
} else {
|
||||
uint8_t amount = shift >> 3;
|
||||
if (!amount) {
|
||||
switch (sh_op) {
|
||||
case 0b00:
|
||||
break;
|
||||
case 0b01:
|
||||
case 0b10:
|
||||
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
|
||||
break;
|
||||
case 0b11:
|
||||
sprintf(ret, "%srrx", (comma ? ", " : ""));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
|
||||
|
||||
const char* print_register_list(int list, int size) {
|
||||
int last = -2;
|
||||
int cnt = 0;
|
||||
static __thread char ret[68];
|
||||
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (list & (1 << i)) {
|
||||
if (last >= 0) {
|
||||
++cnt;
|
||||
"arm_printer.c": """
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arm_printer.h"
|
||||
|
||||
// conditions
|
||||
#define cEQ (0b0000<<28)
|
||||
#define cNE (0b0001<<28)
|
||||
#define cCS (0b0010<<28)
|
||||
#define cCC (0b0011<<28)
|
||||
#define cMI (0b0100<<28)
|
||||
#define cPL (0b0101<<28)
|
||||
#define cVS (0b0110<<28)
|
||||
#define cVC (0b0111<<28)
|
||||
#define cHI (0b1000<<28)
|
||||
#define cLS (0b1001<<28)
|
||||
#define cGE (0b1010<<28)
|
||||
#define cLT (0b1011<<28)
|
||||
#define cGT (0b1100<<28)
|
||||
#define cLE (0b1101<<28)
|
||||
#define c__ (0b1110<<28) // means all
|
||||
|
||||
static const char* conds[16] = {
|
||||
"EQ", "NE", "CS", "CC",
|
||||
"MI", "PL", "VS", "VC",
|
||||
"HI", "LS", "GE", "LT",
|
||||
"GT", "LE", "", "##"
|
||||
};
|
||||
|
||||
static const char* regname[16] = {
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
"r5", "r6", "r7", "r8", "r9",
|
||||
"r10", "r11", "r12", "SP", "LR", "PC"
|
||||
};
|
||||
|
||||
// Single precision are V_:_
|
||||
// Double and quad precision are _:V_
|
||||
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
|
||||
static const char* vecname[96] = {
|
||||
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
|
||||
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
|
||||
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
|
||||
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
|
||||
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
|
||||
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
|
||||
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
|
||||
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
|
||||
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
|
||||
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
|
||||
};
|
||||
|
||||
static const char* dts[16] = {
|
||||
"S8", "S16", "S32", "S64",
|
||||
"U8", "U16", "U32", "U64",
|
||||
"I8", "I16", "I32", "I64",
|
||||
"F8", "F16", "F32", "F64"
|
||||
};
|
||||
|
||||
static const char* shift_type[4] = {
|
||||
"lsl ", "lsr ", "asr ", "ror "
|
||||
};
|
||||
|
||||
const char* print_shift(int shift, int comma) {
|
||||
static __thread char ret[20];
|
||||
ret[0] = '\\0';
|
||||
|
||||
int sh_op = (shift >> 1) & 3;
|
||||
if(shift & 1) {
|
||||
int rs = shift >> 4;
|
||||
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
|
||||
} else {
|
||||
if (last == -1)
|
||||
strcat(ret, ", ");
|
||||
strcat(ret, regname[i]);
|
||||
last = i;
|
||||
uint8_t amount = shift >> 3;
|
||||
if (!amount) {
|
||||
switch (sh_op) {
|
||||
case 0b00:
|
||||
break;
|
||||
case 0b01:
|
||||
case 0b10:
|
||||
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
|
||||
break;
|
||||
case 0b11:
|
||||
sprintf(ret, "%srrx", (comma ? ", " : ""));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
|
||||
|
||||
const char* print_register_list(int list, int size) {
|
||||
int last = -2;
|
||||
int cnt = 0;
|
||||
static __thread char ret[68];
|
||||
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (list & (1 << i)) {
|
||||
if (last >= 0) {
|
||||
++cnt;
|
||||
} else {
|
||||
if (last == -1)
|
||||
strcat(ret, ", ");
|
||||
strcat(ret, regname[i]);
|
||||
last = i;
|
||||
}
|
||||
} else {
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[i - 1]);
|
||||
}
|
||||
if (last != -2) last = -1;
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[i - 1]);
|
||||
strcat(ret, regname[size - 1]);
|
||||
}
|
||||
if (last != -2) last = -1;
|
||||
cnt = 0;
|
||||
strcat(ret, "}");
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[size - 1]);
|
||||
}
|
||||
strcat(ret, "}");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
|
||||
static __thread char ret[68];
|
||||
|
||||
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
|
||||
if (start + (double_prec + 1) * size > 32) {
|
||||
return "!!!";
|
||||
}
|
||||
if (size == 0) {
|
||||
return "!!!";
|
||||
}
|
||||
if (double_prec && (size % 2 == 1)) {
|
||||
strcpy(ret, "!! {");
|
||||
} else {
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
}
|
||||
|
||||
char regChr;
|
||||
if (double_prec) {
|
||||
regChr = 'D';
|
||||
size /= 2;
|
||||
} else {
|
||||
regChr = 'S';
|
||||
start = (start >> 4) + ((start & 0xF) << 1);
|
||||
}
|
||||
|
||||
char tmp[6];
|
||||
for (int cur = start; cur < start + size - 1; ++cur) {
|
||||
sprintf(tmp, "%c%d, ", regChr, cur);
|
||||
strcat(ret, tmp);
|
||||
}
|
||||
sprintf(tmp, "%c%d}", regChr, start + size - 1);
|
||||
strcat(ret, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
|
||||
|
||||
const char* print_modified_imm_NEON(int op_cmode, int imm) {
|
||||
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
|
||||
|
||||
strcpy(&ret[4], "UNPREDICTABLE");
|
||||
|
||||
switch (op_cmode) {
|
||||
case 0b00000: // VMOV.I32
|
||||
case 0b00001: // VORR.I32
|
||||
case 0b10000: // VMVN.I32
|
||||
case 0b10001: // VBIC.I32
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b00010: // VMOV.I32
|
||||
case 0b00011: // VORR.I32
|
||||
case 0b10010: // VMVN.I32
|
||||
case 0b10011: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
|
||||
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
|
||||
static __thread char ret[68];
|
||||
|
||||
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
|
||||
if (start + (double_prec + 1) * size > 32) {
|
||||
return "!!!";
|
||||
}
|
||||
if (size == 0) {
|
||||
return "!!!";
|
||||
}
|
||||
if (double_prec && (size % 2 == 1)) {
|
||||
strcpy(ret, "!! {");
|
||||
} else {
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
}
|
||||
|
||||
char regChr;
|
||||
if (double_prec) {
|
||||
regChr = 'D';
|
||||
size /= 2;
|
||||
} else {
|
||||
regChr = 'S';
|
||||
start = (start >> 4) + ((start & 0xF) << 1);
|
||||
}
|
||||
|
||||
char tmp[6];
|
||||
for (int cur = start; cur < start + size - 1; ++cur) {
|
||||
sprintf(tmp, "%c%d, ", regChr, cur);
|
||||
strcat(ret, tmp);
|
||||
}
|
||||
sprintf(tmp, "%c%d}", regChr, start + size - 1);
|
||||
strcat(ret, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case 0b00100: // VMOV.I32
|
||||
case 0b00101: // VORR.I32
|
||||
case 0b10100: // VMVN.I32
|
||||
case 0b10101: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X0000", imm);
|
||||
|
||||
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
|
||||
|
||||
const char* print_modified_imm_NEON(int op_cmode, int imm) {
|
||||
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
|
||||
|
||||
strcpy(&ret[4], "UNPREDICTABLE");
|
||||
|
||||
switch (op_cmode) {
|
||||
case 0b00000: // VMOV.I32
|
||||
case 0b00001: // VORR.I32
|
||||
case 0b10000: // VMVN.I32
|
||||
case 0b10001: // VBIC.I32
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b00010: // VMOV.I32
|
||||
case 0b00011: // VORR.I32
|
||||
case 0b10010: // VMVN.I32
|
||||
case 0b10011: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
break;
|
||||
case 0b00100: // VMOV.I32
|
||||
case 0b00101: // VORR.I32
|
||||
case 0b10100: // VMVN.I32
|
||||
case 0b10101: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X0000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b00110: // VMOV.I32
|
||||
case 0b00111: // VORR.I32
|
||||
case 0b10110: // VMVN.I32
|
||||
case 0b10111: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X000000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01000: // VMOV.I16
|
||||
case 0b01001: // VORR.I16
|
||||
case 0b11000: // VMVN.I16
|
||||
case 0b11001: // VBIC.I16
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01010: // VMOV.I16
|
||||
case 0b01011: // VORR.I16
|
||||
case 0b11010: // VMVN.I16
|
||||
case 0b11011: // VBIC.I16
|
||||
if (imm) {
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01100: // VMOV.I32
|
||||
case 0b11100: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01101: // VMOV.I32
|
||||
case 0b11101: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFFFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01110: // VMOV.I8
|
||||
strcpy(ret, "I8");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01111: // VMOV.F32
|
||||
strcpy(ret, "F32");
|
||||
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
|
||||
break;
|
||||
case 0b11110: // VMOV.I64
|
||||
{
|
||||
strcpy(ret, "I64");
|
||||
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
|
||||
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
|
||||
}
|
||||
break;
|
||||
case 0b11111: // V???.-
|
||||
default:
|
||||
strcpy(ret, "-");
|
||||
strcpy(&ret[4], "UNDEFINED");
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case 0b00110: // VMOV.I32
|
||||
case 0b00111: // VORR.I32
|
||||
case 0b10110: // VMVN.I32
|
||||
case 0b10111: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X000000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01000: // VMOV.I16
|
||||
case 0b01001: // VORR.I16
|
||||
case 0b11000: // VMVN.I16
|
||||
case 0b11001: // VBIC.I16
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01010: // VMOV.I16
|
||||
case 0b01011: // VORR.I16
|
||||
case 0b11010: // VMVN.I16
|
||||
case 0b11011: // VBIC.I16
|
||||
if (imm) {
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01100: // VMOV.I32
|
||||
case 0b11100: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01101: // VMOV.I32
|
||||
case 0b11101: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFFFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01110: // VMOV.I8
|
||||
strcpy(ret, "I8");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01111: // VMOV.F32
|
||||
strcpy(ret, "F32");
|
||||
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
|
||||
break;
|
||||
case 0b11110: // VMOV.I64
|
||||
|
||||
const char* arm_print(uint32_t opcode) {
|
||||
static __thread char ret[100];
|
||||
memset(ret, 0, sizeof(ret));
|
||||
|
||||
"""
|
||||
}
|
||||
files_guard = {
|
||||
"arm_printer.c": """
|
||||
{
|
||||
strcpy(ret, "I64");
|
||||
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
|
||||
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
|
||||
strcpy(ret, "???");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case 0b11111: // V???.-
|
||||
default:
|
||||
strcpy(ret, "-");
|
||||
strcpy(&ret[4], "UNDEFINED");
|
||||
break;
|
||||
"""
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* arm_print(uint32_t opcode) {
|
||||
static __thread char ret[100];
|
||||
memset(ret, 0, sizeof(ret));
|
||||
|
||||
"""
|
||||
}
|
||||
files_guard = {"arm_printer.c": """{
|
||||
strcpy(ret, "???");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
"""}
|
||||
banner = "/*******************************************************" + ('*'*len(ver)) + "***\n" \
|
||||
" * File automatically generated by rebuild_printer.py (v" + ver + ") *\n" \
|
||||
" *******************************************************" + ('*'*len(ver)) + "***/\n"
|
||||
trim = lambda string: '\n'.join(line[2:] for line in string.splitlines())[1:]
|
||||
# Yes, the for loops are inverted. This is because both dicts should have the same keys.
|
||||
for fhdr in files_guard:
|
||||
files_header[fhdr] = banner + trim(files_header[fhdr])
|
||||
for fhdr in files_header:
|
||||
files_guard[fhdr] = trim(files_guard[fhdr])
|
||||
|
||||
for f in files_header:
|
||||
with open(os.path.join(root, "src", "dynarec", f), 'w') as file:
|
||||
file.write(header.format(version = ver))
|
||||
file.write(files_header[f])
|
||||
file.write(output)
|
||||
file.write(files_guard[f])
|
||||
@@ -1980,6 +1988,6 @@ if __name__ == '__main__':
|
||||
for i, v in enumerate(sys.argv):
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
if main(sys.argv[1], "1.1.0.04") != 0:
|
||||
if main(sys.argv[1], "1.2.0.05") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
+1270
-611
File diff suppressed because it is too large.
Load diff
+26
-17
@@ -21,6 +21,7 @@
|
||||
#include "signals.h"
|
||||
#include <sys/mman.h>
|
||||
#include "custommem.h"
|
||||
#include "dictionnary.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynarec/arm_lock_helper.h"
|
||||
@@ -36,6 +37,7 @@ void initAllHelpers(box86context_t* context)
|
||||
return;
|
||||
my_context = context;
|
||||
init_pthread_helper();
|
||||
init_bridge_helper();
|
||||
init_signal_helper(context);
|
||||
inited = 1;
|
||||
}
|
||||
@@ -48,7 +50,7 @@ void finiAllHelpers(box86context_t* context)
|
||||
return;
|
||||
fini_pthread_helper(context);
|
||||
fini_signal_helper();
|
||||
cleanAlternate();
|
||||
fini_bridge_helper();
|
||||
fini_custommem_helper(context);
|
||||
finied = 1;
|
||||
}
|
||||
@@ -96,6 +98,7 @@ int unlockMutex()
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
|
||||
return ret;
|
||||
@@ -103,7 +106,6 @@ int unlockMutex()
|
||||
|
||||
void relockMutex(int locks)
|
||||
{
|
||||
relockCustommemMutex(locks);
|
||||
#define GO(A, B) \
|
||||
if(locks&(1<<B)) \
|
||||
pthread_mutex_lock(&A); \
|
||||
@@ -118,7 +120,9 @@ void relockMutex(int locks)
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
relockCustommemMutex(locks);
|
||||
}
|
||||
|
||||
static void init_mutexes(box86context_t* context)
|
||||
@@ -129,13 +133,14 @@ static void init_mutexes(box86context_t* context)
|
||||
pthread_mutex_init(&context->mutex_once, &attr);
|
||||
pthread_mutex_init(&context->mutex_once2, &attr);
|
||||
pthread_mutex_init(&context->mutex_trace, &attr);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#else
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_dyndump, &attr);
|
||||
#else
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
@@ -169,9 +174,11 @@ box86context_t *NewBox86Context(int argc)
|
||||
|
||||
context->maplib = NewLibrarian(context, 1);
|
||||
context->local_maplib = NewLibrarian(context, 1);
|
||||
context->versym = NewDictionnary();
|
||||
context->system = NewBridge();
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, vFv, x86Syscall, 0);
|
||||
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
|
||||
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
|
||||
#ifdef BUILD_LIB
|
||||
context->box86lib = RTLD_DEFAULT; // not ideal
|
||||
#else
|
||||
@@ -217,6 +224,7 @@ void FreeBox86Context(box86context_t** context)
|
||||
FreeLibrarian(&ctx->local_maplib, NULL);
|
||||
if(ctx->maplib)
|
||||
FreeLibrarian(&ctx->maplib, NULL);
|
||||
FreeDictionnary(&ctx->versym);
|
||||
|
||||
for(int i=0; i<ctx->elfsize; ++i) {
|
||||
FreeElfHeader(&ctx->elfs[i]);
|
||||
@@ -292,17 +300,6 @@ void FreeBox86Context(box86context_t** context)
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
|
||||
if(ctx->emu_sig)
|
||||
@@ -310,6 +307,18 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 2
|
||||
#define BOX86_REVISION 2
|
||||
#define BOX86_REVISION 4
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+195
-145
@@ -32,9 +32,9 @@
|
||||
// init inside dynablocks.c
|
||||
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
|
||||
static dynablocklist_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block
|
||||
static pthread_mutex_t mutex_mmap;
|
||||
static mmaplist_t *mmaplist;
|
||||
static int mmapsize;
|
||||
static mmaplist_t *mmaplist = NULL;
|
||||
static int mmapsize = 0;
|
||||
static int mmapcap = 0;
|
||||
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
|
||||
static uintptr_t *box86_jumptable[JMPTABL_SIZE];
|
||||
static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
|
||||
@@ -58,8 +58,8 @@ static blocklist_t* p_blocks = NULL; // actual blocks for custom mallo
|
||||
|
||||
typedef union mark_s {
|
||||
struct {
|
||||
unsigned int fill:1;
|
||||
unsigned int size:31;
|
||||
unsigned int fill:1;
|
||||
};
|
||||
uint32_t x32;
|
||||
} mark_t;
|
||||
@@ -68,98 +68,146 @@ typedef struct blockmark_s {
|
||||
mark_t next;
|
||||
} blockmark_t;
|
||||
|
||||
#define NEXT_BLOCK(b) (blockmark_t*)((uintptr_t)(b) + (b)->next.size + sizeof(blockmark_t))
|
||||
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
|
||||
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
|
||||
|
||||
static void printBlock(blockmark_t* b, void* start)
|
||||
{
|
||||
printf_log(LOG_INFO, "========== Block is:\n");
|
||||
do {
|
||||
printf_log(LOG_INFO, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size);
|
||||
b = NEXT_BLOCK(b);
|
||||
} while(b->next.x32);
|
||||
printf_log(LOG_INFO, "===================\n");
|
||||
}
|
||||
|
||||
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, int maxsize, int* size)
|
||||
static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* start)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)block;
|
||||
blockmark_t *m = (blockmark_t*)((start)?start:block);
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
|
||||
*size = m->next.size-sizeof(blockmark_t);
|
||||
if(!m->next.fill && m->next.size>=maxsize) {
|
||||
*size = m->next.size;
|
||||
return m;
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m + m->next.size);
|
||||
m = NEXT_BLOCK(m);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int getMaxFreeBlock(void* block, size_t block_size)
|
||||
static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
|
||||
int maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
if((uintptr_t)block+maxsize>(uintptr_t)m)
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
|
||||
if(start) {
|
||||
blockmark_t *m = (blockmark_t*)start;
|
||||
int maxsize = 0;
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>maxsize) {
|
||||
maxsize = m->next.size;
|
||||
}
|
||||
m = NEXT_BLOCK(m);
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
|
||||
} else {
|
||||
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
|
||||
int maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
if((uintptr_t)block+maxsize>(uintptr_t)m)
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0; // no block large enough left...
|
||||
}
|
||||
m = PREV_BLOCK(m);
|
||||
}
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
|
||||
}
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
|
||||
}
|
||||
|
||||
static void* allocBlock(void* block, void *sub, int size)
|
||||
static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
blockmark_t *n = NEXT_BLOCK(s);
|
||||
|
||||
s->next.fill = 1;
|
||||
s->next.size = size+sizeof(blockmark_t);
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
|
||||
// check if a new mark is worth it
|
||||
if(s->next.size>size+2*sizeof(blockmark_t))
|
||||
s->next.size = size;
|
||||
blockmark_t *m = NEXT_BLOCK(s); // this is new n
|
||||
m->prev.fill = 1;
|
||||
m->prev.size = s->next.size;
|
||||
if(n!=m) {
|
||||
// new mark
|
||||
m->prev.fill = 1;
|
||||
m->prev.size = s->next.size;
|
||||
m->next.fill = 0;
|
||||
m->next.size = (uintptr_t)n - (uintptr_t)m;
|
||||
m->next.size = ((uintptr_t)n - (uintptr_t)m) - sizeof(blockmark_t);
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
}
|
||||
|
||||
if(pstart && sub==*pstart) {
|
||||
// get the next free block
|
||||
m = (blockmark_t*)*pstart;
|
||||
while(m->next.fill)
|
||||
m = NEXT_BLOCK(m);
|
||||
*pstart = (void*)m;
|
||||
}
|
||||
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
|
||||
}
|
||||
static void freeBlock(void *block, void* sub)
|
||||
static size_t freeBlock(void *block, void* sub, void** pstart)
|
||||
{
|
||||
blockmark_t *m = (blockmark_t*)block;
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
blockmark_t *n = NEXT_BLOCK(s);
|
||||
if(block!=sub)
|
||||
m = (blockmark_t*)((uintptr_t)s - s->prev.size);
|
||||
m = PREV_BLOCK(s);
|
||||
s->next.fill = 0;
|
||||
n->prev.fill = 0;
|
||||
// check if merge with previous
|
||||
if (s->prev.x32 && !s->prev.fill) {
|
||||
// remove s...
|
||||
m->next.size += s->next.size;
|
||||
m->next.size += s->next.size + sizeof(blockmark_t);
|
||||
n->prev.size = m->next.size;
|
||||
s = m;
|
||||
}
|
||||
// check if merge with next
|
||||
if(n->next.x32 && !n->next.fill) {
|
||||
blockmark_t *n2 = (blockmark_t*)((uintptr_t)n + n->next.size);
|
||||
blockmark_t *n2 = NEXT_BLOCK(n);
|
||||
//remove n
|
||||
s->next.size += n->next.size;
|
||||
s->next.size += n->next.size + sizeof(blockmark_t);
|
||||
n2->prev.size = s->next.size;
|
||||
}
|
||||
if(pstart && (uintptr_t)*pstart>(uintptr_t)sub) {
|
||||
*pstart = (void*)s;
|
||||
}
|
||||
// return free size at current block (might be bigger)
|
||||
return s->next.size;
|
||||
}
|
||||
// return 1 if block has been expanded to new size, 0 if not
|
||||
static int expandBlock(void* block, void* sub, int newsize)
|
||||
static int expandBlock(void* block, void* sub, size_t newsize)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
newsize = (newsize+3)&~3;
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
blockmark_t *n = NEXT_BLOCK(s);
|
||||
if(s->next.size>=newsize)
|
||||
// big enough, no shrinking...
|
||||
return 1;
|
||||
if(s->next.fill)
|
||||
return 0; // next block is filled
|
||||
if(s->next.size + n->next.size < newsize)
|
||||
// unsigned bitfield of this length gets "promoted" to *signed* int...
|
||||
if((size_t)(s->next.size + n->next.size + sizeof(blockmark_t)) < newsize)
|
||||
return 0; // free space too short
|
||||
// ok, doing the alloc!
|
||||
s->next.size = newsize+sizeof(blockmark_t);
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
|
||||
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<2*sizeof(blockmark_t))
|
||||
s->next.size += n->next.size+sizeof(blockmark_t);
|
||||
else
|
||||
s->next.size = newsize+sizeof(blockmark_t);
|
||||
blockmark_t *m = NEXT_BLOCK(s); // this is new n
|
||||
m->prev.fill = 1;
|
||||
m->prev.size = s->next.size;
|
||||
if(n!=m) {
|
||||
@@ -174,7 +222,7 @@ static int expandBlock(void* block, void* sub, int newsize)
|
||||
return 1;
|
||||
}
|
||||
// return size of block
|
||||
static int sizeBlock(void* sub)
|
||||
static size_t sizeBlock(void* sub)
|
||||
{
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
return s->next.size;
|
||||
@@ -187,12 +235,12 @@ void* customMalloc(size_t size)
|
||||
pthread_mutex_lock(&mutex_blocks);
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if(p_blocks[i].maxfree>=size) {
|
||||
int rsize = 0;
|
||||
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(p_blocks[i].block, size, &rsize, NULL);
|
||||
if(sub) {
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size);
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
|
||||
if(rsize==p_blocks[i].maxfree)
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return ret;
|
||||
}
|
||||
@@ -216,14 +264,14 @@ void* customMalloc(size_t size)
|
||||
blockmark_t* m = (blockmark_t*)p;
|
||||
m->prev.x32 = 0;
|
||||
m->next.fill = 0;
|
||||
m->next.size = allocsize-sizeof(blockmark_t);
|
||||
m = (blockmark_t*)(p+allocsize-sizeof(blockmark_t));
|
||||
m->next.x32 = 0;
|
||||
m->prev.fill = 0;
|
||||
m->prev.size = allocsize-sizeof(blockmark_t);
|
||||
m->next.size = allocsize-2*sizeof(blockmark_t);
|
||||
blockmark_t* n = NEXT_BLOCK(m);
|
||||
n->next.x32 = 0;
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
// alloc 1st block
|
||||
void* ret = allocBlock(p_blocks[i].block, p, size);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return ret;
|
||||
}
|
||||
@@ -245,21 +293,20 @@ void* customRealloc(void* p, size_t size)
|
||||
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
if(expandBlock(p_blocks[i].block, sub, size)) {
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return p;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
if(n_blocks)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Realloc, Malloc'ng again without free\n", (void*)addr);
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
|
||||
return customMalloc(size);
|
||||
}
|
||||
void customFree(void* p)
|
||||
@@ -272,8 +319,8 @@ void customFree(void* p)
|
||||
if ((addr>(uintptr_t)p_blocks[i].block)
|
||||
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
freeBlock(p_blocks[i].block, sub);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
|
||||
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return;
|
||||
}
|
||||
@@ -290,6 +337,8 @@ typedef struct mmaplist_s {
|
||||
size_t size;
|
||||
kh_dynablocks_t* dblist;
|
||||
uint8_t* helper;
|
||||
void* first; // first free block, to speed up things
|
||||
int locked; // don't try to add stuff on locked block
|
||||
} mmaplist_t;
|
||||
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
@@ -297,13 +346,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
// look for free space
|
||||
void* sub = NULL;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].maxfree>=size) {
|
||||
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
|
||||
mmaplist[i].locked = 1;
|
||||
int rsize = 0;
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
|
||||
if(sub) {
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
|
||||
if(rsize==mmaplist[i].maxfree)
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
|
||||
if(rsize==mmaplist[i].maxfree) {
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
|
||||
}
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist;
|
||||
if(!blocks) {
|
||||
blocks = mmaplist[i].dblist = kh_init(dynablocks);
|
||||
@@ -313,9 +364,17 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
int r;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
|
||||
int size255=(size<256)?size:255;
|
||||
for(size_t j=0; j<size255; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
|
||||
if(size!=size255)
|
||||
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
|
||||
mmaplist[i].locked = 0;
|
||||
return ret;
|
||||
} else {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted mmaplist[%d] info?\n", i);
|
||||
if(box86_log >= LOG_DEBUG)
|
||||
printBlock(mmaplist[i].block, mmaplist[i].first);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,8 +384,11 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
{
|
||||
int i = mmapsize++; // yeah, useful post incrementation
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", mmapsize);
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
|
||||
if(mmapsize>mmapcap) {
|
||||
mmapcap += 32;
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
|
||||
}
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box86_pagesize, MMAPSIZE)) {
|
||||
@@ -345,21 +407,23 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
#endif
|
||||
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
mmaplist[i].locked = 1;
|
||||
mmaplist[i].block = p;
|
||||
mmaplist[i].size = MMAPSIZE;
|
||||
mmaplist[i].helper = (uint8_t*)calloc(1, MMAPSIZE);
|
||||
mmaplist[i].first = p;
|
||||
// setup marks
|
||||
blockmark_t* m = (blockmark_t*)p;
|
||||
m->prev.x32 = 0;
|
||||
m->next.fill = 0;
|
||||
m->next.size = MMAPSIZE-sizeof(blockmark_t);
|
||||
m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t));
|
||||
m->next.x32 = 0;
|
||||
m->prev.fill = 0;
|
||||
m->prev.size = MMAPSIZE-sizeof(blockmark_t);
|
||||
m->next.size = MMAPSIZE-2*sizeof(blockmark_t);
|
||||
blockmark_t* n = NEXT_BLOCK(m);
|
||||
n->next.x32 = 0;
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
// alloc 1st block
|
||||
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
|
||||
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size, &mmaplist[i].first);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
|
||||
kh_resize(dynablocks, blocks, 64);
|
||||
khint_t k;
|
||||
@@ -368,6 +432,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
|
||||
mmaplist[i].locked = 0;
|
||||
return sub;
|
||||
}
|
||||
|
||||
@@ -379,15 +444,18 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
if ((addr>(uintptr_t)mmaplist[i].block)
|
||||
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
freeBlock(mmaplist[i].block, sub);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
|
||||
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
|
||||
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist;
|
||||
if(blocks) {
|
||||
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
for(int j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
|
||||
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
|
||||
}
|
||||
if(mmaplist[i].locked) {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
|
||||
++mmaplist[i].locked;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -424,7 +492,6 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
return 0;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
#ifndef USE_MMAP
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box86_pagesize, size)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
@@ -448,18 +515,13 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
return (uintptr_t)p;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
|
||||
uintptr_t ret = FindFreeDynarecMap(db, size);
|
||||
if(!ret)
|
||||
ret = AddNewDynarecMap(db, size);
|
||||
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -468,7 +530,6 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
if(!addr || !size)
|
||||
return;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
free((void*)addr);
|
||||
#else
|
||||
@@ -480,12 +541,9 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
ActuallyFreeDynarecMap(db, addr, size);
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
}
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx)
|
||||
@@ -588,11 +646,12 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
memprot[i] = prot|PROT_DYNAREC;
|
||||
if(!(prot&PROT_DYNAREC))
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
memprot[i] = prot|PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,8 +664,8 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
memprot[i] = prot&~PROT_DYNAREC;
|
||||
if(prot&PROT_DYNAREC) {
|
||||
memprot[i] = prot&~PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
}
|
||||
@@ -627,6 +686,16 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
}
|
||||
}
|
||||
|
||||
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
|
||||
memprot[i] = prot;
|
||||
}
|
||||
}
|
||||
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
@@ -653,9 +722,6 @@ int unlockCustommemMutex()
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 1)
|
||||
#endif
|
||||
#undef GO
|
||||
return ret;
|
||||
}
|
||||
@@ -667,9 +733,6 @@ void relockCustommemMutex(int locks)
|
||||
pthread_mutex_lock(&A); \
|
||||
|
||||
GO(mutex_blocks, 0)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 1)
|
||||
#endif
|
||||
#undef GO
|
||||
}
|
||||
|
||||
@@ -679,9 +742,6 @@ static void init_mutexes(void)
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_blocks, &attr);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&mutex_mmap, &attr);
|
||||
#endif
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
@@ -717,51 +777,41 @@ void fini_custommem_helper(box86context_t *ctx)
|
||||
return;
|
||||
inited = 0;
|
||||
#ifdef DYNAREC
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
for (int i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(mmaplist[i].block, mmaplist[i].size);
|
||||
#else
|
||||
free(mmaplist[i].block);
|
||||
#endif
|
||||
if(mmaplist[i].dblist) {
|
||||
kh_destroy(dynablocks, mmaplist[i].dblist);
|
||||
mmaplist[i].dblist = NULL;
|
||||
if(box86_dynarec) {
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
for (int i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(mmaplist[i].block, mmaplist[i].size);
|
||||
#else
|
||||
free(mmaplist[i].block);
|
||||
#endif
|
||||
if(mmaplist[i].dblist) {
|
||||
kh_destroy(dynablocks, mmaplist[i].dblist);
|
||||
mmaplist[i].dblist = NULL;
|
||||
}
|
||||
if(mmaplist[i].helper) {
|
||||
free(mmaplist[i].helper);
|
||||
mmaplist[i].helper = NULL;
|
||||
}
|
||||
}
|
||||
if(mmaplist[i].helper) {
|
||||
free(mmaplist[i].helper);
|
||||
mmaplist[i].helper = NULL;
|
||||
if(dblist_oversized) {
|
||||
kh_destroy(dynablocks, dblist_oversized);
|
||||
dblist_oversized = NULL;
|
||||
}
|
||||
mmapsize = 0;
|
||||
mmapcap = 0;
|
||||
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
|
||||
uintptr_t idx = 0;
|
||||
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i)
|
||||
if(dynmap[i])
|
||||
FreeDynablockList(&dynmap[i]);
|
||||
free(mmaplist);
|
||||
for (int i=0; i<DYNAMAP_SIZE; ++i)
|
||||
if(box86_jumptable[i]!=box86_jmptbl_default)
|
||||
free(box86_jumptable[i]);
|
||||
}
|
||||
if(dblist_oversized) {
|
||||
kh_destroy(dynablocks, dblist_oversized);
|
||||
dblist_oversized = NULL;
|
||||
}
|
||||
mmapsize = 0;
|
||||
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
|
||||
uintptr_t idx = 0;
|
||||
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
dynablocklist_t* dblist = dynmap[i];
|
||||
if(dblist) {
|
||||
uintptr_t startdb = StartDynablockList(dblist);
|
||||
uintptr_t enddb = EndDynablockList(dblist);
|
||||
uintptr_t startaddr = 0;
|
||||
if(startaddr<startdb) startaddr = startdb;
|
||||
uintptr_t endaddr = 0xFFFFFFFF;
|
||||
if(endaddr>enddb) endaddr = enddb;
|
||||
FreeRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
|
||||
}
|
||||
}
|
||||
for (uintptr_t i=idx; i<=end; ++i)
|
||||
if(dynmap[i])
|
||||
FreeDynablockList(&dynmap[i]);
|
||||
pthread_mutex_destroy(&mutex_mmap);
|
||||
free(mmaplist);
|
||||
for (int i=0; i<DYNAMAP_SIZE; ++i)
|
||||
if(box86_jumptable[i]!=box86_jmptbl_default)
|
||||
free(box86_jumptable[i]);
|
||||
#endif
|
||||
for(int i=0; i<n_blocks; ++i)
|
||||
#ifdef USE_MMAP
|
||||
|
||||
@@ -107,6 +107,8 @@ Op is 20-27
|
||||
#define MOV_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | ((imm5)<<7))
|
||||
// mov dst, src ror imm5
|
||||
#define MOV_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((imm5)<<7))
|
||||
// mov dst, src rrx (1)
|
||||
#define MOV_REG_RRX(dst, src) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((0)<<7))
|
||||
// mov.s dst, src lsl imm5
|
||||
#define MOVS_REG_LSL_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (0<<5) | ((imm5)<<7))
|
||||
// mov.s dst, src lsr imm5
|
||||
@@ -115,6 +117,8 @@ Op is 20-27
|
||||
#define MOVS_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | ((imm5)<<7))
|
||||
// mov.s dst, src ror imm5
|
||||
#define MOVS_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((imm5)<<7))
|
||||
// mov.s dst, src rrx (1)
|
||||
#define MOVS_REG_RRX(dst, src) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((0)<<7))
|
||||
|
||||
// mov.s dst, src lsl rs
|
||||
#define MOVS_REG_LSL_REG(dst, src, rs) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (1<<4) | (0<<5) | ((rs)<<8))
|
||||
@@ -169,6 +173,9 @@ Op is 20-27
|
||||
// rsb cond dst, src, #(imm8)
|
||||
#define RSB_COND_IMM8(cond, dst, src, imm8) \
|
||||
EMIT((cond) | 0x02600000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// rsc dst, src, #(imm8)
|
||||
#define RSC_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2E00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
|
||||
// and dst, src1, src2, lsl #imm
|
||||
#define AND_REG_LSL_IMM5(dst, src1, src2, imm5) \
|
||||
@@ -182,11 +189,14 @@ Op is 20-27
|
||||
// and dst, src, #(imm8)
|
||||
#define AND_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// and dst, src1, #imm ror rot*2
|
||||
#define AND_IMM8_ROR(dst, src, imm8, rot) \
|
||||
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
// and.s dst, src, #(imm8)
|
||||
#define ANDS_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// and.s dst, src1, #imm ror rot*2
|
||||
#define ANDS_IMM8_ROR(src, imm8, rot) \
|
||||
#define ANDS_IMM8_ROR(dst, src, imm8, rot) \
|
||||
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
// add dst, src, #(imm8)
|
||||
#define ADD_IMM8(dst, src, imm8) \
|
||||
@@ -232,6 +242,9 @@ Op is 20-27
|
||||
// cmp.s dst, src, #imm
|
||||
#define CMPS_IMM8(src, imm8) \
|
||||
EMIT(0xe3500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// cmn.s dst, src, #imm
|
||||
#define CMNS_IMM8_COND(cond, src, imm8) \
|
||||
EMIT((cond) | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// tst.s dst, src1, src2, lsl #imm
|
||||
#define TSTS_REG_LSL_IMM5(src1, src2, imm5) \
|
||||
EMIT(0xe1100000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
|
||||
@@ -253,6 +266,9 @@ Op is 20-27
|
||||
// orr.s dst, src1, src2, lsr #imm
|
||||
#define ORRS_REG_LSR_IMM5(dst, src1, src2, imm5) \
|
||||
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
|
||||
// orr.s dst, src1, src2, lsl rs
|
||||
#define ORRS_REG_LSL_REG(dst, src1, src2, rs) \
|
||||
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
|
||||
// orr dst, src1, #imm8
|
||||
#define ORR_IMM8(dst, src, imm8, rot) \
|
||||
EMIT(0xe3800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
|
||||
@@ -302,6 +318,9 @@ Op is 20-27
|
||||
// bic.cond dst, src, IMM8
|
||||
#define BIC_IMM8_COND(cond, dst, src, imm8, rot) \
|
||||
EMIT((cond) | 0x03c00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
|
||||
// bic dst, src1, #imm ror rot*2
|
||||
#define BIC_IMM8_ROR(dst, src, imm8, rot) \
|
||||
EMIT(0xe3c00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
// bic.s dst, src1, #imm ror rot*2
|
||||
#define BICS_IMM8_ROR(dst, src, imm8, rot) \
|
||||
EMIT(0xe3d00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
@@ -324,9 +343,6 @@ Op is 20-27
|
||||
#define MVN_COND_REG_LSL_IMM5(cond, dst, rm, imm5) \
|
||||
EMIT(cond | 0x01e00000 | ((dst) << 12) | (0 << 16) | brLSL(imm5, rm) )
|
||||
|
||||
// Single data transfert construction
|
||||
#define SDT_REG(Cond, P, U, B, W, L, Rn, Rd, ShiftRm) (Cond | (0b00<<26) | (1<<25) | (P<<24) | (U<<23) | (B<<22) | (U<<23) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | ShiftRm)
|
||||
#define SDT_OFF(Cond, P, U, B, W, L, Rn, Rd, Imm12) (Cond | (0b00<<26) | (0<<25) | (P<<24) | (U<<23) | (B<<22) | (U<<23) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | Imm12)
|
||||
// ldr reg, [addr, #+/-imm9]
|
||||
#define LDR_IMM9(reg, addr, imm9) EMIT(0xe5100000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
|
||||
// ldrxx reg, [addr, #+/-imm9]
|
||||
@@ -451,6 +467,10 @@ Op is 20-27
|
||||
#define MULMULA(Cond, A, S, Rd, Rn, Rs, Rm) (Cond | 0b000000<<22 | (A)<<21 | (S)<<20 | (Rd)<<16 | (Rn)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
|
||||
#define MUL(Rd, Rm, Rn) EMIT(MULMULA(c__, 0, 0, (Rd), 0, (Rm), (Rn)))
|
||||
|
||||
#define MLS_gen(Cond, Rd, Ra, Rm, Rn) (Cond | 0b00000110<<20 | (Rd)<<16 | (Ra)<<12 | (Rm)<<8 | 0b1001<<4 | (Rn))
|
||||
//MLS : Rd = Ra - Rm*Rn
|
||||
#define MLS(Rd, Rm, Rn, Ra) EMIT(MLS_gen(c__, Rd, Ra, Rm, Rn))
|
||||
|
||||
#define SMUL_16_gen(cond, Rd, Rm, M, N, Rn) (cond | 0b00010110<<20 | (Rd)<<16 | (Rm)<<8 | 1<<7 | (M)<<6 | (N)<<5 | (Rn))
|
||||
// Signed Mul between Rn[0..15] * Rm[0..15] => Rd
|
||||
#define SMULBB(Rd, Rn, Rm) EMIT(SMUL_16_gen(c__, Rd, Rm, 0, 0, Rn))
|
||||
@@ -466,6 +486,8 @@ Op is 20-27
|
||||
|
||||
// UBFX: Unsigned Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
|
||||
#define UBFX(rd, rn, lsb, width) EMIT(c__ | (0b0111111<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
|
||||
// SBFX: Signed Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
|
||||
#define SBFX(rd, rn, lsb, width) EMIT(c__ | (0b0111101<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
|
||||
|
||||
// BFI: Bit Field Insert: copy any number of low order bit from Rn to any position of Rd
|
||||
#define BFI(rd, rn, lsb, width) EMIT(c__ | (0b0111110<<21) | (((lsb)+(width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b001<<4) | (rn))
|
||||
@@ -543,6 +565,10 @@ Op is 20-27
|
||||
// Preload Cache Rn-Rm
|
||||
#define PLDn(Rn, Rm) EMIT(PLD_gen(0, 1, Rn, 0, 0, Rm))
|
||||
|
||||
#define DMB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0101<<4 | (opt))
|
||||
// Data memory barrier Inner Sharable
|
||||
#define DMB_ISH() EMIT(DMB_gen(0b1011))
|
||||
|
||||
#define SWP_gen(cond, B, Rn, Rt, Rt2) (cond | 0b0001<<24 | (B)<<22 | (Rn)<<16 | (Rt)<<12 | 0b1001<<4 | (Rt2))
|
||||
// SWAP (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2
|
||||
#define SWP(Rt, Rt2, Rn) EMIT(SWP_gen(c__, 0, Rn, Rt, Rt2))
|
||||
@@ -551,17 +577,17 @@ Op is 20-27
|
||||
|
||||
#define SDIV_gen(cond, Rd, Rm, Rn) (cond | 0b0111<<24 | 0b0001<<20 | (Rd)<<16 | 0b1111<<12 | (Rm)<<8 | 0b0001<<4 | (Rn))
|
||||
// Signed Div Rd <- Rn/Rm
|
||||
#define SDIV(Rd, Rm, Rn) EMIT(SDIV_gen(c__, Rd, Rm, Rn))
|
||||
#define SDIV(Rd, Rn, Rm) EMIT(SDIV_gen(c__, Rd, Rm, Rn))
|
||||
|
||||
#define UDIV_gen(cond, Rd, Rm, Rn) (cond | 0b0111<<24 | 0b0011<<20 | (Rd)<<16 | 0b1111<<12 | (Rm)<<8 | 0b0001<<4 | (Rn))
|
||||
// Unsigned Div Rd <- Rn/Rm
|
||||
#define UDIV(Rd, Rm, Rn) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
|
||||
#define UDIV(Rd, Rn, Rm) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
|
||||
|
||||
// Yield
|
||||
#define YIELD(cond) EMIT(cond | 0b00110010<<20 | 0b1111<<12 | 1)
|
||||
|
||||
// VFPU
|
||||
#define TRANSFERT64(C, op) ((0b1100<<24) | (0b010<<21) | (0b101<<9) | ((C)<<8) | ((op)<<4))
|
||||
// UDF
|
||||
#define UDF(imm16) EMIT(0b1110<<28 | 0b011<<25 | 0b11111<<20 | (((imm16)>>4)&0xfff) | 0b1111<<4 | ((imm16)&0xf))
|
||||
|
||||
// Move from FPSCR to Arm register
|
||||
#define VMRS(Rt) EMIT(c__ | (0b1110<<24) | (0b1111<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
|
||||
@@ -595,6 +621,8 @@ Op is 20-27
|
||||
#define VMOVcond_32(cond, Sd, Sm) EMIT(cond | (0b11101<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15))
|
||||
// Move between Sd and Imm
|
||||
#define VMOV_i_32(Sd, Imm8) EMIT(c__ | (0b11101<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Imm8)>>4)&0xf)<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b00<<6) | ((Imm8)&15))
|
||||
// Move between Dd and Imm
|
||||
#define VMOV_i_64(Dd, Imm8) EMIT(c__ | (0b11101<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | ((((Imm8)>>4)&0xf)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b00<<6) | ((Imm8)&15))
|
||||
|
||||
#define VMOVtoDx_gen(Vd, D, Rt, opc1, opc2) (0b1110<<24 | 0<<23 | (opc1)<<21 | (Vd)<<16 | (Rt)<<12 | 0b1011<<8 | (D)<<7 | (opc2)<<5 | 1<<4)
|
||||
// Move between Rt and Dm[x]
|
||||
@@ -633,10 +661,14 @@ Op is 20-27
|
||||
|
||||
// Convert from double Dm to int32 Sd, with Round toward Zero mode
|
||||
#define VCVT_S32_F64(Sd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (1<<8) | (1<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// Convert from double Dm to uint32 Sd, with Round toward Zero mode
|
||||
#define VCVT_U32_F64(Sd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b100<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (1<<8) | (1<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// Convert from double Dm to int32 Sd, with Round selection from FPSCR
|
||||
#define VCVTR_S32_F64(Sd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// Convert from int32 Sm to double Dd
|
||||
#define VCVT_F64_S32(Dd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b111<<19) | (0b000<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
// Convert from uint32 Sm to double Dd
|
||||
#define VCVT_F64_U32(Dd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b111<<19) | (0b000<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
// Convert from single Sm to int32 Sd, with Round toward Zero mode
|
||||
#define VCVT_S32_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
// Convert from single Sm to int32 Sd, with Round selection from FPSCR
|
||||
@@ -683,6 +715,10 @@ Op is 20-27
|
||||
|
||||
// Neg F64 Dd = - Dm
|
||||
#define VNEG_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// Neg F64 Dd = - Dm
|
||||
#define VNEG_F64_cond(cond, Dd, Dm) EMIT((cond) | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// Neg F32 Dd = - Dm
|
||||
#define VNEG_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
|
||||
// Sqrt F64 Dd = - Dm
|
||||
#define VSQRT_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
@@ -691,6 +727,13 @@ Op is 20-27
|
||||
|
||||
// Abs Dd = |Dm|
|
||||
#define VABS_F64(Dd, Dm) EMIT(c__ | (0b11101<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15))
|
||||
// Abs Dd = |Dm|
|
||||
#define VABS_F32(Sd, Sm) EMIT(c__ | (0b11101<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b11<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15))
|
||||
|
||||
// MLS Dd = Dd - Dn*Dm
|
||||
#define VMLS_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b00<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | 1<<6 | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// MLA Dd = Dd + Dn*Dm
|
||||
#define VMLA_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b00<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | 0<<6 | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
|
||||
// NEON
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
arm_epilog:
|
||||
//update register -> emu
|
||||
//pop {r0}
|
||||
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be EIP now)
|
||||
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be Flags now)
|
||||
//restore all used register
|
||||
vpop {d8-d15}
|
||||
pop {r4-r11, pc}
|
||||
pop {r4-r12, pc}
|
||||
//end, return...
|
||||
//bx lr
|
||||
|
||||
@@ -22,6 +22,6 @@ arm_epilog:
|
||||
arm_epilog_fast:
|
||||
//restore all used register
|
||||
vpop {d8-d15}
|
||||
pop {r4-r11, pc}
|
||||
pop {r4-r12, pc}
|
||||
//end, return...
|
||||
//bx lr
|
||||
@@ -73,12 +73,19 @@
|
||||
! VMOV is VORR constrained -> (removed VORR)
|
||||
! VEOR, VBSL, VBIT, VBIF differ only depending on 2 bits: 0/1 0/1 ... VEOR -> @<2> ... @ ... @ V\op\ (field, switchable var, assembly)
|
||||
! Three registers of different lengths (when having L and W variants): op (field) -> Q (field)
|
||||
! MRS: always APSR since program is always in userspace
|
||||
! DBG: option (field and assembly) -> imm (field and assembly)
|
||||
|
||||
; ========== BEGINNING OF REGISTERED INSTRUCTIONS =========
|
||||
|
||||
# This instruction changes the instruction set to Thumb! Disabled (but valid)
|
||||
#ARM_ 1 1 1 1 1 0 1 @<1> imm24 @ set imm24 = (imm24 << 2) + (param << 1)@ @ BLX <label>
|
||||
|
||||
# CPS marked as invalid (in userspace, treated as NOP)
|
||||
;INVALIDATE 1 1 1 1 0 0 0 1 0 0 0 0 <4> <8> <2> 0 <1> <4>
|
||||
ARM_ 1 1 1 1 0 0 0 1 0 0 0 0 (0) (0) (0) 1 (0) (0) (0) (0) (0) (0) @<1> (0) 0 0 0 0 (0) (0) (0) (0) SETEND \%cparam ? 'B' : 'L'\E
|
||||
;INVALIDATE 1 1 1 1 0 0 0 1 0 0 1 0 <4> <8> 0 1 1 1 <4>
|
||||
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
@@ -237,107 +244,141 @@ NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned
|
||||
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
|
||||
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
|
||||
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 0 0 <22>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <20>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 0 0 <20>
|
||||
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 1 0 <22>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 1 1 <6>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 0 0 <1> 1 <4>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 1 0 <3> 1 <4>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <20>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 1 0 <20>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 0 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 1 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> Rm VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
|
||||
|
||||
ARM_ 1 1 1 1 0 1 0 0 @<1> 0 0 1 Rn @<8> @<4> @<4> 'NOP'
|
||||
ARM_ 1 1 1 1 0 1 0 0 U 1 0 1 Rn (1) (1) (1) (1) imm12 PLI [<Rn>, #+/-<imm12>]
|
||||
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 1 1 <4> <8> <4> <4>
|
||||
ARM_ 1 1 1 1 0 1 0 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm12 PLD\param ? "W" : ""\ [<Rn>, #+/-<imm12>]
|
||||
ARM_ 1 1 1 1 0 1 0 1 U (1) 0 1 1 1 1 1 (1) (1) (1) (1) imm12 PLD [PC, #+/-<imm>]
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 0 0 1 1 <4> <8> <4> <4>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 0 0 0 0 <4>
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 (1) (1) (1) (1) CLREX
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 0 0 1 <1> <4>
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 0 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DSB \option\
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 1 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DMB \option\
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 1 0 @<4> @ param=0b1111 const char* option option,"SY","!!!"@ @ ISB \option\
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 0 1 1 1 <4>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 1 <3> <4>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> <4> <4>
|
||||
;INVALIDATE 1 1 1 1 0 1 0 1 1 <1> 1 1 <4> <8> <4> <4>
|
||||
ARM_ 1 1 1 1 0 1 1 0 @<1> 0 0 1 Rn @<8> @<3> 0 @<4> 'NOP'
|
||||
ARMs 1 1 1 1 0 1 1 0 U 1 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLI [<Rn>, +/-<Rm>{, <shift>}]
|
||||
ARMs 1 1 1 1 0 1 1 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLD\param ? "W" : ""\ [<Rn>, +/-<Rm>{, <shift>}]
|
||||
;INVALIDATE 1 1 1 1 0 1 1 <3> 1 1 <4> <8> <3> 0 <4>
|
||||
# Permanently undefined
|
||||
INVALIDATE 1 1 1 1 0 1 1 1 1 1 1 1 <4> <8> 1 1 1 1 <4>
|
||||
;INVALIDATE 1 1 1 1 0 <7> <4> <8> <4> <4>
|
||||
|
||||
; ===== No more 1 1 1 1 ..., so invalidate all of them ====
|
||||
INVALIDATE 1 1 1 1 <28>
|
||||
|
||||
@@ -390,6 +431,8 @@ ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{,
|
||||
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
|
||||
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
|
||||
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
|
||||
ARM_ cond 0 0 0 1 0 0 0 0 (1) (1) (1) (1) Rd (0) (0) 0 (0) 0 0 0 0 (0) (0) (0) (0) MRS<c> <Rd>, APSR
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) (0) (0) 0 (0) 0 0 0 0 Rn @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, <Rn>
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
|
||||
@@ -437,6 +480,18 @@ ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
|
||||
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
|
||||
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 1 YIELD<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 0 WFE<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 1 WFI<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 1 0 0 SEV<c>
|
||||
ARM_ cond/=1110 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 0 1 0 0 CSDB<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 1 1 1 1 imm4 DBG<c> #<imm>
|
||||
INVALIDATE <4> 0 0 1 1 0 0 1 0 0 0 0 0 <8> <8>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) imm12 @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, #<imm>
|
||||
# MSR in system level is invalid/useless in application level
|
||||
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 0 1 <8> <8>
|
||||
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 1 <1> <8> <8>
|
||||
INVALIDATE <4> 0 0 1 1 0 1 1 0 <4> <8> <8>
|
||||
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
|
||||
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
|
||||
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
|
||||
@@ -495,6 +550,8 @@ ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <
|
||||
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
|
||||
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
|
||||
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
|
||||
ARM_ cond 0 1 1 1 0 0 0 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn SDIV<c> <Rd>, <Rn>, <Rm>
|
||||
ARM_ cond 0 1 1 1 0 0 1 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn UDIV<c> <Rd>, <Rn>, <Rm>
|
||||
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
|
||||
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
|
||||
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
|
||||
@@ -504,6 +561,7 @@ ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
|
||||
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
|
||||
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||
ARM_ cond/=1110 0 1 1 1 1 1 1 1 imm12 1 1 1 1 imm4 UDF<c> #<imm16>
|
||||
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
|
||||
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
|
||||
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
|
||||
@@ -537,14 +595,14 @@ INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
|
||||
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
|
||||
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
|
||||
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
|
||||
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
|
||||
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
|
||||
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
|
||||
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
|
||||
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
|
||||
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
|
||||
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
|
||||
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
|
||||
INVALIDATE <4> 1 1 0 <25>
|
||||
@@ -558,6 +616,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>,
|
||||
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
|
||||
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
|
||||
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
|
||||
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt/=1111 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> APSR_nzcv, FPSCR
|
||||
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
|
||||
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
|
||||
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
|
||||
@@ -587,7 +646,7 @@ VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <S
|
||||
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 1 U 1 Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
|
||||
;INVALIDATE <4> 1 1 1 0 1 <1> 1 1 <8> 1 0 1 <4> 0 <4>
|
||||
;INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 0 <4>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
arm_lock_read_b:
|
||||
// address is r0, return is r0
|
||||
dmb ish
|
||||
ldrexb r0, [r0]
|
||||
bx lr
|
||||
|
||||
@@ -31,6 +32,7 @@ arm_lock_write_b:
|
||||
|
||||
arm_lock_read_h:
|
||||
// address is r0, return is r0
|
||||
dmb ish
|
||||
ldrexh r0, [r0]
|
||||
bx lr
|
||||
|
||||
@@ -43,6 +45,7 @@ arm_lock_write_h:
|
||||
arm_lock_read_d:
|
||||
// address is r0, return is r0
|
||||
// r0 needs to be aligned
|
||||
dmb ish
|
||||
ldrex r0, [r0]
|
||||
bx lr
|
||||
|
||||
@@ -55,6 +58,7 @@ arm_lock_write_d:
|
||||
|
||||
arm_lock_read_dd:
|
||||
// address is r2, return is r0, r1
|
||||
dmb ish
|
||||
ldrexd r2, r3, [r2]
|
||||
str r2, [r0]
|
||||
str r3, [r1]
|
||||
@@ -70,6 +74,7 @@ arm_lock_write_dd:
|
||||
arm_lock_xchg:
|
||||
// address is r0, value is r1, return old value in r0
|
||||
// r0 needs to be aligned
|
||||
dmb ish
|
||||
ldrex r2, [r0]
|
||||
strex r3, r1, [r0]
|
||||
cmp r3, #1
|
||||
@@ -80,6 +85,7 @@ arm_lock_xchg:
|
||||
arm_lock_storeifnull:
|
||||
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
|
||||
// r0 needs to be aligned
|
||||
dmb ish
|
||||
ldrex r2, [r0]
|
||||
cmp r2, #0
|
||||
bne arm_lock_storeifnull_exit
|
||||
@@ -93,6 +99,7 @@ arm_lock_storeifnull_exit:
|
||||
|
||||
arm_lock_storeifref:
|
||||
push {r4}
|
||||
dmb ish
|
||||
arm_lock_storeifref_loop:
|
||||
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return new [r0] value (so r1 or old value)
|
||||
ldrex r3, [r0]
|
||||
|
||||
+1215
-795
File diff suppressed because it is too large.
Load diff
@@ -9,7 +9,7 @@
|
||||
.global arm_prolog
|
||||
arm_prolog:
|
||||
//save all used register
|
||||
push {r4-r11, lr}
|
||||
push {r4-r12, lr}
|
||||
vpush {d8-d15}
|
||||
//setup emu -> register
|
||||
//push {r0}
|
||||
|
||||
+55
-31
@@ -2,6 +2,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
@@ -55,12 +57,14 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeDynablock(dynablock_t* db)
|
||||
void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
{
|
||||
if(db) {
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
|
||||
if(db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
// remove from direct if there
|
||||
@@ -76,16 +80,18 @@ void FreeDynablock(dynablock_t* db)
|
||||
// remove and free the sons
|
||||
for (int i=0; i<db->sons_size; ++i) {
|
||||
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
|
||||
FreeDynablock(son);
|
||||
FreeDynablock(son, 0);
|
||||
}
|
||||
// only the father free the DynarecMap
|
||||
if(!db->father) {
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
}
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
free(db);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +105,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
if((*dynablocks)->direct) {
|
||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
|
||||
FreeDynablock((*dynablocks)->direct[i]);
|
||||
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
|
||||
}
|
||||
free((*dynablocks)->direct);
|
||||
}
|
||||
@@ -116,7 +122,7 @@ void MarkDynablock(dynablock_t* db)
|
||||
db = db->father; // mark only father
|
||||
if(db->need_test)
|
||||
return; // already done
|
||||
db->need_test = 1; // test only blocks that can be marked (and so deleted)
|
||||
db->need_test = 1;
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
for(int i=0; i<db->sons_size; ++i)
|
||||
setJumpTableDefault(db->sons[i]->x86_addr);
|
||||
@@ -200,7 +206,7 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db);
|
||||
FreeDynablock(db, 1);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
}
|
||||
@@ -258,7 +264,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
if(dynablocks->direct) {
|
||||
block = dynablocks->direct[addr-dynablocks->text];
|
||||
if(block) {
|
||||
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
|
||||
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
@@ -267,6 +273,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
if (!*created)
|
||||
return block;
|
||||
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm_lock_storeifnull(&dynablocks->direct, p)!=p)
|
||||
@@ -274,27 +281,35 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
}
|
||||
|
||||
// create and add new block
|
||||
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
free(block);
|
||||
*created = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
*created = 1;
|
||||
return block;
|
||||
}
|
||||
|
||||
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
|
||||
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
|
||||
|
||||
void cancelFillBlock()
|
||||
{
|
||||
longjmp(&dynarec_jmpbuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
*/
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
|
||||
{
|
||||
// try the quickest way first: get parent of current and check if ok!
|
||||
dynablocklist_t *dynablocks = NULL;
|
||||
@@ -323,15 +338,19 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(!created)
|
||||
return block; // existing block...
|
||||
|
||||
#if 0
|
||||
if(box86_dynarec_dump)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// fill the block
|
||||
block->x86_addr = (void*)addr;
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock(block, filladdr);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!ret) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
void* old = (void*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
@@ -342,10 +361,6 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
free(block);
|
||||
block = NULL;
|
||||
}
|
||||
#if 0
|
||||
if(box86_dynarec_dump)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// check size
|
||||
if(block && block->x86_size) {
|
||||
int blocksz = block->x86_size;
|
||||
@@ -358,7 +373,10 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
dblist->maxsz = blocksz;
|
||||
}
|
||||
}
|
||||
protectDB((uintptr_t)block->x86_addr, block->x86_size);
|
||||
//protectDB((uintptr_t)block->x86_addr, block->x86_size); // already protected in FillBlock
|
||||
// but check if it already need test
|
||||
if(block->need_test || (block->father && block->father->need_test))
|
||||
return NULL;
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault(block->x86_addr, block->block);
|
||||
for(int i=0; i<block->sons_size; ++i)
|
||||
@@ -372,19 +390,21 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
|
||||
{
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||
// no more current if it gets invalidated too
|
||||
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
|
||||
*current = NULL;
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father);
|
||||
FreeDynablock(father, 0);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||
@@ -393,6 +413,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -401,16 +422,18 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father);
|
||||
FreeDynablock(father, 0);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||
@@ -419,6 +442,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
+16
-6
@@ -19,6 +19,7 @@
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynablock_private.h"
|
||||
#include "bridge.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARM
|
||||
@@ -45,12 +46,21 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
|
||||
dynablock_t* block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
if(!block) {
|
||||
// no block, let link table as is...
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2);
|
||||
printf_log(LOG_INFO, "Warning, jumping to a no-block address from %p (db=%p, x86addr=%p)\n", x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
|
||||
#endif
|
||||
//tableupdate(arm_epilog, addr, table);
|
||||
return arm_epilog;
|
||||
if(hasAlternate((void*)addr)) {
|
||||
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
|
||||
addr = (uintptr_t)getAlternate((void*)addr);
|
||||
R_EIP = addr;
|
||||
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
|
||||
block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
}
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p)\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
|
||||
#endif
|
||||
//tableupdate(arm_epilog, addr, table);
|
||||
return arm_epilog;
|
||||
}
|
||||
}
|
||||
if(!block->done) {
|
||||
// not finished yet... leave linker
|
||||
|
||||
+126
-72
@@ -58,13 +58,15 @@ void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const cha
|
||||
}
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
if(!box86_dynarec_bigblock)
|
||||
return;
|
||||
for(int i=0; i<dyn->next_sz; ++i)
|
||||
if(dyn->next[i]==addr)
|
||||
return;
|
||||
if(dyn->next_sz == dyn->next_cap) {
|
||||
dyn->next_cap += 16;
|
||||
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
}
|
||||
for(int i=0; i<dyn->next_sz; ++i)
|
||||
if(dyn->next[i]==addr)
|
||||
return;
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
@@ -229,53 +231,6 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
|
||||
return (i==n)?1:0;
|
||||
}
|
||||
|
||||
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
|
||||
{
|
||||
if(recurse == 10)
|
||||
return X_PEND;
|
||||
if(ninst == dyn->size)
|
||||
return X_PEND; // no more instructions, or too many jmp loop, stop
|
||||
|
||||
uint32_t needed = dyn->insts[ninst].x86.use_flags;
|
||||
if(needed) {
|
||||
setf &= ~needed;
|
||||
if(!setf) // all flags already used, no need to continue
|
||||
return needed;
|
||||
}
|
||||
|
||||
if(!needed && !dyn->insts[ninst].x86.set_flags && !dyn->insts[ninst].x86.jmp_insts) {
|
||||
int start = ninst;
|
||||
int end = ninst;
|
||||
while(end<dyn->size && !dyn->insts[end].x86.use_flags && !dyn->insts[end].x86.set_flags && !dyn->insts[end].x86.jmp_insts)
|
||||
++end;
|
||||
needed = needed_flags(dyn, end, setf, recurse);
|
||||
for(int i=start; i<end; ++i)
|
||||
dyn->insts[i].x86.need_flags = needed;
|
||||
return needed;
|
||||
}
|
||||
|
||||
if(dyn->insts[ninst].x86.set_flags && (dyn->insts[ninst].x86.state_flags!=SF_MAYSET)) {
|
||||
if((setf & ~dyn->insts[ninst].x86.set_flags) == 0)
|
||||
return needed; // all done, gives all the flags needed
|
||||
setf |= dyn->insts[ninst].x86.set_flags; // add new flags to continue
|
||||
}
|
||||
|
||||
int jinst = dyn->insts[ninst].x86.jmp_insts;
|
||||
if(dyn->insts[ninst].x86.jmp) {
|
||||
dyn->insts[ninst].x86.need_flags = (jinst==-1)?X_PEND:needed_flags(dyn, jinst, setf, recurse+1);
|
||||
if(dyn->insts[ninst].x86.use_flags) // conditionnal jump
|
||||
dyn->insts[ninst].x86.need_flags |= needed_flags(dyn, ninst+1, setf, recurse);
|
||||
} else
|
||||
dyn->insts[ninst].x86.need_flags = needed_flags(dyn, ninst+1, setf, recurse);
|
||||
if(dyn->insts[ninst].x86.state_flags==SF_MAYSET)
|
||||
needed |= dyn->insts[ninst].x86.need_flags;
|
||||
else
|
||||
needed |= (dyn->insts[ninst].x86.need_flags & ~dyn->insts[ninst].x86.set_flags);
|
||||
if(needed == (X_PEND|X_ALL))
|
||||
needed = X_ALL;
|
||||
return needed;
|
||||
}
|
||||
|
||||
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
|
||||
{
|
||||
// x86 instruction is <16 bytes
|
||||
@@ -310,6 +265,22 @@ uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
__thread void* current_helper = NULL;
|
||||
|
||||
void CancelBlock()
|
||||
{
|
||||
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(!helper)
|
||||
return;
|
||||
free(helper->next);
|
||||
free(helper->insts);
|
||||
free(helper->sons_x86);
|
||||
free(helper->sons_arm);
|
||||
if(helper->dynablock && helper->dynablock->block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
|
||||
}
|
||||
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
|
||||
@@ -322,29 +293,52 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
}
|
||||
// init the helper
|
||||
dynarec_arm_t helper = {0};
|
||||
current_helper = &helper;
|
||||
helper.dynablock = block;
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 64; // needs epilog handling
|
||||
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
|
||||
// pass 0, addresses, x86 jump addresses, overall size of the block
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
// no need for next anymore
|
||||
free(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
block->done = 1;
|
||||
free(helper.next);
|
||||
CancelBlock();
|
||||
return (void*)block;
|
||||
}
|
||||
helper.cap = helper.size+3; // needs epilog handling
|
||||
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
|
||||
// already protect the block and compute hash signature
|
||||
protectDB(addr, end-addr+1);
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr+1);
|
||||
// pass 1, addresses, x86 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// Compute flag_need, without taking into account any barriers
|
||||
uint32_t last_need = X_PEND;
|
||||
for(int i = helper.size; i-- > 0;) {
|
||||
last_need |= helper.insts[i].x86.use_flags;
|
||||
if((helper.insts[i].x86.state_flags == SF_SUBSET) && (last_need&X_PEND))
|
||||
last_need = (X_ALL & (~helper.insts[i].x86.set_flags) ) | helper.insts[i].x86.use_flags;
|
||||
if (last_need == (X_PEND | X_ALL)) {
|
||||
last_need = X_ALL;
|
||||
}
|
||||
helper.insts[i].x86.need_flags = last_need;
|
||||
if ((helper.insts[i].x86.set_flags) && !(helper.insts[i].x86.state_flags & SF_MAYSET)) {
|
||||
if (last_need & X_PEND) {
|
||||
last_need = (~helper.insts[i].x86.set_flags) & X_ALL;
|
||||
} else {
|
||||
last_need &= ~helper.insts[i].x86.set_flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
// calculate barriers
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x86.jmp) {
|
||||
uintptr_t j = helper.insts[i].x86.jmp;
|
||||
if(j<start || j>=end)
|
||||
if(j<start || j>=end) {
|
||||
helper.insts[i].x86.jmp_insts = -1;
|
||||
else {
|
||||
} else {
|
||||
// find jump address instruction
|
||||
int k=-1;
|
||||
for(int i2=0; i2<helper.size && k==-1; ++i2) {
|
||||
@@ -356,12 +350,70 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.insts[i].x86.jmp_insts = k;
|
||||
}
|
||||
}
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x86.set_flags && !helper.insts[i].x86.need_flags) {
|
||||
helper.insts[i].x86.need_flags = needed_flags(&helper, i+1, helper.insts[i].x86.set_flags, 0);
|
||||
if((helper.insts[i].x86.need_flags&X_PEND) && (helper.insts[i].x86.state_flags==SF_MAYSET))
|
||||
helper.insts[i].x86.need_flags = X_ALL;
|
||||
// check for the optionnal barriers now
|
||||
for(int i=helper.size-1; i>=0; --i) {
|
||||
if(helper.insts[i].x86.barrier==3)
|
||||
if(helper.insts[i].x86.jmp_insts == -1) {
|
||||
if(i==helper.size-1 || helper.insts[i+1].x86.barrier)
|
||||
helper.insts[i].x86.barrier=2; // nope, end of block or barrier just after
|
||||
else
|
||||
helper.insts[i].x86.barrier=0; // ok, no need for a barrier here after all
|
||||
} else
|
||||
helper.insts[i].x86.barrier=2;
|
||||
}
|
||||
// check to remove useless barrier, in case of jump when destination doesn't needs flags
|
||||
for(int i=helper.size-1; i>=0; --i) {
|
||||
if(helper.insts[i].x86.jmp
|
||||
&& helper.insts[i].x86.jmp_insts>=0
|
||||
&& helper.insts[helper.insts[i].x86.jmp_insts].x86.barrier==1) {
|
||||
int k = helper.insts[i].x86.jmp_insts;
|
||||
//TODO: optimize FPU barrier too
|
||||
if((!helper.insts[k].x86.need_flags)
|
||||
||(helper.insts[k].x86.set_flags==X_ALL
|
||||
&& helper.insts[k].x86.state_flags==SF_SET)
|
||||
||(helper.insts[k].x86.state_flags==SF_SET_PENDING)) {
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
|
||||
helper.insts[k].x86.barrier = 4; // remove barrier (keep FPU barrier, and still reset state flag)
|
||||
}
|
||||
}
|
||||
}
|
||||
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
|
||||
for(int i = helper.size; i-- > 0;) {
|
||||
if(helper.insts[i].x86.barrier==1)
|
||||
// immediate barrier
|
||||
helper.insts[i].x86.use_flags |= X_PEND;
|
||||
else if(helper.insts[i].x86.jmp
|
||||
&& helper.insts[i].x86.jmp_insts>=0
|
||||
) {
|
||||
if(helper.insts[helper.insts[i].x86.jmp_insts].x86.barrier==1)
|
||||
// jumpto barrier
|
||||
helper.insts[i].x86.use_flags |= X_PEND;
|
||||
else
|
||||
helper.insts[i].x86.use_flags |= helper.insts[helper.insts[i].x86.jmp_insts].x86.need_flags;
|
||||
}
|
||||
}
|
||||
for(int i = helper.size; i-- > 0;)
|
||||
helper.insts[i].x86.need_flags = 0;
|
||||
last_need = X_PEND;
|
||||
for(int i = helper.size; i-- > 0;) {
|
||||
helper.insts[i].x86.need_flags = last_need;
|
||||
if((helper.insts[i].x86.state_flags == SF_SUBSET) && (last_need&X_PEND))
|
||||
last_need = (X_ALL & (~helper.insts[i].x86.set_flags) ) | helper.insts[i].x86.use_flags;
|
||||
if ((helper.insts[i].x86.set_flags) && !(helper.insts[i].x86.state_flags & SF_MAYSET)) {
|
||||
if (last_need & X_PEND) {
|
||||
last_need = (~helper.insts[i].x86.set_flags) & X_ALL;
|
||||
} else {
|
||||
last_need &= ~helper.insts[i].x86.set_flags;
|
||||
}
|
||||
}
|
||||
last_need |= helper.insts[i].x86.use_flags;
|
||||
if (last_need == (X_PEND | X_ALL)) {
|
||||
last_need = X_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
// pass 1, float optimisations
|
||||
arm_pass1(&helper, addr);
|
||||
|
||||
// pass 2, instruction size
|
||||
arm_pass2(&helper, addr);
|
||||
@@ -370,8 +422,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
void* p = (void*)AllocDynarecMap(block, sz);
|
||||
if(p==NULL) {
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
CancelBlock();
|
||||
return NULL;
|
||||
}
|
||||
helper.block = p;
|
||||
@@ -415,22 +466,22 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
}
|
||||
// ok, free the helper now
|
||||
free(helper.insts);
|
||||
helper.insts = NULL;
|
||||
free(helper.next);
|
||||
helper.next = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->need_test = 0;
|
||||
//block->x86_addr = (void*)start;
|
||||
block->x86_size = end-start+1;
|
||||
block->x86_size = end-start;
|
||||
if(box86_dynarec_largest<block->x86_size)
|
||||
box86_dynarec_largest = block->x86_size;
|
||||
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
free(helper.sons_x86);
|
||||
free(helper.sons_arm);
|
||||
FreeDynarecMap(block, (uintptr_t)p, sz);
|
||||
CancelBlock();
|
||||
return NULL;
|
||||
}
|
||||
// fill sons if any
|
||||
@@ -444,7 +495,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(created) { // avoid breaking a working block!
|
||||
son->block = helper.sons_arm[i];
|
||||
son->x86_addr = (void*)helper.sons_x86[i];
|
||||
son->x86_size = end-helper.sons_x86[i]+1;
|
||||
son->x86_size = end-helper.sons_x86[i];
|
||||
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
|
||||
son->father = block;
|
||||
son->done = 1;
|
||||
@@ -460,7 +511,10 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
free(sons);
|
||||
}
|
||||
free(helper.sons_x86);
|
||||
helper.sons_x86 = NULL;
|
||||
free(helper.sons_arm);
|
||||
helper.sons_arm = NULL;
|
||||
current_helper = NULL;
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
+340
-202
File diff suppressed because it is too large.
Load diff
+249
-183
File diff suppressed because it is too large.
Load diff
@@ -37,7 +37,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -47,7 +47,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -57,7 +57,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -65,9 +65,19 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_xor32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x39:
|
||||
INST_NAME("CMP FS:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x14);
|
||||
emit_cmp32(dyn, ninst, ed, gd, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x3B:
|
||||
INST_NAME("CMP Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -174,7 +184,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
STR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
@@ -187,7 +197,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
@@ -199,7 +209,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP1(xEAX+(nextop&7));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
POP1(x2);
|
||||
STR_REG_LSL_IMM5(x2, ed, x14, 0);
|
||||
}
|
||||
@@ -259,7 +269,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
i32 = F32S;
|
||||
MOV32(x3, i32);
|
||||
STR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
@@ -278,7 +288,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL FS:Ed");
|
||||
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x86.set_flags, 1) {
|
||||
PASS2IF(ninst && dyn->insts[ninst-1].x86.set_flags, 1) {
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
@@ -286,7 +296,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
MOV_REG(xEIP, xEAX+(nextop&7));
|
||||
} else { // mem
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
|
||||
}
|
||||
BARRIER(1);
|
||||
@@ -305,7 +315,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
PUSH1(x3);
|
||||
}
|
||||
|
||||
+261
-26
@@ -28,7 +28,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t wback, wb1, wb2, wb;
|
||||
uint8_t u8;
|
||||
int fixedaddress;
|
||||
|
||||
@@ -40,7 +40,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -48,9 +48,67 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_add32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x0F: // more opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xAF:
|
||||
INST_NAME("IMUL Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x14);
|
||||
UFLAG_IF {
|
||||
SMULL(x3, gd, gd, ed);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_RES(gd);
|
||||
UFLAG_DF(x3, d_imul32);
|
||||
} else {
|
||||
MUL(gd, gd, ed);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("AND Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_and32(dyn, ninst, ed, gd, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
INST_NAME("AND Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x14);
|
||||
emit_and32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("SUB GS:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_sub32(dyn, ninst, ed, gd, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -58,9 +116,20 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_sub32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("XOR GS:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_xor32(dyn, ninst, gd, ed, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -70,7 +139,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x3B:
|
||||
INST_NAME("CMP Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
@@ -103,7 +172,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -112,7 +181,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -122,7 +191,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC GS:Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -132,7 +201,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB GS:Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -141,7 +210,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -150,7 +219,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -159,7 +228,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -168,7 +237,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
@@ -191,7 +260,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
INST_NAME("ADD Ed, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -200,7 +269,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -210,7 +279,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -220,7 +289,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -229,7 +298,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -238,7 +307,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -247,7 +316,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -256,7 +325,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -278,7 +347,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
STR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
@@ -291,7 +360,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
@@ -303,7 +372,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP1((xEAX+(nextop&7)));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
POP1(x2);
|
||||
STR_REG_LSL_IMM5(x2, ed, x14, 0);
|
||||
}
|
||||
@@ -340,13 +409,179 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
i32 = F32S;
|
||||
MOV32(x3, i32);
|
||||
STR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD1:
|
||||
nextop = F8;
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ed, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETEDO2(x14);
|
||||
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ed, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETEDO2(x14);
|
||||
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOVW(x2, 1);
|
||||
GETEDO2(x14);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcl32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOVW(x2, 1);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO2(x14);
|
||||
emit_shl32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO2(x14);
|
||||
emit_shr32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO2(x14);
|
||||
emit_sar32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ed, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
TSTS_REG_LSL_IMM5(x3, x3, 0);
|
||||
B_MARK2(cEQ);
|
||||
RSB_IMM8(x3, x3, 0x20);
|
||||
GETEDO2(x14);
|
||||
MOV_REG_ROR_REG(ed, ed, x3);
|
||||
WBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x3, 31);
|
||||
B_MARK(cNE);
|
||||
MOV_REG_LSR_IMM5(x1, ed, 31);
|
||||
ADD_REG_LSL_IMM5(x1, x1, ed, 0);
|
||||
BFI(xFlags, x1, F_OF, 1);
|
||||
MARK;
|
||||
BFI(xFlags, ed, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
MARK2;
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ed, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
TSTS_REG_LSL_IMM5(x3, x3, 0);
|
||||
B_MARK2(cEQ);
|
||||
GETEDO2(x14);
|
||||
MOV_REG_ROR_REG(ed, ed, x3);
|
||||
WBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x3, 1);
|
||||
B_MARK(cNE);
|
||||
MOV_REG_LSR_IMM5(x2, ed, 30); // x2 = d>>30
|
||||
XOR_REG_LSR_IMM8(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1))
|
||||
BFI(xFlags, x2, F_OF, 1);
|
||||
MARK;
|
||||
MOV_REG_LSR_IMM5(x2, ed, 31);
|
||||
BFI(xFlags, x2, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
MARK2;
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcl32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ed, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETEDO2(x14);
|
||||
emit_shl32(dyn, ninst, ed, x3, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETEDO2(x14);
|
||||
emit_shr32(dyn, ninst, ed, x3, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, CL");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETEDO2(x14);
|
||||
UFLAG_OP12(ed, x3);
|
||||
MOV_REG_ASR_REG(ed, ed, x3);
|
||||
WBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar32);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
INST_NAME("(ignored) GS:");
|
||||
@@ -362,7 +597,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
PUSH1(x3);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x01:
|
||||
INST_NAME("ADD Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -52,7 +52,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -61,7 +61,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x05:
|
||||
INST_NAME("ADD AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_add16c(dyn, ninst, x1, i32, x3, x14);
|
||||
@@ -88,7 +88,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x09:
|
||||
INST_NAME("OR Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -97,7 +97,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x0B:
|
||||
INST_NAME("OR Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -106,7 +106,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x0D:
|
||||
INST_NAME("OR AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_or16c(dyn, ninst, x1, i32, x3, x14);
|
||||
@@ -119,7 +119,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -129,7 +129,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -139,7 +139,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x15:
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
|
||||
@@ -149,7 +149,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x19:
|
||||
INST_NAME("SBB Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -159,7 +159,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x1B:
|
||||
INST_NAME("SBB Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -169,7 +169,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x1D:
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
|
||||
@@ -178,7 +178,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("AND Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -187,7 +187,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x23:
|
||||
INST_NAME("AND Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -196,7 +196,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x25:
|
||||
INST_NAME("AND AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_and16c(dyn, ninst, x1, i32, x3, x14);
|
||||
@@ -209,7 +209,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("SUB Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -218,7 +218,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -227,7 +227,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("SUB AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
|
||||
@@ -236,7 +236,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("XOR Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -245,7 +245,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -254,7 +254,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x35:
|
||||
INST_NAME("XOR AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_xor16c(dyn, ninst, x1, i32, x3, x14);
|
||||
@@ -263,7 +263,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x39:
|
||||
INST_NAME("CMP Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
@@ -271,7 +271,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x3B:
|
||||
INST_NAME("CMP Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
@@ -279,7 +279,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x3D:
|
||||
INST_NAME("CMP AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
MOVW(x2, i32);
|
||||
UXTH(x1, xEAX, 0);
|
||||
@@ -417,7 +417,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
INST_NAME("ADD Ew, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_add16c(dyn, ninst, ed, i16, x2, x14);
|
||||
@@ -425,7 +425,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_or16c(dyn, ninst, x1, i16, x2, x14);
|
||||
@@ -434,7 +434,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_adc16c(dyn, ninst, x1, i16, x2, x14);
|
||||
@@ -443,7 +443,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_sbb16c(dyn, ninst, x1, i16, x2, x14);
|
||||
@@ -451,7 +451,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_and16c(dyn, ninst, x1, i16, x2, x14);
|
||||
@@ -459,7 +459,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_sub16c(dyn, ninst, x1, i16, x2, x14);
|
||||
@@ -467,7 +467,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
emit_xor16c(dyn, ninst, x1, i16, x2, x14);
|
||||
@@ -475,7 +475,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
if(i16) {
|
||||
@@ -489,7 +489,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0x85:
|
||||
INST_NAME("TEST Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEW(x1);
|
||||
GETGW(x2);
|
||||
@@ -500,15 +500,17 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("XCHG Ew, Gw");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GETGW(x14);
|
||||
GETGD;
|
||||
UXTH(x14, gd, 0);
|
||||
ed = xEAX + (nextop&7);
|
||||
UXTH(x1, ed, 0);
|
||||
// do the swap 14 -> ed, 1 -> gd
|
||||
BFI(gd, x1, 0, 16);
|
||||
BFI(ed, x14, 0, 16);
|
||||
} else {
|
||||
GETGW(x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
GETGD;
|
||||
UXTH(x14, gd, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
#if 0
|
||||
MARKLOCK;
|
||||
// do the swap with exclusive locking
|
||||
@@ -535,7 +537,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(ed, gd, 0, 16);
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
STRH_IMM8(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -549,7 +551,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(gd, ed, 0, 16);
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
BFI(gd, x1, 0, 16);
|
||||
}
|
||||
@@ -563,7 +565,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
BFI(ed, x1, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
STRH_IMM8(x1, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -576,7 +578,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(ed, xEmu, x2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(x1, xEmu, x2);
|
||||
@@ -650,16 +652,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xA7:
|
||||
INST_NAME("CMPSW");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETDIR(x3, 2);
|
||||
LDRHAI_REG_LSL_IMM5(x1, xESI, x3);
|
||||
LDRHAI_REG_LSL_IMM5(x2, xEDI, x3);
|
||||
CALL(cmp16, -1, 0);
|
||||
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
|
||||
break;
|
||||
|
||||
case 0xA9:
|
||||
INST_NAME("TEST AX,Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
u16 = F16;
|
||||
MOVW(x2, u16);
|
||||
UBFX(x1, xEAX, 0, 16);
|
||||
@@ -682,7 +684,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETDIR(x3, 2);
|
||||
UXTH(x1, xEAX, 0);
|
||||
LDRHAI_REG_LSL_IMM5(x2, xEDI, x3);
|
||||
CALL(cmp16, -1, 0);
|
||||
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
|
||||
break;
|
||||
|
||||
case 0xB8:
|
||||
@@ -789,7 +791,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(x1, u16);
|
||||
BFI(ed, x1, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
u16 = F16;
|
||||
MOVW(x1, u16);
|
||||
STRH_IMM8(x1, ed, fixedaddress);
|
||||
@@ -995,7 +997,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0:
|
||||
case 1:
|
||||
INST_NAME("TEST Ew, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
u16 = F16;
|
||||
MOVW(x2, u16);
|
||||
@@ -1009,13 +1011,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("NEG Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1);
|
||||
emit_neg16(dyn, ninst, ed, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("MUL AX, Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1);
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
@@ -1035,14 +1038,27 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1);
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(div16, -1, 0);
|
||||
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
if(arm_div) {
|
||||
GETEW(x1);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
UXTH(x2, xEAX, 0);
|
||||
ORR_REG_LSL_IMM5(x2, x2, xEDX, 16);
|
||||
UDIV(x3, x2, ed);
|
||||
MLS(x14, x3, ed, x2); // x14 = x2 mod ed (i.e. x2 - x3*ed)
|
||||
BFI(xEAX, x3, 1, 16);
|
||||
BFI(xEDX, x14, 1, 16);
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1);
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(div16, -1, 0);
|
||||
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("IDIV Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1);
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
@@ -1053,20 +1069,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("CLC");
|
||||
i32 = dyn->state_flags; //TODO: find a better way to do this
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
if(i32!=SF_SET) {
|
||||
SET_DFNONE(x1);
|
||||
}
|
||||
SET_DFNONE(x1);
|
||||
BFC(xFlags, F_CF, 1);
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("STC");
|
||||
i32 = dyn->state_flags; //TODO: find a better way to do this
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
if(i32!=SF_SET) {
|
||||
SET_DFNONE(x1);
|
||||
}
|
||||
SET_DFNONE(x1);
|
||||
MOVW(x1, 1);
|
||||
BFI(xFlags, x1, F_CF, 1);
|
||||
break;
|
||||
@@ -1083,7 +1093,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("DEC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SET);
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
GETEW(x1);
|
||||
emit_dec16(dyn, ninst, x1, x2, x14);
|
||||
EWBACK;
|
||||
|
||||
+398
-308
File diff suppressed because it is too large.
Load diff
@@ -132,9 +132,9 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(NO, YES) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8);\
|
||||
#define GO(NO, YES) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8, 1); \
|
||||
if(dyn->insts) { \
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
|
||||
+120
-56
@@ -50,9 +50,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FADD ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VADD_F64(v1, v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v1, v1, v2);
|
||||
} else {
|
||||
VADD_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -63,9 +67,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FMUL ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VMUL_F64(v1, v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v1, v1, v2);
|
||||
} else {
|
||||
VMUL_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -76,9 +84,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCOM ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
break;
|
||||
case 0xD8:
|
||||
@@ -90,9 +102,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
@@ -105,9 +121,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FSUB ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VSUB_F64(v1, v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v1, v2);
|
||||
} else {
|
||||
VSUB_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -118,9 +138,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FSUBR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VSUB_F64(v1, v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v2, v1);
|
||||
} else {
|
||||
VSUB_F64(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -131,9 +155,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FDIV ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VDIV_F64(v1, v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v1, v2);
|
||||
} else {
|
||||
VDIV_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -144,143 +172,179 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
INST_NAME("FDIVR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VDIV_F64(v1, v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v2, v1);
|
||||
} else {
|
||||
VDIV_F64(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FADD ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VADD_F64(v1, v1, d1);
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VADD_F64(v1, v1, d1);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VMUL_F64(v1, v1, d1);
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VMUL_F64(v1, v1, d1);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VCMP_F64(v1, d1);
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VCMP_F64(v1, d1);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FCOMP ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VCMP_F64(v1, d1);
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VCMP_F64(v1, d1);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VSUB_F64(v1, v1, d1);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VSUB_F64(v1, v1, d1);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VSUB_F64(v1, d1, v1);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, s0, v1);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VSUB_F64(v1, d1, v1);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VDIV_F64(v1, v1, d1);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VDIV_F64(v1, v1, d1);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VDIV_F64(v1, d1, v1);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, s0, v1);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VDIV_F64(v1, d1, v1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
+267
-82
@@ -23,13 +23,16 @@
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
static const double d_1 = 1.0;
|
||||
static const double d_l2t = L2T;
|
||||
static const double d_l2e = L2E;
|
||||
static const double d_pi = PI;
|
||||
static const double d_lg2 = LG2;
|
||||
static const double d_ln2 = LN2;
|
||||
static const double d_0 = 0.0;
|
||||
static const float f_l2t = L2T;
|
||||
static const float f_l2e = L2E;
|
||||
static const float f_pi = PI;
|
||||
static const float f_lg2 = LG2;
|
||||
static const float f_ln2 = LN2;
|
||||
|
||||
uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
@@ -40,11 +43,13 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int i1, i2, i3;
|
||||
int j32;
|
||||
int parity;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
|
||||
@@ -57,9 +62,13 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FLD STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v2 = x87_do_push(dyn, ninst, x3);
|
||||
VMOV_64(v2, v1);
|
||||
v2 = x87_do_push(dyn, ninst, x3, X87_ST(nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_32(v2, v1);
|
||||
} else {
|
||||
VMOV_64(v2, v1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
@@ -72,11 +81,17 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xCF:
|
||||
INST_NAME("FXCH STx");
|
||||
// swap the cache value, not the double value itself :p
|
||||
i1 = x87_get_cache(dyn, ninst, x1, x2, nextop&7);
|
||||
i2 = x87_get_cache(dyn, ninst, x1, x2, 0);
|
||||
i1 = x87_get_cache(dyn, ninst, 1, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
i2 = x87_get_cache(dyn, ninst, 1, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
i3 = dyn->x87cache[i1];
|
||||
dyn->x87cache[i1] = dyn->x87cache[i2];
|
||||
dyn->x87cache[i2] = i3;
|
||||
// swap those too
|
||||
i1 = x87_get_neoncache(dyn, ninst, x1, x2, nextop&7);
|
||||
i2 = x87_get_neoncache(dyn, ninst, x1, x2, 0);
|
||||
i3 = dyn->n.neoncache[i1].v;
|
||||
dyn->n.neoncache[i1].v = dyn->n.neoncache[i2].v;
|
||||
dyn->n.neoncache[i2].v = i3;
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
@@ -85,78 +100,184 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("FCHS");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
VNEG_F64(v1, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
if(ST_IS_F(0)) {
|
||||
VNEG_F32(v1, v1);
|
||||
} else {
|
||||
VNEG_F64(v1, v1);
|
||||
}
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("FABS");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
VABS_F64(v1, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
if(ST_IS_F(0)) {
|
||||
VABS_F32(v1, v1);
|
||||
} else {
|
||||
VABS_F64(v1, v1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
INST_NAME("FTST");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
VCMP_F64_0(v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32_0(v1);
|
||||
} else {
|
||||
VCMP_F64_0(v1);
|
||||
}
|
||||
FCOM(x1, x2); // same flags...
|
||||
break;
|
||||
case 0xE5:
|
||||
INST_NAME("FXAM");
|
||||
#if 1
|
||||
i1 = x87_get_current_cache(dyn, ninst, 0, NEON_CACHE_ST_D);
|
||||
// value put in x14
|
||||
if(i1==-1) {
|
||||
// not in cache, so check Empty status and load it
|
||||
// x14 will be the actual top
|
||||
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
|
||||
i2 = -dyn->x87stack;
|
||||
if(i2) {
|
||||
if(i2<0) {
|
||||
SUB_IMM8(x14, x14, -i2);
|
||||
} else {
|
||||
ADD_IMM8(x14, x14, i2);
|
||||
}
|
||||
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
|
||||
}
|
||||
ADD_REG_LSL_IMM5(x1, xEmu, x14, 3);
|
||||
LDRD_IMM8(x2, x1, offsetof(x86emu_t, x87)); // load r2/r3 with ST0 anyway, for sign extraction
|
||||
ADD_REG_LSL_IMM5(x1, xEmu, x14, 2);
|
||||
LDR_IMM9(x1, x1, offsetof(x86emu_t, p_regs));
|
||||
CMPS_IMM8(x1, 0b11);
|
||||
MOVW_COND(cEQ, x14, 0b100000100000000); // empty: C3,C2,C0 = 101
|
||||
B_MARK3(cEQ);
|
||||
} else {
|
||||
// simply move from cache reg to r2/r3
|
||||
v1 = dyn->x87reg[i1];
|
||||
VMOVfrV_D(x2, x3, v1);
|
||||
}
|
||||
// get exponant in r1
|
||||
MOV_REG_LSR_IMM5(x1, x3, 20);
|
||||
MOVW(x14, 0x7ff);
|
||||
ANDS_REG_LSL_IMM5(x1, x1, x14, 0);
|
||||
B_MARK(cNE); // not zero or denormal
|
||||
BIC_IMM8_ROR(x1, x3, 0b10, 1); // remove sign bit
|
||||
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
MOVW_COND(cEQ, x14, 0b100000000000000); // Zero: C3,C2,C0 = 100
|
||||
MOVW_COND(cNE, x14, 0b100010000000000); // Denormal: C3,C2,C0 = 110
|
||||
B_MARK3(c__);
|
||||
MARK;
|
||||
CMPS_REG_LSL_IMM5(x1, x14, 0); // infinite/NaN?
|
||||
MOVW_COND(cNE, x14, 0b000010000000000); // normal: C3,C2,C0 = 010
|
||||
B_MARK3(cNE);
|
||||
ORR_IMM8(x1, x1, 0x08, 12); //prepare mask, 0x7ff | 0x800 => 0xfff
|
||||
BIC_REG_LSL_IMM5(x1, x3, x1, 20);
|
||||
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
MOVW_COND(cEQ, x14, 0b000010100000000); // infinity: C3,C2,C0 = 011
|
||||
MOVW_COND(cNE, x14, 0b000000100000000); // NaN: C3,C2,C0 = 001
|
||||
MARK3;
|
||||
// Extract signa & Update SW
|
||||
MOV_REG_LSR_IMM5(x1, x3, 31);
|
||||
BFI(x14, x1, 9, 1); //C1
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BIC_IMM8(x1, x1, 0b01000111, 12);
|
||||
ORR_REG_LSL_IMM5(x14, x14, x1, 0);
|
||||
STRH_IMM8(x14, xEmu, offsetof(x86emu_t, sw));
|
||||
#else
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_refresh(dyn, ninst, x1, x2, 0);
|
||||
CALL(fpu_fxam, -1, 0); // should be possible inline, but is it worth it?
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("FLD1");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_1));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_i_32(v1, 0b01110000);
|
||||
} else {
|
||||
VMOV_i_64(v1, 0b01110000);
|
||||
}
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FLDL2T");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_l2t));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_l2t));
|
||||
VLDR_32(v1, x2, 0);
|
||||
} else {
|
||||
MOV32(x2, (&d_l2t));
|
||||
VLDR_64(v1, x2, 0);
|
||||
}
|
||||
break;
|
||||
case 0xEA:
|
||||
INST_NAME("FLDL2E");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_l2e));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_l2e));
|
||||
VLDR_32(v1, x2, 0);
|
||||
} else {
|
||||
MOV32(x2, (&d_l2e));
|
||||
VLDR_64(v1, x2, 0);
|
||||
}
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("FLDPI");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_pi));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_pi));
|
||||
VLDR_32(v1, x2, 0);
|
||||
} else {
|
||||
MOV32(x2, (&d_pi));
|
||||
VLDR_64(v1, x2, 0);
|
||||
}
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("FLDLG2");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_lg2));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_lg2));
|
||||
VLDR_32(v1, x2, 0);
|
||||
} else {
|
||||
MOV32(x2, (&d_lg2));
|
||||
VLDR_64(v1, x2, 0);
|
||||
}
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("FLDLN2");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_ln2));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_ln2));
|
||||
VLDR_32(v1, x2, 0);
|
||||
} else {
|
||||
MOV32(x2, (&d_ln2));
|
||||
VLDR_64(v1, x2, 0);
|
||||
}
|
||||
break;
|
||||
case 0xEE:
|
||||
INST_NAME("FLDZ");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
MOV32(x2, (&d_0));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_8(v1/2, 0); // float is *2...
|
||||
} else {
|
||||
VMOV_8(v1, 0); // cannot use VMOV_i_F64
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFA:
|
||||
INST_NAME("FSQRT");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
VSQRT_F64(v1, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
if(ST_IS_F(0)) {
|
||||
VSQRT_F32(v1, v1);
|
||||
} else {
|
||||
VSQRT_F64(v1, v1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFC:
|
||||
INST_NAME("FRNDINT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
// use C helper for now, nothing staightforward is available
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_frndint, -1, 0);
|
||||
@@ -174,46 +295,64 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xF0:
|
||||
INST_NAME("F2XM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_f2xm1, -1, 0);
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("FYL2X");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2x, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
VMOV_64(0, v1); // prepare call to log2
|
||||
CALL_1D(log2, 0);
|
||||
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d)*ST(1).d
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FTAN");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_ftan, -1, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x3);
|
||||
MOV32(x2, (&d_1));
|
||||
VLDR_64(v1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
VMOV_64(0, v1); // prepare call to tan
|
||||
CALL_1D(tan, 0);
|
||||
VMOV_64(v1, 0);
|
||||
//emu->sw.f.F87_C2 = 0;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 10, 1); //C2 = 0
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
|
||||
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
|
||||
// and want 1.0 = 0x3ff0000000000000
|
||||
// so 00111111 11110000 00000000 00000000....
|
||||
// a = 0, b = 1, c = 1, d = 1, efgh=0
|
||||
// 0b01110000
|
||||
VMOV_i_64(v2, 0b01110000);
|
||||
break;
|
||||
case 0xF3:
|
||||
INST_NAME("FPATAN");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fpatan, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
VMOV_64(0, v2); // prepare call to atan2
|
||||
VMOV_64(1, v1);
|
||||
CALL_2D(atan2, 0);
|
||||
VMOV_64(v2, 0); //ST(1).d = atan2(ST1.d, ST0.d);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("FXTRACT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fxtract, -1, 0);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("FPREM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem1, -1, 0);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("FDECSTP");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
SUB_IMM8(x2, x2, 1);
|
||||
AND_IMM8(x2, x2, 7);
|
||||
@@ -221,7 +360,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xF7:
|
||||
INST_NAME("FINCSTP");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
ADD_IMM8(x2, x2, 1);
|
||||
AND_IMM8(x2, x2, 7);
|
||||
@@ -229,38 +368,69 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("FPREM");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem, -1, 0);
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("FYL2XP1");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2xp1, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
VMOV_i_64(0, 0b01110000); // D0 = 1.0
|
||||
VADD_F64(0, 0, v1); // prepare call to log2
|
||||
CALL_1D(log2, 0);
|
||||
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fsincos, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
|
||||
VMOV_64(0, v1);
|
||||
CALL_1D(sin, 0);
|
||||
VSWP(v1, 0);
|
||||
CALL_1D(cos, 0);
|
||||
VMOV_64(v2, 0);
|
||||
//emu->sw.f.F87_C2 = 0;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 10, 1); //C2 = 0
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("FSCALE");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fscale, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
//if(ST0.d!=0.0)
|
||||
// ST0.d *= exp2(trunc(ST1.d));
|
||||
VCMP_F64_0(v1);
|
||||
VMRS_APSR();
|
||||
B_NEXT(cEQ);
|
||||
VMOV_64(0, v2);
|
||||
CALL_1DD(trunc, exp2, 0);
|
||||
VMUL_F64(v1, v1, 0);
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("FSIN");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fsin, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
VMOV_64(0, v1); // prepare call to sin
|
||||
CALL_1D(sin, 0);
|
||||
VMOV_64(v1, 0);
|
||||
//emu->sw.f.F87_C2 = 0;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 10, 1); //C2 = 0
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
break;
|
||||
case 0xFF:
|
||||
INST_NAME("FCOS");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fcos, -1, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
VMOV_64(0, v1); // prepare call to cos
|
||||
CALL_1D(cos, 0);
|
||||
VMOV_64(v1, 0);
|
||||
//emu->sw.f.F87_C2 = 0;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 10, 1); //C2 = 0
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
break;
|
||||
|
||||
|
||||
@@ -289,45 +459,58 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD ST0, float[ED]");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
VCVT_F64_F32(v1, s0);
|
||||
if(!ST_IS_F(0)) {
|
||||
VCVT_F64_F32(v1, s0);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VCVT_F32_F64(s0, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else {
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VCVT_F32_F64(s0, v1);
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VSTR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
VMOVfrV(x2, s0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FSTP float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VCVT_F32_F64(s0, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else {
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VCVT_F32_F64(s0, v1);
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VSTR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
VMOVfrV(x2, s0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
@@ -335,8 +518,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
@@ -352,8 +536,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FNSTENV Ed");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
@@ -362,7 +547,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTCW Ew");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
ed = x1;
|
||||
wb1 = 1;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw));
|
||||
|
||||
@@ -52,10 +52,14 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC7:
|
||||
INST_NAME("FCMOVB ST0, STx");
|
||||
READFLAGS(X_CF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, 1<<F_CF);
|
||||
VMOVcond_64(cNE, v1, v2); // F_CF==1
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cNE, v1, v2); // F_CF==1
|
||||
} else {
|
||||
VMOVcond_64(cNE, v1, v2); // F_CF==1
|
||||
}
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -67,10 +71,14 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xCF:
|
||||
INST_NAME("FCMOVE ST0, STx");
|
||||
READFLAGS(X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, 1<<F_ZF);
|
||||
VMOVcond_64(cNE, v1, v2); // F_ZF==1
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cNE, v1, v2); // F_ZF==1
|
||||
} else {
|
||||
VMOVcond_64(cNE, v1, v2); // F_ZF==1
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -82,10 +90,14 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD7:
|
||||
INST_NAME("FCMOVBE ST0, STx");
|
||||
READFLAGS(X_CF|X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF));
|
||||
VMOVcond_64(cNE, v1, v2); // F_CF==1 | F_ZF==1
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cNE, v1, v2); // F_CF==1 | F_ZF==1
|
||||
} else {
|
||||
VMOVcond_64(cNE, v1, v2); // F_CF==1 | F_ZF==1
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
@@ -97,16 +109,24 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xDF:
|
||||
INST_NAME("FCMOVU ST0, STx");
|
||||
READFLAGS(X_PF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, 1<<F_PF);
|
||||
VMOVcond_64(cNE, v1, v2); // F_PF==1
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cNE, v1, v2); // F_PF==1
|
||||
} else {
|
||||
VMOVcond_64(cNE, v1, v2); // F_PF==1
|
||||
}
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FUCOMPP ST0, ST1");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
@@ -129,7 +149,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FIADD ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -139,7 +159,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FIMUL ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -149,7 +169,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FICOM ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -160,7 +180,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FICOMP ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -172,7 +192,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FISUB ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -182,7 +202,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FISUBR ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -192,7 +212,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FIDIV ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -202,7 +222,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FIDIVR ST0, Ed");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
GETED;
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
|
||||
@@ -50,10 +50,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC7:
|
||||
INST_NAME("FCMOVNB ST0, STx");
|
||||
READFLAGS(X_CF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, 1<<F_CF);
|
||||
VMOVcond_64(cEQ, v1, v2); // F_CF==0
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cEQ, v1, v2); // F_CF==0
|
||||
} else {
|
||||
VMOVcond_64(cEQ, v1, v2); // F_CF==0
|
||||
}
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -65,10 +69,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xCF:
|
||||
INST_NAME("FCMOVNE ST0, STx");
|
||||
READFLAGS(X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, 1<<F_ZF);
|
||||
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cEQ, v1, v2); // F_ZF==0
|
||||
} else {
|
||||
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -80,10 +88,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD7:
|
||||
INST_NAME("FCMOVNBE ST0, STx");
|
||||
READFLAGS(X_CF|X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF));
|
||||
VMOVcond_64(cEQ, v1, v2); // F_CF==0 & F_ZF==0
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cEQ, v1, v2); // F_CF==0 & F_ZF==0
|
||||
} else {
|
||||
VMOVcond_64(cEQ, v1, v2); // F_CF==0 & F_ZF==0
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
@@ -95,10 +107,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xDF:
|
||||
INST_NAME("FCMOVNU ST0, STx");
|
||||
READFLAGS(X_PF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
TSTS_IMM8(xFlags, 1<<F_PF);
|
||||
VMOVcond_64(cEQ, v1, v2); // F_PF==0
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVcond_32(cEQ, v1, v2); // F_PF==0
|
||||
} else {
|
||||
VMOVcond_64(cEQ, v1, v2); // F_PF==0
|
||||
}
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("FDISI8087_NOP"); // so.. NOP?
|
||||
@@ -113,7 +129,8 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("FNINIT");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
|
||||
CALL(reset_fpu, -1, 0);
|
||||
break;
|
||||
case 0xE8:
|
||||
@@ -126,9 +143,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMI ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
case 0xF0:
|
||||
@@ -141,9 +162,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF7:
|
||||
INST_NAME("FCOMI ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
|
||||
@@ -159,11 +184,11 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ed");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -173,12 +198,12 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -198,13 +223,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -223,13 +248,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FISTP Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -249,7 +274,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
|
||||
// the FLD is immediatly followed by an FSTP
|
||||
LDR_IMM9(x2, ed, 0);
|
||||
@@ -259,11 +284,12 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
|
||||
nextop = F8; //0xDB
|
||||
nextop = F8; //modrm
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
STR_IMM9(x2, ed, 0);
|
||||
STR_IMM9(x3, ed, 4);
|
||||
STRH_IMM8(x14, ed, 8);
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
@@ -273,8 +299,9 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FSTP tbyte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
|
||||
@@ -46,9 +46,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FADD STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VADD_F64(v1, v1, v2);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v1, v1, v2);
|
||||
} else {
|
||||
VADD_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -59,9 +63,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FMUL STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VMUL_F64(v1, v1, v2);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v1, v1, v2);
|
||||
} else {
|
||||
VMUL_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -72,9 +80,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCOM ST0, STx"); //yep
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
break;
|
||||
case 0xD8:
|
||||
@@ -86,9 +98,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
@@ -101,9 +117,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FSUBR STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VSUB_F64(v1, v2, v1);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v2, v1);
|
||||
} else {
|
||||
VSUB_F64(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -114,9 +134,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FSUB STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VSUB_F64(v1, v1, v2);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v1, v2);
|
||||
} else {
|
||||
VSUB_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -127,9 +151,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FDIVR STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VDIV_F64(v1, v2, v1);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v2, v1);
|
||||
} else {
|
||||
VDIV_F64(v1, v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -140,22 +168,26 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
INST_NAME("FDIV STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VDIV_F64(v1, v1, v2);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v1, v2);
|
||||
} else {
|
||||
VDIV_F64(v1, v1, v2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FADD ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -164,14 +196,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -180,14 +212,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -197,14 +229,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FCOMP ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -215,14 +247,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -231,14 +263,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -247,14 +279,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -263,14 +295,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
|
||||
@@ -31,6 +31,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int parity;
|
||||
uint8_t ed;
|
||||
int v1, v2;
|
||||
int i1, i2, i3;
|
||||
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
@@ -45,7 +46,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREE STx");
|
||||
break; // not handling Tag...
|
||||
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
MOVW(x1, nextop&7);
|
||||
CALL(fpu_do_free, -1, 0);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
@@ -55,9 +59,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FST ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VMOV_64(v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_32(v2, v1);
|
||||
} else {
|
||||
VMOV_64(v2, v1);
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("FSTP ST0, ST0");
|
||||
@@ -71,9 +79,18 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FSTP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VMOV_64(v2, v1);
|
||||
// copy the cache value for st0 to stx
|
||||
i1 = x87_get_cache(dyn, ninst, 0, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
i2 = x87_get_cache(dyn, ninst, 1, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
i3 = dyn->x87cache[i1];
|
||||
dyn->x87cache[i1] = dyn->x87cache[i2];
|
||||
dyn->x87cache[i2] = i3;
|
||||
// swap those too
|
||||
i1 = x87_get_neoncache(dyn, ninst, x1, x2, nextop&7);
|
||||
i2 = x87_get_neoncache(dyn, ninst, x1, x2, 0);
|
||||
i3 = dyn->n.neoncache[i1].v;
|
||||
dyn->n.neoncache[i1].v = dyn->n.neoncache[i2].v;
|
||||
dyn->n.neoncache[i2].v = i3;
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
@@ -86,9 +103,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FUCOM ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
break;
|
||||
case 0xE8:
|
||||
@@ -100,9 +121,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
@@ -138,41 +163,35 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD double");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
#if 0
|
||||
// can bus error...
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_64(v1, ed, fixedaddress);
|
||||
#else
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress + 4);
|
||||
VMOVtoV_D(v1, x2, x3);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP i64, ST0");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fistt64, -1, 0);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST double");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
VSTR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
VMOVfrV_D(x2, x3, v1);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -180,13 +199,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FSTP double");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
VSTR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
VMOVfrV_D(x2, x3, v1);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -195,28 +214,34 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_frstor, -1, 0);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FSAVE m108byte");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fsave, -1, 0);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0);
|
||||
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
|
||||
MOVW(x2, offsetof(x86emu_t, sw));
|
||||
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
|
||||
LDRH_IMM8(x3, x2, 0);
|
||||
BFI(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
|
||||
STRH_IMM8(x3, ed, 0); // store whole sw flags
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0, 0);
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
if(dyn->x87stack) {
|
||||
// update top
|
||||
if(dyn->x87stack>0) {
|
||||
SUB_IMM8(x2, x2, dyn->x87stack);
|
||||
} else {
|
||||
ADD_IMM8(x2, x2, -dyn->x87stack);
|
||||
}
|
||||
AND_IMM8(x2, x2, 7);
|
||||
}
|
||||
BFI(x1, x2, 11, 3); // inject top
|
||||
STRH_IMM8(x1, ed, 0); // store whole sw flags
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "x86trace.h"
|
||||
#include "dynarec_arm.h"
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "arm_printer.h"
|
||||
|
||||
#include "dynarec_arm_helper.h"
|
||||
@@ -40,9 +41,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FADDP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VADD_F64(v2, v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v2, v2, v1);
|
||||
} else {
|
||||
VADD_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xC8:
|
||||
@@ -54,9 +59,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FMULP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VMUL_F64(v2, v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v2, v2, v1);
|
||||
} else {
|
||||
VMUL_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD0:
|
||||
@@ -68,18 +77,26 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xD9:
|
||||
INST_NAME("FCOMPP ST0, ST1");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, 1));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, 1));
|
||||
if(ST_IS_F(0)) {
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
@@ -93,9 +110,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FSUBRP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VSUB_F64(v2, v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v2, v1, v2);
|
||||
} else {
|
||||
VSUB_F64(v2, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE8:
|
||||
@@ -107,9 +128,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FSUBP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VSUB_F64(v2, v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v2, v2, v1);
|
||||
} else {
|
||||
VSUB_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
@@ -121,9 +146,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FDIVRP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VDIV_F64(v2, v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v2, v1, v2);
|
||||
} else {
|
||||
VDIV_F64(v2, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF8:
|
||||
@@ -135,9 +164,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
INST_NAME("FDIVP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VDIV_F64(v2, v2, v1);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v2, v2, v1);
|
||||
} else {
|
||||
VDIV_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
|
||||
+203
-32
@@ -31,13 +31,15 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int32_t j32;
|
||||
uint8_t wback;
|
||||
uint8_t ed;
|
||||
int v1, v2;
|
||||
int v0, v1, v2;
|
||||
int s0;
|
||||
int fixedaddress;
|
||||
int parity;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
@@ -58,6 +60,15 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FNSTSW AX");
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
if(dyn->x87stack) {
|
||||
// update top
|
||||
if(dyn->x87stack>0) {
|
||||
SUB_IMM8(x2, x2, dyn->x87stack);
|
||||
} else {
|
||||
ADD_IMM8(x2, x2, -dyn->x87stack);
|
||||
}
|
||||
AND_IMM8(x2, x2, 7);
|
||||
}
|
||||
BFI(x1, x2, 11, 3); // inject top
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -71,9 +82,14 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMIP ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0))
|
||||
{
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
@@ -87,9 +103,14 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF7:
|
||||
INST_NAME("FCOMIP ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0))
|
||||
{
|
||||
VCMP_F32(v1, v2);
|
||||
} else {
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
@@ -140,17 +161,22 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ew");
|
||||
v1 = x87_do_push(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
LDRSH_IMM8(x1, wback, fixedaddress);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, x1);
|
||||
VCVT_F64_S32(v1, s0);
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVtoV(v1, x1);
|
||||
VCVT_F32_S32(v1, v1);
|
||||
} else {
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, x1);
|
||||
VCVT_F64_S32(v1, s0);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
@@ -159,7 +185,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
if(ST_IS_F(0)) {
|
||||
VCVTR_S32_F32(s0, v1);
|
||||
} else {
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
}
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMOVfrV(ed, s0);
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
@@ -172,9 +202,9 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
@@ -182,7 +212,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
if(ST_IS_F(0)) {
|
||||
VCVTR_S32_F32(s0, v1);
|
||||
} else {
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
}
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMOVfrV(ed, s0);
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
@@ -194,9 +228,9 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FISTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
@@ -204,7 +238,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
if(ST_IS_F(0)) {
|
||||
VCVTR_S32_F32(s0, v1);
|
||||
} else {
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
}
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMOVfrV(ed, s0);
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
@@ -217,32 +255,165 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FBLD ST0, tbytes");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(fpu_fbld, -1, 0);
|
||||
break;
|
||||
case 5: // could be inlined for most thing, but is it usefull?
|
||||
case 5:
|
||||
INST_NAME("FILD ST0, i64");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fild64, -1, 0);
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0);
|
||||
if(parity) {
|
||||
LDRD_IMM8(x2, wback, 0); // x2/x3 is 64bits
|
||||
} else {
|
||||
LDR_IMM9(x2, wback, 0);
|
||||
LDR_IMM9(x3, wback, 4);
|
||||
}
|
||||
if(ninst<dyn->size
|
||||
&& dyn->insts[ninst+1].x86.addr
|
||||
&& *(uint8_t*)dyn->insts[ninst+1].x86.addr==0xDF
|
||||
&& (((*(uint8_t*)(dyn->insts[ninst+1].x86.addr+1))>>3)&7)==7)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Hack for FILD/FISTP i64");
|
||||
} else {
|
||||
// Save xFlags to use it as scratch...
|
||||
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
// set STll(0).ll=i64 and ref=ST(0).q later (emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top])
|
||||
// get TOP
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, top));
|
||||
int a = 0 - dyn->x87stack;
|
||||
if(a<0) {
|
||||
SUB_IMM8(xFlags, xFlags, -a);
|
||||
AND_IMM8(xFlags, xFlags, 7);
|
||||
} else if(a>0) {
|
||||
ADD_IMM8(xFlags, xFlags, a);
|
||||
AND_IMM8(xFlags, xFlags, 7);
|
||||
}
|
||||
ADD_REG_LSL_IMM5(xFlags, xEmu, xFlags, 4); // each fpu_ll is 2 int64: ref than ll
|
||||
ADD_IMM8_ROR(xFlags, xFlags, offsetof(x86emu_t, fpu_ll)>>2, 15);
|
||||
STRD_IMM8(x2, xFlags, 8); // save ll
|
||||
// continue with conversion
|
||||
MOVS_REG_LSR_IMM5(x14, x3, 31); // x14 is sign bit
|
||||
B_MARK(cEQ); // no NEG is no sign bit
|
||||
RSBS_IMM8(x2, x2, 0);
|
||||
RSC_IMM8(x3, x3, 0);
|
||||
MARK;
|
||||
VMOVtoV(s0, x3);
|
||||
VCVT_F64_U32(v1, s0);
|
||||
VEOR(v2, v2, v2);
|
||||
MOVW(x1, 0x41F0);
|
||||
VMOVtoDx_16(v2, 3, x1);
|
||||
VMUL_F64(v1, v1, v2); // v1 = double high part of i64
|
||||
VMOVtoV(s0, x2);
|
||||
VCVT_F64_U32(v2, s0);
|
||||
VADD_F64(v1, v1, v2);
|
||||
TSTS_IMM8(x14, 1);
|
||||
VNEG_F64_cond(cNE, v1, v1);
|
||||
VST1_64(v1, xFlags); // Store STll(0).ref
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FBSTP tbytes, ST0");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(fpu_fbst, -1, 0);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 7: // could be inlined for most thing, but is it usefull?
|
||||
INST_NAME("FISTP i64, ST0");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fistp64, -1, 0);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ninst
|
||||
&& dyn->insts[ninst-1].x86.addr
|
||||
&& *(uint8_t*)dyn->insts[ninst-1].x86.addr==0xDF
|
||||
&& (((*(uint8_t*)(dyn->insts[ninst-1].x86.addr+1))>>3)&7)==5)
|
||||
{
|
||||
if(parity) {
|
||||
STRD_IMM8(x2, ed, 0); // x2/x3 is 64bits
|
||||
} else {
|
||||
STR_IMM9(x2, ed, 0);
|
||||
STR_IMM9(x3, ed, 4);
|
||||
}
|
||||
} else {
|
||||
#if 0
|
||||
v1 = x87_get_st(dyn, ninst, x2, x3, 0);
|
||||
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
// check STll(0).ref==ST(0).q so emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top]
|
||||
// get TOP
|
||||
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
|
||||
int a = 0 - dyn->x87stack;
|
||||
if(a<0) {
|
||||
SUB_IMM8(x14, x14, -a);
|
||||
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
|
||||
} else if(a>0) {
|
||||
ADD_IMM8(x14, x14, a);
|
||||
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
|
||||
}
|
||||
ADD_REG_LSL_IMM5(x14, xEmu, x14, 4); // each fpu_ll is 2 int64: ref than ll
|
||||
MOVW(x2, offsetof(x86emu_t, fpu_ll)); //can be optimized?
|
||||
ADD_REG_LSL_IMM5(x14, x14, x2, 0);
|
||||
VLDR_64(v2, x14, 0);
|
||||
VCEQ_32(v2, v2, v1); // compare
|
||||
VMOVfrV_D(x2, x3, v2);
|
||||
ANDS_REG_LSL_IMM5(x2, x2, x3, 0); // if NE then values are the same!
|
||||
B_MARK(cEQ); // do the i64 conversion
|
||||
// memcpy(ed, &STll(0).ll, sizeof(int64_t));
|
||||
LDRD_IMM8(x2, x14, 8); // load ll
|
||||
B_MARK3(c__);
|
||||
MARK;
|
||||
VEOR(v0, v0, v0);
|
||||
MOVW(x2, 0x41F0);
|
||||
VMOVtoDx_16(v0, 3, x2); // V0 = (1<<32) as double
|
||||
VMOVfrDx_32(x14, v1, 1); // get high part to extract sign
|
||||
VABS_F64(v1 ,v1); //ST0 will be poped, so lost...
|
||||
VDIV_F64(v2, v1, v0); // v2 = abs(ST0)/(1<<32) : so 32 bits high part
|
||||
MSR_nzcvq_0();
|
||||
VMRS(x2); // get fpscr
|
||||
ORR_IMM8(x3, x2, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVT_U32_F64(s0, v2); // convert high part to U32
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMSR(x2); // put back fpscr
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
B_MARK2(cEQ); // not overflow...
|
||||
MARKLOCK;
|
||||
MOV_IMM(x3, 0b10, 1); // 0x80000000
|
||||
MOVW(x2, 0);
|
||||
B_MARK3(c__);
|
||||
MARK2; // continue conversion, it fits an int64!
|
||||
VCVT_F64_U32(v2, s0); // int part now
|
||||
VMLS_F64(v1, v2, v0); // compute low part
|
||||
VMOVfrV(x3, s0); // transfert high path
|
||||
TSTS_IMM8_ROR(x14, 0b10, 1); // test high part with 0x800000000
|
||||
B_MARKLOCK(cNE); // int overflow...
|
||||
VCVT_U32_F64(s0, v1); // convert low part
|
||||
VMOVfrV(x2, s0); // transfert low part
|
||||
TSTS_IMM8_ROR(x14, 0b10, 1); // 0x800000000
|
||||
B_MARK3(cEQ);
|
||||
RSBS_IMM8(x2, x2, 0); // NEG(i64)
|
||||
RSC_IMM8(x3, x3, 0);
|
||||
MARK3;
|
||||
STR_IMM9(x2, x1, 0);
|
||||
STR_IMM9(x3, x1, 4);
|
||||
#else
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x2, x3, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fistp64, -1, 0);
|
||||
#endif
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -76,7 +76,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// emit ADD32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(s1==xESP && (!dyn->insts || dyn->insts[ninst].x86.need_flags==X_PEND))
|
||||
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
|
||||
{
|
||||
// special case when doing math on ESP and only PEND is needed: ignoring it!
|
||||
if(c>=0 && c<256) {
|
||||
@@ -210,7 +210,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(s1==xESP && (!dyn->insts || dyn->insts[ninst].x86.need_flags==X_PEND))
|
||||
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
|
||||
{
|
||||
// special case when doing math on ESP and only PEND is needed: ignoring it!
|
||||
if(c>=0 && c<256) {
|
||||
|
||||
@@ -282,6 +282,8 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
@@ -313,6 +315,8 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
@@ -432,7 +436,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
UBFX(s3, s2, 0, 1);
|
||||
UBFX(s3, s1, (31-c), 1);
|
||||
XOR_IMM8_COND(cCS, s3, s3, 1);
|
||||
BFI(xFlags, s3, F_OF, 1);
|
||||
} else {
|
||||
@@ -460,3 +464,131 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHRD32 instruction, from s1, fill s2 , shift s3, store result in s1 using s4 and s3 as scratch
|
||||
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
int j32;
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
// same flags calc as shr32
|
||||
SET_DF(s4, d_shr32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
CMPS_IMM8(s3, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9_COND(cEQ, s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
B_NEXT(cEQ);
|
||||
|
||||
IFX(X_CF) {
|
||||
MOVS_REG_LSR_REG(s1, s1, s3);
|
||||
} else {
|
||||
MOV_REG_LSR_REG(s1, s1, s3);
|
||||
}
|
||||
IFX(X_ZF|X_CF) {
|
||||
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
|
||||
}
|
||||
RSB_IMM8(s3, s3, 32);
|
||||
IFX(X_ZF) {
|
||||
ORRS_REG_LSL_REG(s1, s1, s2, s3);
|
||||
} else {
|
||||
ORR_REG_LSL_REG(s1, s1, s2, s3);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s3, 31); // 32-c
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit ROL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_rol8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(!c) {
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(c&7) {
|
||||
BFI(s1, s1, 24, 8); // duplicate the value for rotate left
|
||||
MOV_REG_ROR_IMM5(s1, s1, 32-(c&7));
|
||||
}
|
||||
//AND_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_CF) {
|
||||
BFI(xFlags, s1, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
ADD_REG_LSR_IMM5(s3, s1, s1, 7);
|
||||
BFI(xFlags, s3, F_OF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit ROR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_ror8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(!c) {
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(c&7) {
|
||||
BFI(s1, s1, 8, 8); // duplicate the value for Rotate right
|
||||
MOV_REG_ROR_IMM5(s1, s1, c&7);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
AND_IMM8(s1, s1, 0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOV_REG_LSR_IMM5(s3, s1, 7);
|
||||
BFI(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 6);
|
||||
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,8 +326,12 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
|
||||
MOV32(s4, GetParityTab());
|
||||
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
|
||||
AND_REG_LSL_IMM5(s3, s1, s2, 0);
|
||||
AND_IMM8(s3, s3, 31);
|
||||
if(s1==s2) {
|
||||
AND_IMM8(s3, s1, 31);
|
||||
} else {
|
||||
AND_REG_LSL_IMM5(s3, s1, s2, 0);
|
||||
AND_IMM8(s3, s3, 31);
|
||||
}
|
||||
MVN_REG_LSR_REG(s4, s4, s3);
|
||||
BFI(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
|
||||
+320
-192
File diff suppressed because it is too large.
Load diff
@@ -23,17 +23,17 @@
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
|
||||
#define GETEX(a) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7); \
|
||||
#define GETEX(a, w) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7,w);\
|
||||
} else { \
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3); \
|
||||
a = fpu_get_scratch_double(dyn); \
|
||||
if(parity) { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0); \
|
||||
VLDR_64(a, ed, fixedaddress); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);\
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);\
|
||||
LDR_IMM9(x2, ed, fixedaddress+0); \
|
||||
LDR_IMM9(x3, ed, fixedaddress+4); \
|
||||
VMOVtoV_D(a, x2, x3); \
|
||||
@@ -64,12 +64,12 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0, d0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -80,13 +80,13 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSD Ex, Gx");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
VMOVD(d0, v0);
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
@@ -96,12 +96,12 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, d0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -113,7 +113,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("CVTSI2SD Gx, Ed");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETED;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
@@ -126,9 +126,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
VLDR_64(d0, ed, fixedaddress);
|
||||
}
|
||||
@@ -142,9 +142,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
VLDR_64(d0, ed, fixedaddress);
|
||||
}
|
||||
@@ -157,8 +157,8 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("SQRTSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
VSQRT_F64(v0, d0);
|
||||
break;
|
||||
|
||||
@@ -166,46 +166,48 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("ADDSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
VADD_F64(v0, v0, d0);
|
||||
break;
|
||||
case 0x59:
|
||||
INST_NAME("MULSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
VMUL_F64(v0, v0, d0);
|
||||
break;
|
||||
case 0x5A:
|
||||
INST_NAME("CVTSD2SS Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VCVT_F32_F64(s0, d0);
|
||||
VMOV_64(d1, v0);
|
||||
VMOV_32(d1*2, s0);
|
||||
VMOV_64(v0, d1);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
if(v0<16) {
|
||||
VCVT_F32_F64(v0*2, d0);
|
||||
} else {
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
VMOV_64(d1, v0);
|
||||
VCVT_F32_F64(d1*2, d0);
|
||||
VMOV_64(v0, d1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x5C:
|
||||
INST_NAME("SUBSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
VSUB_F64(v0, v0, d0);
|
||||
break;
|
||||
case 0x5D:
|
||||
INST_NAME("MINSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
|
||||
VCMP_F64(v0, d0);
|
||||
VMRS_APSR();
|
||||
@@ -215,16 +217,16 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("DIVSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
VDIV_F64(v0, v0, d0);
|
||||
break;
|
||||
case 0x5F:
|
||||
INST_NAME("MAXSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
|
||||
VCMP_F64(d0, v0);
|
||||
VMRS_APSR();
|
||||
@@ -235,11 +237,11 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("PSHUFLW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -270,11 +272,11 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("HADDPS Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -290,24 +292,20 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("CMPSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(d0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETEX(d0, 0);
|
||||
u8 = F8;
|
||||
if((u8&7)==6){
|
||||
VCMP_F64(d0, v0);
|
||||
} else {
|
||||
VCMP_F64(v0, d0);
|
||||
}
|
||||
VCMP_F64(v0, d0);
|
||||
VMRS_APSR();
|
||||
MOVW(x2, 0);
|
||||
switch(u8&7) {
|
||||
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
|
||||
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); break; // Less than
|
||||
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); break; // Less or equal
|
||||
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
|
||||
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
|
||||
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
|
||||
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
|
||||
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
|
||||
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
|
||||
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
|
||||
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
|
||||
}
|
||||
VMOVtoV_D(v0, x2, x2);
|
||||
@@ -318,12 +316,12 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
// Get Ex as a single, not a quad, with b a intermediary double
|
||||
#define GETEX(a, b) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
b = sse_get_reg(dyn, ninst, x1, nextop&7); \
|
||||
#define GETEX(a, b) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
b = sse_get_reg(dyn, ninst, x1, nextop&7,0);\
|
||||
if(b<16) \
|
||||
a = b; \
|
||||
else { \
|
||||
@@ -38,7 +38,7 @@
|
||||
a = b*2; \
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2); \
|
||||
if(parity) { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0); \
|
||||
VLDR_32(a, ed, fixedaddress); \
|
||||
} else { \
|
||||
GETED; \
|
||||
@@ -46,9 +46,9 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define GETGX(a) \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd)
|
||||
#define GETGX(a, w) \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
|
||||
|
||||
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
@@ -78,8 +78,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
else {
|
||||
@@ -98,7 +98,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
|
||||
VEORQ(v0, v0, v0);
|
||||
VMOVtoDx_32(v0, 0, x2);
|
||||
@@ -108,9 +108,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSS Ex, Gx");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
else {
|
||||
@@ -129,7 +129,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
} else {
|
||||
VMOVfrDx_32(x2, v0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -138,9 +138,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q1, ed);
|
||||
}
|
||||
@@ -154,9 +154,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q1, ed);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("CVTSI2SS Gx, Ed");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
GETED;
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
@@ -203,7 +203,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
else {
|
||||
@@ -214,10 +214,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
@@ -232,7 +232,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
else {
|
||||
@@ -243,10 +243,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
@@ -259,7 +259,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x51:
|
||||
INST_NAME("SQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -279,7 +279,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -307,7 +307,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x53:
|
||||
INST_NAME("RCPSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -330,7 +330,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x58:
|
||||
INST_NAME("ADDSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -350,7 +350,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x59:
|
||||
INST_NAME("MULSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -370,7 +370,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x5A:
|
||||
INST_NAME("CVTSS2SD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s0, d0);
|
||||
VCVT_F64_F32(v0, s0);
|
||||
break;
|
||||
@@ -378,9 +378,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("CVTTPS2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -391,7 +391,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x5C:
|
||||
INST_NAME("SUBSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -411,7 +411,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x5D:
|
||||
INST_NAME("MINSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -434,7 +434,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x5E:
|
||||
INST_NAME("DIVSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -454,7 +454,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x5F:
|
||||
INST_NAME("MAXSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -480,12 +480,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -498,11 +498,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("PSHUFHW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -534,12 +534,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
VLD1_64(v0, ed);
|
||||
}
|
||||
VEOR(v0+1, v0+1, v0+1);
|
||||
@@ -548,13 +548,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVDQU Ex,Gx");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -566,11 +565,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
|
||||
case 0xBC:
|
||||
INST_NAME("TZCNT Gd, Ed");
|
||||
SETFLAGS(X_CF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x3);
|
||||
nextop = F8;
|
||||
GETED;
|
||||
GETGD;
|
||||
SET_DFNONE(x3);
|
||||
TSTS_REG_LSL_IMM5(ed, ed, 0);
|
||||
MOVW_COND(cEQ, x3, 1);
|
||||
MOVW_COND(cNE, x3, 0);
|
||||
@@ -586,7 +585,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0xC2:
|
||||
INST_NAME("CMPSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETGX(v0, 1);
|
||||
GETEX(s1, v1);
|
||||
if(v0==v1)
|
||||
d0 = s1/2;
|
||||
@@ -599,21 +598,17 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
s0 = d0*2;
|
||||
u8 = F8;
|
||||
if((u8&7)==6){
|
||||
VCMP_F32(s1, s0);
|
||||
} else {
|
||||
VCMP_F32(s0, s1);
|
||||
}
|
||||
VCMP_F32(s0, s1);
|
||||
VMRS_APSR();
|
||||
MOVW(x2, 0);
|
||||
switch(u8&7) {
|
||||
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
|
||||
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); break; // Less than
|
||||
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); break; // Less or equal
|
||||
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
|
||||
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
|
||||
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
|
||||
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
|
||||
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
|
||||
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
|
||||
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered
|
||||
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
|
||||
}
|
||||
VMOVtoDx_32(v0, 0, x2);
|
||||
@@ -623,7 +618,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("CVTDQ2PD Gx, Ex");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v1<16)
|
||||
v0 = v1;
|
||||
else {
|
||||
@@ -634,10 +629,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
#include "dynarec_arm.h"
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "bridge.h"
|
||||
|
||||
void arm_fstp(x86emu_t* emu, void* p)
|
||||
{
|
||||
if(ST0.q!=STld(0).ref)
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, p);
|
||||
else
|
||||
memcpy(p, &STld(0).ld, 10);
|
||||
@@ -50,6 +51,7 @@ void arm_fyl2x(x86emu_t* emu)
|
||||
void arm_ftan(x86emu_t* emu)
|
||||
{
|
||||
ST0.d = tan(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
void arm_fpatan(x86emu_t* emu)
|
||||
{
|
||||
@@ -71,31 +73,15 @@ void arm_fprem(x86emu_t* emu)
|
||||
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
|
||||
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
|
||||
}
|
||||
void arm_fyl2xp1(x86emu_t* emu)
|
||||
{
|
||||
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
|
||||
}
|
||||
void arm_fsincos(x86emu_t* emu)
|
||||
{
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
}
|
||||
void arm_frndint(x86emu_t* emu)
|
||||
{
|
||||
ST0.d = fpu_round(emu, ST0.d);
|
||||
}
|
||||
void arm_fscale(x86emu_t* emu)
|
||||
{
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
}
|
||||
void arm_fsin(x86emu_t* emu)
|
||||
{
|
||||
ST0.d = sin(ST0.d);
|
||||
}
|
||||
void arm_fcos(x86emu_t* emu)
|
||||
{
|
||||
ST0.d = cos(ST0.d);
|
||||
}
|
||||
|
||||
void arm_fbld(x86emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
fpu_fbld(emu, ed);
|
||||
@@ -106,8 +92,8 @@ void arm_fild64(x86emu_t* emu, int64_t* ed)
|
||||
int64_t tmp;
|
||||
memcpy(&tmp, ed, sizeof(tmp));
|
||||
ST0.d = tmp;
|
||||
STll(0).ll = tmp;
|
||||
STll(0).ref = ST0.q;
|
||||
STll(0).sq = tmp;
|
||||
STll(0).sref = ST0.sq;
|
||||
}
|
||||
|
||||
void arm_fbstp(x86emu_t* emu, uint8_t* ed)
|
||||
@@ -118,8 +104,8 @@ void arm_fbstp(x86emu_t* emu, uint8_t* ed)
|
||||
void arm_fistp64(x86emu_t* emu, int64_t* ed)
|
||||
{
|
||||
// used of memcpy to avoid aligments issues
|
||||
if(STll(0).ref==ST(0).q) {
|
||||
memcpy(ed, &STll(0).ll, sizeof(int64_t));
|
||||
if(STll(0).sref==ST(0).sq) {
|
||||
memcpy(ed, &STll(0).sq, sizeof(int64_t));
|
||||
} else {
|
||||
int64_t tmp;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
@@ -141,7 +127,7 @@ void arm_fld(x86emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
memcpy(&STld(0).ld, ed, 10);
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
STld(0).ref = ST0.q;
|
||||
STld(0).uref = ST0.q;
|
||||
}
|
||||
|
||||
void arm_ud(x86emu_t* emu)
|
||||
@@ -204,7 +190,7 @@ int fpu_get_scratch_quad(dynarec_arm_t* dyn)
|
||||
if(dyn->fpu_extra_qscratch) {
|
||||
dynarec_log(LOG_NONE, "Warning, Extra QScratch slot taken and need another one!\n");
|
||||
} else
|
||||
dyn->fpu_extra_qscratch = fpu_get_reg_quad(dyn);
|
||||
dyn->fpu_extra_qscratch = fpu_get_reg_quad(dyn, NEON_CACHE_SCR, 0);
|
||||
return dyn->fpu_extra_qscratch;
|
||||
}
|
||||
int i = (dyn->fpu_scratch+3)&(~3);
|
||||
@@ -220,14 +206,15 @@ void fpu_reset_scratch(dynarec_arm_t* dyn)
|
||||
dyn->fpu_extra_qscratch = 0;
|
||||
}
|
||||
}
|
||||
#define FPUFIRST 8
|
||||
// Get a FPU double reg
|
||||
int fpu_get_reg_double(dynarec_arm_t* dyn)
|
||||
int fpu_get_reg_double(dynarec_arm_t* dyn, unsigned int t, unsigned int n)
|
||||
{
|
||||
// TODO: check upper limit?
|
||||
int i=0;
|
||||
while (dyn->fpuused[i]) ++i;
|
||||
dyn->fpuused[i] = 1;
|
||||
dyn->n.neoncache[i].n = n;
|
||||
dyn->n.neoncache[i].t = t;
|
||||
return i+FPUFIRST; // return a Dx
|
||||
}
|
||||
// Free a FPU double reg
|
||||
@@ -236,13 +223,19 @@ void fpu_free_reg_double(dynarec_arm_t* dyn, int reg)
|
||||
// TODO: check upper limit?
|
||||
int i=reg-FPUFIRST;
|
||||
dyn->fpuused[i] = 0;
|
||||
if(dyn->n.neoncache[i].t!=NEON_CACHE_ST_F && dyn->n.neoncache[i].t!=NEON_CACHE_ST_D)
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
}
|
||||
// Get a FPU quad reg
|
||||
int fpu_get_reg_quad(dynarec_arm_t* dyn)
|
||||
int fpu_get_reg_quad(dynarec_arm_t* dyn, unsigned int t, unsigned int n)
|
||||
{
|
||||
int i=0;
|
||||
while (dyn->fpuused[i] || dyn->fpuused[i+1]) i+=2;
|
||||
dyn->fpuused[i] = dyn->fpuused[i+1] = 1;
|
||||
dyn->n.neoncache[i].t = t;
|
||||
dyn->n.neoncache[i].n = n;
|
||||
dyn->n.neoncache[i+1].t = t;
|
||||
dyn->n.neoncache[i+1].n = n;
|
||||
return i+FPUFIRST; // Return a Dx, not a Qx
|
||||
}
|
||||
// Free a FPU quad reg
|
||||
@@ -250,13 +243,164 @@ void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
|
||||
{
|
||||
int i=reg-FPUFIRST;
|
||||
dyn->fpuused[i] = dyn->fpuused[i+1] = 0;
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
dyn->n.neoncache[i+1].v = 0;
|
||||
}
|
||||
// Reset fpu regs counter
|
||||
void fpu_reset_reg(dynarec_arm_t* dyn)
|
||||
{
|
||||
dyn->fpu_reg = 0;
|
||||
for (int i=0; i<24; ++i)
|
||||
for (int i=0; i<24; ++i) {
|
||||
dyn->fpuused[i]=0;
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
if(!dyn->insts)
|
||||
return NEON_CACHE_ST_D;
|
||||
for(int i=0; i<24; ++i)
|
||||
if((dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a)
|
||||
return dyn->insts[ninst].n.neoncache[i].t;
|
||||
// not in the cache yet, so will be fetched...
|
||||
return NEON_CACHE_ST_D;
|
||||
}
|
||||
|
||||
int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
(void)ninst;
|
||||
if(!dyn->insts)
|
||||
return NEON_CACHE_ST_D;
|
||||
for(int i=0; i<24; ++i)
|
||||
if((dyn->n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
|| dyn->n.neoncache[i].t==NEON_CACHE_ST_D)
|
||||
&& dyn->n.neoncache[i].n==a)
|
||||
return dyn->n.neoncache[i].t;
|
||||
// not in the cache yet, so will be fetched...
|
||||
return NEON_CACHE_ST_D;
|
||||
}
|
||||
|
||||
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a, int st)
|
||||
{
|
||||
if(a+dyn->insts[ninst].n.stack_next-st<0)
|
||||
// The STx has been pushed at the end of instructon, so stop going back
|
||||
return -1;
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a+dyn->insts[ninst].n.stack-st)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a, int st)
|
||||
{
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
&& dyn->insts[ninst].n.neoncache[i].n==a+dyn->insts[ninst].n.stack-st)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a, int st)
|
||||
{
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].t==NEON_CACHE_ST_F
|
||||
&& dyn->n.neoncache[i].n==a+dyn->n.stack-st)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st);
|
||||
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st);
|
||||
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
|
||||
{
|
||||
if(a == dyn->insts[ninst].n.combined1) {
|
||||
int i = neoncache_get_st_f_noback(dyn, ninst, dyn->insts[ninst].n.combined2, st);
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined2 %d i=%d\n", ninst, dyn->insts[ninst].n.combined2 ,i);
|
||||
if(i>=0) {
|
||||
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
|
||||
neoncache_promote_double_internal(dyn, ninst-1, maxinst, dyn->insts[ninst].n.combined2, st);
|
||||
// go forward is combined is not pop'd
|
||||
if(dyn->insts[ninst].n.stack_next-dyn->insts[ninst].n.stack<=dyn->insts[ninst].n.combined2)
|
||||
neoncache_promote_double_forward(dyn, ninst+1, maxinst, dyn->insts[ninst].n.combined2, st);
|
||||
}
|
||||
} else if(a == dyn->insts[ninst].n.combined2) {
|
||||
int i = neoncache_get_st_f_noback(dyn, ninst, dyn->insts[ninst].n.combined1, st);
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined1 %d i=%d\n", ninst, dyn->insts[ninst].n.combined1 ,i);
|
||||
if(i>=0) {
|
||||
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
|
||||
neoncache_promote_double_internal(dyn, ninst-1, maxinst, dyn->insts[ninst].n.combined1, st);
|
||||
// go forward is combined is not pop'd
|
||||
if(dyn->insts[ninst].n.stack_next-dyn->insts[ninst].n.stack<=dyn->insts[ninst].n.combined1)
|
||||
neoncache_promote_double_forward(dyn, ninst+1, maxinst, dyn->insts[ninst].n.combined1, st);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
|
||||
{
|
||||
while(ninst>=0) {
|
||||
int i = neoncache_get_st_f(dyn, ninst, a, st);
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d/%d, i=%d\n", ninst, a, st, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
|
||||
if(i<0) return;
|
||||
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
|
||||
a+=dyn->insts[ninst].n.stack-st; // adjust STx
|
||||
st = dyn->insts[ninst].n.stack; // new stack depth
|
||||
// check combined propagation too
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d/%d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, st, dyn->insts[ninst].n.stack);
|
||||
neoncache_promote_double_combined(dyn, ninst, maxinst, a, st);
|
||||
}
|
||||
--ninst;
|
||||
}
|
||||
}
|
||||
|
||||
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
|
||||
{
|
||||
while(ninst<maxinst) {
|
||||
int i = neoncache_get_st_f_noback(dyn, ninst, a, st);
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d/%d, i=%d\n", ninst, a, st, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
|
||||
if(i<0) return;
|
||||
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
|
||||
a+=dyn->insts[ninst].n.stack-st; // adjust STx
|
||||
st = dyn->insts[ninst].n.stack; // new stack depth
|
||||
// check combined propagation too
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d/%d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, st, dyn->insts[ninst].n.stack);
|
||||
neoncache_promote_double_combined(dyn, ninst, maxinst, a, st);
|
||||
}
|
||||
++ninst;
|
||||
}
|
||||
neoncache_promote_double(dyn, ninst, a, st);
|
||||
}
|
||||
|
||||
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a, int st)
|
||||
{
|
||||
int i = neoncache_get_current_st_f(dyn, a, st);
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d/%d i=%d\n", ninst, a, st, dyn->n.stack, i);
|
||||
if(i<0) return;
|
||||
dyn->n.neoncache[i].t = NEON_CACHE_ST_D;
|
||||
a+=dyn->n.stack-st;
|
||||
st = dyn->n.stack;
|
||||
// check combined propagation too
|
||||
if(dyn->n.combined1 || dyn->n.combined2) {
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
|
||||
if(dyn->n.combined1 == a)
|
||||
neoncache_promote_double(dyn, ninst, dyn->n.combined2, st);
|
||||
else if(dyn->n.combined2 == a)
|
||||
neoncache_promote_double(dyn, ninst, dyn->n.combined1, st);
|
||||
}
|
||||
if(!ninst) return;
|
||||
neoncache_promote_double_internal(dyn, ninst-1, ninst, a, st);
|
||||
}
|
||||
|
||||
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b)
|
||||
{
|
||||
dyn->n.combined1=a;
|
||||
dyn->n.combined2=b;
|
||||
if( neoncache_get_current_st(dyn, ninst, a)==NEON_CACHE_ST_F
|
||||
&& neoncache_get_current_st(dyn, ninst, b)==NEON_CACHE_ST_F )
|
||||
return NEON_CACHE_ST_F;
|
||||
return NEON_CACHE_ST_D;
|
||||
}
|
||||
|
||||
#define F8 *(uint8_t*)(addr++)
|
||||
@@ -336,7 +480,7 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
|
||||
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = *(uint32_t*)a1;
|
||||
addr = (uintptr_t)getAlternate(*(void**)a1);
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
return 0;
|
||||
|
||||
@@ -8,20 +8,14 @@ void arm_fstp(x86emu_t* emu, void* p);
|
||||
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n);
|
||||
|
||||
void arm_f2xm1(x86emu_t* emu);
|
||||
void arm_fyl2x(x86emu_t* emu);
|
||||
void arm_ftan(x86emu_t* emu);
|
||||
void arm_fpatan(x86emu_t* emu);
|
||||
void arm_fxtract(x86emu_t* emu);
|
||||
void arm_fprem(x86emu_t* emu);
|
||||
void arm_fyl2xp1(x86emu_t* emu);
|
||||
void arm_fsincos(x86emu_t* emu);
|
||||
void arm_frndint(x86emu_t* emu);
|
||||
void arm_fscale(x86emu_t* emu);
|
||||
void arm_fsin(x86emu_t* emu);
|
||||
void arm_fcos(x86emu_t* emu);
|
||||
void arm_fbld(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fild64(x86emu_t* emu, int64_t* ed);
|
||||
void arm_fbstp(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fbst(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fistp64(x86emu_t* emu, int64_t* ed);
|
||||
void arm_fistt64(x86emu_t* emu, int64_t* ed);
|
||||
void arm_fld(x86emu_t* emu, uint8_t* ed);
|
||||
@@ -31,6 +25,8 @@ void arm_fprem1(x86emu_t* emu);
|
||||
|
||||
void arm_ud(x86emu_t* emu);
|
||||
|
||||
#define FPUFIRST 8
|
||||
|
||||
// Get an FPU single scratch reg
|
||||
int fpu_get_scratch_single(dynarec_arm_t* dyn);
|
||||
// Get an FPU double scratch reg
|
||||
@@ -39,17 +35,28 @@ int fpu_get_scratch_double(dynarec_arm_t* dyn);
|
||||
int fpu_get_scratch_quad(dynarec_arm_t* dyn);
|
||||
// Reset scratch regs counter
|
||||
void fpu_reset_scratch(dynarec_arm_t* dyn);
|
||||
// Get an FPU double reg
|
||||
int fpu_get_reg_double(dynarec_arm_t* dyn);
|
||||
// Get an FPU double reg, with NEON_CACHE_TYPE
|
||||
int fpu_get_reg_double(dynarec_arm_t* dyn, unsigned int t, unsigned int n);
|
||||
// Free a FPU double reg
|
||||
void fpu_free_reg_double(dynarec_arm_t* dyn, int reg);
|
||||
// Get an FPU quad reg
|
||||
int fpu_get_reg_quad(dynarec_arm_t* dyn);
|
||||
int fpu_get_reg_quad(dynarec_arm_t* dyn, unsigned int t, unsigned int n);
|
||||
// Free a FPU quad reg
|
||||
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg);
|
||||
// Reset fpu regs counter
|
||||
void fpu_reset_reg(dynarec_arm_t* dyn);
|
||||
|
||||
// ---- Neon cache functions
|
||||
// Get type for STx
|
||||
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// Get if STx is FLOAT or DOUBLE
|
||||
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a, int st);
|
||||
// Get actual type for STx
|
||||
int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// Back-propagate a change float->double
|
||||
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a, int st);
|
||||
// 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*
|
||||
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
|
||||
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
|
||||
// Do the GETED, but don't emit anything...
|
||||
|
||||
+344
-191
@@ -26,7 +26,7 @@
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask)
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask, int getfixonly)
|
||||
{
|
||||
uint8_t ret = 2;
|
||||
uint8_t scratch = 2;
|
||||
@@ -62,6 +62,8 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
} else if((nextop&7)==5) {
|
||||
uint32_t tmp = F32;
|
||||
MOV32(ret, tmp);
|
||||
if(getfixonly)
|
||||
*fixaddress = tmp;
|
||||
} else {
|
||||
ret = xEAX+(nextop&7);
|
||||
}
|
||||
@@ -332,6 +334,11 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags)
|
||||
{
|
||||
if(ret!=-2 && !mask) {
|
||||
// ARM ABI require the stack to be 8-bytes aligned!
|
||||
// so, if no mask asked, add one to stay 8-bytes aligned
|
||||
if(ret!=x3) mask=1<<x3; else mask=1<<x14;
|
||||
}
|
||||
if(ret!=-2) {
|
||||
PUSH(xSP, (1<<xEmu) | mask);
|
||||
}
|
||||
@@ -354,6 +361,63 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t
|
||||
SET_NODF();
|
||||
}
|
||||
|
||||
#if defined(__ARM_PCS) && !defined(__ARM_PCS_VFP)
|
||||
// if __ARM_PCS then AARCCH32 is target
|
||||
// if __ARM_PCS_VFP then -mfloat-abi=hard is used
|
||||
#define ARM_SOFTFP
|
||||
#endif
|
||||
// call a function with n double args (taking care of the SOFTFP / HARD call) that return a double too
|
||||
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags)
|
||||
{
|
||||
if(ret!=-2 && !mask) {
|
||||
// ARM ABI require the stack to be 8-bytes aligned!
|
||||
// so, if no mask asked, add one to stay 8-bytes aligned
|
||||
if(ret!=xFlags) mask=1<<xFlags; else mask=1<<x3;
|
||||
}
|
||||
if(ret!=-2) {
|
||||
PUSH(xSP, (1<<xEmu) | mask);
|
||||
}
|
||||
fpu_pushcache(dyn, ninst, reg);
|
||||
if(saveflags) {
|
||||
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
#ifdef ARM_SOFTFP
|
||||
if(n==1) {
|
||||
SUB_IMM8(xSP, xSP, 8);
|
||||
VST1_64(0, xSP); //store args on the stack
|
||||
} else { // n == 2, nothing else!
|
||||
SUB_IMM8(xSP, xSP, n*8);
|
||||
ADD_IMM8(reg, xSP, 8);
|
||||
VST1_64(1, reg);
|
||||
VST1_64(0, xSP); //store args on the stack
|
||||
}
|
||||
#endif
|
||||
MOV32(reg, (uintptr_t)fnc);
|
||||
BLX(reg);
|
||||
if(fnc2) {
|
||||
#ifdef ARM_SOFTFP
|
||||
STM(xSP, (1<<0)|(1<<1)); // put r0:r1 result on the stack for next call
|
||||
#endif
|
||||
MOV32(reg, (uintptr_t)fnc2);
|
||||
BLX(reg);
|
||||
}
|
||||
#ifdef ARM_SOFTFP
|
||||
ADD_IMM8(xSP, xSP, n*8);
|
||||
VMOVtoV_64(0, 0, 1); // load r0:r1 to D0 to simulate hardfo
|
||||
#endif
|
||||
fpu_popcache(dyn, ninst, reg);
|
||||
if(ret>=0) {
|
||||
MOV_REG(ret, 0);
|
||||
}
|
||||
if(ret!=-2) {
|
||||
POP(xSP, (1<<xEmu) | mask);
|
||||
}
|
||||
if(saveflags) {
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
SET_NODF();
|
||||
}
|
||||
|
||||
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Get TLSData\n");
|
||||
@@ -389,21 +453,25 @@ void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
|
||||
// x87 stuffs
|
||||
static void x87_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
#if STEP > 1
|
||||
dyn->x87count = 0;
|
||||
#if STEP > 0
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->x87cache[i] = -1;
|
||||
dyn->x87stack = 0;
|
||||
dyn->n.stack_next = 0;
|
||||
dyn->n.stack_pop = 0;
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].t == NEON_CACHE_ST_F || dyn->n.neoncache[i].t == NEON_CACHE_ST_D)
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
if(!dyn->x87stack)
|
||||
return;
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, scratch);
|
||||
mmx_purgecache(dyn, ninst, 0, scratch);
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->x87stack);
|
||||
int a = dyn->x87stack;
|
||||
// Add x87stack to emu fpu_stack
|
||||
@@ -423,41 +491,70 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
}
|
||||
AND_IMM8(scratch, scratch, 7);
|
||||
STR_IMM9(scratch, xEmu, offsetof(x86emu_t, top));
|
||||
// reset x87stack
|
||||
// reset x87stack, but not the stack count of neoncache
|
||||
dyn->x87stack = 0;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b)
|
||||
{
|
||||
#if STEP > 1
|
||||
int i1 = neoncache_get_st(dyn, ninst, a);
|
||||
int i2 = neoncache_get_st(dyn, ninst, b);
|
||||
if(i1!=i2) {
|
||||
MESSAGE(LOG_DUMP, "Warning, ST cache incoherent between ST%d(%d) and ST%d(%d)\n", a, i1, b, i2);
|
||||
}
|
||||
|
||||
return i1;
|
||||
}
|
||||
|
||||
// On step 1, Float/Double for ST is actualy computed and back-propagated
|
||||
// On step 2-3, the value is just read for inst[...].n.neocache[..]
|
||||
// the reg returned is *2 for FLOAT
|
||||
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t)
|
||||
{
|
||||
#if STEP > 0
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, s1);
|
||||
++dyn->x87count;
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
dyn->x87stack+=1;
|
||||
dyn->n.stack+=1;
|
||||
dyn->n.stack_next+=1;
|
||||
// move all regs in cache, and find a free one
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
|
||||
++dyn->n.neoncache[j].n;
|
||||
int ret = -1;
|
||||
for(int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]!=-1)
|
||||
++dyn->x87cache[i];
|
||||
else if(ret==-1) {
|
||||
dyn->x87cache[i] = 0;
|
||||
ret=dyn->x87reg[i]=fpu_get_reg_double(dyn);
|
||||
ret=dyn->x87reg[i]=fpu_get_reg_double(dyn, t, 0);
|
||||
#if STEP == 1
|
||||
// need to check if reg is compatible with float
|
||||
if((ret>15) && (t == NEON_CACHE_ST_F))
|
||||
dyn->n.neoncache[ret-FPUFIRST].t = NEON_CACHE_ST_D;
|
||||
#else
|
||||
dyn->n.neoncache[ret-FPUFIRST].t = X87_ST0;
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
return ret * dyn->n.neoncache[ret-FPUFIRST].t;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, s1);
|
||||
++dyn->x87count;
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
dyn->x87stack+=1;
|
||||
dyn->n.stack+=1;
|
||||
dyn->n.stack_next+=1;
|
||||
// move all regs in cache
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
|
||||
++dyn->n.neoncache[j].n;
|
||||
for(int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]!=-1)
|
||||
++dyn->x87cache[i];
|
||||
@@ -467,10 +564,12 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
}
|
||||
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, s1);
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
dyn->x87stack-=1;
|
||||
dyn->n.stack_next-=1;
|
||||
dyn->n.stack_pop+=1;
|
||||
// move all regs in cache, poping ST0
|
||||
for(int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]!=-1) {
|
||||
@@ -480,25 +579,24 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
dyn->x87reg[i] = -1;
|
||||
}
|
||||
}
|
||||
--dyn->x87count;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3)
|
||||
{
|
||||
#if STEP > 1
|
||||
dyn->x87count = 0;
|
||||
#if STEP > 0
|
||||
int ret = 0;
|
||||
for (int i=0; i<8 && !ret; ++i)
|
||||
if(dyn->x87cache[i] != -1)
|
||||
ret = 1;
|
||||
if(!ret && !dyn->x87stack) // nothing to do
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tPurge x87 Cache and Synch Stackcount (%+d)\n", dyn->x87stack);
|
||||
MESSAGE(LOG_DUMP, "\tPurge %sx87 Cache and Synch Stackcount (%+d)---\n", next?"locally ":"", dyn->x87stack);
|
||||
int a = dyn->x87stack;
|
||||
if(a!=0) {
|
||||
// reset x87stack
|
||||
dyn->x87stack = 0;
|
||||
if(!next)
|
||||
dyn->x87stack = 0;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
@@ -547,33 +645,58 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
}
|
||||
if(ret!=0) {
|
||||
// --- set values
|
||||
// prepare offset to fpu => s1
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
// Get top
|
||||
// loop all cache entries
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]!=-1) {
|
||||
ADD_IMM8(s3, s2, dyn->x87cache[i]);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + st)&7
|
||||
ADD_REG_LSL_IMM5(s3, s1, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
VSTR_64(dyn->x87reg[i], s3, 0); // save the value
|
||||
fpu_free_reg_double(dyn, dyn->x87reg[i]);
|
||||
dyn->x87reg[i] = -1;
|
||||
dyn->x87cache[i] = -1;
|
||||
#if STEP == 1
|
||||
if(!next) // don't force promotion here
|
||||
neoncache_promote_double(dyn, ninst, dyn->x87cache[i], dyn->n.stack_next);
|
||||
#endif
|
||||
#if STEP == 3
|
||||
if(!next && neoncache_get_st_f(dyn, ninst, dyn->x87cache[i], dyn->n.stack_next)>=0) {
|
||||
MESSAGE(LOG_DUMP, "Warning, incoherency with purged ST%d cache\n", dyn->x87cache[i]);
|
||||
}
|
||||
#endif
|
||||
if(dyn->x87cache[i]) {
|
||||
ADD_IMM8(s3, s2, dyn->x87cache[i]);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + st)&7
|
||||
ADD_REG_LSL_IMM5(s3, xEmu, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
} else {
|
||||
ADD_REG_LSL_IMM5(s3, xEmu, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
}
|
||||
if(next) {
|
||||
// need to check if a ST_F need local promotion
|
||||
if(neoncache_get_st_f(dyn, ninst, dyn->x87cache[i], dyn->n.stack_next)>=0) {
|
||||
VCVT_F64_F32(0, dyn->x87reg[i]*2);
|
||||
VSTR_64(0, s3, offsetof(x86emu_t, x87)); // save the value
|
||||
} else {
|
||||
VSTR_64(dyn->x87reg[i], s3, offsetof(x86emu_t, x87)); // save the value
|
||||
}
|
||||
} else {
|
||||
VSTR_64(dyn->x87reg[i], s3, offsetof(x86emu_t, x87)); // save the value
|
||||
fpu_free_reg_double(dyn, dyn->x87reg[i]);
|
||||
dyn->x87reg[i] = -1;
|
||||
dyn->x87cache[i] = -1;
|
||||
dyn->n.stack_pop+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!next) {
|
||||
dyn->n.stack_next = 0;
|
||||
#if STEP == 1
|
||||
// refresh the cached valued, in case it's a purge outside a instruction
|
||||
dyn->insts[ninst].n = dyn->n;
|
||||
#endif
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = 0;
|
||||
for (int i=0; (i<8) && (!ret); ++i)
|
||||
@@ -581,13 +704,6 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
ret = 1;
|
||||
if(!ret) // nothing to do
|
||||
return;
|
||||
// prepare offset to fpu => s1
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
// Get top
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
// loop all cache entries
|
||||
@@ -595,50 +711,66 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
if(dyn->x87cache[i]!=-1) {
|
||||
ADD_IMM8(s3, s2, dyn->x87cache[i]);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + i)&7
|
||||
ADD_REG_LSL_IMM5(s3, s1, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
VSTR_64(dyn->x87reg[i], s3, 0); // save the value
|
||||
ADD_REG_LSL_IMM5(s3, xEmu, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
if(ST_IS_F(dyn->x87cache[i])) {
|
||||
VCVT_F64_F32(0, dyn->x87reg[i]*2); // use D0 as scratch...
|
||||
VSTR_64(0, s3, offsetof(x86emu_t, x87));
|
||||
} else {
|
||||
VSTR_64(dyn->x87reg[i], s3, offsetof(x86emu_t, x87)); // save the value
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
|
||||
{
|
||||
#if STEP > 1
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, s1);
|
||||
#if STEP > 0
|
||||
// search in cache first
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]==st)
|
||||
if(dyn->x87cache[i]==st) {
|
||||
#if STEP == 1
|
||||
if(t==NEON_CACHE_ST_D && (dyn->n.neoncache[dyn->x87reg[i]-FPUFIRST].t==NEON_CACHE_ST_F))
|
||||
neoncache_promote_double(dyn, ninst, st, dyn->n.stack);
|
||||
#endif
|
||||
return i;
|
||||
MESSAGE(LOG_DUMP, "\tCreate x87 Cache for ST%d\n", st);
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int populate, int s1, int s2, int st, int t)
|
||||
{
|
||||
#if STEP > 0
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
int ret = x87_get_current_cache(dyn, ninst, st, t);
|
||||
if(ret!=-1)
|
||||
return ret;
|
||||
MESSAGE(LOG_DUMP, "\tCreate %sx87 Cache for ST%d\n", populate?"and populate ":"", st);
|
||||
// get a free spot
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
if(dyn->x87cache[i]==-1)
|
||||
ret = i;
|
||||
// found, setup and grab the value
|
||||
dyn->x87cache[ret] = st;
|
||||
dyn->x87reg[ret] = fpu_get_reg_double(dyn);
|
||||
++dyn->x87count;
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a) {
|
||||
if(a<0) {
|
||||
SUB_IMM8(s2, s2, -a);
|
||||
} else {
|
||||
ADD_IMM8(s2, s2, a);
|
||||
dyn->x87reg[ret] = fpu_get_reg_double(dyn, NEON_CACHE_ST_D, st);
|
||||
if(populate) {
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a) {
|
||||
if(a<0) {
|
||||
SUB_IMM8(s2, s2, -a);
|
||||
} else {
|
||||
ADD_IMM8(s2, s2, a);
|
||||
}
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
|
||||
}
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
|
||||
ADD_REG_LSL_IMM5(s2, xEmu, s2, 3);
|
||||
VLDR_64(dyn->x87reg[ret], s2, offsetof(x86emu_t, x87));
|
||||
}
|
||||
ADD_REG_LSL_IMM5(s2, s1, s2, 3);
|
||||
VLDR_64(dyn->x87reg[ret], s2, 0);
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
|
||||
return ret;
|
||||
@@ -646,11 +778,30 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
|
||||
int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
return dyn->x87reg[x87_get_cache(dyn, ninst, s1, s2, a)];
|
||||
#if STEP > 0
|
||||
for(int ii=0; ii<24; ++ii)
|
||||
if((dyn->n.neoncache[ii].t == NEON_CACHE_ST_F || dyn->n.neoncache[ii].t == NEON_CACHE_ST_D)
|
||||
&& dyn->n.neoncache[ii].n==st)
|
||||
return ii;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t)
|
||||
{
|
||||
#if STEP > 0
|
||||
int ret = dyn->x87reg[x87_get_cache(dyn, ninst, 1, s1, s2, a, t)];
|
||||
return ret * dyn->n.neoncache[ret-FPUFIRST].t;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
int x87_get_st_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t)
|
||||
{
|
||||
#if STEP > 0
|
||||
int ret = dyn->x87reg[x87_get_cache(dyn, ninst, 0, s1, s2, a, t)];
|
||||
return ret * dyn->n.neoncache[ret-FPUFIRST].t;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@@ -659,7 +810,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
|
||||
|
||||
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
@@ -669,12 +820,7 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
|
||||
// prepare offset to fpu => s1
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
|
||||
// Get top
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
// Update
|
||||
@@ -683,14 +829,19 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
|
||||
}
|
||||
ADD_REG_LSL_IMM5(s2, s1, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
VSTR_64(dyn->x87reg[ret], s2, 0); // save the value
|
||||
if(ST_IS_F(dyn->x87cache[ret])) {
|
||||
VCVT_F64_F32(0, dyn->x87reg[ret]*2); // use D0 as scratch...
|
||||
VSTR_64(0, s2, 0);
|
||||
} else {
|
||||
VSTR_64(dyn->x87reg[ret], s2, 0); // save the value
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
@@ -699,13 +850,11 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
if(ret==-1) // nothing to do
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
|
||||
#if STEP == 1
|
||||
neoncache_promote_double(dyn, ninst, st, dyn->n.stack);
|
||||
#endif
|
||||
// prepare offset to fpu => s1
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
|
||||
// Get top
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
// Update
|
||||
@@ -715,31 +864,29 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
}
|
||||
ADD_REG_LSL_IMM5(s2, s1, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
VSTR_64(dyn->x87reg[ret], s2, 0); // save the value
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
|
||||
MESSAGE(LOG_DUMP, "\t--------Forget x87 Cache for ST%d\n", st);
|
||||
// and forget that cache
|
||||
fpu_free_reg_double(dyn, dyn->x87reg[ret]);
|
||||
dyn->n.neoncache[dyn->x87reg[ret]].v = 0;
|
||||
dyn->x87cache[ret] = -1;
|
||||
dyn->x87reg[ret] = -1;
|
||||
--dyn->x87count;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
if(dyn->mmxcount)
|
||||
mmx_purgecache(dyn, ninst, s1);
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
// search in cache first
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]==st) {
|
||||
#if STEP == 1
|
||||
neoncache_promote_double(dyn, ninst, st, dyn->n.stack);
|
||||
#endif
|
||||
// refresh the value
|
||||
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a<0) {
|
||||
@@ -763,14 +910,8 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
ret = i;
|
||||
// found, setup and grab the value
|
||||
dyn->x87cache[ret] = st;
|
||||
dyn->x87reg[ret] = fpu_get_reg_double(dyn);
|
||||
++dyn->x87count;
|
||||
if(offsetof(x86emu_t, mmx87)<256) {
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx87));
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, mmx87));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
dyn->x87reg[ret] = fpu_get_reg_double(dyn, NEON_CACHE_ST_D, st);
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a<0) {
|
||||
@@ -824,29 +965,32 @@ void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
// MMX helpers
|
||||
static void mmx_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
dyn->mmxcount = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->mmxcache[i] = -1;
|
||||
#endif
|
||||
}
|
||||
static int isx87Empty(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
#if STEP > 0
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i] != -1)
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
// get neon register for a MMX reg, create the entry if needed
|
||||
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int a)
|
||||
{
|
||||
#if STEP > 1
|
||||
if(dyn->x87count)
|
||||
x87_purgecache(dyn, ninst, s1, s2, s3);
|
||||
#if STEP > 0
|
||||
if(!dyn->x87stack && isx87Empty(dyn, ninst))
|
||||
x87_purgecache(dyn, ninst, 0, s1, s2, s3);
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
++dyn->mmxcount;
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_double(dyn);
|
||||
int offs = offsetof(x86emu_t, mmx87[a]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_double(dyn, NEON_CACHE_MM, a);
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx[a]));
|
||||
VLD1_32(ret, s1);
|
||||
return ret;
|
||||
#else
|
||||
@@ -856,37 +1000,32 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int a)
|
||||
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
|
||||
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int a)
|
||||
{
|
||||
#if STEP > 1
|
||||
if(dyn->x87count)
|
||||
x87_purgecache(dyn, ninst, s1, s2, s3);
|
||||
#if STEP > 0
|
||||
if(!dyn->x87stack && isx87Empty(dyn, ninst))
|
||||
x87_purgecache(dyn, ninst, 0, s1, s2, s3);
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
++dyn->mmxcount;
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_double(dyn);
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_double(dyn, NEON_CACHE_MM, a);
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// purge the MMX cache only(needs 3 scratch registers)
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
if(!dyn->mmxcount)
|
||||
return;
|
||||
dyn->mmxcount = 0;
|
||||
if(!next)
|
||||
dyn->mmxcount = 0;
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->mmxcache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
MESSAGE(LOG_DUMP, "\tPurge MMX Cache ------\n");
|
||||
int offs = offsetof(x86emu_t, mmx87[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\tPurge %sMMX Cache ------\n", next?"locally ":"");
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx[i]));
|
||||
old = i+1; //+1 because VST1 with write back
|
||||
} else {
|
||||
if(old!=i) {
|
||||
@@ -895,8 +1034,10 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
old = i+1;
|
||||
}
|
||||
VST1_32_W(dyn->mmxcache[i], s1);
|
||||
fpu_free_reg_double(dyn, dyn->mmxcache[i]);
|
||||
dyn->mmxcache[i] = -1;
|
||||
if(!next) {
|
||||
fpu_free_reg_double(dyn, dyn->mmxcache[i]);
|
||||
dyn->mmxcache[i] = -1;
|
||||
}
|
||||
}
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
|
||||
@@ -906,18 +1047,12 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
#ifdef HAVE_TRACE
|
||||
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->mmxcache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
int offs = offsetof(x86emu_t, mmx87[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, mmx[i]));
|
||||
old = i+1;
|
||||
} else {
|
||||
if(old!=i) {
|
||||
@@ -935,18 +1070,26 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
// SSE / SSE2 helpers
|
||||
static void sse_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->ssecache[i] = -1;
|
||||
dyn->ssecache[i].v = -1;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a SSE reg, create the entry if needed
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite)
|
||||
{
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
int ret = dyn->ssecache[a] = fpu_get_reg_quad(dyn);
|
||||
#if STEP > 0
|
||||
if(dyn->ssecache[a].v!=-1) {
|
||||
if(forwrite) {
|
||||
dyn->ssecache[a].write = 1; // update only if forwrite
|
||||
dyn->n.neoncache[dyn->ssecache[a].reg+0-FPUFIRST].t = NEON_CACHE_XMMW;
|
||||
dyn->n.neoncache[dyn->ssecache[a].reg+1-FPUFIRST].t = NEON_CACHE_XMMW;
|
||||
}
|
||||
return dyn->ssecache[a].reg;
|
||||
}
|
||||
dyn->ssecache[a].reg = fpu_get_reg_quad(dyn, forwrite?NEON_CACHE_XMMW:NEON_CACHE_XMMR, a);
|
||||
int ret = dyn->ssecache[a].reg;
|
||||
dyn->ssecache[a].write = forwrite;
|
||||
int offs = offsetof(x86emu_t, xmm[a]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, (offs>>2), 0xf);
|
||||
@@ -963,41 +1106,50 @@ int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
|
||||
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
int ret = dyn->ssecache[a] = fpu_get_reg_quad(dyn);
|
||||
return ret;
|
||||
#if STEP > 0
|
||||
if(dyn->ssecache[a].v!=-1) {
|
||||
dyn->ssecache[a].write = 1;
|
||||
dyn->n.neoncache[dyn->ssecache[a].reg+0-FPUFIRST].t = NEON_CACHE_XMMW;
|
||||
dyn->n.neoncache[dyn->ssecache[a].reg+1-FPUFIRST].t = NEON_CACHE_XMMW;
|
||||
return dyn->ssecache[a].reg;
|
||||
}
|
||||
dyn->ssecache[a].reg = fpu_get_reg_quad(dyn, NEON_CACHE_XMMW, a);
|
||||
dyn->ssecache[a].write = 1; // it will be write...
|
||||
return dyn->ssecache[a].reg;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// purge the SSE cache only(needs 3 scratch registers)
|
||||
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
// purge the SSE cache only(needs 1 scratch registers)
|
||||
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
MESSAGE(LOG_DUMP, "\tPurge SSE Cache ------\n");
|
||||
int offs = offsetof(x86emu_t, xmm[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
if(dyn->ssecache[i].v!=-1) {
|
||||
if(dyn->ssecache[i].write) {
|
||||
if (old==-1) {
|
||||
MESSAGE(LOG_DUMP, "\tPurge %sSSE Cache ------\n", next?"locally ":"");
|
||||
int offs = offsetof(x86emu_t, xmm[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
old = i+1; //+1 because VST1Q with write back
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
if(old!=i) {
|
||||
ADD_IMM8(s1, s1, (i-old)*16);
|
||||
}
|
||||
old = i+1;
|
||||
}
|
||||
old = i+1; //+1 because VST1Q with write back
|
||||
} else {
|
||||
if(old!=i) {
|
||||
ADD_IMM8(s1, s1, (i-old)*16);
|
||||
}
|
||||
old = i+1;
|
||||
VST1Q_32_W(dyn->ssecache[i].reg, s1);
|
||||
}
|
||||
if(!next) {
|
||||
fpu_free_reg_quad(dyn, dyn->ssecache[i].reg);
|
||||
dyn->ssecache[i].v = -1;
|
||||
}
|
||||
VST1Q_32_W(dyn->ssecache[i], s1);
|
||||
fpu_free_reg_quad(dyn, dyn->ssecache[i]);
|
||||
dyn->ssecache[i] = -1;
|
||||
}
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
|
||||
@@ -1007,10 +1159,10 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
#ifdef HAVE_TRACE
|
||||
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
if(dyn->ssecache[i].v!=-1 && dyn->ssecache[i].write) {
|
||||
if (old==-1) {
|
||||
int offs = offsetof(x86emu_t, xmm[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
@@ -1026,7 +1178,7 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
}
|
||||
old = i+1;
|
||||
}
|
||||
VST1Q_32_W(dyn->ssecache[i], s1);
|
||||
VST1Q_32_W(dyn->ssecache[i].reg, s1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1034,7 +1186,7 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
// only need to push 16-31...
|
||||
int n=0;
|
||||
for (int i=16; i<32; i++)
|
||||
@@ -1061,7 +1213,7 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
// only need to push 16-31...
|
||||
int n=0;
|
||||
for (int i=16; i<32; i++)
|
||||
@@ -1086,12 +1238,13 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
#endif
|
||||
}
|
||||
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3)
|
||||
{
|
||||
x87_purgecache(dyn, ninst, s1, s2, s3);
|
||||
mmx_purgecache(dyn, ninst, s1);
|
||||
sse_purgecache(dyn, ninst, s1);
|
||||
fpu_reset_reg(dyn);
|
||||
x87_purgecache(dyn, ninst, next, s1, s2, s3);
|
||||
mmx_purgecache(dyn, ninst, next, s1);
|
||||
sse_purgecache(dyn, ninst, next, s1);
|
||||
if(!next)
|
||||
fpu_reset_reg(dyn);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -1116,7 +1269,7 @@ void fpu_reset(dynarec_arm_t* dyn, int ninst)
|
||||
// get the single reg that from the double "reg" (so Dx[idx])
|
||||
int fpu_get_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx)
|
||||
{
|
||||
#if STEP > 1
|
||||
#if STEP > 0
|
||||
if(reg<16)
|
||||
return reg*2+idx;
|
||||
int a = fpu_get_scratch_double(dyn);
|
||||
@@ -1143,4 +1296,4 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
AND_IMM8(s3, s1, 31);
|
||||
MVN_REG_LSR_REG(s4, s4, s3);
|
||||
BFI(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,10 @@
|
||||
#define F32 *(uint32_t*)(addr+=4, addr-4)
|
||||
#define F32S *(int32_t*)(addr+=4, addr-4)
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(uint32_t*)(addr+a)
|
||||
#define PK16(a) *(uint16_t*)(addr+a)
|
||||
#define PKip(a) *(uint8_t*)(ip+a)
|
||||
#define PK32(a) *(uint32_t*)(addr+a)
|
||||
#define PK16(a) *(uint16_t*)(addr+a)
|
||||
#define PKip(a) *(uint8_t*)(ip+a)
|
||||
#define PKa(a) *(uint8_t*)(a)
|
||||
|
||||
// GETGD get x86 register in gd
|
||||
#define GETGD gd = xEAX+((nextop&0x38)>>3)
|
||||
@@ -33,7 +34,7 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0); \
|
||||
LDR_IMM9(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -42,7 +43,7 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0); \
|
||||
LDR_IMM9(hint, wback, fixedaddress); \
|
||||
ed = hint; \
|
||||
}
|
||||
@@ -52,7 +53,7 @@
|
||||
MOV_REG(ret, ed); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0); \
|
||||
ed = ret; \
|
||||
LDR_IMM9(ed, wback, fixedaddress); \
|
||||
}
|
||||
@@ -65,7 +66,7 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
|
||||
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -74,7 +75,7 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
|
||||
ADD_REG_LSL_IMM5(wback, wback, O, 0);\
|
||||
LDR_IMM9(x1, wback, 0); \
|
||||
ed = x1; \
|
||||
@@ -93,7 +94,7 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0); \
|
||||
LDRH_IMM8(i, wback, fixedaddress); \
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
@@ -105,7 +106,7 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
|
||||
LDRH_IMM8(i, wback, fixedaddress); \
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
@@ -117,7 +118,7 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
|
||||
LDRSH_IMM8(i, wback, fixedaddress);\
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
@@ -137,7 +138,7 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0); \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
@@ -151,7 +152,7 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0); \
|
||||
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
@@ -166,7 +167,7 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
|
||||
LDRSB_IMM8(i, wback, fixedaddress);\
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
@@ -204,6 +205,12 @@
|
||||
// CALL_S will use x3 for the call address. Return value can be put in ret (unless ret is -1)
|
||||
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
|
||||
#define CALL_S(F, ret, M) call_c(dyn, ninst, F, x3, ret, M, 0)
|
||||
// CALL_1D will use x3 for the call address. Return value in D0, 1 ARG in D0
|
||||
#define CALL_1D(F, M) call_d(dyn, ninst, F, NULL, 1, x3, -1, M, 0)
|
||||
// CALL_2D will use x3 for the call address. Return value in D0, 2 ARGs in D0, D1
|
||||
#define CALL_2D(F, M) call_d(dyn, ninst, F, NULL, 2, x3, -1, M, 0)
|
||||
// CALL_1DD will use x3 for the call address. Return value in D0, 1 ARG in D0, cals 2 functions in a row
|
||||
#define CALL_1DD(F, F2, M) call_d(dyn, ninst, F, F2, 1, x3, -1, M, 0)
|
||||
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
@@ -243,11 +250,11 @@
|
||||
j32 = GETMARKLOCK-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
|
||||
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(X_PEND) || !dyn->insts[ninst].x86.need_flags))
|
||||
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A)))
|
||||
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
|
||||
#define IFX(A) if((dyn->insts[ninst].x86.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if((dyn->insts[ninst].x86.need_flags&(X_PEND) || !dyn->insts[ninst].x86.need_flags))
|
||||
#define IFXX(A) if((dyn->insts[ninst].x86.need_flags==(A)))
|
||||
#define IFX2X(A, B) if((dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if((dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
|
||||
|
||||
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
|
||||
#define FCOM(s1, s2) \
|
||||
@@ -271,14 +278,9 @@
|
||||
/* greater than leave 0 */ \
|
||||
} \
|
||||
SET_DFNONE(s1); \
|
||||
IFX(X_OF|X_PEND) { \
|
||||
BFC(xFlags, F_OF, 1); \
|
||||
} \
|
||||
IFX(X_AF|X_PEND) { \
|
||||
BFC(xFlags, F_AF, 1); \
|
||||
} \
|
||||
IFX(X_SF|X_PEND) { \
|
||||
BFC(xFlags, F_SF, 1); \
|
||||
IFX(X_OF|X_AF|X_SF|X_PEND) { \
|
||||
/* clear 0b100010010000 */ \
|
||||
BIC_IMM8(xFlags, xFlags, 0b10001001, 14); \
|
||||
} \
|
||||
|
||||
|
||||
@@ -289,7 +291,7 @@
|
||||
|
||||
#ifndef READFLAGS
|
||||
#define READFLAGS(A) \
|
||||
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
|
||||
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET && dyn->state_flags!=SF_SET_PENDING) { \
|
||||
if(dyn->state_flags!=SF_PENDING) { \
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
|
||||
TSTS_REG_LSL_IMM5(x3, x3, 0); \
|
||||
@@ -304,12 +306,13 @@
|
||||
#endif
|
||||
#ifndef SETFLAGS
|
||||
#define SETFLAGS(A, B) \
|
||||
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x86.need_flags&(~((A)|X_PEND)))) \
|
||||
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A))); \
|
||||
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
|
||||
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x86.need_flags&(~((A)/*|X_PEND*/)))) \
|
||||
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A)|X_PEND)); \
|
||||
dyn->state_flags = (B==SF_SUBSET)?SF_SET: \
|
||||
((B==SF_SET_PENDING && !(dyn->insts[ninst].x86.need_flags&X_PEND)?SF_SET:B))
|
||||
#endif
|
||||
#ifndef JUMP
|
||||
#define JUMP(A)
|
||||
#define JUMP(A, C)
|
||||
#endif
|
||||
#ifndef BARRIER
|
||||
#define BARRIER(A)
|
||||
@@ -317,12 +320,12 @@
|
||||
#ifndef BARRIER_NEXT
|
||||
#define BARRIER_NEXT(A)
|
||||
#endif
|
||||
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
|
||||
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
|
||||
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x86.need_flags)
|
||||
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_RES(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
|
||||
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
|
||||
#define UFLAG_IF if(dyn->insts[ninst].x86.need_flags)
|
||||
#ifndef DEFAULT
|
||||
#define DEFAULT *ok = -1; BARRIER(2)
|
||||
#endif
|
||||
@@ -376,6 +379,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define retn_to_epilog STEPNAME(retn_to_epilog_)
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog_)
|
||||
#define call_c STEPNAME(call_c_)
|
||||
#define call_d STEPNAME(call_d_)
|
||||
#define grab_fsdata STEPNAME(grab_fsdata_)
|
||||
#define grab_tlsdata STEPNAME(grab_tlsdata_)
|
||||
#define emit_cmp8 STEPNAME(emit_cmp8)
|
||||
@@ -444,17 +448,23 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define emit_shr32c STEPNAME(emit_shr32c)
|
||||
#define emit_sar32c STEPNAME(emit_sar32c)
|
||||
#define emit_rol32c STEPNAME(emit_rol32c)
|
||||
#define emit_rol8c STEPNAME(emit_rol8c)
|
||||
#define emit_ror32c STEPNAME(emit_ror32c)
|
||||
#define emit_ror8c STEPNAME(emit_ror8c)
|
||||
#define emit_shrd32c STEPNAME(emit_shrd32c)
|
||||
#define emit_shld32c STEPNAME(emit_shld32c)
|
||||
#define emit_shrd32 STEPNAME(emit_shrd32)
|
||||
|
||||
#define emit_pf STEPNAME(emit_pf)
|
||||
|
||||
#define x87_do_push STEPNAME(x87_do_push)
|
||||
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
|
||||
#define x87_do_pop STEPNAME(x87_do_pop)
|
||||
#define x87_get_current_cache STEPNAME(x87_get_current_cache)
|
||||
#define x87_get_cache STEPNAME(x87_get_cache)
|
||||
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
|
||||
#define x87_get_st STEPNAME(x87_get_st)
|
||||
#define x87_get_st_empty STEPNAME(x87_get_st)
|
||||
#define x87_refresh STEPNAME(x87_refresh)
|
||||
#define x87_forget STEPNAME(x87_forget)
|
||||
#define x87_reget_st STEPNAME(x87_reget_st)
|
||||
@@ -483,7 +493,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define fpu_putback_single_reg STEPNAME(fpu_putback_single_reg)
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask, int getfixonly);
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
|
||||
@@ -496,6 +506,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags);
|
||||
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags);
|
||||
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
|
||||
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
|
||||
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
|
||||
@@ -566,9 +577,12 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
@@ -576,15 +590,21 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
// 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 x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t);
|
||||
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
|
||||
void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
// fpu pop. All previous returned Dd should be considered invalid
|
||||
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
// get cache index for a x87 reg, return -1 if cache doesn't exist
|
||||
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t);
|
||||
// get cache index for a x87 reg, create the entry if needed
|
||||
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
|
||||
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int populate, int s1, int s2, int a, int t);
|
||||
// get neoncache index for a x87 reg
|
||||
int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
|
||||
// get vfpu register for a x87 reg, create the entry if needed
|
||||
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
|
||||
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
|
||||
// get vfpu register for a x87 reg, create the entry if needed. Do not fetch the Stx if not already in cache
|
||||
int x87_get_st_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
|
||||
// refresh a value from the cache ->emu (nothing done if value is not cached)
|
||||
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
|
||||
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
|
||||
@@ -598,6 +618,30 @@ void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
// Set rounding according to mxcsr flags, return reg to restore flags
|
||||
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
|
||||
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
|
||||
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
|
||||
|
||||
#if STEP == 0
|
||||
#define ST_IS_F(A) 0
|
||||
#define X87_COMBINE(A, B) NEON_CACHE_ST_D
|
||||
#define X87_ST0 NEON_CACHE_ST_D
|
||||
#define X87_ST(A) NEON_CACHE_ST_D
|
||||
#elif STEP == 1
|
||||
#define ST_IS_F(A) (neoncache_get_current_st(dyn, ninst, A)==NEON_CACHE_ST_F)
|
||||
#define X87_COMBINE(A, B) neoncache_combine_st(dyn, ninst, A, B)
|
||||
#define X87_ST0 neoncache_get_current_st(dyn, ninst, 0)
|
||||
#define X87_ST(A) neoncache_get_current_st(dyn, ninst, A)
|
||||
#else
|
||||
#define ST_IS_F(A) (neoncache_get_st(dyn, ninst, A)==NEON_CACHE_ST_F)
|
||||
#if STEP == 3
|
||||
#define X87_COMBINE(A, B) neoncache_st_coherency(dyn, ninst, A, B)
|
||||
#else
|
||||
#define X87_COMBINE(A, B) neoncache_get_st(dyn, ninst, A)
|
||||
#endif
|
||||
#define X87_ST0 neoncache_get_st(dyn, ninst, 0)
|
||||
#define X87_ST(A) neoncache_get_st(dyn, ninst, A)
|
||||
#endif
|
||||
|
||||
//MMX helpers
|
||||
// get neon register for a MMX reg, create the entry if needed
|
||||
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int a);
|
||||
@@ -606,17 +650,17 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
|
||||
|
||||
//SSE/SSE2 helpers
|
||||
// get neon register for a SSE reg, create the entry if needed
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
|
||||
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
|
||||
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
|
||||
// common coproc helpers
|
||||
// reset the cache
|
||||
void fpu_reset(dynarec_arm_t* dyn, int ninst);
|
||||
// purge the FPU cache (needs 3 scratch registers)
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
// purge the FPU cache (needs 3 scratch registers) next=1 if for a conditionnal branch jumping out of block (no tracking updated)
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
@@ -31,6 +32,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
int ninst = 0;
|
||||
uintptr_t ip = addr;
|
||||
uintptr_t init_addr = addr;
|
||||
MAYUSE(init_addr);
|
||||
int need_epilog = 1;
|
||||
dyn->sons_size = 0;
|
||||
// Clean up (because there are multiple passes)
|
||||
@@ -41,9 +43,21 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
INIT;
|
||||
while(ok) {
|
||||
ip = addr;
|
||||
if(dyn->insts && (dyn->insts[ninst].x86.barrier==1)) {
|
||||
if((dyn->insts[ninst].x86.barrier==1)) {
|
||||
NEW_BARRIER_INST;
|
||||
}
|
||||
// propagate ST stack state, especial stack pop that are defered
|
||||
if(dyn->n.stack_pop) {
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D || dyn->n.neoncache[j].t == NEON_CACHE_ST_F)) {
|
||||
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
|
||||
dyn->n.neoncache[j].v = 0;
|
||||
else
|
||||
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
|
||||
}
|
||||
dyn->n.stack_pop = 0;
|
||||
}
|
||||
dyn->n.stack = dyn->n.stack_next;
|
||||
NEW_INST;
|
||||
fpu_reset_scratch(dyn);
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -66,17 +80,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
|
||||
INST_EPILOG;
|
||||
|
||||
if(dyn->insts && dyn->insts[ninst+1].x86.barrier) {
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
if(dyn->insts[ninst+1].x86.barrier) {
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
if(dyn->insts[ninst+1].x86.barrier!=2) {
|
||||
dyn->state_flags = 0;
|
||||
dyn->dfnone = 0;
|
||||
}
|
||||
}
|
||||
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
|
||||
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
|
||||
ok = 1;
|
||||
}
|
||||
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3))
|
||||
#if STEP == 0
|
||||
if(!ok && !need_epilog && box86_dynarec_bigblock && getProtection(addr+3))
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
@@ -89,25 +104,26 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ok<0) {ok = 0; need_epilog=1;}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if(ok && !isJumpTableDefault((void*)addr))
|
||||
#else
|
||||
if(ok && dyn->insts && (ninst==dyn->size))
|
||||
if(ok && (ninst==dyn->size))
|
||||
#endif
|
||||
{
|
||||
#if STEP == 3
|
||||
dynarec_log(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
|
||||
#endif
|
||||
BARRIER(2);
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_next(dyn, addr, 0, ninst);
|
||||
ok=0; need_epilog=0;
|
||||
}
|
||||
}
|
||||
if(need_epilog) {
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
|
||||
}
|
||||
FINI;
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
|
||||
#define INIT uintptr_t sav_addr=addr
|
||||
#define FINI dyn->isize = addr-sav_addr
|
||||
#define FINI \
|
||||
dyn->isize = addr-sav_addr;\
|
||||
dyn->insts[ninst].x86.addr = addr;\
|
||||
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
|
||||
#define MESSAGE(A, ...)
|
||||
#define SETFLAGS(A, B)
|
||||
#define READFLAGS(A)
|
||||
#define READFLAGS(A) dyn->insts[ninst].x86.use_flags = A
|
||||
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
|
||||
#define EMIT(A)
|
||||
#define JUMP(A) add_next(dyn, (uintptr_t)A)
|
||||
#define NEW_INST ++dyn->size
|
||||
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
|
||||
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x86.barrier = A
|
||||
#define NEW_INST \
|
||||
++dyn->size; \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
dyn->insts = (instruction_arm_t*)realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
|
||||
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
|
||||
dyn->cap *= 2; \
|
||||
} \
|
||||
dyn->insts[ninst].x86.addr = ip; \
|
||||
if(ninst) {dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;}
|
||||
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name)
|
||||
#define DEFAULT \
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
#define INIT
|
||||
#define FINI \
|
||||
dyn->insts[ninst].x86.addr = addr; \
|
||||
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
|
||||
#define FINI
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A)
|
||||
#define READFLAGS(A) dyn->insts[ninst].x86.use_flags = A
|
||||
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
|
||||
#define JUMP(A) dyn->insts[ninst].x86.jmp = A
|
||||
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
|
||||
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x86.barrier = A
|
||||
#define READFLAGS(A)
|
||||
#define SETFLAGS(A,B)
|
||||
|
||||
#define NEW_INST dyn->n.combined1 = dyn->n.combined2 = 0
|
||||
|
||||
#define INST_EPILOG dyn->insts[ninst].n = dyn->n
|
||||
|
||||
#define NEW_INST \
|
||||
dyn->insts[ninst].x86.addr = ip; \
|
||||
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name)
|
||||
@@ -12,16 +12,34 @@
|
||||
#define INST_NAME(name) \
|
||||
if(box86_dynarec_dump) {\
|
||||
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, state=%d/%d, set=%X, use=%X, need=%X%s\n", \
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d, set=%X, use=%X, need=%X", \
|
||||
(box86_dynarec_dump>1)?"\e[32m":"", \
|
||||
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
|
||||
dyn->insts[ninst].size/4, \
|
||||
ninst, \
|
||||
dyn->insts[ninst].x86.barrier, \
|
||||
dyn->insts[ninst].x86.state_flags, \
|
||||
dyn->state_flags, \
|
||||
dyn->insts[ninst].x86.set_flags, \
|
||||
dyn->insts[ninst].x86.use_flags, \
|
||||
dyn->insts[ninst].x86.need_flags, \
|
||||
(box86_dynarec_dump>1)?"\e[m":""); \
|
||||
dyn->insts[ninst].x86.need_flags); \
|
||||
for(int ii=0; ii<24; ++ii) { \
|
||||
switch(dyn->insts[ninst].n.neoncache[ii].t) { \
|
||||
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:ST%d", ii+8, dyn->insts[ninst].n.neoncache[ii].n); break; \
|
||||
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:st%d", (ii+8)*2, dyn->insts[ninst].n.neoncache[ii].n); break; \
|
||||
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:MM%d", ii+8, dyn->insts[ninst].n.neoncache[ii].n); break; \
|
||||
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:XMM%d", (ii+8)/2, dyn->insts[ninst].n.neoncache[ii].n); ++ii; break; \
|
||||
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:xmm%d", (ii+8)/2, dyn->insts[ninst].n.neoncache[ii].n); ++ii; break; \
|
||||
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:Scratch", ii+8); break; \
|
||||
case NEON_CACHE_NONE: \
|
||||
default: break; \
|
||||
} \
|
||||
} \
|
||||
if(dyn->n.stack || dyn->insts[ninst].n.stack_next) \
|
||||
printf_log(LOG_NONE, " X87:%d/%d", dyn->n.stack, dyn->insts[ninst].n.stack_next);\
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
|
||||
printf_log(LOG_NONE, " CMB:%d/%d", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
|
||||
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
|
||||
}
|
||||
|
||||
#define NEW_BARRIER_INST \
|
||||
|
||||
@@ -4,6 +4,30 @@
|
||||
#include "dynarec_private.h"
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
|
||||
#define NEON_CACHE_NONE 0
|
||||
#define NEON_CACHE_ST_D 1
|
||||
#define NEON_CACHE_ST_F 2
|
||||
#define NEON_CACHE_MM 3
|
||||
#define NEON_CACHE_XMMW 4
|
||||
#define NEON_CACHE_XMMR 5
|
||||
#define NEON_CACHE_SCR 6
|
||||
typedef union neon_cache_s {
|
||||
int8_t v;
|
||||
struct {
|
||||
unsigned int t:4; // reg type
|
||||
unsigned int n:4; // reg number
|
||||
};
|
||||
} neon_cache_t;
|
||||
typedef struct neoncache_s {
|
||||
neon_cache_t neoncache[24];
|
||||
int8_t stack;
|
||||
int8_t stack_next;
|
||||
int8_t stack_pop;
|
||||
uint8_t combined1;
|
||||
uint8_t combined2;
|
||||
} neoncache_t;
|
||||
|
||||
typedef struct instruction_arm_s {
|
||||
instruction_x86_t x86;
|
||||
@@ -18,8 +42,17 @@ typedef struct instruction_arm_s {
|
||||
int pass2choice;// value for choices that are fixed on pass2 for pass3
|
||||
uintptr_t natcall;
|
||||
int retn;
|
||||
neoncache_t n;
|
||||
} instruction_arm_t;
|
||||
|
||||
typedef union sse_cache_s {
|
||||
int v;
|
||||
struct {
|
||||
uint8_t reg;
|
||||
uint8_t write;
|
||||
};
|
||||
} sse_cache_t;
|
||||
|
||||
typedef struct dynarec_arm_s {
|
||||
instruction_arm_t *insts;
|
||||
int32_t size;
|
||||
@@ -33,10 +66,10 @@ typedef struct dynarec_arm_s {
|
||||
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
|
||||
int x87reg[8]; // reg used for x87cache entry
|
||||
int mmxcache[8];// cache status for the 8 MMX registers
|
||||
int ssecache[8];// cache status for the 8 SSE(2) registers
|
||||
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
|
||||
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
|
||||
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
|
||||
int x87stack; // cache stack counter
|
||||
int x87count; // number of x87 register used
|
||||
int mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
|
||||
int fpu_scratch;// scratch counter
|
||||
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
|
||||
@@ -48,6 +81,7 @@ typedef struct dynarec_arm_s {
|
||||
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
|
||||
void** sons_arm; // the arm address of potential dynablock sons
|
||||
int sons_size; // number of potential dynablock sons
|
||||
dynablock_t* dynablock;
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
#define SF_UNKNOWN 0
|
||||
#define SF_SET 1
|
||||
#define SF_PENDING 2
|
||||
#define SF_MAYSET 3
|
||||
#define SF_SUBSET 4
|
||||
#define SF_SET_PENDING 3
|
||||
#define SF_MAYSET 4
|
||||
#define SF_SUBSET 5
|
||||
|
||||
typedef struct instruction_x86_s {
|
||||
uintptr_t addr; //address of the instruction
|
||||
int32_t size; // size of the instruction
|
||||
int barrier; // next instruction is a jump point, so no optim allowed
|
||||
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
|
||||
int jmp_cond; // 1 of conditionnal jump
|
||||
int jmp_insts; // instuction to jump to (-1 if out of the block)
|
||||
uint32_t use_flags; // 0 or combination of X_?F
|
||||
uint32_t set_flags; // 0 or combination of X_?F
|
||||
|
||||
+94
-47
@@ -1,3 +1,4 @@
|
||||
ARM_ 1 1 1 1 0 0 0 1 0 0 0 0 (0) (0) (0) 1 (0) (0) (0) (0) (0) (0) @<1> (0) 0 0 0 0 (0) (0) (0) (0) SETEND \%cparam ? 'B' : 'L'\E
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
@@ -141,99 +142,128 @@ NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned
|
||||
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
|
||||
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
|
||||
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 1 1 <6>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 0 0 <1> 1 <4>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 1 0 <3> 1 <4>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 0 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 1 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> Rm VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\], <Rm>
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
|
||||
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
|
||||
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
|
||||
ARM_ 1 1 1 1 0 1 0 0 @<1> 0 0 1 Rn @<8> @<4> @<4> 'NOP'
|
||||
ARM_ 1 1 1 1 0 1 0 0 U 1 0 1 Rn (1) (1) (1) (1) imm12 PLI [<Rn>, #+/-<imm12>]
|
||||
ARM_ 1 1 1 1 0 1 0 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm12 PLD\param ? "W" : ""\ [<Rn>, #+/-<imm12>]
|
||||
ARM_ 1 1 1 1 0 1 0 1 U (1) 0 1 1 1 1 1 (1) (1) (1) (1) imm12 PLD [PC, #+/-<imm>]
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 (1) (1) (1) (1) CLREX
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 0 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DSB \option\
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 1 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DMB \option\
|
||||
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 1 0 @<4> @ param=0b1111 const char* option option,"SY","!!!"@ @ ISB \option\
|
||||
ARM_ 1 1 1 1 0 1 1 0 @<1> 0 0 1 Rn @<8> @<3> 0 @<4> 'NOP'
|
||||
ARMs 1 1 1 1 0 1 1 0 U 1 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLI [<Rn>, +/-<Rm>{, <shift>}]
|
||||
ARMs 1 1 1 1 0 1 1 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLD\param ? "W" : ""\ [<Rn>, +/-<Rm>{, <shift>}]
|
||||
INVALIDATE 1 1 1 1 0 1 1 1 1 1 1 1 <4> <8> 1 1 1 1 <4>
|
||||
INVALIDATE 1 1 1 1 <28>
|
||||
ARMS cond 0 0 0 0 0 0 0 S Rn Rd imm5 type 0 Rm AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
|
||||
ARM_ cond 0 0 0 0 0 0 0 S Rd (0) (0) (0) (0) Rm 1 0 0 1 Rn MUL{S}<c> <Rd>, <Rn>, <Rm>
|
||||
@@ -283,6 +313,8 @@ ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{,
|
||||
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
|
||||
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
|
||||
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
|
||||
ARM_ cond 0 0 0 1 0 0 0 0 (1) (1) (1) (1) Rd (0) (0) 0 (0) 0 0 0 0 (0) (0) (0) (0) MRS<c> <Rd>, APSR
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) (0) (0) 0 (0) 0 0 0 0 Rn @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, <Rn>
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
|
||||
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
|
||||
@@ -330,6 +362,17 @@ ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
|
||||
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
|
||||
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 1 YIELD<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 0 WFE<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 1 WFI<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 1 0 0 SEV<c>
|
||||
ARM_ cond/=1110 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 0 1 0 0 CSDB<c>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 1 1 1 1 imm4 DBG<c> #<imm>
|
||||
INVALIDATE <4> 0 0 1 1 0 0 1 0 0 0 0 0 <8> <8>
|
||||
ARM_ cond 0 0 1 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) imm12 @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, #<imm>
|
||||
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 0 1 <8> <8>
|
||||
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 1 <1> <8> <8>
|
||||
INVALIDATE <4> 0 0 1 1 0 1 1 0 <4> <8> <8>
|
||||
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
|
||||
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
|
||||
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
|
||||
@@ -388,6 +431,8 @@ ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <
|
||||
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
|
||||
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
|
||||
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
|
||||
ARM_ cond 0 1 1 1 0 0 0 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn SDIV<c> <Rd>, <Rn>, <Rm>
|
||||
ARM_ cond 0 1 1 1 0 0 1 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn UDIV<c> <Rd>, <Rn>, <Rm>
|
||||
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
|
||||
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
|
||||
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
|
||||
@@ -397,6 +442,7 @@ ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
|
||||
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
|
||||
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
|
||||
ARM_ cond/=1110 0 1 1 1 1 1 1 1 imm12 1 1 1 1 imm4 UDF<c> #<imm16>
|
||||
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
|
||||
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
|
||||
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
|
||||
@@ -427,14 +473,14 @@ INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
|
||||
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
|
||||
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
|
||||
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
|
||||
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
|
||||
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
|
||||
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
|
||||
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
|
||||
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
|
||||
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
|
||||
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
|
||||
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
|
||||
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
|
||||
INVALIDATE <4> 1 1 0 <25>
|
||||
@@ -446,6 +492,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>,
|
||||
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
|
||||
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
|
||||
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
|
||||
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt/=1111 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> APSR_nzcv, FPSCR
|
||||
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
|
||||
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
|
||||
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
|
||||
@@ -472,6 +519,6 @@ VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <S
|
||||
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 1 U 1 Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
|
||||
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
|
||||
INVALIDATE <32>
|
||||
+62
-59
@@ -200,13 +200,14 @@ const char* DumpRelType(int t)
|
||||
return buff;
|
||||
}
|
||||
|
||||
const char* DumpSym(elfheader_t *h, Elf32_Sym* sym)
|
||||
const char* DumpSym(elfheader_t *h, Elf32_Sym* sym, int version)
|
||||
{
|
||||
static char buff[4096];
|
||||
const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version)));
|
||||
memset(buff, 0, sizeof(buff));
|
||||
sprintf(buff, "\"%s\", value=%p, size=%d, info/other=%d/%d index=%d",
|
||||
sprintf(buff, "\"%s\", value=%p, size=%d, info/other=%d/%d index=%d (ver=%d/%s)",
|
||||
h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size,
|
||||
sym->st_info, sym->st_other, sym->st_shndx);
|
||||
sym->st_info, sym->st_other, sym->st_shndx, version, vername);
|
||||
return buff;
|
||||
}
|
||||
|
||||
@@ -221,116 +222,118 @@ const char* IdxSymName(elfheader_t *h, int sym)
|
||||
|
||||
void DumpMainHeader(Elf32_Ehdr *header, elfheader_t *h)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP) {
|
||||
printf_log(LOG_DUMP, "ELF Dump main header\n");
|
||||
printf_log(LOG_DUMP, " Entry point = %p\n", (void*)header->e_entry);
|
||||
printf_log(LOG_DUMP, " Program Header table offset = %p\n", (void*)header->e_phoff);
|
||||
printf_log(LOG_DUMP, " Section Header table offset = %p\n", (void*)header->e_shoff);
|
||||
printf_log(LOG_DUMP, " Flags = 0x%X\n", header->e_flags);
|
||||
printf_log(LOG_DUMP, " ELF Header size = %d\n", header->e_ehsize);
|
||||
printf_log(LOG_DUMP, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
|
||||
printf_log(LOG_DUMP, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
|
||||
printf_log(LOG_DUMP, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
|
||||
printf_log(LOG_DUMP, "ELF Dump ==========\n");
|
||||
if(box86_dump) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump main header\n");
|
||||
printf_dump(LOG_NEVER, " Entry point = %p\n", (void*)header->e_entry);
|
||||
printf_dump(LOG_NEVER, " Program Header table offset = %p\n", (void*)header->e_phoff);
|
||||
printf_dump(LOG_NEVER, " Section Header table offset = %p\n", (void*)header->e_shoff);
|
||||
printf_dump(LOG_NEVER, " Flags = 0x%X\n", header->e_flags);
|
||||
printf_dump(LOG_NEVER, " ELF Header size = %d\n", header->e_ehsize);
|
||||
printf_dump(LOG_NEVER, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
|
||||
printf_dump(LOG_NEVER, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
|
||||
printf_dump(LOG_NEVER, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
|
||||
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
|
||||
|
||||
printf_log(LOG_DUMP, "ELF Dump PEntries (%d)\n", h->numSHEntries);
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numPHEntries; ++i)
|
||||
printf_log(LOG_DUMP, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump PEntries ====\n");
|
||||
printf_dump(LOG_NEVER, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
|
||||
|
||||
printf_log(LOG_DUMP, "ELF Dump Sections (%d)\n", h->numSHEntries);
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numSHEntries; ++i)
|
||||
printf_log(LOG_DUMP, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_log(LOG_DUMP, "ELF Dump Sections ====\n");
|
||||
printf_dump(LOG_NEVER, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpSymTab(elfheader_t *h)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP && h->SymTab) {
|
||||
if(box86_dump && h->SymTab) {
|
||||
const char* name = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump SymTab(%d)=\n", h->numSymTab);
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab(%d)=\n", h->numSymTab);
|
||||
for (int i=0; i<h->numSymTab; ++i)
|
||||
printf_log(LOG_DUMP, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
|
||||
printf_dump(LOG_NEVER, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
|
||||
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
|
||||
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
|
||||
printf_log(LOG_DUMP, "ELF Dump SymTab=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicSections(elfheader_t *h)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP && h->Dynamic) {
|
||||
printf_log(LOG_DUMP, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
|
||||
if(box86_dump && h->Dynamic) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
printf_log(LOG_DUMP, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump Dynamic=====\n");
|
||||
printf_dump(LOG_NEVER, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynSym(elfheader_t *h)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP && h->DynSym) {
|
||||
if(box86_dump && h->DynSym) {
|
||||
const char* name = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump DynSym(%d)=\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i)
|
||||
printf_log(LOG_DUMP, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump DynSym=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym(%d)=\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i) {
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
printf_dump(LOG_NEVER, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
|
||||
}
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicNeeded(elfheader_t *h)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP && h->DynStrTab) {
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
|
||||
if(box86_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED) {
|
||||
printf_log(LOG_DUMP, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicRPath(elfheader_t *h)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP && h->DynStrTab) {
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
if(box86_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag==DT_RPATH) {
|
||||
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
|
||||
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
}
|
||||
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
|
||||
printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRelTable(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP) {
|
||||
if(box86_dump) {
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
|
||||
for (int i = 0; i<cnt; ++i)
|
||||
printf_log(LOG_DUMP, " %s:Rel[%d] = %p (0x%X: %s, sym=0x%0X/%s)\n", elfname,
|
||||
printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%X: %s, sym=0x%0X/%s)\n", elfname,
|
||||
i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType(ELF32_R_TYPE(rel[i].r_info)),
|
||||
ELF32_R_SYM(rel[i].r_info), IdxSymName(h, ELF32_R_SYM(rel[i].r_info)));
|
||||
printf_log(LOG_DUMP, "ELF Dump Rel Table=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump Rel Table=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRelATable(elfheader_t *h, int cnt, Elf32_Rela *rela, const char* name)
|
||||
{
|
||||
if(box86_log>=LOG_DUMP && h->rela) {
|
||||
if(box86_dump && h->rela) {
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
|
||||
for (int i = 0; i<cnt; ++i)
|
||||
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%X: %s, sym=0x%X/%s) Addend=%d\n", elfname,
|
||||
printf_dump(LOG_NEVER, " %s:RelA[%d] = %p (0x%X: %s, sym=0x%X/%s) Addend=%d\n", elfname,
|
||||
i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF32_R_TYPE(rela[i].r_info)),
|
||||
ELF32_R_SYM(rela[i].r_info), IdxSymName(h, ELF32_R_SYM(rela[i].r_info)),
|
||||
rela[i].r_addend);
|
||||
printf_log(LOG_DUMP, "ELF Dump RelA Table=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump RelA Table=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,24 +344,24 @@ void DumpBinary(char* p, int sz)
|
||||
unsigned char* d = (unsigned char*)p;
|
||||
int delta = ((uintptr_t)p)&0xf;
|
||||
for (int i = 0; sz; ++i) {
|
||||
printf_log(LOG_DUMP, "%p ", (void*)(((uintptr_t)d)&~0xf));
|
||||
printf_dump(LOG_NEVER, "%p ", (void*)(((uintptr_t)d)&~0xf));
|
||||
int n = 16 - delta;
|
||||
if (n>sz) n = sz;
|
||||
int fill = 16-sz;
|
||||
for (int j = 0; j<delta; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
for (int j = 0; j<n; ++j)
|
||||
printf_log(LOG_DUMP, "%02X ", d[j]);
|
||||
printf_dump(LOG_NEVER, "%02X ", d[j]);
|
||||
for (int j = 0; j<fill; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_log(LOG_DUMP, " | ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
printf_dump(LOG_NEVER, " | ");
|
||||
for (int j = 0; j<delta; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
for (int j = 0; j<n; ++j)
|
||||
printf_log(LOG_DUMP, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
|
||||
printf_dump(LOG_NEVER, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
|
||||
for (int j = 0; j<fill; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_log(LOG_DUMP, "\n");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
printf_dump(LOG_NEVER, "\n");
|
||||
d+=n;
|
||||
sz-=n;
|
||||
delta=0;
|
||||
|
||||
+314
-171
@@ -30,6 +30,8 @@
|
||||
#include "box86stack.h"
|
||||
#include "custommem.h"
|
||||
#include "wine_tools.h"
|
||||
#include "dictionnary.h"
|
||||
#include "symbols.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#endif
|
||||
@@ -124,7 +126,9 @@ int CalcLoadAddr(elfheader_t* head)
|
||||
head->stackalign = head->PHEntries[i].p_align;
|
||||
}
|
||||
if(head->PHEntries[i].p_type == PT_TLS) {
|
||||
head->tlsaddr = head->PHEntries[i].p_vaddr;
|
||||
head->tlssize = head->PHEntries[i].p_memsz;
|
||||
head->tlsfilesize = head->PHEntries[i].p_filesz;
|
||||
head->tlsalign = head->PHEntries[i].p_align;
|
||||
// force alignement...
|
||||
if(head->tlsalign>1)
|
||||
@@ -203,18 +207,18 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
head->multiblock_n = n; // might be less in fact
|
||||
for (int i=0; i<head->multiblock_n; ++i) {
|
||||
|
||||
printf_log(LOG_DEBUG, "Allocating 0x%x memory @%p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
|
||||
printf_log(LOG_DEBUG, "Allocating 0x%x memory %p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
|
||||
void* p = mmap((void*)head->multiblock_offs[i], head->multiblock_size[i]
|
||||
, PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
, MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/
|
||||
, -1, 0);
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%x/0x%x) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name);
|
||||
printf_log(LOG_NONE, "Cannot create memory map (%p 0x%x/0x%x) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name);
|
||||
return 1;
|
||||
}
|
||||
if(head->multiblock_offs[i] &&( p!=(void*)head->multiblock_offs[i])) {
|
||||
if((head->e_type!=ET_DYN)) {
|
||||
printf_log(LOG_NONE, "Error, memory map (@%p 0x%x/0x%x) for elf \"%s\" allocated @%p\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name, p);
|
||||
printf_log(LOG_NONE, "Error, memory map (%p 0x%x/0x%x) for elf \"%s\" allocated %p\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name, p);
|
||||
return 1;
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Allocated memory is not at hinted %p but %p (size %p) \"%s\"\n", (void*)head->multiblock_offs[i], p, (void*)head->multiblock_size[i], head->name);
|
||||
@@ -236,17 +240,17 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
}
|
||||
} else {
|
||||
// vaddr is 0, load everything has a One block
|
||||
printf_log(LOG_DEBUG, "Allocating 0x%x memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
|
||||
printf_log(LOG_DEBUG, "Allocating 0x%x memory %p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
|
||||
void* p = mmap((void*)offs, head->memsz
|
||||
, PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
, MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
|
||||
, -1, 0);
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%x/0x%x) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name);
|
||||
printf_log(LOG_NONE, "Cannot create memory map (%p 0x%x/0x%x) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name);
|
||||
return 1;
|
||||
}
|
||||
if(offs && (p!=(void*)offs) && (head->e_type!=ET_DYN)) {
|
||||
printf_log(LOG_NONE, "Error, memory map (@%p 0x%x/0x%x) for elf \"%s\" allocated @%p\n", (void*)offs, head->memsz, head->align, head->name, p);
|
||||
printf_log(LOG_NONE, "Error, memory map (%p 0x%x/0x%x) for elf \"%s\" allocated %p\n", (void*)offs, head->memsz, head->align, head->name, p);
|
||||
return 1;
|
||||
}
|
||||
setProtection((uintptr_t)p, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
@@ -286,12 +290,19 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)e->p_paddr + head->delta;
|
||||
printf_log(LOG_DEBUG, "Loading block #%i @%p (0x%x/0x%x)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(e->p_filesz) {
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d (size=%d)\n", i, e->p_filesz);
|
||||
return 1;
|
||||
void* p = (void*)-1;
|
||||
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
|
||||
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%x/0x%x, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
|
||||
p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
|
||||
}
|
||||
if(p!=dest) {
|
||||
printf_log(LOG_DEBUG, "Loading block #%d %p (0x%x/0x%x)\n",i, dest, e->p_filesz, e->p_memsz);
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(e->p_filesz) {
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d (size=%d)\n", i, e->p_filesz);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
@@ -308,7 +319,7 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
if(head->PHEntries[i].p_type == PT_TLS) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase);
|
||||
printf_log(LOG_DEBUG, "Loading TLS block #%i @%p (0x%x/0x%x)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
printf_log(LOG_DEBUG, "Loading TLS block #%i %p (0x%x/0x%x)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
if(e->p_filesz) {
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
@@ -330,7 +341,7 @@ int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)e->p_paddr + head->delta;
|
||||
printf_log(LOG_DEBUG, "Re-loading block #%i @%p (0x%x/0x%x)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
printf_log(LOG_DEBUG, "Re-loading block #%i %p (0x%x/0x%x)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
int ret = fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(ret==-1) {printf_log(LOG_NONE, "Fail to (re)seek PT_LOAD part #%d (offset=%d, errno=%d/%s)\n", i, e->p_offset, errno, strerror(errno)); return 1;}
|
||||
#ifdef DYNAREC
|
||||
@@ -353,7 +364,7 @@ int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
// TLS data are just a copy, no need to re-load it
|
||||
return 0;
|
||||
}
|
||||
int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t** p)
|
||||
int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t** p, int version, const char* vername)
|
||||
{
|
||||
if(!h)
|
||||
return 0;
|
||||
@@ -365,10 +376,16 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
|
||||
int t = ELF32_R_TYPE(rel[i].r_info);
|
||||
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel[i].r_info)];
|
||||
const char* symname = SymName(h, sym);
|
||||
if(!strcmp(symname, name) && t==R_386_COPY) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint32_t*)(rel[i].r_offset + h->delta);
|
||||
return 1;
|
||||
if(t==R_386_COPY && symname && !strcmp(symname, name)) {
|
||||
int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint32_t*)(rel[i].r_offset + h->delta);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -386,14 +403,9 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
uintptr_t offs = 0;
|
||||
uintptr_t end = 0;
|
||||
uintptr_t tmp = 0;
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:0;
|
||||
const char* ver = GetSymbolVersion(head, version);
|
||||
char SymbolVersionned[501];
|
||||
strncpy(SymbolVersionned, symname, 500);
|
||||
if(ver) {
|
||||
strncat(SymbolVersionned, "@", 500);
|
||||
strncat(SymbolVersionned, ver, 500);
|
||||
}
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
elfheader_t* h_tls = head;
|
||||
if(bind==STB_LOCAL) {
|
||||
offs = sym->st_value + head->delta;
|
||||
@@ -401,23 +413,17 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
} else {
|
||||
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
|
||||
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
|
||||
if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_386_GLOB_DAT) {
|
||||
/*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_386_GLOB_DAT) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
}
|
||||
}*/
|
||||
// so weak symbol are the one left, and try versionned symbol first
|
||||
if(!offs && !end) {
|
||||
h_tls = NULL;
|
||||
if(local_maplib) {
|
||||
GetGlobalSymbolStartEnd(local_maplib, SymbolVersionned, &offs, &end);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end);
|
||||
}
|
||||
if(!offs && !end) {
|
||||
GetGlobalSymbolStartEnd(maplib, SymbolVersionned, &offs, &end);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end);
|
||||
}
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
}
|
||||
}
|
||||
uintptr_t globoffs, globend;
|
||||
@@ -426,23 +432,25 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
switch(t) {
|
||||
case R_386_NONE:
|
||||
// can be ignored
|
||||
printf_log(LOG_DUMP, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
|
||||
printf_dump(LOG_NEVER, "Ignoring [%d] %s %p (%p)\n", i, DumpRelType(t), p, (void*)(p?(*p):0));
|
||||
break;
|
||||
case R_386_TLS_TPOFF:
|
||||
// Negated offset in static TLS block
|
||||
{
|
||||
if(h_tls)
|
||||
if(!symname || !symname[0]) {
|
||||
h_tls = head;
|
||||
offs = sym->st_value;
|
||||
else {
|
||||
} else {
|
||||
h_tls = NULL;
|
||||
if(local_maplib)
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname);
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
|
||||
if(!h_tls)
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname);
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname, version, vername);
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int*)p;
|
||||
printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
|
||||
*p = (uint32_t)((int32_t)offs + h_tls->tlsbase);
|
||||
delta = *(int32_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)((int32_t)offs + h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
|
||||
}
|
||||
@@ -451,18 +459,20 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
case R_386_TLS_TPOFF32:
|
||||
// Non-negated offset in static TLS block???
|
||||
{
|
||||
if(h_tls)
|
||||
if(!symname || !symname[0]) {
|
||||
h_tls = head;
|
||||
offs = sym->st_value;
|
||||
else {
|
||||
} else {
|
||||
h_tls = NULL;
|
||||
if(local_maplib)
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname);
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
|
||||
if(!h_tls)
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname);
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname, version, vername);
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int*)p;
|
||||
printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
|
||||
*p = (uint32_t)(-((int32_t)offs + h_tls->tlsbase));
|
||||
delta = *(int32_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)(-(int32_t)offs + h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
|
||||
}
|
||||
@@ -470,37 +480,37 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
break;
|
||||
case R_386_PC32:
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_PC32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
if(offs)
|
||||
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+(offs-(uintptr_t)p)), (void*)offs);
|
||||
offs = (offs - (uintptr_t)p);
|
||||
if(!offs)
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
|
||||
*p += offs;
|
||||
break;
|
||||
case R_386_GLOB_DAT:
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp)) {
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
|
||||
// set global offs / size for the symbol
|
||||
offs = sym->st_value + head->delta;
|
||||
offs = sym->st_value;
|
||||
end = offs + sym->st_size;
|
||||
if(sym->st_size) {
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) size=%d on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
|
||||
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size);
|
||||
if(sym->st_size && offs) {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY %p/%p (%p/%p -> %p/%p) size=%d on sym=%s (ver %d/%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, version, vername?vername:"(none)");
|
||||
memmove((void*)globoffs, (void*)(offs + head->delta), sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddWeakSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT with R_386_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);
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY %p/%p (%p/%p -> %p/%p) null sized/value on sym=%s (ver %d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname, version, vername?vername:"(none)");
|
||||
}
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
if (GetGlobalNoWeakSymbolStartEnd(maplib, symname, &globoffs, &globend)) {
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__"))
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s version %d/%s not found, cannot apply R_386_GLOB_DAT %p (%p) in %s\n", symname, version, vername?vername:"(none)", p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT %p (%p -> %p) on sym=%s (ver %d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
|
||||
*p = offs;
|
||||
}
|
||||
}
|
||||
@@ -510,39 +520,38 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
uintptr_t old_offs = offs;
|
||||
uintptr_t old_end = end;
|
||||
offs = 0;
|
||||
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end); // try globaldata symbols first
|
||||
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first, with exact version (enabling local symbol)
|
||||
if(offs==0) {
|
||||
if(local_maplib)
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head);
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs)
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head); // get original copy if any
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername); // get original copy if any
|
||||
}
|
||||
if(!offs) {
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
}
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_COPY %p with sym=%s (ver %d/%s), %p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", (void*)offs, sym->st_size);
|
||||
memmove(p, (void*)offs, sym->st_size);
|
||||
if(LOG_DUMP<=box86_log) {
|
||||
if(box86_dump) {
|
||||
uint32_t*k = (uint32_t*)p;
|
||||
for (int i=0; i<((sym->st_size>128)?128:sym->st_size); i+=4, ++k)
|
||||
printf_log(LOG_DUMP, "%s0x%08X", i?" ":"", *k);
|
||||
printf_log(LOG_DUMP, "%s)\n", (sym->st_size>128)?" ...":"");
|
||||
printf_dump(LOG_NEVER, "%s0x%08X", i?" ":"", *k);
|
||||
printf_dump(LOG_NEVER, "%s)\n", (sym->st_size>128)?" ...":"");
|
||||
}
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY %p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
break;
|
||||
case R_386_RELATIVE:
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
|
||||
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
|
||||
*p += head->delta;
|
||||
break;
|
||||
case R_386_32:
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
// return -1;
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
|
||||
*p += offs;
|
||||
}
|
||||
break;
|
||||
@@ -553,14 +562,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
else {
|
||||
if(!h_tls) {
|
||||
if(local_maplib)
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname);
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
|
||||
if(!h_tls)
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname);
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname, version, vername);
|
||||
}
|
||||
offs = getElfIndex(my_context, h_tls);
|
||||
}
|
||||
if(p) {
|
||||
printf_log(LOG_DUMP, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
|
||||
@@ -570,17 +579,16 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
// Offset in TLS block
|
||||
if (!offs && !end) {
|
||||
if(bind==STB_WEAK) {
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 @%p (%p)\n", symname, p, *(void**)p);
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p)\n", symname, p, *(void**)p);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
// return -1;
|
||||
} else {
|
||||
if(h_tls)
|
||||
offs = sym->st_value;
|
||||
if(p) {
|
||||
int tlsoffset = offs; // it's not an offset in elf memory
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_TLS_DTPOFF32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
|
||||
*p = tlsoffset;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
|
||||
@@ -598,21 +606,20 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
) {
|
||||
if (!offs) {
|
||||
if(bind==STB_WEAK) {
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT %p (%p)\n", symname, p, *(void**)p);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
// return -1;
|
||||
} else {
|
||||
if(p) {
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_JMP_SLOT @%p with sym=%s(%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, SymbolVersionned, *(void**)p, (void*)offs);
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, symname, vername?"@":"", vername?vername:"", *(void**)p, (void*)offs);
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Preparing (if needed) %s R_386_JMP_SLOT @%p (0x%x->0x%0x) with sym=%s(%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, SymbolVersionned, version);
|
||||
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version);
|
||||
*p += head->delta;
|
||||
}
|
||||
break;
|
||||
@@ -627,7 +634,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
{
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rela[i].r_info)];
|
||||
int bind = ELF32_ST_BIND(sym->st_info);
|
||||
const char* symname = SymName(head, sym);
|
||||
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rela[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
uint32_t *p = (uint32_t*)(rela[i].r_offset + head->delta);
|
||||
uintptr_t offs = 0;
|
||||
uintptr_t end = 0;
|
||||
@@ -638,15 +649,15 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
break;
|
||||
case R_386_COPY:
|
||||
if(local_maplib)
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head);
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs)
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head);
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
if(offs) {
|
||||
// add r_addend to p?
|
||||
printf_log(LOG_DUMP, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
|
||||
printf_dump(LOG_NEVER, "Apply R_386_COPY %p with sym=%s, %p size=%d\n", p, symname, (void*)offs, sym->st_size);
|
||||
memcpy(p, (void*)(offs+rela[i].r_addend), sym->st_size);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY %p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -691,7 +702,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
return -1;
|
||||
}
|
||||
if(pltResolver==~0) {
|
||||
pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0);
|
||||
pltResolver = AddBridge(my_context->system, vFEv, PltResolver, 0, "(PltResolver)");
|
||||
}
|
||||
if(head->pltgot) {
|
||||
*(uintptr_t*)(head->pltgot+head->delta+8) = pltResolver;
|
||||
@@ -756,30 +767,14 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
|
||||
{
|
||||
uintptr_t ep = h->entrypoint + h->delta;
|
||||
printf_log(LOG_DEBUG, "Entry Point is %p\n", (void*)ep);
|
||||
if(box86_log>=LOG_DUMP) {
|
||||
printf_log(LOG_DUMP, "(short) Dump of Entry point\n");
|
||||
if(box86_dump) {
|
||||
printf_dump(LOG_NEVER, "(short) Dump of Entry point\n");
|
||||
int sz = 64;
|
||||
uintptr_t lastbyte = GetLastByte(h);
|
||||
if (ep + sz > lastbyte)
|
||||
sz = lastbyte - ep;
|
||||
DumpBinary((char*)ep, sz);
|
||||
}
|
||||
/*
|
||||
// but instead of regular entrypoint, lets grab "main", it will be easier to manage I guess
|
||||
uintptr_t m = FindSymbol(maplib, "main");
|
||||
if(m) {
|
||||
ep = m;
|
||||
printf_log(LOG_DEBUG, "Using \"main\" as Entry Point @%p\n", ep);
|
||||
if(box86_log>=LOG_DUMP) {
|
||||
printf_log(LOG_DUMP, "(short) Dump of Entry point\n");
|
||||
int sz = 64;
|
||||
uintptr_t lastbyte = GetLastByte(h);
|
||||
if (ep + sz > lastbyte)
|
||||
sz = lastbyte - ep;
|
||||
DumpBinary((char*)ep, sz);
|
||||
}
|
||||
}
|
||||
*/
|
||||
return ep;
|
||||
}
|
||||
|
||||
@@ -788,33 +783,118 @@ uintptr_t GetLastByte(elfheader_t* h)
|
||||
return (uintptr_t)h->memory/* + h->delta*/ + h->memsz;
|
||||
}
|
||||
|
||||
#ifndef STB_GNU_UNIQUE
|
||||
#define STB_GNU_UNIQUE 10
|
||||
#endif
|
||||
|
||||
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
|
||||
{
|
||||
printf_log(LOG_DUMP, "Will look for Symbol to add in SymTable(%d)\n", h->numSymTab);
|
||||
if(box86_dump && h->DynSym) DumpDynSym(h);
|
||||
int libcef = (strstr(h->name, "libcef.so") || strstr(h->name, "libnode.so"))?1:0;
|
||||
//libcef.so is linked with tcmalloc staticaly, but this cannot be easily supported in box64, so hacking some "unlink" here
|
||||
const char* avoid_libcef[] = {"malloc", "realloc", "free", "calloc", "cfree",
|
||||
"__libc_calloc", "__libc_cfree", "__libc_memallign", "__liv_pvalloc",
|
||||
"__libcrealloc", "__libc_valloc", "__posix_memalign",
|
||||
"valloc", "pvalloc", "posix_memalign", "malloc_stats", "malloc_usable_size",
|
||||
/*"mallopt",*/ "localtime_r",
|
||||
//c++ symbol from libstdc++ too, but those are generic...
|
||||
};
|
||||
printf_dump(LOG_NEVER, "Will look for Symbol to add in SymTable(%d)\n", h->numSymTab);
|
||||
for (int i=0; i<h->numSymTab; ++i) {
|
||||
const char * symname = h->StrTab+h->SymTab[i].st_name;
|
||||
int bind = ELF32_ST_BIND(h->SymTab[i].st_info);
|
||||
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
|
||||
int vis = h->SymTab[i].st_other&0x3;
|
||||
uint32_t sz = h->SymTab[i].st_size;
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
|
||||
if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname))
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
|
||||
uint32_t sz = h->SymTab[i].st_size;
|
||||
printf_log(LOG_DUMP, "Adding Symbol(bind=%s) \"%s\" with offset=%p sz=%d\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, (void*)offs, sz);
|
||||
if(bind==STB_LOCAL)
|
||||
AddSymbol(localsymbols, symname, offs, sz);
|
||||
else // add in local and global map
|
||||
if(bind==STB_WEAK) {
|
||||
AddSymbol(weaksymbols, symname, offs, sz);
|
||||
} else {
|
||||
AddSymbol(mapsymbols, symname, offs, sz);
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) /*&& (h->SymTab[i].st_shndx!=0)*/) {
|
||||
if(/*sz &&*/ strstr(symname, "@@")) {
|
||||
/*char symnameversionned[strlen(symname)+1];
|
||||
strcpy(symnameversionned, symname);
|
||||
// extact symname@@vername
|
||||
char* p = strchr(symnameversionned, '@');
|
||||
*p=0;
|
||||
p+=2;*/
|
||||
//symname = AddDictionnary(my_context->versym, symnameversionned);
|
||||
const char* vername;
|
||||
symname = AddDefault(my_context->versym, symname, &vername);
|
||||
//const char* vername = AddDictionnary(my_context->versym, p);
|
||||
if(!sz || !h->SymTab[i].st_shndx)
|
||||
continue;
|
||||
if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, vername))
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
|
||||
printf_dump(LOG_NEVER, "Adding Default Versionned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%d\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz);
|
||||
if(bind==STB_LOCAL)
|
||||
AddSymbol(localsymbols, symname, offs, sz, 2, vername);
|
||||
else // add in local and global map
|
||||
if(bind==STB_WEAK) {
|
||||
AddSymbol(weaksymbols, symname, offs, sz, 2, vername);
|
||||
} else {
|
||||
AddSymbol(mapsymbols, symname, offs, sz, 2, vername);
|
||||
}
|
||||
} else {
|
||||
int to_add = (!h->SymTab[i].st_shndx)?0:1;
|
||||
if(libcef) {
|
||||
if(strstr(symname, "_Zn")==symname || strstr(symname, "_Zd")==symname)
|
||||
to_add = 0;
|
||||
for(int j=0; j<sizeof(avoid_libcef)/sizeof(avoid_libcef[0]) && to_add; ++j)
|
||||
if(!strcmp(symname, avoid_libcef[j]))
|
||||
to_add = 0;
|
||||
}
|
||||
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, -1, NULL)))
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
|
||||
printf_dump(LOG_NEVER, "Adding Symbol(bind=%s) \"%s\" with offset=%p sz=%d\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, (void*)offs, sz);
|
||||
if(bind==STB_LOCAL)
|
||||
AddSymbol(localsymbols, symname, offs, sz, 1, NULL);
|
||||
else // add in local and global map
|
||||
if(bind==STB_WEAK) {
|
||||
AddSymbol(weaksymbols, symname, offs, sz, 1, NULL);
|
||||
} else {
|
||||
AddSymbol(mapsymbols, symname, offs, sz, 1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf_log(LOG_DUMP, "Will look for Symbol to add in DynSym (%d)\n", h->numDynSym);
|
||||
|
||||
printf_dump(LOG_NEVER, "Will look for Symbol to add in DynSym (%d)\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i) {
|
||||
const char * symname = h->DynStr+h->DynSym[i].st_name;
|
||||
int bind = ELF32_ST_BIND(h->DynSym[i].st_info);
|
||||
int type = ELF32_ST_TYPE(h->DynSym[i].st_info);
|
||||
int vis = h->DynSym[i].st_other&0x3;
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
|
||||
uint32_t sz = h->DynSym[i].st_size;
|
||||
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
if(version!=-1) version &= 0x7fff;
|
||||
const char* vername = GetSymbolVersion(h, version);
|
||||
int to_add = 1;
|
||||
if(libcef) {
|
||||
if(strstr(symname, "_Zn")==symname || strstr(symname, "_Zd")==symname)
|
||||
to_add = 0;
|
||||
for(int j=0; j<sizeof(avoid_libcef)/sizeof(avoid_libcef[0]) && to_add; ++j)
|
||||
if(!strcmp(symname, avoid_libcef[j]))
|
||||
to_add = 0;
|
||||
}
|
||||
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, -1, NULL)))
|
||||
continue;
|
||||
printf_dump(LOG_NEVER, "Adding Versionned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%d\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
|
||||
if(bind==STB_LOCAL) {
|
||||
AddWeakSymbol(localsymbols, symname, offs, sz, version, vername);
|
||||
} else { // add in local and global map
|
||||
if(bind==STB_WEAK) {
|
||||
AddWeakSymbol(weaksymbols, symname, offs, sz, version, vername);
|
||||
} else {
|
||||
AddWeakSymbol(mapsymbols, symname, offs, sz, version?version:1, vername);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printf_dump(LOG_NEVER, "Will look for Symbol to add in DynSym (%d)\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i) {
|
||||
const char * symname = h->DynStr+h->DynSym[i].st_name;
|
||||
int bind = ELF32_ST_BIND(h->DynSym[i].st_info);
|
||||
@@ -827,7 +907,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
|
||||
uint32_t sz = h->DynSym[i].st_size;
|
||||
printf_log(LOG_DUMP, "Adding Symbol(bind=%s) \"%s\" with offset=%p sz=%d\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, (void*)offs, sz);
|
||||
printf_dump(LOG_NEVER, "Adding Symbol(bind=%s) \"%s\" with offset=%p sz=%d\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, (void*)offs, sz);
|
||||
if(bind==STB_LOCAL)
|
||||
AddSymbol(localsymbols, symname, offs, sz);
|
||||
else // add in local and global map
|
||||
@@ -838,7 +918,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -905,16 +985,22 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
|
||||
h->neededlibs = neededlibs;
|
||||
|
||||
DumpDynamicNeeded(h);
|
||||
int cnt = 0;
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED) {
|
||||
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, needed, box86, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed);
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
}
|
||||
}
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED)
|
||||
++cnt;
|
||||
const char* nlibs[cnt];
|
||||
int j=0;
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED)
|
||||
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, nlibs, cnt, box86, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading one of needed lib\n");
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -949,14 +1035,28 @@ void RunElfInit(elfheader_t* h, x86emu_t *emu)
|
||||
context->deferedInitList[context->deferedInitSz++] = h;
|
||||
return;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
// Refresh no-file part of TLS in case default value changed
|
||||
if(h->tlsfilesize) {
|
||||
char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
|
||||
printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%x\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
|
||||
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
|
||||
tlsdatasize_t* ptr;
|
||||
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL)
|
||||
if(ptr->tlssize==my_context->tlssize) {
|
||||
// refresh in tlsdata too
|
||||
dest = (char*)(ptr->tlsdata+ptr->tlssize+h->tlsbase);
|
||||
printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%x\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
|
||||
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
|
||||
}
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
|
||||
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
// and check init array now
|
||||
Elf32_Addr *addr = (Elf32_Addr*)(h->initarray + h->delta);
|
||||
for (int i=0; i<h->initarray_sz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Calling Init[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
|
||||
}
|
||||
|
||||
@@ -975,11 +1075,13 @@ void RunDeferedElfInit(x86emu_t *emu)
|
||||
context->deferedInit = 0;
|
||||
if(!context->deferedInitList)
|
||||
return;
|
||||
for (int i=0; i<context->deferedInitSz; ++i)
|
||||
RunElfInit(context->deferedInitList[i], emu);
|
||||
free(context->deferedInitList);
|
||||
int Sz = context->deferedInitSz;
|
||||
elfheader_t** List = context->deferedInitList;
|
||||
context->deferedInitList = NULL;
|
||||
context->deferedInitCap = context->deferedInitSz = 0;
|
||||
for (int i=0; i<Sz; ++i)
|
||||
RunElfInit(List[i], emu);
|
||||
free(List);
|
||||
}
|
||||
|
||||
void RunElfFini(elfheader_t* h, x86emu_t *emu)
|
||||
@@ -994,13 +1096,13 @@ void RunElfFini(elfheader_t* h, x86emu_t *emu)
|
||||
// first check fini array
|
||||
Elf32_Addr *addr = (Elf32_Addr*)(h->finiarray + h->delta);
|
||||
for (int i=h->finiarray_sz-1; i>=0; --i) {
|
||||
printf_log(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
printf_log(LOG_DEBUG, "Calling Fini[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
|
||||
}
|
||||
// then the "old-style" fini
|
||||
if(h->finientry) {
|
||||
uintptr_t p = h->finientry + h->delta;
|
||||
printf_log(LOG_DEBUG, "Calling Fini for %s @%p\n", ElfName(h), (void*)p);
|
||||
printf_log(LOG_DEBUG, "Calling Fini for %s %p\n", ElfName(h), (void*)p);
|
||||
RunFunctionWithEmu(emu, 0, p, 0);
|
||||
}
|
||||
h->init_done = 0; // can be re-inited again...
|
||||
@@ -1099,6 +1201,43 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername)
|
||||
{
|
||||
if(ver==-1)
|
||||
return name;
|
||||
const char *v=NULL;
|
||||
if(ver==0)
|
||||
v="";
|
||||
if(ver==1)
|
||||
v="*";
|
||||
if(!v && !vername)
|
||||
return name;
|
||||
if(ver>1)
|
||||
v = vername;
|
||||
char buf[strlen(name)+strlen(v)+1+1];
|
||||
strcpy(buf, name);
|
||||
strcat(buf, "@");
|
||||
strcat(buf, v);
|
||||
return AddDictionnary(my_context->versym, buf);
|
||||
}
|
||||
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2)
|
||||
{
|
||||
if(strcmp(name1, name2)) //name are different, no need to go further
|
||||
return 0;
|
||||
if(ver1==-1 || ver2==-1) // don't check version, so ok
|
||||
return 1;
|
||||
if(ver1==ver2 && ver1<2) // same ver (local or global), ok
|
||||
return 1;
|
||||
if(ver1==0 || ver2==0) // one is local, the other is not, no match
|
||||
return 0;
|
||||
if(ver1==1 || ver2==1) // one if global, ok
|
||||
return 1;
|
||||
if(!strcmp(vername1, vername2)) // same vername
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* GetDTatOffset(box86context_t* context, int index, int offset)
|
||||
{
|
||||
return (void*)((char*)GetTLSPointer(context, context->elfs[index])+offset);
|
||||
@@ -1239,6 +1378,21 @@ void ResetSpecialCaseMainElf(elfheader_t* h)
|
||||
memcpy((void*)sym->st_value+h->delta, stdout, sym->st_size);
|
||||
my__IO_2_1_stdout_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stdout_ to %p\n", my__IO_2_1_stdout_);
|
||||
} else
|
||||
if(strcmp(symname, "_IO_stderr_")==0 && ((void*)sym->st_value+h->delta)) {
|
||||
memcpy((void*)sym->st_value+h->delta, stderr, sym->st_size);
|
||||
my__IO_2_1_stderr_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_stderr_ to %p\n", my__IO_2_1_stderr_);
|
||||
} else
|
||||
if(strcmp(symname, "_IO_stdin_")==0 && ((void*)sym->st_value+h->delta)) {
|
||||
memcpy((void*)sym->st_value+h->delta, stdin, sym->st_size);
|
||||
my__IO_2_1_stdin_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_stdin_ to %p\n", my__IO_2_1_stdin_);
|
||||
} else
|
||||
if(strcmp(symname, "_IO_stdout_")==0 && ((void*)sym->st_value+h->delta)) {
|
||||
memcpy((void*)sym->st_value+h->delta, stdout, sym->st_size);
|
||||
my__IO_2_1_stdout_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_stdout_ to %p\n", my__IO_2_1_stdout_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1288,48 +1442,37 @@ EXPORT void PltResolver(x86emu_t* emu)
|
||||
uintptr_t addr = Pop32(emu);
|
||||
int slot = (int)Pop32(emu);
|
||||
elfheader_t *h = (elfheader_t*)addr;
|
||||
printf_log(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", (void*)addr, slot, *(void**)(R_ESP), h->name, h->VerSym);
|
||||
|
||||
printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", (void*)addr, slot, *(void**)(R_ESP), h->name, h->VerSym);
|
||||
Elf32_Rel * rel = (Elf32_Rel *)(h->jmprel + h->delta + slot);
|
||||
|
||||
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel->r_info)];
|
||||
int bind = ELF32_ST_BIND(sym->st_info);
|
||||
const char* symname = SymName(h, sym);
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel->r_info)]:0;
|
||||
const char* ver = GetSymbolVersion(h, version);
|
||||
char symnameversionned[501];
|
||||
strncpy(symnameversionned, symname, 500);
|
||||
if(ver) {
|
||||
strncat(symnameversionned, "@", 500);
|
||||
strncat(symnameversionned, ver, 500);
|
||||
}
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel->r_info)]:-1;
|
||||
if(version!=-1) version &= 0x7fff;
|
||||
const char* vername = GetSymbolVersion(h, version);
|
||||
uint32_t *p = (uint32_t*)(rel->r_offset + h->delta);
|
||||
uintptr_t offs = 0;
|
||||
uintptr_t end = 0;
|
||||
|
||||
library_t* lib = h->lib;
|
||||
lib_t* local_maplib = GetMaplib(lib);
|
||||
if(local_maplib) {
|
||||
GetGlobalSymbolStartEnd(local_maplib, symnameversionned, &offs, &end);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end);
|
||||
}
|
||||
if(!offs && !end) {
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symnameversionned, &offs, &end);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end);
|
||||
}
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername);
|
||||
if(!offs && !end && !version)
|
||||
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL);
|
||||
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: PltReolver: Symbol %s(%s) not found, cannot apply R_386_JMP_SLOT @%p (%p) in %s\n", symname, symnameversionned, p, *(void**)p, h->name);
|
||||
printf_log(LOG_NONE, "Error: PltReolver: Symbol %s(ver %d: %s%s%s) not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name);
|
||||
emu->quit = 1;
|
||||
return;
|
||||
} else {
|
||||
if(p) {
|
||||
printf_log(LOG_DEBUG, "PltReolver: Apply %s R_386_JMP_SLOT @%p with sym=%s(%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, symnameversionned,*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
|
||||
printf_dump(LOG_DEBUG, " Apply %s R_386_JMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "PltReolver: Warning, Symbol %s(%s) found, but Jump Slot Offset is NULL \n", symname, symnameversionned);
|
||||
printf_log(LOG_NONE, "PltReolver: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ struct elfheader_s {
|
||||
Elf32_Half* VerSym;
|
||||
Elf32_Verneed* VerNeed;
|
||||
int szVerNeed;
|
||||
Elf32_Verdef* VerDef;
|
||||
int szVerDef;
|
||||
int e_type;
|
||||
|
||||
intptr_t delta; // should be 0
|
||||
@@ -71,7 +73,9 @@ struct elfheader_s {
|
||||
uint32_t memsz;
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
uintptr_t tlsaddr;
|
||||
uint32_t tlssize;
|
||||
uint32_t tlsfilesize;
|
||||
int tlsalign;
|
||||
|
||||
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
|
||||
+36
-8
@@ -177,14 +177,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
if(box86_log>=LOG_DUMP) DumpMainHeader(&header, h);
|
||||
if(box86_dump) DumpMainHeader(&header, h);
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
|
||||
if(box86_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
|
||||
if(box86_dump && h->SymTab) DumpSymTab(h);
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
|
||||
if(box86_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
|
||||
if(box86_dump && h->Dynamic) DumpDynamicSections(h);
|
||||
// grab DT_REL & DT_RELA stuffs
|
||||
// also grab the DT_STRTAB string table
|
||||
{
|
||||
@@ -212,7 +212,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->relaent = val;
|
||||
break;
|
||||
case DT_PLTGOT:
|
||||
h->pltgot = val;
|
||||
h->pltgot = ptr;
|
||||
break;
|
||||
case DT_PLTREL:
|
||||
h->pltrel = val;
|
||||
@@ -221,7 +221,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->pltsz = val;
|
||||
break;
|
||||
case DT_JMPREL:
|
||||
h->jmprel = val;
|
||||
h->jmprel = ptr;
|
||||
break;
|
||||
case DT_STRTAB:
|
||||
h->DynStrTab = (char *)(ptr);
|
||||
@@ -254,13 +254,21 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
|
||||
break;
|
||||
case DT_VERNEEDNUM:
|
||||
h->szVerNeed = val / sizeof(Elf32_Verneed);
|
||||
h->szVerNeed = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
|
||||
break;
|
||||
case DT_VERNEED:
|
||||
h->VerNeed = (Elf32_Verneed*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
|
||||
break;
|
||||
case DT_VERDEFNUM:
|
||||
h->szVerDef = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
|
||||
break;
|
||||
case DT_VERDEF:
|
||||
h->VerDef = (Elf32_Verdef*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(h->rel) {
|
||||
@@ -335,7 +343,6 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
|
||||
if(box86_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
|
||||
}
|
||||
|
||||
return h;
|
||||
@@ -345,6 +352,8 @@ const char* GetSymbolVersion(elfheader_t* h, int version)
|
||||
{
|
||||
if(!h->VerNeed || (version<2))
|
||||
return NULL;
|
||||
/*if(version==1)
|
||||
return "*";*/
|
||||
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
@@ -355,5 +364,24 @@ const char* GetSymbolVersion(elfheader_t* h, int version)
|
||||
}
|
||||
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
|
||||
}
|
||||
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index)
|
||||
{
|
||||
if(!h->VerDef || (index<1))
|
||||
return NULL;
|
||||
Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef + h->delta);
|
||||
while(def) {
|
||||
if(def->vd_ndx==index) {
|
||||
if(def->vd_cnt<1)
|
||||
return NULL;
|
||||
/*if(def->vd_flags&VER_FLG_BASE)
|
||||
return NULL;*/
|
||||
Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux);
|
||||
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
|
||||
}
|
||||
def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -111,7 +111,7 @@
|
||||
} else getecommono(A, reg32_t, O)
|
||||
#define getem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->mmx87[(nextop&7)]; \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else getecommon(A, mmx87_regs_t)
|
||||
#define getex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
@@ -141,7 +141,7 @@
|
||||
#define EX opex
|
||||
#define GB emu->regs[(nextop>>3)&3].byte[(nextop>>5)&0x1]
|
||||
#define GD emu->regs[((nextop&0x38)>>3)]
|
||||
#define GM emu->mmx87[((nextop&0x38)>>3)]
|
||||
#define GM emu->mmx[((nextop&0x38)>>3)]
|
||||
#define GX emu->xmm[((nextop&0x38)>>3)]
|
||||
|
||||
// Alias
|
||||
|
||||
+78
-40
@@ -3,6 +3,18 @@
|
||||
_0f_0x00: /* VERx Ed */
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* SLDT Ew */
|
||||
GET_EW;
|
||||
EW->word[0] = 0;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
EW->word[1] = 0;
|
||||
break;
|
||||
case 1: /* STR Ew */
|
||||
GET_EW;
|
||||
EW->word[0] = 0x7f; // dummy return
|
||||
if((nextop&0xC0)==0xC0)
|
||||
EW->word[1] = 0;
|
||||
break;
|
||||
case 4: //VERR
|
||||
case 5: //VERW
|
||||
GET_EW;
|
||||
@@ -18,6 +30,18 @@
|
||||
_0f_0x01:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* SGDT Ed */
|
||||
GET_ED;
|
||||
ED->word[0] = 0x7f; // dummy return...
|
||||
ED->word[1] = 0x000c;
|
||||
ED->word[2] = 0xd000;
|
||||
break;
|
||||
case 1: /* SIDT Ed */
|
||||
GET_ED;
|
||||
ED->word[0] = 0xfff; // dummy return, like "disabled"
|
||||
ED->word[1] = 0;
|
||||
ED->word[2] = 0;
|
||||
break;
|
||||
case 4: /* SMSW Ew */
|
||||
GET_ED;
|
||||
// dummy for now... Do I need to track CR0 state?
|
||||
@@ -214,6 +238,17 @@
|
||||
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
|
||||
}
|
||||
break;
|
||||
case 0x09: /* PSIGNW Gm, Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
if (EM->sw[i] < 0) {
|
||||
GM.sw[i] = -GM.sw[i];
|
||||
} else if (EM->sw[i] == 0) {
|
||||
GM.sw[i] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x0B: /* PMULHRSW Gm, Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
@@ -250,6 +285,31 @@
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0x3A:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0xF: /* palignr */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
tmp8u = F8;
|
||||
if (tmp8u >= 16) {
|
||||
GM.q = 0;
|
||||
} else if (tmp8u > 8) {
|
||||
tmp8u -= 8;
|
||||
GM.q >>= tmp8u*8;
|
||||
} else if (tmp8u == 8 || tmp8u == 0) {
|
||||
|
||||
} else {
|
||||
GM.q <<= (8-tmp8u)*8;
|
||||
GM.q |= (EM->q >> tmp8u*8);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0x3F:
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip-2;
|
||||
@@ -722,12 +782,13 @@
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = GD.byte[0];
|
||||
tmp32s = GD.sdword[0];
|
||||
tmp8u=tmp32s&31;
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
@@ -754,12 +815,13 @@
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = GD.byte[0];
|
||||
tmp32s = GD.sdword[0];
|
||||
tmp8u=tmp32s&31;
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
@@ -789,20 +851,10 @@
|
||||
GET_ED;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FXSAVE m512byte */
|
||||
// should save flags & all
|
||||
// copy MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(((void*)(ED))+32+i*16, &emu->mmx87[0], sizeof(emu->mmx87[0]));
|
||||
// copy SSE regs
|
||||
memcpy(((void*)(ED))+160, &emu->xmm[0], sizeof(emu->xmm));
|
||||
fpu_fxsave(emu, ED);
|
||||
break;
|
||||
case 1: /* FXRSTOR m512byte */
|
||||
// should restore flags & all
|
||||
// copy back MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx87[i], ((void*)(ED))+32+i*16, sizeof(emu->mmx87[0]));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], ((void*)(ED))+160/4, sizeof(emu->xmm));
|
||||
fpu_fxrstor(emu, ED);
|
||||
break;
|
||||
case 2: /* LDMXCSR Md */
|
||||
emu->mxcsr = ED->dword[0];
|
||||
@@ -844,12 +896,13 @@
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = GD.byte[0];
|
||||
tmp32s = GD.sdword[0];
|
||||
tmp8u=tmp32s&31;
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
@@ -875,10 +928,6 @@
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -889,10 +938,6 @@
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
@@ -905,10 +950,6 @@
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
@@ -920,10 +961,6 @@
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -940,12 +977,13 @@
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = GD.byte[0];
|
||||
tmp32s = GD.sdword[0];
|
||||
tmp8u=tmp32s&31;
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
}
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
|
||||
+10
-6
@@ -8,9 +8,9 @@
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7: /* FLD STx */
|
||||
ll = ST(nextop&7).q;
|
||||
ll = ST(nextop&7).sq;
|
||||
fpu_do_push(emu);
|
||||
ST0.q = ll;
|
||||
ST0.sq = ll;
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -20,9 +20,9 @@
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* FXCH STx */
|
||||
ll = ST(nextop&7).q;
|
||||
ST(nextop&7).q = ST0.q;
|
||||
ST0.q = ll;
|
||||
ll = ST(nextop&7).sq;
|
||||
ST(nextop&7).sq = ST0.sq;
|
||||
ST0.sq = ll;
|
||||
break;
|
||||
|
||||
case 0xD0: /* FNOP */
|
||||
@@ -153,19 +153,23 @@
|
||||
case 0xFB: /* FSINCOS */
|
||||
fpu_do_push(emu);
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
case 0xFC: /* FRNDINT */
|
||||
ST0.d = fpu_round(emu, ST0.d);
|
||||
break;
|
||||
case 0xFD: /* FSCALE */
|
||||
// this could probably be done by just altering the exponant part of the float...
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
break;
|
||||
case 0xFE: /* FSIN */
|
||||
ST0.d = sin(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
case 0xFF: /* FCOS */
|
||||
ST0.d = cos(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -133,11 +133,11 @@
|
||||
fpu_do_push(emu);
|
||||
memcpy(&STld(0).ld, ED, 10);
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
STld(0).ref = ST0.q;
|
||||
STld(0).uref = ST0.q;
|
||||
break;
|
||||
case 7: /* FSTP tbyte */
|
||||
GET_ED;
|
||||
if(ST0.q!=STld(0).ref)
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, ED);
|
||||
else
|
||||
memcpy(ED, &STld(0).ld, 10);
|
||||
|
||||
+6
-6
@@ -125,8 +125,8 @@
|
||||
tmp64s = *(int64_t*)ED;
|
||||
fpu_do_push(emu);
|
||||
ST0.d = tmp64s;
|
||||
STll(0).ll = tmp64s;
|
||||
STll(0).ref = ST0.q;
|
||||
STll(0).sq = tmp64s;
|
||||
STll(0).sref = ST0.sq;
|
||||
break;
|
||||
case 6: /* FBSTP tbytes, ST0 */
|
||||
GET_ED;
|
||||
@@ -137,8 +137,8 @@
|
||||
GET_ED;
|
||||
if((uintptr_t)ED & 0x7) {
|
||||
// un-aligned!
|
||||
if(STll(0).ref==ST(0).q)
|
||||
memcpy(ED, &STll(0).ll, sizeof(int64_t));
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
memcpy(ED, &STll(0).sq, sizeof(int64_t));
|
||||
else {
|
||||
int64_t i64;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
@@ -148,8 +148,8 @@
|
||||
memcpy(ED, &i64, sizeof(int64_t));
|
||||
}
|
||||
} else {
|
||||
if(STll(0).ref==ST(0).q)
|
||||
*(int64_t*)ED = STll(0).ll;
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
*(int64_t*)ED = STll(0).sq;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
*(int64_t*)ED = 0x8000000000000000LL;
|
||||
|
||||
+2
-2
@@ -218,8 +218,8 @@
|
||||
tmp8s = 0;
|
||||
switch(tmp8u&7) {
|
||||
case 0: tmp8s=(GX.d[0] == EX->d[0]); break;
|
||||
case 1: tmp8s=isless(GX.d[0], EX->d[0]); break;
|
||||
case 2: tmp8s=islessequal(GX.d[0], EX->d[0]); break;
|
||||
case 1: tmp8s=isless(GX.d[0], EX->d[0]) && !(isnan(GX.d[0]) || isnan(EX->d[0])); break;
|
||||
case 2: tmp8s=islessequal(GX.d[0], EX->d[0]) && !(isnan(GX.d[0]) || isnan(EX->d[0])); break;
|
||||
case 3: tmp8s=isnan(GX.d[0]) || isnan(EX->d[0]); break;
|
||||
case 4: tmp8s=(GX.d[0] != EX->d[0]); break;
|
||||
case 5: tmp8s=isnan(GX.d[0]) || isnan(EX->d[0]) || isgreaterequal(GX.d[0], EX->d[0]); break;
|
||||
|
||||
+20
-2
@@ -182,6 +182,24 @@
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xBD: /* LZCNT Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp32u = ED->dword[0];
|
||||
if(tmp32u) {
|
||||
tmp8u = 0;
|
||||
while(!(tmp32u&(1<<(31-tmp8u)))) ++tmp8u;
|
||||
GD.dword[0] = tmp8u;
|
||||
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
SET_FLAG(F_CF);
|
||||
CLEAR_FLAG(F_ZF);
|
||||
GD.dword[0] = 32;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC2: /* CMPSS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -189,8 +207,8 @@
|
||||
tmp8s = 0;
|
||||
switch(tmp8u&7) {
|
||||
case 0: tmp8s=(GX.f[0] == EX->f[0]); break;
|
||||
case 1: tmp8s=isless(GX.f[0], EX->f[0]); break;
|
||||
case 2: tmp8s=islessequal(GX.f[0], EX->f[0]); break;
|
||||
case 1: tmp8s=isless(GX.f[0], EX->f[0]) && !(isnan(GX.f[0]) || isnan(EX->f[0])); break;
|
||||
case 2: tmp8s=islessequal(GX.f[0], EX->f[0]) && !(isnan(GX.f[0]) || isnan(EX->f[0])); break;
|
||||
case 3: tmp8s=isnan(GX.f[0]) || isnan(EX->f[0]); break;
|
||||
case 4: tmp8s=(GX.f[0] != EX->f[0]); break;
|
||||
case 5: tmp8s=isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(GX.f[0], EX->f[0]); break;
|
||||
|
||||
+18
-12
@@ -49,13 +49,13 @@ uint32_t* GetParityTab()
|
||||
|
||||
void PushExit(x86emu_t* emu)
|
||||
{
|
||||
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
|
||||
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
|
||||
Push(emu, endMarker);
|
||||
}
|
||||
|
||||
void* GetExit()
|
||||
{
|
||||
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
|
||||
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
|
||||
}
|
||||
|
||||
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
||||
@@ -211,12 +211,12 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
newemu->old_ip = emu->old_ip;
|
||||
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
|
||||
memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
|
||||
memcpy(newemu->mmx87, emu->mmx87, sizeof(emu->mmx87));
|
||||
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
|
||||
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
|
||||
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
|
||||
newemu->cw = emu->cw;
|
||||
newemu->cw_mask_all = emu->cw_mask_all;
|
||||
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
@@ -308,7 +308,7 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
|
||||
if(trace_emm) {
|
||||
// do emm reg is needed
|
||||
for(int i=0; i<8; ++i) {
|
||||
sprintf(tmp, "mm%d:%016llx", i, emu->mmx87[i].q);
|
||||
sprintf(tmp, "mm%d:%016llx", i, emu->mmx[i].q);
|
||||
strcat(buff, tmp);
|
||||
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
|
||||
}
|
||||
@@ -323,13 +323,18 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
|
||||
}
|
||||
// start with FPU regs...
|
||||
if(emu->fpu_stack) {
|
||||
for (int i=0; i<emu->fpu_stack; i++) {
|
||||
sprintf(tmp, "ST%d=%f", i, emu->mmx87[(emu->top+i)&7].d);
|
||||
if(emu->fpu_stack<8)
|
||||
for (int i=0; i<emu->fpu_stack; i++) {
|
||||
sprintf(tmp, "ST%d=%f", i, emu->x87[(emu->top+i)&7].d);
|
||||
strcat(buff, tmp);
|
||||
int c = 10-strlen(tmp);
|
||||
if(c<1) c=1;
|
||||
while(c--) strcat(buff, " ");
|
||||
if(i==3) strcat(buff, "\n");
|
||||
}
|
||||
else {
|
||||
sprintf(tmp, "Warning, incoherent fpu_stack=%d", emu->fpu_stack);
|
||||
strcat(buff, tmp);
|
||||
int c = 10-strlen(tmp);
|
||||
if(c<1) c=1;
|
||||
while(c--) strcat(buff, " ");
|
||||
if(i==3) strcat(buff, "\n");
|
||||
}
|
||||
strcat(buff, "\n");
|
||||
}
|
||||
@@ -401,7 +406,8 @@ void EmuCall(x86emu_t* emu, uintptr_t addr)
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_EBX = old_ebx;
|
||||
R_EDI = old_edi;
|
||||
|
||||
@@ -28,10 +28,10 @@ typedef struct x86emu_s {
|
||||
reg32_t regs[8];
|
||||
x86flags_t eflags;
|
||||
reg32_t ip;
|
||||
uintptr_t old_ip;
|
||||
// fpu / mmx
|
||||
mmx87_regs_t mmx87[8];
|
||||
uint16_t cw,cw_mask_all;
|
||||
mmx87_regs_t x87[8];
|
||||
mmx87_regs_t mmx[8];
|
||||
uint16_t cw;
|
||||
x87flags_t sw;
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separatly
|
||||
int fpu_stack;
|
||||
@@ -42,6 +42,7 @@ typedef struct x86emu_s {
|
||||
// sse
|
||||
sse_regs_t xmm[8];
|
||||
uint32_t mxcsr;
|
||||
uintptr_t old_ip;
|
||||
// defered flags
|
||||
defered_flags_t df;
|
||||
uint32_t op1;
|
||||
|
||||
+24
-12
@@ -70,7 +70,7 @@ void x86Int3(x86emu_t* emu)
|
||||
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
|
||||
{
|
||||
R_EIP += 2;
|
||||
#ifdef RK3399
|
||||
#if defined(RK3399) || defined(GOA_CLONE)
|
||||
volatile // to avoid addr to be put in an VFPU register
|
||||
#endif
|
||||
uint32_t addr = Fetch32(emu);
|
||||
@@ -86,7 +86,6 @@ void x86Int3(x86emu_t* emu)
|
||||
int have_trace = 0;
|
||||
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
|
||||
if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
int tid = GetTID();
|
||||
char buff[256] = "\0";
|
||||
char buff2[64] = "\0";
|
||||
@@ -96,12 +95,7 @@ void x86Int3(x86emu_t* emu)
|
||||
int perr = 0;
|
||||
uint32_t *pu32 = NULL;
|
||||
const char *s = NULL;
|
||||
{
|
||||
Dl_info info;
|
||||
if(dladdr((void*)addr, &info))
|
||||
s = info.dli_sname;
|
||||
}
|
||||
if(!s) s = GetNativeName((void*)addr);
|
||||
s = GetNativeName((void*)addr);
|
||||
if(addr==(uintptr_t)PltResolver) {
|
||||
snprintf(buff, 256, "%s", " ... ");
|
||||
} else
|
||||
@@ -182,10 +176,10 @@ void x86Int3(x86emu_t* emu)
|
||||
perr = 1;
|
||||
} else if(!strcmp(s, "my_mmap64")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
|
||||
perr = 1;
|
||||
perr = 3;
|
||||
} else if(!strcmp(s, "my_mmap")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
|
||||
perr = 1;
|
||||
perr = 3;
|
||||
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "gtk_signal_connect_full")) {
|
||||
@@ -208,8 +202,12 @@ void x86Int3(x86emu_t* emu)
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "my___snprintf_chk")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "my_snprintf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "my_sprintf")==s) {
|
||||
@@ -221,6 +219,15 @@ void x86Int3(x86emu_t* emu)
|
||||
if(((uintptr_t)pu32)<0x5) // probably a _chk function
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
|
||||
} else if(strstr(s, "my_wprintf")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
if(((uintptr_t)pu32)<0x5) // probably a _chk function
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
|
||||
} else if(strstr(s, "my___vswprintf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 6;
|
||||
} else if(strstr(s, "puts")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
} else if(strstr(s, "fputs")==s) {
|
||||
@@ -269,10 +276,10 @@ void x86Int3(x86emu_t* emu)
|
||||
} else {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
}
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, "%s =>", buff);
|
||||
pthread_mutex_unlock(&emu->context->mutex_trace);
|
||||
w(emu, addr); // some function never come back, so unlock the mutex first!
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
if(post)
|
||||
switch(post) {
|
||||
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
|
||||
@@ -291,11 +298,16 @@ void x86Int3(x86emu_t* emu)
|
||||
snprintf(buff2, 63, "NULL Surface");
|
||||
}
|
||||
break;
|
||||
case 6: snprintf(buff2, 63, "(%S)", pu32?((wchar_t*)pu32):L"nil");
|
||||
break;
|
||||
}
|
||||
if(perr==1 && ((int)R_EAX)<0)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
else if(perr==2 && R_EAX==0)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
else if(perr==3 && ((int)R_EAX)==-1)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
|
||||
pthread_mutex_unlock(&emu->context->mutex_trace);
|
||||
} else
|
||||
|
||||
+15
-15
@@ -714,7 +714,7 @@ uint8_t rol8(x86emu_t *emu, uint8_t d, uint8_t s)
|
||||
if((cnt = s % 8) != 0) {
|
||||
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -741,7 +741,7 @@ uint16_t rol16(x86emu_t *emu, uint16_t d, uint8_t s)
|
||||
if((cnt = s % 16) != 0) {
|
||||
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -768,7 +768,7 @@ uint32_t rol32(x86emu_t *emu, uint32_t d, uint8_t s)
|
||||
if((cnt = s % 32) != 0) {
|
||||
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -795,7 +795,7 @@ uint8_t ror8(x86emu_t *emu, uint8_t d, uint8_t s)
|
||||
if((cnt = s % 8) != 0) {
|
||||
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -822,7 +822,7 @@ uint16_t ror16(x86emu_t *emu, uint16_t d, uint8_t s)
|
||||
if((cnt = s % 16) != 0) {
|
||||
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -849,7 +849,7 @@ uint32_t ror32(x86emu_t *emu, uint32_t d, uint8_t s)
|
||||
if((cnt = s % 32) != 0) {
|
||||
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -1276,10 +1276,10 @@ void div16(x86emu_t *emu, uint16_t s)
|
||||
INTR_RAISE_DIV0(emu);
|
||||
return;
|
||||
}
|
||||
CLEAR_FLAG(F_CF);
|
||||
CLEAR_FLAG(F_SF);
|
||||
CONDITIONAL_SET_FLAG(div == 0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
|
||||
//CLEAR_FLAG(F_CF);
|
||||
//CLEAR_FLAG(F_SF);
|
||||
//CONDITIONAL_SET_FLAG(div == 0, F_ZF);
|
||||
//CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
|
||||
|
||||
R_AX = (uint16_t)div;
|
||||
R_DX = (uint16_t)mod;
|
||||
@@ -1305,11 +1305,11 @@ void div32(x86emu_t *emu, uint32_t s)
|
||||
INTR_RAISE_DIV0(emu);
|
||||
return;
|
||||
}
|
||||
CLEAR_FLAG(F_CF);
|
||||
CLEAR_FLAG(F_AF);
|
||||
CLEAR_FLAG(F_SF);
|
||||
SET_FLAG(F_ZF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
|
||||
//CLEAR_FLAG(F_CF);
|
||||
//CLEAR_FLAG(F_AF);
|
||||
//CLEAR_FLAG(F_SF);
|
||||
//SET_FLAG(F_ZF);
|
||||
//CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
|
||||
|
||||
R_EAX = (uint32_t)div;
|
||||
R_EDX = (uint32_t)mod;
|
||||
|
||||
@@ -97,6 +97,7 @@ Implements the DEC instruction and side effects.
|
||||
****************************************************************************/
|
||||
static inline uint8_t dec8(x86emu_t *emu, uint8_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
emu->res = d - 1;
|
||||
emu->op1 = d;
|
||||
emu->df = d_dec8;
|
||||
@@ -109,6 +110,7 @@ Implements the DEC instruction and side effects.
|
||||
****************************************************************************/
|
||||
static inline uint16_t dec16(x86emu_t *emu, uint16_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
emu->res = d - 1;
|
||||
emu->op1 = d;
|
||||
emu->df = d_dec16;
|
||||
@@ -122,6 +124,7 @@ Implements the DEC instruction and side effects.
|
||||
****************************************************************************/
|
||||
static inline uint32_t dec32(x86emu_t *emu, uint32_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
emu->res = d - 1;
|
||||
emu->op1 = d;
|
||||
emu->df = d_dec32;
|
||||
@@ -135,6 +138,7 @@ Implements the INC instruction and side effects.
|
||||
****************************************************************************/
|
||||
static inline uint8_t inc8(x86emu_t *emu, uint8_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
emu->res = d + 1;
|
||||
emu->op1 = d;
|
||||
emu->df = d_inc8;
|
||||
@@ -147,6 +151,7 @@ Implements the INC instruction and side effects.
|
||||
****************************************************************************/
|
||||
static inline uint16_t inc16(x86emu_t *emu, uint16_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
emu->res = d + 1;
|
||||
emu->op1 = d;
|
||||
emu->df = d_inc16;
|
||||
@@ -159,6 +164,7 @@ Implements the INC instruction and side effects.
|
||||
****************************************************************************/
|
||||
static inline uint32_t inc32(x86emu_t *emu, uint32_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
if(emu->df == d_shr32) {
|
||||
// workaround for some wine trickery
|
||||
uint32_t cnt = emu->op2;
|
||||
|
||||
+16
-10
@@ -94,7 +94,7 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_0xD6, &&_0xD7,
|
||||
&&_0xD8, &&_0xD9, &&_0xDA, &&_0xDB, &&_0xDC, &&_0xDD, &&_0xDE, &&_0xDF,
|
||||
&&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_0xE4, &&_0xE5, &&_0xE6, &&_0xE7,
|
||||
&&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_default, &&_default,
|
||||
&&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_0xEE, &&_default,
|
||||
&&_0xF0, &&_0xF1, &&_0xF2, &&_0xF3, &&_0xF4, &&_0xF5, &&_0xF6, &&_0xF7,
|
||||
&&_0xF8, &&_0xF9, &&_0xFA, &&_0xFB, &&_0xFC, &&_0xFD, &&_0xFE, &&_0xFF
|
||||
};
|
||||
@@ -107,7 +107,7 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
|
||||
&&_0f_0x28, &&_0f_0x29, &&_0f_0x2A, &&_0f_0x2B, &&_0f_0x2C, &&_0f_0x2D, &&_0f_0x2E, &&_0f_0x2F,
|
||||
&&_default, &&_0f_0x31, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
|
||||
&&_0f_0x38, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_0f_0x3F, //0x38-0x3F
|
||||
&&_0f_0x38, &&_default, &&_0f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_0f_0x3F, //0x38-0x3F
|
||||
&&_0f_0x40_0, &&_0f_0x40_1, &&_0f_0x40_2, &&_0f_0x40_3, &&_0f_0x40_4, &&_0f_0x40_5, &&_0f_0x40_6, &&_0f_0x40_7,
|
||||
&&_0f_0x40_8, &&_0f_0x40_9, &&_0f_0x40_A, &&_0f_0x40_B, &&_0f_0x40_C, &&_0f_0x40_D, &&_0f_0x40_E, &&_0f_0x40_F,
|
||||
&&_0f_0x50, &&_0f_0x51, &&_0f_0x52, &&_0f_0x53, &&_0f_0x54, &&_0f_0x55, &&_0f_0x56, &&_0f_0x57, //0x50-0x57
|
||||
@@ -685,7 +685,10 @@ _trace:
|
||||
_0x8C: /* MOV Ed, Seg */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
if((nextop&0xC0)==0xC0)
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
else
|
||||
ED->word[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
NEXT;
|
||||
_0x8D: /* LEA Gd,M */
|
||||
nextop = F8;
|
||||
@@ -900,16 +903,16 @@ _trace:
|
||||
_0xC4: /* LES Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
emu->segs[_ES] = ED->word[0];
|
||||
emu->segs[_ES] = *(__uint16_t*)(((char*)ED)+4);
|
||||
emu->segs_serial[_ES] = 0;
|
||||
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
|
||||
GD.dword[0] = *(uint32_t*)ED;
|
||||
NEXT;
|
||||
_0xC5: /* LDS Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
emu->segs[_DS] = ED->word[0];
|
||||
emu->segs[_DS] = *(__uint16_t*)(((char*)ED)+4);
|
||||
emu->segs_serial[_DS] = 0;
|
||||
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
|
||||
GD.dword[0] = *(uint32_t*)ED;
|
||||
NEXT;
|
||||
_0xC6: /* MOV Eb,Ib */
|
||||
nextop = F8;
|
||||
@@ -976,7 +979,7 @@ _trace:
|
||||
|
||||
_0xCF: /* IRET */
|
||||
ip = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu)&0xffff;
|
||||
emu->segs_serial[_CS] = 0;
|
||||
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
|
||||
RESET_FLAGS(emu);
|
||||
@@ -1120,6 +1123,9 @@ _trace:
|
||||
_0xED: /* IN EAX, DX */
|
||||
R_EAX = 0; // nothing... should do a warning maybe?
|
||||
NEXT;
|
||||
_0xEE: /* OUT DX, AL */
|
||||
//nothing goes out...
|
||||
NEXT;
|
||||
|
||||
_0xF0: /* LOCK */
|
||||
emu->old_ip = R_EIP;
|
||||
@@ -1581,11 +1587,11 @@ _trace:
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, R_CS);
|
||||
Push(emu, ip);
|
||||
ip = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
STEP
|
||||
goto fini; // in case there is a change of CS
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
|
||||
@@ -854,12 +854,36 @@ void RunGS(x86emu_t *emu)
|
||||
GD.dword[0] = adc32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x21: /* AND Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = and32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x23: /* AND Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = and32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x29: /* SUB GS:Ed, Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = sub32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x2B: /* SUB Gd, GS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x31: /* XOR Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = xor32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x33: /* XOR Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -1012,6 +1036,39 @@ void RunGS(x86emu_t *emu)
|
||||
ED->dword[0] = F32;
|
||||
break;
|
||||
|
||||
case 0xD0: /* GRP2 Eb,1 */
|
||||
case 0xD2: /* GRP2 Eb,CL */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
tmp8u = (opcode==0xD0)?1:R_CL;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
|
||||
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
|
||||
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
|
||||
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
|
||||
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
|
||||
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
case 0xD1: /* GRP2 Ed,1 */
|
||||
case 0xD3: /* GRP2 Ed,CL */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
tmp8u = (opcode==0xD1)?1:R_CL;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
|
||||
case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
|
||||
case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
--ip; // ignore FS: to execute regular opcode
|
||||
@@ -1112,6 +1169,11 @@ void RunFS(x86emu_t *emu)
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
case 0x39: /* CMP FS:Ed, GD */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
cmp32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
case 0x3B: /* CMP GD, FS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -1409,6 +1471,12 @@ void RunGS0F(x86emu_t *emu, uintptr_t tlsdata)
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
switch(opcode) {
|
||||
case 0xAF: /* IMUL Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = imul32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0xB6: /* MOVZX Gd,GS:Eb */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
|
||||
+49
-24
@@ -133,6 +133,18 @@ void Run660F(x86emu_t *emu)
|
||||
) /* 0x40 -> 0x4F CMOVxx Gw,Ew */ // conditional move, no sign
|
||||
#undef GOCOND
|
||||
|
||||
case 0x01: /* GROUP */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* SMSW Ew */
|
||||
EW->word[0] = 0; // dummy operation. Should be CR0 -> Ew
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
}
|
||||
break;
|
||||
case 0x10: /* MOVUPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -845,8 +857,15 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xA3: /* BT Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
tmp32s = GW.sword[0];
|
||||
tmp8u=tmp32s&15;
|
||||
tmp32s >>= 4;
|
||||
GET_EW;
|
||||
if(EW->word[0] & (1<<(GW.word[0]&15)))
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
@@ -865,11 +884,18 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xAB: /* BTS Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
tmp32s = GW.sword[0];
|
||||
tmp8u=tmp32s&15;
|
||||
tmp32s >>= 4;
|
||||
GET_EW;
|
||||
if(EW->word[0] & (1<<(GW.word[0]&15)))
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
EW->word[0] |= (1<<(GW.word[0]&15));
|
||||
EW->word[0] |= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
@@ -904,10 +930,17 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xB3: /* BTR Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
tmp32s = GW.sword[0];
|
||||
tmp8u=tmp32s&15;
|
||||
tmp32s >>= 4;
|
||||
GET_EW;
|
||||
if(EW->word[0] & (1<<(GW.word[0]&15))) {
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<(GW.word[0]&15));
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
break;
|
||||
@@ -930,10 +963,6 @@ void Run660F(x86emu_t *emu)
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
|
||||
}
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -944,25 +973,18 @@ void Run660F(x86emu_t *emu)
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
|
||||
}
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else
|
||||
} else {
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
case 6: /* BTR Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uint16_t*)(ED))+(tmp8u>>4));
|
||||
}
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
@@ -974,10 +996,6 @@ void Run660F(x86emu_t *emu)
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
|
||||
}
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -994,12 +1012,19 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xBB: /* BTC Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
tmp32s = GW.sword[0];
|
||||
tmp8u=tmp32s&15;
|
||||
tmp32s >>= 4;
|
||||
GET_EW;
|
||||
if(EW->word[0] & (1<<(GW.word[0]&15)))
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<(GW.word[0]&15));
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
break;
|
||||
case 0xBC: /* BSF Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
@@ -37,6 +37,7 @@ void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit
|
||||
Push(emu, (uint32_t)my_context->argc);
|
||||
|
||||
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_init\n", my_context->argc, my_context->argv, my_context->envv, main);
|
||||
// should call structors->preinit_array and structors->init_array!
|
||||
// call main and finish
|
||||
PushExit(emu);
|
||||
R_EIP=(uint32_t)main;
|
||||
@@ -76,6 +77,13 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
|
||||
const char* GetNativeName(void* p)
|
||||
{
|
||||
static char buff[500] = {0};
|
||||
#ifdef HAVE_TRACE
|
||||
{
|
||||
const char* n = getBridgeName(p);
|
||||
if(n)
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
Dl_info info;
|
||||
if(dladdr(p, &info)==0) {
|
||||
const char *ret = GetNameOffset(my_context->maplib, p);
|
||||
|
||||
@@ -153,7 +153,7 @@ static inline mmx87_regs_t* GetEm(x86emu_t *emu, uint32_t v)
|
||||
{
|
||||
uint32_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->mmx87[m&0x07];
|
||||
return &emu->mmx[m&0x07];
|
||||
} else return (mmx87_regs_t*)GetECommon(emu, m);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ static inline reg32_t* GetGb(x86emu_t *emu, uint32_t v)
|
||||
static inline mmx87_regs_t* GetGm(x86emu_t *emu, uint32_t v)
|
||||
{
|
||||
uint8_t m = (v&0x38)>>3;
|
||||
return &emu->mmx87[m&7];
|
||||
return &emu->mmx[m&7];
|
||||
}
|
||||
|
||||
static inline sse_regs_t* GetGx(x86emu_t *emu, uint32_t v)
|
||||
|
||||
@@ -234,6 +234,7 @@ scwrap_t syscallwrap[] = {
|
||||
{ 311, __NR_set_robust_list, 2 },
|
||||
{ 312, __NR_get_robust_list, 4 },
|
||||
{ 318, __NR_getcpu, 3},
|
||||
{ 328, __NR_eventfd2, 2},
|
||||
#ifdef NOALIGN
|
||||
{ 329, __NR_epoll_create1, 1 },
|
||||
#endif
|
||||
@@ -332,7 +333,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
switch(syscallwrap[i].nbpars) {
|
||||
case 0: *(int32_t*)&R_EAX = syscall(sc); break;
|
||||
case 1: *(int32_t*)&R_EAX = syscall(sc, R_EBX); break;
|
||||
case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break;
|
||||
case 2: if(s==33) {printf_log(LOG_DEBUG, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break;
|
||||
case 3: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break;
|
||||
case 4: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break;
|
||||
case 5: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break;
|
||||
@@ -377,7 +378,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
char* prog = (char*)R_EBX;
|
||||
char** argv = (char**)R_ECX;
|
||||
char** envv = (char**)R_EDX;
|
||||
printf_log(LOG_DUMP, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
|
||||
printf_log(LOG_DEBUG, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
|
||||
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
}
|
||||
break;
|
||||
@@ -639,7 +640,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
{
|
||||
uint32_t s = u32(0);
|
||||
printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
|
||||
printf_log(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
|
||||
// check wrapper first
|
||||
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
|
||||
for (int i=0; i<cnt; i++) {
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ uint32_t my_set_thread_area(thread_area_t* td)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
|
||||
EXPORT uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
|
||||
{
|
||||
printf_log(/*LOG_DEBUG*/LOG_INFO, "modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
|
||||
if(!td) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
void reset_fpu(x86emu_t* emu)
|
||||
{
|
||||
memset(emu->mmx87, 0, sizeof(emu->mmx87));
|
||||
memset(emu->x87, 0, sizeof(emu->x87));
|
||||
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
|
||||
emu->cw = 0x37F;
|
||||
emu->sw.x16 = 0x0000;
|
||||
@@ -167,7 +167,7 @@ void D2LD(void* d, void* ld)
|
||||
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
|
||||
int32_t exp80 = s.ud[1]&0x7ff00000;
|
||||
int32_t exp80final = (exp80>>20);
|
||||
int64_t mant80 = s.q&0x000fffffffffffffLL;
|
||||
int64_t mant80 = s.sq&0x000fffffffffffffLL;
|
||||
int64_t mant80final = (mant80 << 11);
|
||||
if(exp80final==0x7ff) {
|
||||
// NaN and Infinite
|
||||
@@ -183,7 +183,7 @@ void D2LD(void* d, void* ld)
|
||||
}
|
||||
}
|
||||
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
|
||||
val.f.q = mant80final;
|
||||
val.f.sq = mant80final;
|
||||
memcpy(ld, &val, 10);
|
||||
/*memcpy(ld, &f.ll, 8);
|
||||
memcpy((char*)ld + 8, &val.b, 2);*/
|
||||
@@ -269,7 +269,11 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
{
|
||||
xsave_t *p = (xsave_t*)ed;
|
||||
// should save flags & all
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
uint8_t tags = 0;
|
||||
@@ -285,7 +289,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
p->MxCsr_Mask = 0;
|
||||
// copy MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
|
||||
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
|
||||
}
|
||||
@@ -300,8 +304,59 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
|
||||
// copy back MMX regs...
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
|
||||
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
|
||||
}
|
||||
|
||||
void fpu_fxam(x86emu_t* emu) {
|
||||
emu->sw.f.F87_C1 = (ST0.ud[1]&0x80000000)?1:0;
|
||||
if(emu->p_regs[emu->top].tag == 0b11) {
|
||||
//Empty
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
if(isinf(ST0.d))
|
||||
{
|
||||
//Infinity
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
if(isnan(ST0.d))
|
||||
{
|
||||
//NaN
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
if((ST0.ud[0]|(ST0.ud[1]&0x7fffffff))==0)
|
||||
{
|
||||
//Zero
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
return;
|
||||
}
|
||||
if((ST0.ud[1]&0x7FF00000)==0)
|
||||
{
|
||||
// denormals
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
return;
|
||||
}
|
||||
// normal...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
}
|
||||
@@ -18,9 +18,9 @@ void Run66D9(x86emu_t *emu);
|
||||
void Run66DD(x86emu_t *emu);
|
||||
void RunDF(x86emu_t *emu);
|
||||
|
||||
#define ST0 emu->mmx87[emu->top]
|
||||
#define ST1 emu->mmx87[(emu->top+1)&7]
|
||||
#define ST(a) emu->mmx87[(emu->top+(a))&7]
|
||||
#define ST0 emu->x87[emu->top]
|
||||
#define ST1 emu->x87[(emu->top+1)&7]
|
||||
#define ST(a) emu->x87[(emu->top+(a))&7]
|
||||
|
||||
#define STld(a) emu->fpu_ld[(emu->top+(a))&7]
|
||||
#define STll(a) emu->fpu_ll[(emu->top+(a))&7]
|
||||
@@ -132,41 +132,7 @@ static inline double fpu_round(x86emu_t* emu, double d) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void fpu_fxam(x86emu_t* emu) {
|
||||
emu->sw.f.F87_C1 = (ST0.ud[1]&0x80000000)?1:0;
|
||||
if(!emu->fpu_stack) {
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
if(isinf(ST0.d))
|
||||
{ // TODO: Unsuported and denormal not analysed...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
if(isnan(ST0.d))
|
||||
{ // TODO: Unsuported and denormal not analysed...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
if(ST0.d==0.0)
|
||||
{
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
return;
|
||||
}
|
||||
// normal...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
|
||||
}
|
||||
void fpu_fxam(x86emu_t* emu);
|
||||
|
||||
static inline void fpu_ftst(x86emu_t* emu) {
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include "pathcoll.h"
|
||||
#include "dictionnary.h"
|
||||
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct cleanup_s cleanup_t;
|
||||
@@ -81,6 +82,7 @@ typedef struct box86context_s {
|
||||
|
||||
char* fullpath;
|
||||
char* box86path; // path of current box86 executable
|
||||
char* box64path; // path of box64 executable (beside box86, if it exists)
|
||||
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
@@ -96,6 +98,7 @@ typedef struct box86context_s {
|
||||
|
||||
lib_t *maplib; // lib and symbols handling
|
||||
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
|
||||
dic_t *versym; // dictionnary of versionned symbols
|
||||
|
||||
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
|
||||
bridge_t *system; // other bridges
|
||||
@@ -121,6 +124,7 @@ typedef struct box86context_s {
|
||||
#endif
|
||||
pthread_mutex_t mutex_tls;
|
||||
pthread_mutex_t mutex_thread;
|
||||
pthread_mutex_t mutex_bridge;
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
library_t *sdl1lib; // shortcut to SDL1 library (if loaded)
|
||||
|
||||
@@ -10,9 +10,9 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
bridge_t *NewBridge();
|
||||
void FreeBridge(bridge_t** bridge);
|
||||
|
||||
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
|
||||
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
|
||||
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
void* GetNativeFnc(uintptr_t fnc);
|
||||
void* GetNativeFncOrFnc(uintptr_t fnc);
|
||||
@@ -22,4 +22,11 @@ void* getAlternate(void* addr);
|
||||
void addAlternate(void* addr, void* alt);
|
||||
void cleanAlternate();
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
const char* getBridgeName(void* addr);
|
||||
#endif
|
||||
|
||||
void init_bridge_helper();
|
||||
void fini_bridge_helper();
|
||||
|
||||
#endif //__BRIDGE_H_
|
||||
@@ -38,6 +38,7 @@ uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size);
|
||||
|
||||
+7
-1
@@ -4,6 +4,7 @@
|
||||
|
||||
typedef struct box86context_s box86context_t;
|
||||
extern int box86_log; // log level
|
||||
extern int box86_dump; // dump elf or not
|
||||
extern int box86_dynarec_log;
|
||||
extern int box86_dynarec;
|
||||
extern int box86_pagesize;
|
||||
@@ -12,6 +13,8 @@ extern int box86_dynarec_dump;
|
||||
extern int box86_dynarec_trace;
|
||||
extern int box86_dynarec_forced;
|
||||
extern int box86_dynarec_largest;
|
||||
extern int box86_dynarec_bigblock;
|
||||
extern int box86_dynarec_strongmem;
|
||||
extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
@@ -36,12 +39,15 @@ extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
#define LOG_NONE 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
#define LOG_DUMP 3
|
||||
#define LOG_NEVER 3
|
||||
#define LOG_VERBOSE 3
|
||||
|
||||
extern FILE* ftrace;
|
||||
|
||||
#define printf_log(L, ...) do {if(L<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define printf_dump(L, ...) do {if(box86_dump || (L<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#ifndef __DICTIONNARY_H_
|
||||
#define __DICTIONNARY_H_
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct dic_s dic_t;
|
||||
|
||||
dic_t *NewDictionnary();
|
||||
void FreeDictionnary(dic_t **dic);
|
||||
|
||||
const char* AddDictionnary(dic_t* dic, const char* s);
|
||||
int ExistDictionnary(dic_t* dic, const char* s);
|
||||
|
||||
const char* AddDefault(dic_t* dic, const char* s, const char** vername);
|
||||
const char* ExistDefault(dic_t* dic, const char* s);
|
||||
|
||||
#endif //__DICTIONNARY_H_
|
||||
@@ -9,7 +9,7 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
uint32_t X31_hash_code(void* addr, int len);
|
||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||
void FreeDynablock(dynablock_t* db);
|
||||
void FreeDynablock(dynablock_t* db, int need_lock);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
@@ -28,4 +28,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
// Create and Add an new dynablock in the list, handling direct/map
|
||||
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
|
||||
|
||||
// for use in signal handler
|
||||
void cancelFillBlock();
|
||||
|
||||
#endif //__DYNABLOCK_H_
|
||||
@@ -4,6 +4,7 @@
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
void CancelBlock();
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr);
|
||||
|
||||
#endif //__DYNAREC_ARM_H_
|
||||
@@ -6,7 +6,7 @@ typedef struct elfheader_s elfheader_t;
|
||||
const char* DumpSection(Elf32_Shdr *s, char* SST);
|
||||
const char* DumpDynamic(Elf32_Dyn *s);
|
||||
const char* DumpPHEntry(Elf32_Phdr *e);
|
||||
const char* DumpSym(elfheader_t *h, Elf32_Sym* sym);
|
||||
const char* DumpSym(elfheader_t *h, Elf32_Sym* sym, int version);
|
||||
const char* DumpRelType(int t);
|
||||
const char* SymName(elfheader_t *h, Elf32_Sym* sym);
|
||||
const char* IdxSymName(elfheader_t *h, int sym);
|
||||
|
||||
@@ -56,5 +56,8 @@ void CreateMemorymapFile(box86context_t* context, int fd);
|
||||
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
|
||||
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version);
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index);
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername);
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
|
||||
|
||||
#endif //__ELF_LOADER_H_
|
||||
@@ -15,8 +15,9 @@ char* ResolveFile(const char* filename, path_collection_t* paths);
|
||||
|
||||
// 1: if file is an x86 elf, 0: if not (or not found)
|
||||
int FileIsX86ELF(const char* filename);
|
||||
int FileIsX64ELF(const char* filename);
|
||||
|
||||
#if defined(RPI) || defined(RK3399)
|
||||
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE)
|
||||
void sanitize_mojosetup_gtk_background();
|
||||
#endif
|
||||
|
||||
|
||||
Loaded 100 of 700 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user