asm: make use regular asserts that will just work on baremetal

Previously had wonky line pointer in asm_main. New interface simpler and more portable.

Add tests for ASSERT_EQ_ and family in arm and aarch64, previously on x86_64.

ASSERT_EQ_ and family in ARM can now either take =123, =addr or var, before this
the = was added on macros so var was not possible.

Define the main function directly in assembly, the C driver was useless.
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-05-23 00:00:00 +00:00
parent 72200dee4e
commit c8c4f89854
90 changed files with 1003 additions and 978 deletions

View File

@@ -1,9 +1,9 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
mov $1, %rax
add $2, %rax
LKMC_ASSERT_EQ(%rax, $3)
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -3,9 +3,9 @@
* Add a bunch of floating point numbers in one go.
*/
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
.bss
output: .skip 16
.data
@@ -28,4 +28,4 @@ LKMC_ENTRY
/* 2x 64-bit */
TEST(d)
#undef TEST
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,87 +0,0 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
#ifndef COMMON_ARCH_H
#define COMMON_ARCH_H
/* This and other macros may make C function calls, and therefore can destroy
* non-callee saved registers. */
#define LKMC_ASSERT_EQ(general1, general2) \
mov general2, %rdi; \
push %rdi; \
mov general1, %rdi; \
pop %rsi; \
LKMC_ASSERT_EQ_DO(64); \
;
#define LKMC_ASSERT_EQ_DO(bits) \
call lkmc_assert_eq_ ## bits; \
cmp $0, %rax; \
LKMC_ASSERT(je); \
;
#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
lea label1(%rip), %rdi; \
lea label2(%rip), %rsi; \
mov const_size, %rdx; \
call lkmc_assert_memcmp; \
cmp $0, %rax; \
LKMC_ASSERT(je); \
;
/* Program entry point.
*
* Return with LKMC_EXIT.
*
* Basically implements an x86_64 prologue:
*
* - save callee saved registers
* x86_64 explained at: https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call/55207335#55207335
* - save register arguments for later usage
*/
#define LKMC_ENTRY \
.text; \
.global asm_main; \
asm_main: \
push %rbp; \
mov %rsp, %rbp; \
push %r15; \
push %r14; \
push %r13; \
push %r12; \
push %rbx; \
push %rdi; \
sub $8, %rsp; \
asm_main_after_prologue: \
;
/* Meant to be called at the end of LKMC_ENTRY.*
*
* Branching to "fail" makes tests fail with exit status 1.
*
* If LKMC_EXIT is reached, the program ends successfully.
*/
#define LKMC_EXIT \
mov $0, %rax; \
jmp pass; \
fail: \
/* -0x30(%rbp) is argument 1 which we pushed at prologue */ \
mov -0x30(%rbp), %rbx; \
movl %eax, (%rbx); \
mov $1, %rax; \
pass: \
add $16, %rsp; \
pop %rbx; \
pop %r12; \
pop %r13; \
pop %r14; \
pop %r15; \
pop %rbp; \
ret; \
;
#define LKMC_FAIL \
mov $__LINE__, %eax; \
jmp fail; \
;
#endif

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
#define ASSERT_DIFF(label1, label2, result) \
lea label2(%rip), %rax; \
lea label1(%rip), %rbx; \
@@ -15,7 +15,7 @@ LKMC_ENTRY
ASSERT_DIFF(myquad, myocta, 8)
ASSERT_DIFF(myocta, theend, 16)
#undef ASSERT_DIF
LKMC_EXIT
LKMC_EPILOGUE
mybyte:
.byte 0x12
myword:

View File

@@ -1,16 +1,26 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
mov $0x123456789ABCDEF0, %r12
mov $0x123456789ABCDEF0, %r13
/* Passing examples. */
/* Register immediate. */
LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF0)
LKMC_ASSERT_EQ(%r12, %r13)
LKMC_ASSERT_EQ(%r12, myvar)
LKMC_ASSERT_EQ($0x123456789ABCDEF0, %r12)
/* Register register. */
LKMC_ASSERT_EQ(%r12, %r13)
LKMC_ASSERT_EQ(%r13, %r12)
/* Register memory. */
LKMC_ASSERT_EQ(%r12, myvar)
LKMC_ASSERT_EQ(myvar, %r12)
/* Now let's fail. */
LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF1)
LKMC_EXIT
LKMC_EPILOGUE
myvar: .quad 0x123456789ABCDEF0

View File

@@ -1,11 +1,15 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* Pass */
LKMC_ASSERT_MEMCMP(var0, var1, $0x10)
LKMC_ASSERT_MEMCMP(var0, var1, size)
/* Fail */
LKMC_ASSERT_MEMCMP(var0, var2, $0x10)
LKMC_EXIT
LKMC_EPILOGUE
var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444
size: .quad 0x10

View File

@@ -5,9 +5,9 @@
* The different variants basically determine if carries get forwarded or not.
*/
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
.data
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
@@ -35,4 +35,4 @@ LKMC_ENTRY
/* 2x 16-bit */
TEST(q)
#undef TEST
LKMC_EXIT
LKMC_EPILOGUE