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 x0, 1
add x1, x0, 2
LKMC_ASSERT_EQ(x1, 3)
LKMC_EXIT
LKMC_ASSERT_EQ(x1, =3)
LKMC_EPILOGUE

View File

@@ -3,9 +3,9 @@
* Add a bunch of integers in one go.
*/
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
.data
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
@@ -22,11 +22,11 @@ LKMC_ENTRY
add v2. ## size, v0. ## size, v1. ## size; \
adr x0, output; \
st1 {v2. ## size}, [x0]; \
LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10)
LKMC_ASSERT_MEMCMP(output, expect_ ## size, =0x10)
/* 4x 32-bit */
TEST(4s)
/* 2x 64-bit */
TEST(2d)
#undef TEST
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,11 +1,11 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
#include "common.h"
#include <lkmc.h>
.data
data_label:
.word 0x1234678
LKMC_ENTRY
LKMC_PROLOGUE
/* 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
@@ -18,4 +18,4 @@ LKMC_ENTRY
ldr x1, =data_label
label:
LKMC_ASSERT_EQ_REG(x0, x1)
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
adrp x0, label
adr x1, label
label:
@@ -10,4 +10,4 @@ label:
bic x1, x1, 0xFF
bic x1, x1, 0xF00
LKMC_ASSERT_EQ_REG(x0, x1)
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,12 +1,12 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* cbz == 0 */
mov x0, 0
cbz x0, 1f
LKMC_FAIL
LKMC_ASSERT_FAIL
1:
/* cbz != 0 */
@@ -14,13 +14,13 @@ LKMC_ENTRY
cbz x0, 1f
b 2f
1:
LKMC_FAIL
LKMC_ASSERT_FAIL
2:
/* cbnz != 0 */
mov x0, 1
cbnz x0, 1f
LKMC_FAIL
LKMC_ASSERT_FAIL
1:
/* cbnz == 0 */
@@ -28,6 +28,6 @@ LKMC_ENTRY
cbnz x0, 1f
b 2f
1:
LKMC_FAIL
LKMC_ASSERT_FAIL
2:
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,11 +1,11 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
ldr x0, =0x1122334455667788
ldr x1, =0xFFFFFFFFFFFFFFFF
bfi x1, x0, 16, 32
LKMC_ASSERT_EQ(x1, 0xFFFF55667788FFFF)
LKMC_EXIT
LKMC_ASSERT_EQ(x1, =0xFFFF55667788FFFF)
LKMC_EPILOGUE

View File

@@ -1,19 +1,19 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cbz-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* Branch. */
mov x0, 0x0
cbz x0, ok
LKMC_FAIL
LKMC_ASSERT_FAIL
ok:
/* Don't branch. */
mov x0, 0x1
cbz x0, ko
LKMC_EXIT
LKMC_EPILOGUE
ko:
LKMC_FAIL
LKMC_ASSERT_FAIL

View File

@@ -1,7 +1,7 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
#include "common.h"
LKMC_ENTRY
#include <lkmc.h>
LKMC_PROLOGUE
# mycomment
/* ARMv8 has // instead of @ as for comments. */
@@ -14,4 +14,4 @@ LKMC_ENTRY
@ mycomment
nop @ mycomment
#endif
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,83 +0,0 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
#ifndef COMMON_ARCH_H
#define COMMON_ARCH_H
#define LKMC_ASSERT_EQ(reg, const) \
mov x0, reg; \
ldr x1, =const; \
LKMC_ASSERT_EQ_DO(64); \
;
#define LKMC_ASSERT_EQ_DO(bits) \
bl lkmc_assert_eq_ ## bits; \
cmp x0, 0; \
LKMC_ASSERT(beq); \
;
#define LKMC_ASSERT_EQ_REG(reg1, reg2) \
str reg2, [sp, -16]!; \
mov x0, reg1; \
ldr x1, [sp], 16; \
LKMC_ASSERT_EQ_DO(64); \
;
#define LKMC_ASSERT_EQ_REG_32(reg1, reg2) \
str reg2, [sp, -4]!; \
mov w0, reg1; \
ldr w1, [sp], 4; \
LKMC_ASSERT_EQ_DO(32); \
;
#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
adr x0, label1; \
adr x1, label2; \
ldr x2, =const_size; \
bl lkmc_assert_memcmp; \
cmp x0, 0; \
LKMC_ASSERT(beq); \
;
#define LKMC_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 LKMC_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 LKMC_FAIL \
ldr w0, =__LINE__; \
b fail; \
;
#endif

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cset-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* Test values. */
mov x19, 0
mov x20, 1
@@ -10,19 +10,19 @@ LKMC_ENTRY
/* eq is true, set x21 = 1. */
cmp x19, x19
cset x21, eq
LKMC_ASSERT_EQ(x21, 1)
LKMC_ASSERT_EQ(x21, =1)
/* eq is false, set x21 = 0. */
cmp x19, x20
cset x21, eq
LKMC_ASSERT_EQ(x21, 0)
LKMC_ASSERT_EQ(x21, =0)
/* Same for ne. */
cmp x19, x19
cset x21, ne
LKMC_ASSERT_EQ(x21, 0)
LKMC_ASSERT_EQ(x21, =0)
cmp x19, x20
cset x21, ne
LKMC_ASSERT_EQ(x21, 1)
LKMC_EXIT
LKMC_ASSERT_EQ(x21, =1)
LKMC_EPILOGUE

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#advanced-simd-instructions */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* 1.5 + 2.5 == 4.0
* using 64-bit double immediates.
*/
@@ -57,4 +57,4 @@ my_double_sum_expect:
#if 0
fmov d0, 1.23456798
#endif
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
.data
input0_4s: .float 1.5, 2.5, 3.5, 4.5
input1_4s: .float 5.5, 6.5, 7.5, 8.5
@@ -24,11 +24,11 @@ LKMC_ENTRY
fadd v2. ## size, v0. ## size, v1. ## size; \
adr x0, output; \
st1 {v2. ## size}, [x0]; \
LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10)
LKMC_ASSERT_MEMCMP(output, expect_ ## size, =0x10)
/* 4x 32-bit */
TEST(4s)
/* 2x 64-bit */
TEST(2d)
#undef TEST
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,13 +1,13 @@
/* 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) \
adr x0, label1; \
adr x1, label2; \
sub x0, x1, x0; \
LKMC_ASSERT_EQ(x0, result)
LKMC_ASSERT_EQ(x0, =result)
ASSERT_DIFF(mybyte, myword, 1)
ASSERT_DIFF(myword, mylong, 4)
@@ -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,9 +1,9 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */
#include "common.h"
LKMC_ENTRY
#include <lkmc.h>
LKMC_PROLOGUE
mov x0, 1
mov x0, 0x1
mov x0, 1
mov x0, 0x1
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ld2-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
.data
u32_interleave: .word \
0x11111111, 0x55555555, \
@@ -22,5 +22,5 @@ LKMC_ENTRY
add v2.4s, v0.4s, v1.4s
adr x0, u32_interleave_sum
st1 {v2.4s}, [x0]
LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, 0x10)
LKMC_EXIT
LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, =0x10)
LKMC_EPILOGUE

View File

@@ -0,0 +1,35 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
#include <lkmc.h>
LKMC_PROLOGUE
ldr x19, =0x123456789ABCDEF0
ldr x20, =0x123456789ABCDEF0
ldr x21, =0x000000009ABCDEF0
/* Passing examples. */
/* Register immediate. */
LKMC_ASSERT_EQ(x19, =0x123456789ABCDEF0)
#if 0
/* Syntax not supported. */
LKMC_ASSERT_EQ(=0x123456789ABCDEF0, x19)
#endif
/* Register register. */
LKMC_ASSERT_EQ_REG(x19, x20)
LKMC_ASSERT_EQ_REG(x20, x19)
LKMC_ASSERT_EQ_REG_32(w19, w21)
LKMC_ASSERT_EQ_REG_32(w21, w19)
/* Register memory. */
LKMC_ASSERT_EQ(x19, myvar)
#if 0
/* Syntax not supported. */
LKMC_ASSERT_EQ(myvar, x19)
#endif
/* Now let's fail. */
LKMC_ASSERT_EQ(x19, =0x123456789ABCDEF1)
LKMC_EPILOGUE
myvar: .quad 0x123456789ABCDEF0

View File

@@ -0,0 +1,15 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
#include <lkmc.h>
LKMC_PROLOGUE
/* Pass */
LKMC_ASSERT_MEMCMP(var0, var1, =0x10)
LKMC_ASSERT_MEMCMP(var0, var1, size)
/* Fail */
LKMC_ASSERT_MEMCMP(var0, var2, =0x10)
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

@@ -1,13 +1,13 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movk-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
movk x0, 0x4444, lsl 0
movk x0, 0x3333, lsl 16
movk x0, 0x2222, lsl 32
movk x0, 0x1111, lsl 48
LKMC_ASSERT_EQ(x0, 0x1111222233334444)
LKMC_ASSERT_EQ(x0, =0x1111222233334444)
/* Set a label (addresses are 48-bit) with immediates:
*
@@ -23,4 +23,4 @@ LKMC_ENTRY
adr x1, label
label:
LKMC_ASSERT_EQ_REG(x0, x1)
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,9 +1,9 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movn-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
ldr x0, =0x123456789ABCDEF0
movn x0, 0x8888, lsl 16
LKMC_ASSERT_EQ(x0, 0xFFFFFFFF7777FFFF)
LKMC_EXIT
LKMC_ASSERT_EQ(x0, =0xFFFFFFFF7777FFFF)
LKMC_EPILOGUE

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
#if 0
/* Unlike v7, we can't use PC like any other register in ARMv8,
* since it is not a general purpose register anymore.
@@ -16,7 +16,7 @@ LKMC_ENTRY
* exception return.
*/
ldr pc, =10f
LKMC_FAIL
LKMC_ASSERT_FAIL
10:
#endif
#if 0
@@ -32,7 +32,7 @@ LKMC_ENTRY
pc_relative_ldr:
.quad 0x123456789ABCDEF0
1:
LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
LKMC_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
@@ -41,14 +41,14 @@ pc_relative_ldr:
b 1f
.quad 0x123456789ABCDEF0
1:
LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0)
/* Analogous for b with PC. */
mov x0, 0
/* Jumps over mov to LKMC_ASSERT_EQ. */
b 8
mov x0, 1
LKMC_ASSERT_EQ(x0, 0)
LKMC_ASSERT_EQ(x0, =0)
/* Trying to use the old "LDR (immediate)" PC-relative
* syntax does not work.
@@ -66,13 +66,13 @@ pc_relative_ldr:
/* You just have to use adr + "STR (register)". */
ldr x0, pc_relative_str
LKMC_ASSERT_EQ(x0, 0x0)
LKMC_ASSERT_EQ(x0, =0x0)
adr x1, pc_relative_str
ldr x0, pc_relative_ldr
str x0, [x1]
ldr x0, pc_relative_str
LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
LKMC_EXIT
LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0)
LKMC_EPILOGUE
.data
pc_relative_str:
.quad 0x0000000000000000

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* 31 64-bit eXtended general purpose registers. */
mov x0, 0
@@ -43,5 +43,5 @@ LKMC_ENTRY
ldr x0, =0x1111222233334444
ldr x1, =0x5555666677778888
mov w0, w1
LKMC_ASSERT_EQ(x0, 0x0000000077778888)
LKMC_EXIT
LKMC_ASSERT_EQ(x0, =0x0000000077778888)
LKMC_EPILOGUE

View File

@@ -1,16 +1,16 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-ret-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
mov x19, 1
bl inc
LKMC_ASSERT_EQ(x19, 2)
LKMC_ASSERT_EQ(x19, =2)
bl inc2
LKMC_ASSERT_EQ(x19, 3)
LKMC_ASSERT_EQ(x19, =3)
bl inc3
LKMC_ASSERT_EQ(x19, 4)
LKMC_EXIT
LKMC_ASSERT_EQ(x19, =4)
LKMC_EPILOGUE
/* void inc(uint64_t *i) { (*i)++ } */
inc:

View File

@@ -1,13 +1,13 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-str-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
ldr x0, myvar
LKMC_ASSERT_EQ(x0, 0x12346789ABCDEF0)
LKMC_ASSERT_EQ(x0, =0x12346789ABCDEF0)
#if 0
/* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */
str x0, myvar
#endif
LKMC_EXIT
LKMC_EPILOGUE
myvar: .quad 0x12346789ABCDEF0

View File

@@ -1,17 +1,17 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfm-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
ldr x19, =0x1122334455667788
// lsr alias: imms == 63
ldr x20, =0xFFFFFFFFFFFFFFFF
ubfm x20, x19, 16, 63
LKMC_ASSERT_EQ(x20, 0x0000112233445566)
LKMC_ASSERT_EQ(x20, =0x0000112233445566)
ldr x20, =0xFFFFFFFFFFFFFFFF
ubfm x20, x19, 32, 63
LKMC_ASSERT_EQ(x20, 0x0000000011223344)
LKMC_EXIT
LKMC_ASSERT_EQ(x20, =0x0000000011223344)
LKMC_EPILOGUE

View File

@@ -1,15 +1,15 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfx-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
ldr x19, =0x1122334455667788
ldr x20, =0xFFFFFFFFFFFFFFFF
ubfx x20, x19, 8, 16
LKMC_ASSERT_EQ(x20, 0x0000000000006677)
LKMC_ASSERT_EQ(x20, =0x0000000000006677)
ldr x20, =0xFFFFFFFFFFFFFFFF
ubfx x20, x19, 8, 32
LKMC_ASSERT_EQ(x20, 0x0000000044556677)
LKMC_EXIT
LKMC_ASSERT_EQ(x20, =0x0000000044556677)
LKMC_EPILOGUE

View File

@@ -1,10 +1,10 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
.long 0
#if 0
udf 0
#endif
LKMC_EXIT
LKMC_EPILOGUE

View File

@@ -1,8 +1,8 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-x31-register */
#include "common.h"
#include <lkmc.h>
LKMC_ENTRY
LKMC_PROLOGUE
/* ERROR: can never use the name x31. */
#if 0
mov x31, 31
@@ -11,12 +11,12 @@ LKMC_ENTRY
/* mov (register) is an alias for ORR, which accepts xzr. */
mov x19, 1
mov x19, xzr
LKMC_ASSERT_EQ(x19, 0)
LKMC_ASSERT_EQ(x19, =0)
/* Same encoding as the mov version. */
mov x19, 1
orr x19, xzr, xzr
LKMC_ASSERT_EQ(x19, 0)
LKMC_ASSERT_EQ(x19, =0)
/* So, orr, which is not an alias, can only take xzr, not sp. */
#if 0
@@ -26,7 +26,7 @@ LKMC_ENTRY
/* Zero register discards result if written to. */
mov x19, 1
orr xzr, x19, x19
LKMC_ASSERT_EQ(xzr, 0)
LKMC_ASSERT_EQ(xzr, =0)
/* MOV (to/from SP) is an alias for ADD (immediate). */
mov x19, sp
@@ -36,7 +36,7 @@ LKMC_ENTRY
/* Exact same encoding as above. */
add x20, sp, 0
mov sp, x19
LKMC_ASSERT_EQ(x20, 1)
LKMC_ASSERT_EQ(x20, =1)
/* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */
#if 0
@@ -48,4 +48,4 @@ LKMC_ENTRY
* does not say anything about SP, and so does accept xzr just fine.
*/
add xzr, xzr, xzr
LKMC_EXIT
LKMC_EPILOGUE