mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
Make this repo good enough to move in cpp-cheat, x86-assembly-cheat and arm-assembly-cheat in
This commit is a large squash, the full development branch is available at: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/asm This notably means a refactor of the userland build and testing, to support: - improved assembly infrastructure unified across arm and x86 - native in-tree build and test helpers - parallel building and testing, which implies thread_pool.py - selection of what to build and test from the CLI - path_properties.py to indicate how to build and run different examples - in full system, move all userland stuff into /lkmc - prefix everything that we defined across files with LKMC - --gdb uber convenient helper - remove import imp which was deprecated Full commit messages from the branch follow: 1: userland: add assembly support Move arm assembly cheat here, and start some work on x86 cheat as well. 2: document userland asm syscall interfaces 3: userland assembly: structure readme 4: x86 fail works 5: asm: more links 6: userland: add ported to all archs 7: move all our stuff into /lkmc in guest Motivation: userland is getting several new subdirectories, it would be too insane to just dump all of that in the guest root filesystem. To alleviate the cd pain, .profile puts user inside /lkmc by default. 8: start the big userland migration 9: migrate all 10: bak 11: build-userland-in-tree is now a Python command ./build calls it, we did this to allow --download-dependencies to work perfectly. 12: rename include to lkmc 13: mtops.h is perfect now 14: userland: make build perfect 15: preparing test_user_mode, need to generalize stuff as usual 16: asm: prefix every linux specific with linux/ 17: userland: maybe it really works 18: userland: fix kernel version to work on older ubuntu Expose --kernel-version to allow customization. Update LTP info. 19: userland: build really truly working now userland test: start work, in a working state, but no features 20: test-user-mode: make perfect like build-userland Multithreading and target selection. 21: userland: get a bit closer to perfection 22: thread_pool: support passing thread IDs Then use that to fix gem5 error log read race. 23: userland: native testing 24: userland: path properties getting nice! 25: userland: move posix/environ from cpp-cheat 26: gem5: --debug-flags without =, looks nicer whenever it can be done 27: run: rename --wait-gdb in --gdb-wait, --gdb prefix might become a thing 28: run: create --tmux-program gdb to open gem5 GDB 29: run: create the uber convenient --gdb option 30: userland: move getchar from cpp-cheat 31: prebuilt: kernel boot aarch64 does not work on Ubuntu 16.04 32: userland: x86_64 linux hello world make PIE 33: userland: try to make userland executable selection saner Only allow existing files to be built, stop extension expansion madness. cli_function: get_cli print booleans properly, was printing without --no- for negations. 34: userland: only link to lkmc.o if needed 35: path_properties: make data very compact with only tuples and dicts Spend 2 hours of my life thinking about low value tree walks ;-) 36: userland: move more userland/arch/ logic into property tree 37: userland: make libs work Working for build, but now test-user-mode-in-tree is not using --in-tree, TODO fix later on. 38: userland: make libs really work 39: userland: document path_properties 40: userland: classify linux 41: waste your life 42: common: fix absolute path runs --gdb: allow running from arbitrary directory 43: baremetal: arm allow using floating point instructions 44: baremetal: stat preparing to make perfect like userland/ 45: run: fix image check logic accounting for userland Was failing if I try to run userland (with abspath) when out/ directory is not present. 46: cli-function: raise if the config file is given and does not exist 47: common: define missing 'ld' variable, this broke m5 build 48: rum: --qemu-which host now works for user mode as well as system Don't fall back on host QEMU automatically, too much insanity. 49: userland: refix silly mistakes 50: userland: use path_properties flags for all builds, including lkmc. and userland/arch/main.c Without this in particular, --gdb fails on assembly because main.c was not being built with -ggdb3. 51: userland: start refactor to show failing values on failure! aarch64 basically done, but missing: - other archs - maybe convert main.c into C++ to use templates? - full review of ASSERT_EQ calling convention issues not seen by tests by chance - documentation 52: readme: releases are more stable... 53: submodules: sort gitmodules 54: test-baremetal: same interface as test-user-mode In particular, runs tests in parallel, and allows selecting given tests 55: baremetal: allow arbitrary exit status with the magic string test-baremetal: fix missing setting x0 return value Examples were just returning on ret without setting x0, which led to failures... those were not noticed because of how broken the testing system was ;-) 56: baremetal: ah, actually nope, it didn't work :-( Workaround for now. Works on asserts, but not on exit 1. Some other day, maybe. https://github.com/cirosantilli/linux-kernel-module-cheat/issues/59 57: panic on panic: improve behaviour description 58: baremetal: get exit status working with on_exit :-) 59: baremetal: implement C assert 60: test-baremetal: remove commented out exit status workaround 61: test-user-mode: handle exit status for signals. Fix #61. 62: aarch64: fix ASSERT_EQ_REG tests on gem5 Was doing an 8-byte aligned store, which gem5 dislikes. But the ARMARM says bad things may happen there, notably a signal: "D1.8.2 SP alignment checking" so gem5 is not really too wrong, QEMU just happens to work by chance. 63: userland assembly: build empty.S and fail.S to toplevel and run fail.S with path_properties exit_status They were just duplicating stuff needlessly while we don't support non-native in-tree builds, which leads to executable conflicts for C file anyways. 64: gem5: use a single build tree for all build types gem5 already has different object names for each build type it seems, so let's just make sure that works and save some disk space. 65: userland x86_64: ASSERT_EQ show actual and expected values 66: assert_fail.c: add to readme index 67: userland x86_64: implement ASSERT_MEMCMP 68: userland x86_64: allow ASSERT_EQ to take just about anything 69: gas data sizes 70: gas_data_sizes.S: make PIE for all ISAs 71: x86: paddq 72: x86 paddq: test entire family 73: Get rid of imp, started giving deprecation warning every time in Python 3.7 in Ubuntu 19.04. Please python stop torturing me with refactors. Make ./run -u blow up if executable not found, otherwise I go crazy. Get ./test-gdb back to life after the ./run relative path refactor, forgot to test this. 74: fix run-toolchain, qemu-monitor, trace-boot, trace2line, bisect-linux-boot-gem5. Fixes part of #63 I'm sad no one reported qemu-monitor break, that one is kind of important. count.out arguments broke it as an init program, since the kernel adds trash parameters to every init. Is anyone using this repo, I wonder? Keep pushing, keep pushing. One day it gets good enough, and the whole world will see. 75: x86 assembly: addpd 76: Fix import_path circular dependency by splitting it out. Use import thread_pool instead from, from is evil. Fix poweroff.out path for ./trace-boot. 77: run: rename cryptic tmu to tmux-split, ./run is good now so I never use it anymore explicitly 78: assembly SIMD add: make uniform for all ISAs, mark as entry point to learning SIMD 79: start moving arm-assembly-cheat readme in here 80: arm assembly: move some more in 81: move more arm in 82: userland: attempt to fix all assembly example links to README 83: assembly: improve organization of simd add 84: ld2 move in 85: Make userland / assembly getting started more uniform / visible Forward --gcc-which to ./run --tmux. Use gdb-multiarch for --gcc-which host. 86: userland: disable PIE explicitly on command line for all executables 87: userland: make userland content a better landing page 88: build: check git version from --version and degrade gracefully 89: build: make --dry-run work again on all 90: import_path: importlib explicit for Ubuntu 16.04 91: make all submodules point to my forks git servers are insane, submodule implementation is crap, what can you do 92: build: log warning on git too old for --update 93: build-linux: do olddefconfig even if no fragments In particular, gem5 kernel 4.15 needs it 94: userland content: improve a bit landing page for cpp-cheat
This commit is contained in:
9
userland/arch/aarch64/add.S
Normal file
9
userland/arch/aarch64/add.S
Normal file
@@ -0,0 +1,9 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
mov x0, 1
|
||||
add x1, x0, 2
|
||||
ASSERT_EQ(x1, 3)
|
||||
EXIT
|
||||
32
userland/arch/aarch64/add_vector.S
Normal file
32
userland/arch/aarch64/add_vector.S
Normal file
@@ -0,0 +1,32 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-add-vector-instruction
|
||||
*
|
||||
* Add a bunch of integers in one go.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
.data
|
||||
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
||||
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
|
||||
expect_4s: .long 0x04040403, 0x06060605, 0x08080807, 0x0A0A0A09
|
||||
expect_2d: .long 0x04040403, 0x06060606, 0x08080807, 0x0A0A0A0A
|
||||
.bss
|
||||
output: .skip 16
|
||||
.text
|
||||
#define TEST(size) \
|
||||
adr x0, input0; \
|
||||
ld1 {v0. ## size}, [x0]; \
|
||||
adr x1, input1; \
|
||||
ld1 {v1. ## size}, [x1]; \
|
||||
add v2. ## size, v0. ## size, v1. ## size; \
|
||||
adr x0, output; \
|
||||
st1 {v2. ## size}, [x0]; \
|
||||
ASSERT_MEMCMP(output, expect_ ## size, 0x10)
|
||||
|
||||
/* 4x 32-bit */
|
||||
TEST(4s)
|
||||
/* 2x 64-bit */
|
||||
TEST(2d)
|
||||
#undef TEST
|
||||
EXIT
|
||||
21
userland/arch/aarch64/adr.S
Normal file
21
userland/arch/aarch64/adr.S
Normal file
@@ -0,0 +1,21 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
.data
|
||||
data_label:
|
||||
.word 0x1234678
|
||||
ENTRY
|
||||
/* This is not possible in v7 because the label is in another section.
|
||||
* objdump says that this generates a R_AARCH64_ADR_PRE relocation.
|
||||
* which looks specific to ADR, and therefore makes it more likely
|
||||
* that there was no such relocation in v7.
|
||||
*
|
||||
* This relocation is particularly important because str does not have a
|
||||
* pc-relative mode in ARMv8.
|
||||
*/
|
||||
adr x0, data_label
|
||||
ldr x1, =data_label
|
||||
label:
|
||||
ASSERT_EQ_REG(x0, x1)
|
||||
EXIT
|
||||
13
userland/arch/aarch64/adrp.S
Normal file
13
userland/arch/aarch64/adrp.S
Normal file
@@ -0,0 +1,13 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
adrp x0, label
|
||||
adr x1, label
|
||||
label:
|
||||
/* Clear the lower 12 bits. */
|
||||
bic x1, x1, 0xFF
|
||||
bic x1, x1, 0xF00
|
||||
ASSERT_EQ_REG(x0, x1)
|
||||
EXIT
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void) {
|
||||
uint32_t myvar = 1;
|
||||
__asm__ (
|
||||
"add %[myvar], %[myvar], 1;"
|
||||
: [myvar] "=r" (myvar)
|
||||
:
|
||||
:
|
||||
);
|
||||
assert(myvar == 2);
|
||||
}
|
||||
33
userland/arch/aarch64/beq.S
Normal file
33
userland/arch/aarch64/beq.S
Normal file
@@ -0,0 +1,33 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
/* cbz == 0 */
|
||||
mov x0, 0
|
||||
cbz x0, 1f
|
||||
FAIL
|
||||
1:
|
||||
|
||||
/* cbz != 0 */
|
||||
mov x0, 1
|
||||
cbz x0, 1f
|
||||
b 2f
|
||||
1:
|
||||
FAIL
|
||||
2:
|
||||
|
||||
/* cbnz != 0 */
|
||||
mov x0, 1
|
||||
cbnz x0, 1f
|
||||
FAIL
|
||||
1:
|
||||
|
||||
/* cbnz == 0 */
|
||||
mov x0, 0
|
||||
cbnz x0, 1f
|
||||
b 2f
|
||||
1:
|
||||
FAIL
|
||||
2:
|
||||
EXIT
|
||||
11
userland/arch/aarch64/bfi.S
Normal file
11
userland/arch/aarch64/bfi.S
Normal file
@@ -0,0 +1,11 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
ldr x0, =0x1122334455667788
|
||||
|
||||
ldr x1, =0xFFFFFFFFFFFFFFFF
|
||||
bfi x1, x0, 16, 32
|
||||
ASSERT_EQ(x1, 0xFFFF55667788FFFF)
|
||||
EXIT
|
||||
1
userland/arch/aarch64/c/build
Symbolic link
1
userland/arch/aarch64/c/build
Symbolic link
@@ -0,0 +1 @@
|
||||
../build
|
||||
17
userland/arch/aarch64/c/earlyclobber.c
Normal file
17
userland/arch/aarch64/c/earlyclobber.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gcc-inline-assembly-early-clobbers */
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void) {
|
||||
uint64_t in = 1;
|
||||
uint64_t out;
|
||||
__asm__ (
|
||||
"add %[out], %[in], 1;"
|
||||
"add %[out], %[in], 1;"
|
||||
: [out] "=&r" (out)
|
||||
: [in] "r" (in)
|
||||
:
|
||||
);
|
||||
assert(out == 2);
|
||||
}
|
||||
1
userland/arch/aarch64/c/freestanding/build
Symbolic link
1
userland/arch/aarch64/c/freestanding/build
Symbolic link
@@ -0,0 +1 @@
|
||||
../build
|
||||
1
userland/arch/aarch64/c/freestanding/linux/build
Symbolic link
1
userland/arch/aarch64/c/freestanding/linux/build
Symbolic link
@@ -0,0 +1 @@
|
||||
../build
|
||||
39
userland/arch/aarch64/c/freestanding/linux/hello.c
Normal file
39
userland/arch/aarch64/c/freestanding/linux/hello.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* aarch64 freestanding C inline assemby Linux hello world
|
||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#linux-system-calls
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
void _start(void) {
|
||||
uint64_t exit_status;
|
||||
|
||||
/* write */
|
||||
{
|
||||
char msg[] = "hello\n";
|
||||
uint64_t syscall_return;
|
||||
register uint64_t x0 __asm__ ("x0") = 1; /* stdout */
|
||||
register char *x1 __asm__ ("x1") = msg;
|
||||
register uint64_t x2 __asm__ ("x2") = sizeof(msg);
|
||||
register uint64_t x8 __asm__ ("x8") = 64; /* syscall number */
|
||||
__asm__ __volatile__ (
|
||||
"svc 0;"
|
||||
: "+r" (x0)
|
||||
: "r" (x1), "r" (x2), "r" (x8)
|
||||
: "memory"
|
||||
);
|
||||
syscall_return = x0;
|
||||
exit_status = (syscall_return != sizeof(msg));
|
||||
}
|
||||
|
||||
/* exit */
|
||||
{
|
||||
register uint64_t x0 __asm__ ("x0") = exit_status;
|
||||
register uint64_t x8 __asm__ ("x8") = 93;
|
||||
__asm__ __volatile__ (
|
||||
"svc 0;"
|
||||
: "+r" (x0)
|
||||
: "r" (x8)
|
||||
:
|
||||
);
|
||||
}
|
||||
}
|
||||
42
userland/arch/aarch64/c/freestanding/linux/hello_clobbers.c
Normal file
42
userland/arch/aarch64/c/freestanding/linux/hello_clobbers.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Like hello.c trying to do it without named register variables.
|
||||
* The code is more complicated, and I was not able to get as efficient,
|
||||
* so better just stick to named register variables.
|
||||
*
|
||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#linux-system-calls
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
void _start(void) {
|
||||
uint64_t exit_status;
|
||||
|
||||
/* write */
|
||||
{
|
||||
char msg[] = "hello\n";
|
||||
uint64_t syscall_return;
|
||||
__asm__ (
|
||||
"mov x0, 1;" /* stdout */
|
||||
"mov x1, %[msg];"
|
||||
"mov x2, %[len];"
|
||||
"mov x8, 64;" /* syscall number */
|
||||
"svc 0;"
|
||||
"mov %[syscall_return], x0;"
|
||||
: [syscall_return] "=r" (syscall_return)
|
||||
: [msg] "p" (msg),
|
||||
[len] "i" (sizeof(msg))
|
||||
: "x0", "x1", "x2", "x8", "memory"
|
||||
);
|
||||
exit_status = (syscall_return != sizeof(msg));
|
||||
}
|
||||
|
||||
/* exit */
|
||||
__asm__ (
|
||||
"mov x0, %[exit_status];"
|
||||
"mov x8, 93;" /* syscall number */
|
||||
"svc 0;"
|
||||
:
|
||||
: [exit_status] "r" (exit_status)
|
||||
: "x0", "x8"
|
||||
);
|
||||
}
|
||||
|
||||
1
userland/arch/aarch64/c/freestanding/linux/test
Symbolic link
1
userland/arch/aarch64/c/freestanding/linux/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
1
userland/arch/aarch64/c/freestanding/test
Symbolic link
1
userland/arch/aarch64/c/freestanding/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
18
userland/arch/aarch64/c/inc.c
Normal file
18
userland/arch/aarch64/c/inc.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Increment a variable in inline assembly.
|
||||
*
|
||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#gcc-inline-assembly
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void) {
|
||||
uint64_t io = 1;
|
||||
__asm__ (
|
||||
"add %[io], %[io], 1;"
|
||||
: [io] "+r" (io)
|
||||
:
|
||||
:
|
||||
);
|
||||
assert(io == 2);
|
||||
}
|
||||
25
userland/arch/aarch64/c/inc_float.c
Normal file
25
userland/arch/aarch64/c/inc_float.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gcc-inline-assembly-floating-point-arm */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
int main(void) {
|
||||
float my_float = 1.5;
|
||||
__asm__ (
|
||||
"fmov s0, 1.0;"
|
||||
"fadd %s[my_float], %s[my_float], s0;"
|
||||
: [my_float] "+w" (my_float)
|
||||
:
|
||||
: "s0"
|
||||
);
|
||||
assert(my_float == 2.5);
|
||||
|
||||
double my_double = 1.5;
|
||||
__asm__ (
|
||||
"fmov d0, 1.0;"
|
||||
"fadd %d[my_double], %d[my_double], d0;"
|
||||
: [my_double] "+w" (my_double)
|
||||
:
|
||||
: "d0"
|
||||
);
|
||||
assert(my_double == 2.5);
|
||||
}
|
||||
39
userland/arch/aarch64/c/linux/asm_from_c.c
Normal file
39
userland/arch/aarch64/c/linux/asm_from_c.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
uint64_t my_asm_func(void);
|
||||
/* { return 42; } */
|
||||
__asm__(
|
||||
".global my_asm_func;"
|
||||
"my_asm_func:"
|
||||
"mov x0, 42;"
|
||||
"ret;"
|
||||
);
|
||||
|
||||
/* Now a more complex example that also calls a C function.
|
||||
* We have to store the return value x30 for later because bl modifies it.
|
||||
* https://stackoverflow.com/questions/27941220/push-lr-and-pop-lr-in-arm-arch64/34504752#34504752
|
||||
* We are not modifying any other callee saved register in this function,
|
||||
* since my_c_func is not either (unless GCC has a bug ;-)), so everything else if fine.
|
||||
*/
|
||||
uint64_t my_asm_func_2(void);
|
||||
/* { return my_c_func(); } */
|
||||
__asm__(
|
||||
".global my_asm_func_2;"
|
||||
"my_asm_func_2:"
|
||||
"str x30, [sp, -16]!;"
|
||||
"bl my_c_func;"
|
||||
"ldr x30, [sp], 16;"
|
||||
"ret;"
|
||||
);
|
||||
|
||||
uint64_t my_c_func(void) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
assert(my_asm_func() == 42);
|
||||
assert(my_asm_func_2() == 42);
|
||||
}
|
||||
1
userland/arch/aarch64/c/linux/build
Symbolic link
1
userland/arch/aarch64/c/linux/build
Symbolic link
@@ -0,0 +1 @@
|
||||
../build
|
||||
1
userland/arch/aarch64/c/linux/test
Symbolic link
1
userland/arch/aarch64/c/linux/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
18
userland/arch/aarch64/c/multiline.cpp
Normal file
18
userland/arch/aarch64/c/multiline.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// https://stackoverflow.com/questions/3666013/how-to-write-multiline-inline-assembly-code-in-gcc-c/54575948#54575948
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void) {
|
||||
uint64_t io = 0;
|
||||
__asm__ (
|
||||
R"(
|
||||
add %[io], %[io], #1
|
||||
add %[io], %[io], #1
|
||||
)"
|
||||
: [io] "+r" (io)
|
||||
:
|
||||
:
|
||||
);
|
||||
assert(io == 2);
|
||||
}
|
||||
27
userland/arch/aarch64/c/reg_var.c
Normal file
27
userland/arch/aarch64/c/reg_var.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gcc-inline-assembly-register-variables */
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void) {
|
||||
register uint32_t x0 __asm__ ("x0");
|
||||
register uint32_t x1 __asm__ ("x1");
|
||||
uint32_t new_x0;
|
||||
uint32_t new_x1;
|
||||
{
|
||||
x0 = 1;
|
||||
x1 = 2;
|
||||
__asm__ (
|
||||
"add %[x0], x0, #1;"
|
||||
"add %[x1], x1, #1;"
|
||||
: [x0] "+r" (x0),
|
||||
[x1] "+r" (x1)
|
||||
:
|
||||
:
|
||||
);
|
||||
new_x0 = x0;
|
||||
new_x1 = x1;
|
||||
}
|
||||
assert(new_x0 == 2);
|
||||
assert(new_x1 == 3);
|
||||
}
|
||||
28
userland/arch/aarch64/c/reg_var_float.c
Normal file
28
userland/arch/aarch64/c/reg_var_float.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gcc-inline-assembly-register-variables */
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void) {
|
||||
register double d0 __asm__ ("d0");
|
||||
register double d1 __asm__ ("d1");
|
||||
double new_d0;
|
||||
double new_d1;
|
||||
{
|
||||
d0 = 1.5;
|
||||
d1 = 2.5;
|
||||
__asm__ (
|
||||
"fmov d2, 1.5;"
|
||||
"fadd %d[d0], d0, d2;"
|
||||
"fadd %d[d1], d1, d2;"
|
||||
: [d0] "+w" (d0),
|
||||
[d1] "+w" (d1)
|
||||
:
|
||||
: "d2"
|
||||
);
|
||||
new_d0 = d0;
|
||||
new_d1 = d1;
|
||||
}
|
||||
assert(new_d0 == 3.0);
|
||||
assert(new_d1 == 4.0);
|
||||
}
|
||||
1
userland/arch/aarch64/c/test
Symbolic link
1
userland/arch/aarch64/c/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
19
userland/arch/aarch64/cbz.S
Normal file
19
userland/arch/aarch64/cbz.S
Normal file
@@ -0,0 +1,19 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cbz-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
|
||||
/* Branch. */
|
||||
mov x0, 0x0
|
||||
cbz x0, ok
|
||||
FAIL
|
||||
ok:
|
||||
|
||||
/* Don't branch. */
|
||||
mov x0, 0x1
|
||||
cbz x0, ko
|
||||
|
||||
EXIT
|
||||
ko:
|
||||
FAIL
|
||||
17
userland/arch/aarch64/comments.S
Normal file
17
userland/arch/aarch64/comments.S
Normal file
@@ -0,0 +1,17 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
|
||||
|
||||
#include "common.h"
|
||||
ENTRY
|
||||
# mycomment
|
||||
|
||||
/* ARMv8 has // instead of @ as for comments. */
|
||||
// mycomment
|
||||
nop // mycomment
|
||||
|
||||
/* All these fail. Lol, different than v7, no consistency. */
|
||||
#if 0
|
||||
nop # mycomment
|
||||
@ mycomment
|
||||
nop @ mycomment
|
||||
#endif
|
||||
EXIT
|
||||
83
userland/arch/aarch64/common_arch.h
Normal file
83
userland/arch/aarch64/common_arch.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
|
||||
|
||||
#ifndef COMMON_ARCH_H
|
||||
#define COMMON_ARCH_H
|
||||
|
||||
#define ASSERT_EQ(reg, const) \
|
||||
mov x0, reg; \
|
||||
ldr x1, =const; \
|
||||
ASSERT_EQ_DO(64); \
|
||||
;
|
||||
|
||||
#define ASSERT_EQ_DO(bits) \
|
||||
bl assert_eq_ ## bits; \
|
||||
cmp x0, 0; \
|
||||
ASSERT(beq); \
|
||||
;
|
||||
|
||||
#define ASSERT_EQ_REG(reg1, reg2) \
|
||||
str reg2, [sp, -16]!; \
|
||||
mov x0, reg1; \
|
||||
ldr x1, [sp], 16; \
|
||||
ASSERT_EQ_DO(64); \
|
||||
;
|
||||
|
||||
#define ASSERT_EQ_REG_32(reg1, reg2) \
|
||||
str reg2, [sp, -4]!; \
|
||||
mov w0, reg1; \
|
||||
ldr w1, [sp], 4; \
|
||||
ASSERT_EQ_DO(32); \
|
||||
;
|
||||
|
||||
#define ASSERT_MEMCMP(label1, label2, const_size) \
|
||||
adr x0, label1; \
|
||||
adr x1, label2; \
|
||||
ldr x2, =const_size; \
|
||||
bl assert_memcmp; \
|
||||
cmp x0, 0; \
|
||||
ASSERT(beq); \
|
||||
;
|
||||
|
||||
#define ENTRY \
|
||||
.text; \
|
||||
.global asm_main; \
|
||||
asm_main: \
|
||||
sub sp, sp, 0xA0; \
|
||||
stp x29, x30, [sp]; \
|
||||
stp x27, x28, [sp, 0x10]; \
|
||||
stp x25, x26, [sp, 0x20]; \
|
||||
stp x23, x24, [sp, 0x30]; \
|
||||
stp x21, x22, [sp, 0x40]; \
|
||||
stp x19, x20, [sp, 0x50]; \
|
||||
stp x6, x7, [sp, 0x60]; \
|
||||
stp x4, x5, [sp, 0x70]; \
|
||||
stp x2, x3, [sp, 0x80]; \
|
||||
stp x0, x1, [sp, 0x90]; \
|
||||
asm_main_after_prologue: \
|
||||
;
|
||||
|
||||
#define EXIT \
|
||||
mov w0, 0; \
|
||||
mov w1, 0; \
|
||||
b pass; \
|
||||
fail: \
|
||||
ldr x1, [sp, 0x90]; \
|
||||
str w0, [x1]; \
|
||||
mov w0, 1; \
|
||||
pass: \
|
||||
ldp x19, x20, [sp, 0x50]; \
|
||||
ldp x21, x22, [sp, 0x40]; \
|
||||
ldp x23, x24, [sp, 0x30]; \
|
||||
ldp x25, x26, [sp, 0x20]; \
|
||||
ldp x27, x28, [sp, 0x10]; \
|
||||
ldp x29, x30, [sp]; \
|
||||
add sp, sp, 0xA0; \
|
||||
ret; \
|
||||
;
|
||||
|
||||
#define FAIL \
|
||||
ldr w0, =__LINE__; \
|
||||
b fail; \
|
||||
;
|
||||
|
||||
#endif
|
||||
28
userland/arch/aarch64/cset.S
Normal file
28
userland/arch/aarch64/cset.S
Normal file
@@ -0,0 +1,28 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cset-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
/* Test values. */
|
||||
mov x19, 0
|
||||
mov x20, 1
|
||||
|
||||
/* eq is true, set x21 = 1. */
|
||||
cmp x19, x19
|
||||
cset x21, eq
|
||||
ASSERT_EQ(x21, 1)
|
||||
|
||||
/* eq is false, set x21 = 0. */
|
||||
cmp x19, x20
|
||||
cset x21, eq
|
||||
ASSERT_EQ(x21, 0)
|
||||
|
||||
/* Same for ne. */
|
||||
cmp x19, x19
|
||||
cset x21, ne
|
||||
ASSERT_EQ(x21, 0)
|
||||
|
||||
cmp x19, x20
|
||||
cset x21, ne
|
||||
ASSERT_EQ(x21, 1)
|
||||
EXIT
|
||||
60
userland/arch/aarch64/fadd_scalar.S
Normal file
60
userland/arch/aarch64/fadd_scalar.S
Normal file
@@ -0,0 +1,60 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#advanced-simd-instructions */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
/* 1.5 + 2.5 == 4.0
|
||||
* using 64-bit double immediates.
|
||||
*/
|
||||
fmov d0, 1.5
|
||||
fmov d1, 2.5
|
||||
fadd d2, d0, d1
|
||||
fmov d3, 4.0
|
||||
/* Unlike VFP vcmp, this stores the status
|
||||
* automatically in the main CPSR.
|
||||
*/
|
||||
fcmp d2, d3
|
||||
ASSERT(beq)
|
||||
|
||||
/* Now with a memory stored value. */
|
||||
.data
|
||||
my_double_0:
|
||||
.double 1.5
|
||||
my_double_1:
|
||||
.double 2.5
|
||||
my_double_sum_expect:
|
||||
.double 4.0
|
||||
.text
|
||||
ldr d0, my_double_0
|
||||
ldr d1, my_double_1
|
||||
fadd d2, d0, d1
|
||||
ldr d3, my_double_sum_expect
|
||||
fcmp d2, d3
|
||||
ASSERT(beq)
|
||||
|
||||
/* Now in 32-bit. */
|
||||
fmov s0, 1.5
|
||||
fmov s1, 2.5
|
||||
fadd s2, s0, s1
|
||||
fmov s3, 4.0
|
||||
fcmp s2, s3
|
||||
ASSERT(beq)
|
||||
|
||||
/* TODO why? What's the point of q then?
|
||||
* Error: operand mismatch -- `fmov q0,1.5'
|
||||
*/
|
||||
#if 0
|
||||
fmov q0, 1.5
|
||||
#endif
|
||||
|
||||
/* Much like integers, immediates are constrained to
|
||||
* fit in 32-byte instructions. TODO exact rules.
|
||||
*
|
||||
* Assembly here would fail with:
|
||||
*
|
||||
* Error: invalid floating-point constant at operand 2
|
||||
*/
|
||||
#if 0
|
||||
fmov d0, 1.23456798
|
||||
#endif
|
||||
EXIT
|
||||
34
userland/arch/aarch64/fadd_vector.S
Normal file
34
userland/arch/aarch64/fadd_vector.S
Normal file
@@ -0,0 +1,34 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-fadd-vector-instruction
|
||||
*
|
||||
* Add a bunch of floating point numbers in one go.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
.data
|
||||
input0_4s: .float 1.5, 2.5, 3.5, 4.5
|
||||
input1_4s: .float 5.5, 6.5, 7.5, 8.5
|
||||
expect_4s: .float 7.0, 9.0, 11.0, 13.0
|
||||
input0_2d: .double 1.5, 2.5
|
||||
input1_2d: .double 5.5, 6.5
|
||||
expect_2d: .double 7.0, 9.0
|
||||
.bss
|
||||
output: .skip 16
|
||||
.text
|
||||
#define TEST(size) \
|
||||
adr x0, input0_ ## size; \
|
||||
ld1 {v0. ## size}, [x0]; \
|
||||
adr x1, input1_ ## size; \
|
||||
ld1 {v1. ## size}, [x1]; \
|
||||
fadd v2. ## size, v0. ## size, v1. ## size; \
|
||||
adr x0, output; \
|
||||
st1 {v2. ## size}, [x0]; \
|
||||
ASSERT_MEMCMP(output, expect_ ## size, 0x10)
|
||||
|
||||
/* 4x 32-bit */
|
||||
TEST(4s)
|
||||
/* 2x 64-bit */
|
||||
TEST(2d)
|
||||
#undef TEST
|
||||
EXIT
|
||||
1
userland/arch/aarch64/freestanding/build
Symbolic link
1
userland/arch/aarch64/freestanding/build
Symbolic link
@@ -0,0 +1 @@
|
||||
../build
|
||||
1
userland/arch/aarch64/freestanding/linux/build
Symbolic link
1
userland/arch/aarch64/freestanding/linux/build
Symbolic link
@@ -0,0 +1 @@
|
||||
../build
|
||||
22
userland/arch/aarch64/freestanding/linux/hello.S
Normal file
22
userland/arch/aarch64/freestanding/linux/hello.S
Normal file
@@ -0,0 +1,22 @@
|
||||
/* aarch64 freestanding Linux hello world
|
||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#linux-system-calls
|
||||
*/
|
||||
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
asm_main_after_prologue:
|
||||
/* write */
|
||||
mov x0, 1 /* stdout */
|
||||
adr x1, msg /* buffer */
|
||||
ldr x2, =len /* len */
|
||||
mov x8, 64 /* syscall number */
|
||||
svc 0
|
||||
|
||||
/* exit */
|
||||
mov x0, 0 /* exit status */
|
||||
mov x8, 93 /* syscall number */
|
||||
svc 0
|
||||
msg:
|
||||
.ascii "hello\n"
|
||||
len = . - msg
|
||||
1
userland/arch/aarch64/freestanding/linux/test
Symbolic link
1
userland/arch/aarch64/freestanding/linux/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
1
userland/arch/aarch64/freestanding/test
Symbolic link
1
userland/arch/aarch64/freestanding/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
29
userland/arch/aarch64/gas_data_sizes.S
Normal file
29
userland/arch/aarch64/gas_data_sizes.S
Normal file
@@ -0,0 +1,29 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
#define ASSERT_DIFF(label1, label2, result) \
|
||||
adr x0, label1; \
|
||||
adr x1, label2; \
|
||||
sub x0, x1, x0; \
|
||||
ASSERT_EQ(x0, result)
|
||||
|
||||
ASSERT_DIFF(mybyte, myword, 1)
|
||||
ASSERT_DIFF(myword, mylong, 4)
|
||||
ASSERT_DIFF(mylong, myquad, 4)
|
||||
ASSERT_DIFF(myquad, myocta, 8)
|
||||
ASSERT_DIFF(myocta, theend, 16)
|
||||
#undef ASSERT_DIF
|
||||
EXIT
|
||||
mybyte:
|
||||
.byte 0x12
|
||||
myword:
|
||||
.word 0x1234
|
||||
mylong:
|
||||
.long 0x12345678
|
||||
myquad:
|
||||
.quad 0x123456789ABCDEF0
|
||||
myocta:
|
||||
.octa 0x123456789ABCDEF0123456789ABCDEF0
|
||||
theend:
|
||||
9
userland/arch/aarch64/immediates.S
Normal file
9
userland/arch/aarch64/immediates.S
Normal file
@@ -0,0 +1,9 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */
|
||||
|
||||
#include "common.h"
|
||||
ENTRY
|
||||
mov x0, 1
|
||||
mov x0, 0x1
|
||||
mov x0, 1
|
||||
mov x0, 0x1
|
||||
EXIT
|
||||
26
userland/arch/aarch64/ld2.S
Normal file
26
userland/arch/aarch64/ld2.S
Normal file
@@ -0,0 +1,26 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ld2-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
.data
|
||||
u32_interleave: .word \
|
||||
0x11111111, 0x55555555, \
|
||||
0x22222222, 0x66666666, \
|
||||
0x33333333, 0x77777777, \
|
||||
0x44444444, 0x88888888
|
||||
u32_interleave_sum_expect: .word \
|
||||
0x66666666, \
|
||||
0x88888888, \
|
||||
0xAAAAAAAA, \
|
||||
0xCCCCCCCC
|
||||
.bss
|
||||
u32_interleave_sum: .skip 16
|
||||
.text
|
||||
adr x0, u32_interleave
|
||||
ld2 {v0.4s, v1.4s}, [x0]
|
||||
add v2.4s, v0.4s, v1.4s
|
||||
adr x0, u32_interleave_sum
|
||||
st1 {v2.4s}, [x0]
|
||||
ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, 0x10)
|
||||
EXIT
|
||||
26
userland/arch/aarch64/movk.S
Normal file
26
userland/arch/aarch64/movk.S
Normal file
@@ -0,0 +1,26 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movk-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
movk x0, 0x4444, lsl 0
|
||||
movk x0, 0x3333, lsl 16
|
||||
movk x0, 0x2222, lsl 32
|
||||
movk x0, 0x1111, lsl 48
|
||||
ASSERT_EQ(x0, 0x1111222233334444)
|
||||
|
||||
/* Set a label (addresses are 48-bit) with immediates:
|
||||
*
|
||||
* * https://stackoverflow.com/questions/38570495/aarch64-relocation-prefixes
|
||||
* * https://sourceware.org/binutils/docs-2.26/as/AArch64_002dRelocations.html
|
||||
*
|
||||
* This could be used if the label is too far away for
|
||||
* adr relative addressing.
|
||||
*/
|
||||
movz x0, :abs_g2:label /* bits 32-47, overflow check */
|
||||
movk x0, :abs_g1_nc:label /* bits 16-31, no overflow check */
|
||||
movk x0, :abs_g0_nc:label /* bits 0-15, no overflow check */
|
||||
adr x1, label
|
||||
label:
|
||||
ASSERT_EQ_REG(x0, x1)
|
||||
EXIT
|
||||
9
userland/arch/aarch64/movn.S
Normal file
9
userland/arch/aarch64/movn.S
Normal file
@@ -0,0 +1,9 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movn-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
ldr x0, =0x123456789ABCDEF0
|
||||
movn x0, 0x8888, lsl 16
|
||||
ASSERT_EQ(x0, 0xFFFFFFFF7777FFFF)
|
||||
EXIT
|
||||
78
userland/arch/aarch64/pc.S
Normal file
78
userland/arch/aarch64/pc.S
Normal file
@@ -0,0 +1,78 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
#if 0
|
||||
/* Unlike v7, we can't use PC like any other register in ARMv8,
|
||||
* since it is not a general purpose register anymore.
|
||||
*
|
||||
* Only branch instructions can modify the PC.
|
||||
*
|
||||
* B1.2.1 "Registers in AArch64 state" says:
|
||||
*
|
||||
* Software cannot write directly to the PC. It
|
||||
* can only be updated on a branch, exception entry or
|
||||
* exception return.
|
||||
*/
|
||||
ldr pc, =10f
|
||||
FAIL
|
||||
10:
|
||||
#endif
|
||||
#if 0
|
||||
mov x0, pc
|
||||
#endif
|
||||
|
||||
/* LDR PC-relative loads exist in ARMv8, but they have a separate encoding
|
||||
* "LDR (literal)" instead of "LDR (immediate)":
|
||||
* https://stackoverflow.com/questions/28638981/howto-write-pc-relative-adressing-on-arm-asm/54480999#54480999
|
||||
*/
|
||||
ldr x0, pc_relative_ldr
|
||||
b 1f
|
||||
pc_relative_ldr:
|
||||
.quad 0x123456789ABCDEF0
|
||||
1:
|
||||
ASSERT_EQ(x0, 0x123456789ABCDEF0)
|
||||
|
||||
/* Just for fun, we can also use relative numbers instead of labels.
|
||||
* https://reverseengineering.stackexchange.com/questions/17666/how-does-the-ldr-instruction-work-on-arm/20567#20567
|
||||
*/
|
||||
ldr x0, 0x8
|
||||
b 1f
|
||||
.quad 0x123456789ABCDEF0
|
||||
1:
|
||||
ASSERT_EQ(x0, 0x123456789ABCDEF0)
|
||||
|
||||
/* Analogous for b with PC. */
|
||||
mov x0, 0
|
||||
/* Jumps over mov to ASSERT_EQ. */
|
||||
b 8
|
||||
mov x0, 1
|
||||
ASSERT_EQ(x0, 0)
|
||||
|
||||
/* Trying to use the old "LDR (immediate)" PC-relative
|
||||
* syntax does not work.
|
||||
*/
|
||||
#if 0
|
||||
/* 64-bit integer or SP register expected at operand 2 -- `ldr x0,[pc]' */
|
||||
ldr x0, [pc]
|
||||
#endif
|
||||
|
||||
/* There is however no analogue for str. TODO rationale? */
|
||||
#if 0
|
||||
/* Error: invalid addressing mode at operand 2 -- `str x0,pc_relative_str' */
|
||||
str x0, pc_relative_str
|
||||
#endif
|
||||
|
||||
/* You just have to use adr + "STR (register)". */
|
||||
ldr x0, pc_relative_str
|
||||
ASSERT_EQ(x0, 0x0)
|
||||
adr x1, pc_relative_str
|
||||
ldr x0, pc_relative_ldr
|
||||
str x0, [x1]
|
||||
ldr x0, pc_relative_str
|
||||
ASSERT_EQ(x0, 0x123456789ABCDEF0)
|
||||
EXIT
|
||||
.data
|
||||
pc_relative_str:
|
||||
.quad 0x0000000000000000
|
||||
47
userland/arch/aarch64/registers.S
Normal file
47
userland/arch/aarch64/registers.S
Normal file
@@ -0,0 +1,47 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
|
||||
/* 31 64-bit eXtended general purpose registers. */
|
||||
mov x0, 0
|
||||
mov x1, 1
|
||||
mov x2, 2
|
||||
mov x3, 3
|
||||
mov x4, 4
|
||||
mov x5, 5
|
||||
mov x6, 6
|
||||
mov x7, 7
|
||||
mov x8, 8
|
||||
mov x9, 9
|
||||
mov x10, 10
|
||||
mov x11, 11
|
||||
mov x12, 12
|
||||
mov x13, 13
|
||||
mov x14, 14
|
||||
mov x15, 15
|
||||
mov x16, 16
|
||||
mov x17, 17
|
||||
mov x18, 18
|
||||
mov x19, 19
|
||||
mov x20, 20
|
||||
mov x21, 21
|
||||
mov x22, 22
|
||||
mov x23, 23
|
||||
mov x24, 24
|
||||
mov x25, 25
|
||||
mov x26, 26
|
||||
mov x27, 27
|
||||
mov x28, 28
|
||||
mov x29, 29
|
||||
|
||||
/* x30 is the link register. BL stores the return address here. */
|
||||
/*mov x30, 30*/
|
||||
|
||||
/* W form addresses the lower 4 bytes word, and zeroes the top. */
|
||||
ldr x0, =0x1111222233334444
|
||||
ldr x1, =0x5555666677778888
|
||||
mov w0, w1
|
||||
ASSERT_EQ(x0, 0x0000000077778888)
|
||||
EXIT
|
||||
28
userland/arch/aarch64/ret.S
Normal file
28
userland/arch/aarch64/ret.S
Normal file
@@ -0,0 +1,28 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-ret-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
mov x19, 1
|
||||
bl inc
|
||||
ASSERT_EQ(x19, 2)
|
||||
bl inc2
|
||||
ASSERT_EQ(x19, 3)
|
||||
bl inc3
|
||||
ASSERT_EQ(x19, 4)
|
||||
EXIT
|
||||
|
||||
/* void inc(uint64_t *i) { (*i)++ } */
|
||||
inc:
|
||||
add x19, x19, 1
|
||||
ret
|
||||
|
||||
/* Same but explicit return register. */
|
||||
inc2:
|
||||
add x19, x19, 1
|
||||
ret x30
|
||||
|
||||
/* Same but with br. */
|
||||
inc3:
|
||||
add x19, x19, 1
|
||||
br x30
|
||||
13
userland/arch/aarch64/str.S
Normal file
13
userland/arch/aarch64/str.S
Normal file
@@ -0,0 +1,13 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-str-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
ldr x0, myvar
|
||||
ASSERT_EQ(x0, 0x12346789ABCDEF0)
|
||||
#if 0
|
||||
/* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */
|
||||
str x0, myvar
|
||||
#endif
|
||||
EXIT
|
||||
myvar: .quad 0x12346789ABCDEF0
|
||||
1
userland/arch/aarch64/test
Symbolic link
1
userland/arch/aarch64/test
Symbolic link
@@ -0,0 +1 @@
|
||||
../test
|
||||
17
userland/arch/aarch64/ubfm.S
Normal file
17
userland/arch/aarch64/ubfm.S
Normal file
@@ -0,0 +1,17 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfm-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
ldr x19, =0x1122334455667788
|
||||
|
||||
// lsr alias: imms == 63
|
||||
|
||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||
ubfm x20, x19, 16, 63
|
||||
ASSERT_EQ(x20, 0x0000112233445566)
|
||||
|
||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||
ubfm x20, x19, 32, 63
|
||||
ASSERT_EQ(x20, 0x0000000011223344)
|
||||
EXIT
|
||||
15
userland/arch/aarch64/ubfx.S
Normal file
15
userland/arch/aarch64/ubfx.S
Normal file
@@ -0,0 +1,15 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfx-instruction */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
ldr x19, =0x1122334455667788
|
||||
|
||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||
ubfx x20, x19, 8, 16
|
||||
ASSERT_EQ(x20, 0x0000000000006677)
|
||||
|
||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||
ubfx x20, x19, 8, 32
|
||||
ASSERT_EQ(x20, 0x0000000044556677)
|
||||
EXIT
|
||||
51
userland/arch/aarch64/x31.S
Normal file
51
userland/arch/aarch64/x31.S
Normal file
@@ -0,0 +1,51 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-x31-register */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
ENTRY
|
||||
/* ERROR: can never use the name x31. */
|
||||
#if 0
|
||||
mov x31, 31
|
||||
#endif
|
||||
|
||||
/* mov (register) is an alias for ORR, which accepts xzr. */
|
||||
mov x19, 1
|
||||
mov x19, xzr
|
||||
ASSERT_EQ(x19, 0)
|
||||
|
||||
/* Same encoding as the mov version. */
|
||||
mov x19, 1
|
||||
orr x19, xzr, xzr
|
||||
ASSERT_EQ(x19, 0)
|
||||
|
||||
/* So, orr, which is not an alias, can only take xzr, not sp. */
|
||||
#if 0
|
||||
orr sp, sp, sp
|
||||
#endif
|
||||
|
||||
/* Zero register discards result if written to. */
|
||||
mov x19, 1
|
||||
orr xzr, x19, x19
|
||||
ASSERT_EQ(xzr, 0)
|
||||
|
||||
/* MOV (to/from SP) is an alias for ADD (immediate). */
|
||||
mov x19, sp
|
||||
mov sp, 1
|
||||
/* Alias to add. */
|
||||
mov x20, sp
|
||||
/* Exact same encoding as above. */
|
||||
add x20, sp, 0
|
||||
mov sp, x19
|
||||
ASSERT_EQ(x20, 1)
|
||||
|
||||
/* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */
|
||||
#if 0
|
||||
/* Error: integer register expected in the extended/shifted operand register at operand 3 -- `add xzr,xzr,1' */
|
||||
add xzr, xzr, 1
|
||||
#endif
|
||||
|
||||
/* Note however that ADD (register), unlike ADD (immediate),
|
||||
* does not say anything about SP, and so does accept xzr just fine.
|
||||
*/
|
||||
add xzr, xzr, xzr
|
||||
EXIT
|
||||
Reference in New Issue
Block a user