userland: scope every header identifier with lkmc_

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-05-21 00:00:01 +00:00
parent 6fe9e5bae7
commit 72200dee4e
78 changed files with 369 additions and 377 deletions

View File

@@ -26,7 +26,7 @@ class PathProperties:
'-fno-pie', LF, '-fno-pie', LF,
'-no-pie', LF, '-no-pie', LF,
], ],
'cc_flags_after': ['-lm'], 'cc_flags_after': ['-lm', LF],
'cc_pedantic': True, 'cc_pedantic': True,
'cxx_std': default_cxx_std, 'cxx_std': default_cxx_std,
# Expected program exit status. When signals are raised, this refers # Expected program exit status. When signals are raised, this refers

View File

@@ -2,8 +2,8 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov x0, 1 mov x0, 1
add x1, x0, 2 add x1, x0, 2
ASSERT_EQ(x1, 3) LKMC_ASSERT_EQ(x1, 3)
EXIT LKMC_EXIT

View File

@@ -5,7 +5,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.data .data
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4 input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515 input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
@@ -22,11 +22,11 @@ ENTRY
add v2. ## size, v0. ## size, v1. ## size; \ add v2. ## size, v0. ## size, v1. ## size; \
adr x0, output; \ adr x0, output; \
st1 {v2. ## size}, [x0]; \ st1 {v2. ## size}, [x0]; \
ASSERT_MEMCMP(output, expect_ ## size, 0x10) LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10)
/* 4x 32-bit */ /* 4x 32-bit */
TEST(4s) TEST(4s)
/* 2x 64-bit */ /* 2x 64-bit */
TEST(2d) TEST(2d)
#undef TEST #undef TEST
EXIT LKMC_EXIT

View File

@@ -5,7 +5,7 @@
.data .data
data_label: data_label:
.word 0x1234678 .word 0x1234678
ENTRY LKMC_ENTRY
/* This is not possible in v7 because the label is in another section. /* This is not possible in v7 because the label is in another section.
* objdump says that this generates a R_AARCH64_ADR_PRE relocation. * objdump says that this generates a R_AARCH64_ADR_PRE relocation.
* which looks specific to ADR, and therefore makes it more likely * which looks specific to ADR, and therefore makes it more likely
@@ -17,5 +17,5 @@ ENTRY
adr x0, data_label adr x0, data_label
ldr x1, =data_label ldr x1, =data_label
label: label:
ASSERT_EQ_REG(x0, x1) LKMC_ASSERT_EQ_REG(x0, x1)
EXIT LKMC_EXIT

View File

@@ -2,12 +2,12 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
adrp x0, label adrp x0, label
adr x1, label adr x1, label
label: label:
/* Clear the lower 12 bits. */ /* Clear the lower 12 bits. */
bic x1, x1, 0xFF bic x1, x1, 0xFF
bic x1, x1, 0xF00 bic x1, x1, 0xF00
ASSERT_EQ_REG(x0, x1) LKMC_ASSERT_EQ_REG(x0, x1)
EXIT LKMC_EXIT

View File

@@ -2,11 +2,11 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* cbz == 0 */ /* cbz == 0 */
mov x0, 0 mov x0, 0
cbz x0, 1f cbz x0, 1f
FAIL LKMC_FAIL
1: 1:
/* cbz != 0 */ /* cbz != 0 */
@@ -14,13 +14,13 @@ ENTRY
cbz x0, 1f cbz x0, 1f
b 2f b 2f
1: 1:
FAIL LKMC_FAIL
2: 2:
/* cbnz != 0 */ /* cbnz != 0 */
mov x0, 1 mov x0, 1
cbnz x0, 1f cbnz x0, 1f
FAIL LKMC_FAIL
1: 1:
/* cbnz == 0 */ /* cbnz == 0 */
@@ -28,6 +28,6 @@ ENTRY
cbnz x0, 1f cbnz x0, 1f
b 2f b 2f
1: 1:
FAIL LKMC_FAIL
2: 2:
EXIT LKMC_EXIT

View File

@@ -2,10 +2,10 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr x0, =0x1122334455667788 ldr x0, =0x1122334455667788
ldr x1, =0xFFFFFFFFFFFFFFFF ldr x1, =0xFFFFFFFFFFFFFFFF
bfi x1, x0, 16, 32 bfi x1, x0, 16, 32
ASSERT_EQ(x1, 0xFFFF55667788FFFF) LKMC_ASSERT_EQ(x1, 0xFFFF55667788FFFF)
EXIT LKMC_EXIT

View File

@@ -2,18 +2,18 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Branch. */ /* Branch. */
mov x0, 0x0 mov x0, 0x0
cbz x0, ok cbz x0, ok
FAIL LKMC_FAIL
ok: ok:
/* Don't branch. */ /* Don't branch. */
mov x0, 0x1 mov x0, 0x1
cbz x0, ko cbz x0, ko
EXIT LKMC_EXIT
ko: ko:
FAIL LKMC_FAIL

View File

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

View File

@@ -3,42 +3,42 @@
#ifndef COMMON_ARCH_H #ifndef COMMON_ARCH_H
#define COMMON_ARCH_H #define COMMON_ARCH_H
#define ASSERT_EQ(reg, const) \ #define LKMC_ASSERT_EQ(reg, const) \
mov x0, reg; \ mov x0, reg; \
ldr x1, =const; \ ldr x1, =const; \
ASSERT_EQ_DO(64); \ LKMC_ASSERT_EQ_DO(64); \
; ;
#define ASSERT_EQ_DO(bits) \ #define LKMC_ASSERT_EQ_DO(bits) \
bl assert_eq_ ## bits; \ bl lkmc_assert_eq_ ## bits; \
cmp x0, 0; \ cmp x0, 0; \
ASSERT(beq); \ LKMC_ASSERT(beq); \
; ;
#define ASSERT_EQ_REG(reg1, reg2) \ #define LKMC_ASSERT_EQ_REG(reg1, reg2) \
str reg2, [sp, -16]!; \ str reg2, [sp, -16]!; \
mov x0, reg1; \ mov x0, reg1; \
ldr x1, [sp], 16; \ ldr x1, [sp], 16; \
ASSERT_EQ_DO(64); \ LKMC_ASSERT_EQ_DO(64); \
; ;
#define ASSERT_EQ_REG_32(reg1, reg2) \ #define LKMC_ASSERT_EQ_REG_32(reg1, reg2) \
str reg2, [sp, -4]!; \ str reg2, [sp, -4]!; \
mov w0, reg1; \ mov w0, reg1; \
ldr w1, [sp], 4; \ ldr w1, [sp], 4; \
ASSERT_EQ_DO(32); \ LKMC_ASSERT_EQ_DO(32); \
; ;
#define ASSERT_MEMCMP(label1, label2, const_size) \ #define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
adr x0, label1; \ adr x0, label1; \
adr x1, label2; \ adr x1, label2; \
ldr x2, =const_size; \ ldr x2, =const_size; \
bl assert_memcmp; \ bl lkmc_assert_memcmp; \
cmp x0, 0; \ cmp x0, 0; \
ASSERT(beq); \ LKMC_ASSERT(beq); \
; ;
#define ENTRY \ #define LKMC_ENTRY \
.text; \ .text; \
.global asm_main; \ .global asm_main; \
asm_main: \ asm_main: \
@@ -56,7 +56,7 @@ asm_main: \
asm_main_after_prologue: \ asm_main_after_prologue: \
; ;
#define EXIT \ #define LKMC_EXIT \
mov w0, 0; \ mov w0, 0; \
mov w1, 0; \ mov w1, 0; \
b pass; \ b pass; \
@@ -75,7 +75,7 @@ pass: \
ret; \ ret; \
; ;
#define FAIL \ #define LKMC_FAIL \
ldr w0, =__LINE__; \ ldr w0, =__LINE__; \
b fail; \ b fail; \
; ;

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Test values. */ /* Test values. */
mov x19, 0 mov x19, 0
mov x20, 1 mov x20, 1
@@ -10,19 +10,19 @@ ENTRY
/* eq is true, set x21 = 1. */ /* eq is true, set x21 = 1. */
cmp x19, x19 cmp x19, x19
cset x21, eq cset x21, eq
ASSERT_EQ(x21, 1) LKMC_ASSERT_EQ(x21, 1)
/* eq is false, set x21 = 0. */ /* eq is false, set x21 = 0. */
cmp x19, x20 cmp x19, x20
cset x21, eq cset x21, eq
ASSERT_EQ(x21, 0) LKMC_ASSERT_EQ(x21, 0)
/* Same for ne. */ /* Same for ne. */
cmp x19, x19 cmp x19, x19
cset x21, ne cset x21, ne
ASSERT_EQ(x21, 0) LKMC_ASSERT_EQ(x21, 0)
cmp x19, x20 cmp x19, x20
cset x21, ne cset x21, ne
ASSERT_EQ(x21, 1) LKMC_ASSERT_EQ(x21, 1)
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 1.5 + 2.5 == 4.0 /* 1.5 + 2.5 == 4.0
* using 64-bit double immediates. * using 64-bit double immediates.
*/ */
@@ -14,7 +14,7 @@ ENTRY
* automatically in the main CPSR. * automatically in the main CPSR.
*/ */
fcmp d2, d3 fcmp d2, d3
ASSERT(beq) LKMC_ASSERT(beq)
/* Now with a memory stored value. */ /* Now with a memory stored value. */
.data .data
@@ -30,7 +30,7 @@ my_double_sum_expect:
fadd d2, d0, d1 fadd d2, d0, d1
ldr d3, my_double_sum_expect ldr d3, my_double_sum_expect
fcmp d2, d3 fcmp d2, d3
ASSERT(beq) LKMC_ASSERT(beq)
/* Now in 32-bit. */ /* Now in 32-bit. */
fmov s0, 1.5 fmov s0, 1.5
@@ -38,7 +38,7 @@ my_double_sum_expect:
fadd s2, s0, s1 fadd s2, s0, s1
fmov s3, 4.0 fmov s3, 4.0
fcmp s2, s3 fcmp s2, s3
ASSERT(beq) LKMC_ASSERT(beq)
/* TODO why? What's the point of q then? /* TODO why? What's the point of q then?
* Error: operand mismatch -- `fmov q0,1.5' * Error: operand mismatch -- `fmov q0,1.5'
@@ -57,4 +57,4 @@ my_double_sum_expect:
#if 0 #if 0
fmov d0, 1.23456798 fmov d0, 1.23456798
#endif #endif
EXIT LKMC_EXIT

View File

@@ -5,7 +5,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.data .data
input0_4s: .float 1.5, 2.5, 3.5, 4.5 input0_4s: .float 1.5, 2.5, 3.5, 4.5
input1_4s: .float 5.5, 6.5, 7.5, 8.5 input1_4s: .float 5.5, 6.5, 7.5, 8.5
@@ -24,11 +24,11 @@ ENTRY
fadd v2. ## size, v0. ## size, v1. ## size; \ fadd v2. ## size, v0. ## size, v1. ## size; \
adr x0, output; \ adr x0, output; \
st1 {v2. ## size}, [x0]; \ st1 {v2. ## size}, [x0]; \
ASSERT_MEMCMP(output, expect_ ## size, 0x10) LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10)
/* 4x 32-bit */ /* 4x 32-bit */
TEST(4s) TEST(4s)
/* 2x 64-bit */ /* 2x 64-bit */
TEST(2d) TEST(2d)
#undef TEST #undef TEST
EXIT LKMC_EXIT

View File

@@ -2,12 +2,12 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
#define ASSERT_DIFF(label1, label2, result) \ #define ASSERT_DIFF(label1, label2, result) \
adr x0, label1; \ adr x0, label1; \
adr x1, label2; \ adr x1, label2; \
sub x0, x1, x0; \ sub x0, x1, x0; \
ASSERT_EQ(x0, result) LKMC_ASSERT_EQ(x0, result)
ASSERT_DIFF(mybyte, myword, 1) ASSERT_DIFF(mybyte, myword, 1)
ASSERT_DIFF(myword, mylong, 4) ASSERT_DIFF(myword, mylong, 4)
@@ -15,7 +15,7 @@ ENTRY
ASSERT_DIFF(myquad, myocta, 8) ASSERT_DIFF(myquad, myocta, 8)
ASSERT_DIFF(myocta, theend, 16) ASSERT_DIFF(myocta, theend, 16)
#undef ASSERT_DIF #undef ASSERT_DIF
EXIT LKMC_EXIT
mybyte: mybyte:
.byte 0x12 .byte 0x12
myword: myword:

View File

@@ -1,9 +1,9 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov x0, 1 mov x0, 1
mov x0, 0x1 mov x0, 0x1
mov x0, 1 mov x0, 1
mov x0, 0x1 mov x0, 0x1
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.data .data
u32_interleave: .word \ u32_interleave: .word \
0x11111111, 0x55555555, \ 0x11111111, 0x55555555, \
@@ -22,5 +22,5 @@ ENTRY
add v2.4s, v0.4s, v1.4s add v2.4s, v0.4s, v1.4s
adr x0, u32_interleave_sum adr x0, u32_interleave_sum
st1 {v2.4s}, [x0] st1 {v2.4s}, [x0]
ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, 0x10) LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, 0x10)
EXIT LKMC_EXIT

View File

@@ -2,12 +2,12 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
movk x0, 0x4444, lsl 0 movk x0, 0x4444, lsl 0
movk x0, 0x3333, lsl 16 movk x0, 0x3333, lsl 16
movk x0, 0x2222, lsl 32 movk x0, 0x2222, lsl 32
movk x0, 0x1111, lsl 48 movk x0, 0x1111, lsl 48
ASSERT_EQ(x0, 0x1111222233334444) LKMC_ASSERT_EQ(x0, 0x1111222233334444)
/* Set a label (addresses are 48-bit) with immediates: /* Set a label (addresses are 48-bit) with immediates:
* *
@@ -22,5 +22,5 @@ ENTRY
movk x0, :abs_g0_nc:label /* bits 0-15, no overflow check */ movk x0, :abs_g0_nc:label /* bits 0-15, no overflow check */
adr x1, label adr x1, label
label: label:
ASSERT_EQ_REG(x0, x1) LKMC_ASSERT_EQ_REG(x0, x1)
EXIT LKMC_EXIT

View File

@@ -2,8 +2,8 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr x0, =0x123456789ABCDEF0 ldr x0, =0x123456789ABCDEF0
movn x0, 0x8888, lsl 16 movn x0, 0x8888, lsl 16
ASSERT_EQ(x0, 0xFFFFFFFF7777FFFF) LKMC_ASSERT_EQ(x0, 0xFFFFFFFF7777FFFF)
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
#if 0 #if 0
/* Unlike v7, we can't use PC like any other register in ARMv8, /* Unlike v7, we can't use PC like any other register in ARMv8,
* since it is not a general purpose register anymore. * since it is not a general purpose register anymore.
@@ -16,7 +16,7 @@ ENTRY
* exception return. * exception return.
*/ */
ldr pc, =10f ldr pc, =10f
FAIL LKMC_FAIL
10: 10:
#endif #endif
#if 0 #if 0
@@ -32,7 +32,7 @@ ENTRY
pc_relative_ldr: pc_relative_ldr:
.quad 0x123456789ABCDEF0 .quad 0x123456789ABCDEF0
1: 1:
ASSERT_EQ(x0, 0x123456789ABCDEF0) LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
/* Just for fun, we can also use relative numbers instead of labels. /* 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 * 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 b 1f
.quad 0x123456789ABCDEF0 .quad 0x123456789ABCDEF0
1: 1:
ASSERT_EQ(x0, 0x123456789ABCDEF0) LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
/* Analogous for b with PC. */ /* Analogous for b with PC. */
mov x0, 0 mov x0, 0
/* Jumps over mov to ASSERT_EQ. */ /* Jumps over mov to LKMC_ASSERT_EQ. */
b 8 b 8
mov x0, 1 mov x0, 1
ASSERT_EQ(x0, 0) LKMC_ASSERT_EQ(x0, 0)
/* Trying to use the old "LDR (immediate)" PC-relative /* Trying to use the old "LDR (immediate)" PC-relative
* syntax does not work. * syntax does not work.
@@ -66,13 +66,13 @@ pc_relative_ldr:
/* You just have to use adr + "STR (register)". */ /* You just have to use adr + "STR (register)". */
ldr x0, pc_relative_str ldr x0, pc_relative_str
ASSERT_EQ(x0, 0x0) LKMC_ASSERT_EQ(x0, 0x0)
adr x1, pc_relative_str adr x1, pc_relative_str
ldr x0, pc_relative_ldr ldr x0, pc_relative_ldr
str x0, [x1] str x0, [x1]
ldr x0, pc_relative_str ldr x0, pc_relative_str
ASSERT_EQ(x0, 0x123456789ABCDEF0) LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
EXIT LKMC_EXIT
.data .data
pc_relative_str: pc_relative_str:
.quad 0x0000000000000000 .quad 0x0000000000000000

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 31 64-bit eXtended general purpose registers. */ /* 31 64-bit eXtended general purpose registers. */
mov x0, 0 mov x0, 0
@@ -43,5 +43,5 @@ ENTRY
ldr x0, =0x1111222233334444 ldr x0, =0x1111222233334444
ldr x1, =0x5555666677778888 ldr x1, =0x5555666677778888
mov w0, w1 mov w0, w1
ASSERT_EQ(x0, 0x0000000077778888) LKMC_ASSERT_EQ(x0, 0x0000000077778888)
EXIT LKMC_EXIT

View File

@@ -2,15 +2,15 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov x19, 1 mov x19, 1
bl inc bl inc
ASSERT_EQ(x19, 2) LKMC_ASSERT_EQ(x19, 2)
bl inc2 bl inc2
ASSERT_EQ(x19, 3) LKMC_ASSERT_EQ(x19, 3)
bl inc3 bl inc3
ASSERT_EQ(x19, 4) LKMC_ASSERT_EQ(x19, 4)
EXIT LKMC_EXIT
/* void inc(uint64_t *i) { (*i)++ } */ /* void inc(uint64_t *i) { (*i)++ } */
inc: inc:

View File

@@ -2,12 +2,12 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr x0, myvar ldr x0, myvar
ASSERT_EQ(x0, 0x12346789ABCDEF0) LKMC_ASSERT_EQ(x0, 0x12346789ABCDEF0)
#if 0 #if 0
/* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */ /* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */
str x0, myvar str x0, myvar
#endif #endif
EXIT LKMC_EXIT
myvar: .quad 0x12346789ABCDEF0 myvar: .quad 0x12346789ABCDEF0

View File

@@ -2,16 +2,16 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr x19, =0x1122334455667788 ldr x19, =0x1122334455667788
// lsr alias: imms == 63 // lsr alias: imms == 63
ldr x20, =0xFFFFFFFFFFFFFFFF ldr x20, =0xFFFFFFFFFFFFFFFF
ubfm x20, x19, 16, 63 ubfm x20, x19, 16, 63
ASSERT_EQ(x20, 0x0000112233445566) LKMC_ASSERT_EQ(x20, 0x0000112233445566)
ldr x20, =0xFFFFFFFFFFFFFFFF ldr x20, =0xFFFFFFFFFFFFFFFF
ubfm x20, x19, 32, 63 ubfm x20, x19, 32, 63
ASSERT_EQ(x20, 0x0000000011223344) LKMC_ASSERT_EQ(x20, 0x0000000011223344)
EXIT LKMC_EXIT

View File

@@ -2,14 +2,14 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr x19, =0x1122334455667788 ldr x19, =0x1122334455667788
ldr x20, =0xFFFFFFFFFFFFFFFF ldr x20, =0xFFFFFFFFFFFFFFFF
ubfx x20, x19, 8, 16 ubfx x20, x19, 8, 16
ASSERT_EQ(x20, 0x0000000000006677) LKMC_ASSERT_EQ(x20, 0x0000000000006677)
ldr x20, =0xFFFFFFFFFFFFFFFF ldr x20, =0xFFFFFFFFFFFFFFFF
ubfx x20, x19, 8, 32 ubfx x20, x19, 8, 32
ASSERT_EQ(x20, 0x0000000044556677) LKMC_ASSERT_EQ(x20, 0x0000000044556677)
EXIT LKMC_EXIT

View File

@@ -2,9 +2,9 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.long 0 .long 0
#if 0 #if 0
udf 0 udf 0
#endif #endif
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* ERROR: can never use the name x31. */ /* ERROR: can never use the name x31. */
#if 0 #if 0
mov x31, 31 mov x31, 31
@@ -11,12 +11,12 @@ ENTRY
/* mov (register) is an alias for ORR, which accepts xzr. */ /* mov (register) is an alias for ORR, which accepts xzr. */
mov x19, 1 mov x19, 1
mov x19, xzr mov x19, xzr
ASSERT_EQ(x19, 0) LKMC_ASSERT_EQ(x19, 0)
/* Same encoding as the mov version. */ /* Same encoding as the mov version. */
mov x19, 1 mov x19, 1
orr x19, xzr, xzr orr x19, xzr, xzr
ASSERT_EQ(x19, 0) LKMC_ASSERT_EQ(x19, 0)
/* So, orr, which is not an alias, can only take xzr, not sp. */ /* So, orr, which is not an alias, can only take xzr, not sp. */
#if 0 #if 0
@@ -26,7 +26,7 @@ ENTRY
/* Zero register discards result if written to. */ /* Zero register discards result if written to. */
mov x19, 1 mov x19, 1
orr xzr, x19, x19 orr xzr, x19, x19
ASSERT_EQ(xzr, 0) LKMC_ASSERT_EQ(xzr, 0)
/* MOV (to/from SP) is an alias for ADD (immediate). */ /* MOV (to/from SP) is an alias for ADD (immediate). */
mov x19, sp mov x19, sp
@@ -36,7 +36,7 @@ ENTRY
/* Exact same encoding as above. */ /* Exact same encoding as above. */
add x20, sp, 0 add x20, sp, 0
mov sp, x19 mov sp, x19
ASSERT_EQ(x20, 1) LKMC_ASSERT_EQ(x20, 1)
/* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */ /* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */
#if 0 #if 0
@@ -48,4 +48,4 @@ ENTRY
* does not say anything about SP, and so does accept xzr just fine. * does not say anything about SP, and so does accept xzr just fine.
*/ */
add xzr, xzr, xzr add xzr, xzr, xzr
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Immediate encoding. /* Immediate encoding.
* *
@@ -11,7 +11,7 @@ ENTRY
mov r0, 1 mov r0, 1
/* r1 = r0 + 2 */ /* r1 = r0 + 2 */
add r1, r0, 2 add r1, r0, 2
ASSERT_EQ(r1, 3) LKMC_ASSERT_EQ(r1, 3)
/* If src == dest, we can omit one of them. /* If src == dest, we can omit one of them.
* *
@@ -19,12 +19,12 @@ ENTRY
*/ */
mov r0, 1 mov r0, 1
add r0, 2 add r0, 2
ASSERT_EQ(r0, 3) LKMC_ASSERT_EQ(r0, 3)
/* Same as above but explicit. */ /* Same as above but explicit. */
mov r0, 1 mov r0, 1
add r0, r0, 2 add r0, r0, 2
ASSERT_EQ(r0, 3) LKMC_ASSERT_EQ(r0, 3)
#if 0 #if 0
/* But we cannot omit the register if there is a shift when using .syntx unified: /* But we cannot omit the register if there is a shift when using .syntx unified:
@@ -44,7 +44,7 @@ ENTRY
mov r0, 1 mov r0, 1
mov r1, 2 mov r1, 2
add r2, r0, r1 add r2, r0, r1
ASSERT_EQ(r2, 3) LKMC_ASSERT_EQ(r2, 3)
/* Register encoding, omit implicit register. /* Register encoding, omit implicit register.
* *
@@ -53,6 +53,6 @@ ENTRY
mov r0, 1 mov r0, 1
mov r1, 2 mov r1, 2
add r1, r0 add r1, r0
ASSERT_EQ(r1, 3) LKMC_ASSERT_EQ(r1, 3)
EXIT LKMC_EXIT

View File

@@ -2,36 +2,36 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Offset mode with immediate. Add 4 to the address register, /* Offset mode with immediate. Add 4 to the address register,
* which ends up * reading myvar6 instead of myvar. * which ends up * reading myvar6 instead of myvar.
*/ */
adr r4, myvar adr r4, myvar
ldr r5, [r4, 4] ldr r5, [r4, 4]
ASSERT_EQ(r5, 0x9ABCDEF0) LKMC_ASSERT_EQ(r5, 0x9ABCDEF0)
/* r4 was not modified. */ /* r4 was not modified. */
ASSERT_EQ(r4, myvar) LKMC_ASSERT_EQ(r4, myvar)
/* Pre-indexed mode: modify register, then use it. */ /* Pre-indexed mode: modify register, then use it. */
adr r4, myvar adr r4, myvar
ldr r5, [r4, 4]! ldr r5, [r4, 4]!
ASSERT_EQ(r5, 0x9ABCDEF0) LKMC_ASSERT_EQ(r5, 0x9ABCDEF0)
/* r4 was modified. */ /* r4 was modified. */
ASSERT_EQ(r4, myvar6) LKMC_ASSERT_EQ(r4, myvar6)
/* Post-indexed mode: use register, then modify it. */ /* Post-indexed mode: use register, then modify it. */
adr r4, myvar adr r4, myvar
ldr r5, [r4], 4 ldr r5, [r4], 4
ASSERT_EQ(r5, 0x12345678) LKMC_ASSERT_EQ(r5, 0x12345678)
/* r4 was modified. */ /* r4 was modified. */
ASSERT_EQ(r4, myvar6) LKMC_ASSERT_EQ(r4, myvar6)
/* Offset in register. */ /* Offset in register. */
adr r4, myvar adr r4, myvar
mov r5, 4 mov r5, 4
ldr r6, [r4, r5] ldr r6, [r4, r5]
ASSERT_EQ(r6, 0x9ABCDEF0) LKMC_ASSERT_EQ(r6, 0x9ABCDEF0)
/* Offset in shifted register: /* Offset in shifted register:
* r6 = * r6 =
@@ -42,9 +42,9 @@ ENTRY
adr r4, myvar adr r4, myvar
mov r5, 2 mov r5, 2
ldr r6, [r4, r5, lsl 1] ldr r6, [r4, r5, lsl 1]
ASSERT_EQ(r6, 0x9ABCDEF0) LKMC_ASSERT_EQ(r6, 0x9ABCDEF0)
EXIT LKMC_EXIT
myvar: myvar:
.word 0x12345678 .word 0x12345678
myvar6: myvar6:

View File

@@ -5,7 +5,7 @@
.data .data
data_label: data_label:
.word 0x1234678 .word 0x1234678
ENTRY LKMC_ENTRY
adr r4, label adr r4, label
/* objdump tells us that this uses the literal pool, /* objdump tells us that this uses the literal pool,
* it does not get converted to adr, which is the better * it does not get converted to adr, which is the better
@@ -14,8 +14,8 @@ ENTRY
ldr r5, =label ldr r5, =label
adrl r6, label adrl r6, label
label: label:
ASSERT_EQ_REG(r4, r5) LKMC_ASSERT_EQ_REG(r4, r5)
ASSERT_EQ_REG(r4, r6) LKMC_ASSERT_EQ_REG(r4, r6)
#if 0 #if 0
/* Error: symbol .data is in a different section. /* Error: symbol .data is in a different section.
@@ -30,4 +30,4 @@ label:
*/ */
adr r5, data_label adr r5, data_label
#endif #endif
EXIT LKMC_EXIT

View File

@@ -2,26 +2,26 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 0x00 && 0xFF == 0x00 */ /* 0x00 && 0xFF == 0x00 */
mov r0, 0x00 mov r0, 0x00
and r0, 0xFF and r0, 0xFF
ASSERT_EQ(r0, 0x00) LKMC_ASSERT_EQ(r0, 0x00)
/* 0x0F && 0xF0 == 0x00 */ /* 0x0F && 0xF0 == 0x00 */
mov r0, 0x0F mov r0, 0x0F
and r0, 0xF0 and r0, 0xF0
ASSERT_EQ(r0, 0x00) LKMC_ASSERT_EQ(r0, 0x00)
/* 0x0F && 0xFF == 0x0F */ /* 0x0F && 0xFF == 0x0F */
mov r0, 0x0F mov r0, 0x0F
and r0, 0xFF and r0, 0xFF
ASSERT_EQ(r0, 0x0F) LKMC_ASSERT_EQ(r0, 0x0F)
/* 0xF0 && 0xFF == 0xF0 */ /* 0xF0 && 0xFF == 0xF0 */
mov r0, 0xF0 mov r0, 0xF0
and r0, 0xFF and r0, 0xFF
ASSERT_EQ(r0, 0xF0) LKMC_ASSERT_EQ(r0, 0xF0)
EXIT LKMC_EXIT

View File

@@ -1,9 +1,9 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-b-instruction */ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-b-instruction */
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Jump over the fail. 26-bit PC-relative. */ /* Jump over the fail. 26-bit PC-relative. */
b ok b ok
FAIL LKMC_FAIL
ok: ok:
EXIT LKMC_EXIT

View File

@@ -2,27 +2,27 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Smaller*/ /* Smaller*/
mov r0, 1 mov r0, 1
cmp r0, 2 cmp r0, 2
ASSERT(ble) LKMC_ASSERT(ble)
ASSERT(blt) LKMC_ASSERT(blt)
ASSERT(bne) LKMC_ASSERT(bne)
/* Equal. */ /* Equal. */
mov r1, 0 mov r1, 0
cmp r1, 0 cmp r1, 0
ASSERT(beq) LKMC_ASSERT(beq)
ASSERT(bge) LKMC_ASSERT(bge)
ASSERT(ble) LKMC_ASSERT(ble)
/* Greater. */ /* Greater. */
mov r0, 2 mov r0, 2
cmp r0, 1 cmp r0, 1
ASSERT(bge) LKMC_ASSERT(bge)
ASSERT(bgt) LKMC_ASSERT(bgt)
ASSERT(bne) LKMC_ASSERT(bne)
EXIT LKMC_EXIT

View File

@@ -2,9 +2,9 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr r0, =0x11223344 ldr r0, =0x11223344
ldr r1, =0xFFFFFFFF ldr r1, =0xFFFFFFFF
bfi r1, r0, 8, 16 bfi r1, r0, 8, 16
ASSERT_EQ(r1, 0xFF3344FF) LKMC_ASSERT_EQ(r1, 0xFF3344FF)
EXIT LKMC_EXIT

View File

@@ -2,9 +2,9 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 0x0F & ~0x55 == 0x0F & 0xAA == 0x0A */ /* 0x0F & ~0x55 == 0x0F & 0xAA == 0x0A */
mov r0, 0x0F mov r0, 0x0F
bic r0, 0x55 bic r0, 0x55
ASSERT_EQ(r0, 0x0A) LKMC_ASSERT_EQ(r0, 0x0A)
EXIT LKMC_EXIT

View File

@@ -2,11 +2,11 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov r0, 1 mov r0, 1
bl inc bl inc
ASSERT_EQ(r0, 2) LKMC_ASSERT_EQ(r0, 2)
EXIT LKMC_EXIT
/* void inc(int *i) { (*i)++ } */ /* void inc(int *i) { (*i)++ } */
inc: inc:

View File

@@ -2,16 +2,16 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr r0, =0x7FFFFFFF ldr r0, =0x7FFFFFFF
clz r1, r0 clz r1, r0
ASSERT_EQ(r1, 1) LKMC_ASSERT_EQ(r1, 1)
ldr r0, =0x3FFFFFFF ldr r0, =0x3FFFFFFF
clz r1, r0 clz r1, r0
ASSERT_EQ(r1, 2) LKMC_ASSERT_EQ(r1, 2)
ldr r0, =0x1FFFFFFF ldr r0, =0x1FFFFFFF
clz r1, r0 clz r1, r0
ASSERT_EQ(r1, 3) LKMC_ASSERT_EQ(r1, 3)
EXIT LKMC_EXIT

View File

@@ -1,7 +1,7 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
# mycomment # mycomment
@ mycomment @ mycomment
/* # only works at the beginning of the line. /* # only works at the beginning of the line.
@@ -11,4 +11,4 @@ ENTRY
nop # mycomment nop # mycomment
#endif #endif
nop @ mycomment nop @ mycomment
EXIT LKMC_EXIT

View File

@@ -8,35 +8,35 @@
/* Assert that a register equals a constant. /* Assert that a register equals a constant.
* * reg: the register to check * * reg: the register to check
* * const: the constant to compare to. Only works for literals or labels, not for registers. * * const: the constant to compare to. Only works for literals or labels, not for registers.
* For register / register comparison, use ASSERT_EQ_REG. * For register / register comparison, use LKMC_ASSERT_EQ_REG.
*/ */
#define ASSERT_EQ(reg, const) \ #define LKMC_ASSERT_EQ(reg, const) \
mov r0, reg; \ mov r0, reg; \
ldr r1, =const; \ ldr r1, =const; \
ASSERT_EQ_DO; \ LKMC_ASSERT_EQ_DO; \
; ;
#define ASSERT_EQ_DO \ #define LKMC_ASSERT_EQ_DO \
bl assert_eq_32; \ bl lkmc_assert_eq_32; \
cmp r0, 0; \ cmp r0, 0; \
ASSERT(beq); \ LKMC_ASSERT(beq); \
; ;
#define ASSERT_EQ_REG(reg1, reg2) \ #define LKMC_ASSERT_EQ_REG(reg1, reg2) \
str reg2, [sp, -4]!; \ str reg2, [sp, -4]!; \
mov r0, reg1; \ mov r0, reg1; \
ldr r1, [sp], 4; \ ldr r1, [sp], 4; \
ASSERT_EQ_DO; \ LKMC_ASSERT_EQ_DO; \
; ;
/* Assert that two arrays are the same. */ /* Assert that two arrays are the same. */
#define ASSERT_MEMCMP(label1, label2, const_size) \ #define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
ldr r0, =label1; \ ldr r0, =label1; \
ldr r1, =label2; \ ldr r1, =label2; \
ldr r2, =const_size; \ ldr r2, =const_size; \
bl assert_memcmp; \ bl lkmc_assert_memcmp; \
cmp r0, 0; \ cmp r0, 0; \
ASSERT(beq); \ LKMC_ASSERT(beq); \
; ;
/* Store all callee saved registers, and LR in case we make further BL calls. /* Store all callee saved registers, and LR in case we make further BL calls.
@@ -44,7 +44,7 @@
* Also save the input arguments r0-r3 on the stack, so we can access them later on, * Also save the input arguments r0-r3 on the stack, so we can access them later on,
* despite those registers being overwritten. * despite those registers being overwritten.
*/ */
#define ENTRY \ #define LKMC_ENTRY \
.text; \ .text; \
.global asm_main; \ .global asm_main; \
asm_main: \ asm_main: \
@@ -52,15 +52,15 @@ asm_main: \
asm_main_after_prologue: \ asm_main_after_prologue: \
; ;
/* Meant to be called at the end of ENTRY.* /* Meant to be called at the end of LKMC_ENTRY.*
* *
* Branching to "fail" makes tests fail with exit status 1. * Branching to "fail" makes tests fail with exit status 1.
* *
* If EXIT is reached, the program ends successfully. * If LKMC_EXIT is reached, the program ends successfully.
* *
* Restore LR and bx jump to it to return from asm_main. * Restore LR and bx jump to it to return from asm_main.
*/ */
#define EXIT \ #define LKMC_EXIT \
mov r0, 0; \ mov r0, 0; \
mov r1, 0; \ mov r1, 0; \
b pass; \ b pass; \
@@ -75,16 +75,9 @@ pass: \
; ;
/* Always fail. */ /* Always fail. */
#define FAIL \ #define LKMC_FAIL \
ldr r0, =__LINE__; \ ldr r0, =__LINE__; \
b fail; \ b fail; \
; ;
#define MEMCMP(s1, s2, n) \
ldr r0, =s1; \
ldr r1, =s2; \
ldr r2, =n; \
bl memcmp; \
;
#endif #endif

View File

@@ -2,15 +2,15 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov r0, 0 mov r0, 0
mov r1, 1 mov r1, 1
cmp r0, 1 cmp r0, 1
/* Previous cmp failed, skip this operation. */ /* Previous cmp failed, skip this operation. */
addeq r1, 1 addeq r1, 1
ASSERT_EQ(r1, 1) LKMC_ASSERT_EQ(r1, 1)
cmp r0, 0 cmp r0, 0
/* Previous passed, do this operation. */ /* Previous passed, do this operation. */
addeq r1, 1 addeq r1, 1
ASSERT_EQ(r1, 2) LKMC_ASSERT_EQ(r1, 2)
EXIT LKMC_EXIT

View File

@@ -14,12 +14,12 @@ myquad:
myocta: myocta:
.octa 0x123456789ABCDEF0123456789ABCDEF0 .octa 0x123456789ABCDEF0123456789ABCDEF0
theend: theend:
ENTRY LKMC_ENTRY
#define ASSERT_DIFF(label1, label2, result) \ #define ASSERT_DIFF(label1, label2, result) \
ldr r0, =label1; \ ldr r0, =label1; \
ldr r1, =label2; \ ldr r1, =label2; \
sub r0, r1, r0; \ sub r0, r1, r0; \
ASSERT_EQ(r0, result) LKMC_ASSERT_EQ(r0, result)
ASSERT_DIFF(mybyte, myword, 1) ASSERT_DIFF(mybyte, myword, 1)
ASSERT_DIFF(myword, mylong, 4) ASSERT_DIFF(myword, mylong, 4)
@@ -27,4 +27,4 @@ ENTRY
ASSERT_DIFF(myquad, myocta, 8) ASSERT_DIFF(myquad, myocta, 8)
ASSERT_DIFF(myocta, theend, 16) ASSERT_DIFF(myocta, theend, 16)
#undef ASSERT_DIF #undef ASSERT_DIF
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* This is the default. We hack it in common.h however. */ /* This is the default. We hack it in common.h however. */
.syntax divided .syntax divided
/* These fail. */ /* These fail. */
@@ -21,4 +21,4 @@ ENTRY
mov r0, 0x1 mov r0, 0x1
mov r0, $1 mov r0, $1
mov r0, $0x1 mov r0, $0x1
EXIT LKMC_EXIT

View File

@@ -11,7 +11,7 @@ my_array:
my_array_expect: my_array_expect:
.word 0x11111112, 0x22222223, 0x33333334, 0x44444445 .word 0x11111112, 0x22222223, 0x33333334, 0x44444445
ENTRY LKMC_ENTRY
/* Increment. */ /* Increment. */
ldr r0, =my_array ldr r0, =my_array
mov r1, NELEM mov r1, NELEM
@@ -23,5 +23,5 @@ increment:
sub r1, 1 sub r1, 1
cmp r1, 0 cmp r1, 0
bne increment bne increment
ASSERT_MEMCMP(my_array, my_array_expect, 0x10) LKMC_ASSERT_MEMCMP(my_array, my_array_expect, 0x10)
EXIT LKMC_EXIT

View File

@@ -11,7 +11,7 @@ my_array_0:
my_array_1: my_array_1:
.word 0x55555555, 0x66666666, 0x77777777, 0x88888888 .word 0x55555555, 0x66666666, 0x77777777, 0x88888888
ENTRY LKMC_ENTRY
/* Load r5, r6, r7 and r8 starting from the address in r4. Don't change r4 */ /* Load r5, r6, r7 and r8 starting from the address in r4. Don't change r4 */
ldr r4, =my_array_0 ldr r4, =my_array_0
@@ -20,11 +20,11 @@ ENTRY
ldr r7, =0 ldr r7, =0
ldr r8, =0 ldr r8, =0
ldmia r4, {r5-r8} ldmia r4, {r5-r8}
ASSERT_EQ(r4, my_array_0) LKMC_ASSERT_EQ(r4, my_array_0)
ASSERT_EQ(r5, 0x11111111) LKMC_ASSERT_EQ(r5, 0x11111111)
ASSERT_EQ(r6, 0x22222222) LKMC_ASSERT_EQ(r6, 0x22222222)
ASSERT_EQ(r7, 0x33333333) LKMC_ASSERT_EQ(r7, 0x33333333)
ASSERT_EQ(r8, 0x44444444) LKMC_ASSERT_EQ(r8, 0x44444444)
/* Swapping the order of r5 and r6 on the mnemonic makes no difference to load order. /* Swapping the order of r5 and r6 on the mnemonic makes no difference to load order.
* *
@@ -38,8 +38,8 @@ ENTRY
ldr r5, =0 ldr r5, =0
ldr r6, =0 ldr r6, =0
ldmia r4, {r6,r5} ldmia r4, {r6,r5}
ASSERT_EQ(r5, 0x11111111) LKMC_ASSERT_EQ(r5, 0x11111111)
ASSERT_EQ(r6, 0x22222222) LKMC_ASSERT_EQ(r6, 0x22222222)
#endif #endif
/* Modify the array */ /* Modify the array */
@@ -51,11 +51,11 @@ ENTRY
stmdb r4, {r5-r8} stmdb r4, {r5-r8}
/* Verify that my_array_0 changed and is equal to my_array_1. */ /* Verify that my_array_0 changed and is equal to my_array_1. */
ASSERT_MEMCMP(my_array_0, my_array_1, 0x10) LKMC_ASSERT_MEMCMP(my_array_0, my_array_1, 0x10)
/* Load registers and increment r4. */ /* Load registers and increment r4. */
ldr r4, =my_array_0 ldr r4, =my_array_0
ldmia r4!, {r5-r8} ldmia r4!, {r5-r8}
ASSERT_EQ(r4, my_array_1) LKMC_ASSERT_EQ(r4, my_array_1)
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Mnemonic for a PC relative load: /* Mnemonic for a PC relative load:
* *
@@ -12,13 +12,13 @@ ENTRY
* .... * ....
*/ */
ldr r0, myvar ldr r0, myvar
ASSERT_EQ(r0, 0x12345678) LKMC_ASSERT_EQ(r0, 0x12345678)
/* Mnemonic PC relative load with an offset. /* Mnemonic PC relative load with an offset.
* Load myvar2 instead of myvar. * Load myvar2 instead of myvar.
*/ */
ldr r0, myvar + 4 ldr r0, myvar + 4
ASSERT_EQ(r0, 0x9ABCDEF0) LKMC_ASSERT_EQ(r0, 0x9ABCDEF0)
/* First store the address in r0 using a magic =myvar, which creates /* First store the address in r0 using a magic =myvar, which creates
* a new variable containing the address and PC-relative addresses it * a new variable containing the address and PC-relative addresses it
@@ -33,17 +33,17 @@ ENTRY
*/ */
ldr r0, =myvar ldr r0, =myvar
ldr r1, [r0] ldr r1, [r0]
ASSERT_EQ(r1, 0x12345678) LKMC_ASSERT_EQ(r1, 0x12345678)
/* More efficiently, use r0 as the address to read, and write to r0 itself. */ /* More efficiently, use r0 as the address to read, and write to r0 itself. */
ldr r0, =myvar ldr r0, =myvar
ldr r0, [r0] ldr r0, [r0]
ASSERT_EQ(r0, 0x12345678) LKMC_ASSERT_EQ(r0, 0x12345678)
/* Same as =myvar but store a constant to a register. /* Same as =myvar but store a constant to a register.
* Can also be done with movw and movt. */ * Can also be done with movw and movt. */
ldr r0, =0x11112222 ldr r0, =0x11112222
ASSERT_EQ(r0, 0x11112222) LKMC_ASSERT_EQ(r0, 0x11112222)
/* We can also use GAS tolower16 and topper16 and movw and movt /* We can also use GAS tolower16 and topper16 and movw and movt
* to load the address of myvar into r0 with two immediates. * to load the address of myvar into r0 with two immediates.
@@ -56,9 +56,9 @@ ENTRY
movw r0, #:lower16:myvar movw r0, #:lower16:myvar
movt r0, #:upper16:myvar movt r0, #:upper16:myvar
ldr r1, [r0] ldr r1, [r0]
ASSERT_EQ(r1, 0x12345678) LKMC_ASSERT_EQ(r1, 0x12345678)
EXIT LKMC_EXIT
myvar: myvar:
.word 0x12345678 .word 0x12345678
myvar2: myvar2:

View File

@@ -2,11 +2,11 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr r0, =myvar ldr r0, =myvar
mov r1, 0x0 mov r1, 0x0
ldrb r1, [r0] ldrb r1, [r0]
ASSERT_EQ(r1, 0x00000078) LKMC_ASSERT_EQ(r1, 0x00000078)
EXIT LKMC_EXIT
myvar: myvar:
.word 0x12345678 .word 0x12345678

View File

@@ -2,11 +2,11 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr r0, =myvar ldr r0, =myvar
mov r1, 0x0 mov r1, 0x0
ldrh r1, [r0] ldrh r1, [r0]
ASSERT_EQ(r1, 0x00005678) LKMC_ASSERT_EQ(r1, 0x00005678)
EXIT LKMC_EXIT
myvar: myvar:
.word 0x12345678 .word 0x12345678

View File

@@ -12,21 +12,21 @@ my_array_0:
my_array_1: my_array_1:
.word 0x55555555, 0x66666666, 0x77777777, 0x88888888 .word 0x55555555, 0x66666666, 0x77777777, 0x88888888
ENTRY LKMC_ENTRY
/* puts("hello world") */ /* puts("hello world") */
/* r0 is first argument. */ /* r0 is first argument. */
ldr r0, =puts_s ldr r0, =puts_s
bl puts bl puts
/* Check exit status >= 0 for success. */ /* Check exit status >= 0 for success. */
cmp r0, 0 cmp r0, 0
ASSERT(bge) LKMC_ASSERT(bge)
/* printf */ /* printf */
ldr r0, =printf_format ldr r0, =printf_format
ldr r1, =0x12345678 ldr r1, =0x12345678
bl printf bl printf
cmp r0, 0 cmp r0, 0
ASSERT(bge) LKMC_ASSERT(bge)
/* memcpy and memcmp. */ /* memcpy and memcmp. */
@@ -36,7 +36,7 @@ ENTRY
ldr r2, =0x10 ldr r2, =0x10
bl memcmp bl memcmp
cmp r0, 0 cmp r0, 0
ASSERT(blt) LKMC_ASSERT(blt)
/* Copy. */ /* Copy. */
ldr r0, =my_array_0 ldr r0, =my_array_0
@@ -49,11 +49,11 @@ ENTRY
ldr r1, =my_array_1 ldr r1, =my_array_1
ldr r2, =0x10 ldr r2, =0x10
bl memcmp bl memcmp
ASSERT_EQ(r0, 0) LKMC_ASSERT_EQ(r0, 0)
/* exit(0) */ /* exit(0) */
mov r0, 0 mov r0, 0
bl exit bl exit
/* Never reached, just for the fail symbol. */ /* Never reached, just for the fail symbol. */
EXIT LKMC_EXIT

View File

@@ -2,18 +2,18 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Immediate. */ /* Immediate. */
mov r0, 0 mov r0, 0
ASSERT_EQ(r0, 0) LKMC_ASSERT_EQ(r0, 0)
mov r0, 1 mov r0, 1
ASSERT_EQ(r0, 1) LKMC_ASSERT_EQ(r0, 1)
/* Register. */ /* Register. */
mov r0, 0 mov r0, 0
mov r1, 1 mov r1, 1
mov r1, r0 mov r1, r0
ASSERT_EQ(r1, 0) LKMC_ASSERT_EQ(r1, 0)
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* movt (top) and movw (TODO what is w) set the higher /* movt (top) and movw (TODO what is w) set the higher
* and lower 16 bits of the register. * and lower 16 bits of the register.
@@ -10,7 +10,7 @@ ENTRY
movw r0, 0xFFFF movw r0, 0xFFFF
movt r0, 0x1234 movt r0, 0x1234
add r0, 1 add r0, 1
ASSERT_EQ(r0, 0x12350000) LKMC_ASSERT_EQ(r0, 0x12350000)
/* movw also zeroes out the top bits, allowing small 16-bit /* movw also zeroes out the top bits, allowing small 16-bit
* C constants to be assigned in a single instruction. * C constants to be assigned in a single instruction.
@@ -22,6 +22,6 @@ ENTRY
*/ */
ldr r0, =0x12345678 ldr r0, =0x12345678
movw r0, 0x1111 movw r0, 0x1111
ASSERT_EQ(r0, 0x00001111) LKMC_ASSERT_EQ(r0, 0x00001111)
EXIT LKMC_EXIT

View File

@@ -5,11 +5,11 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 2 * 3 = 6 */ /* 2 * 3 = 6 */
mov r0, 0 mov r0, 0
mov r1, 2 mov r1, 2
mov r2, 3 mov r2, 3
mul r1, r2 mul r1, r2
ASSERT_EQ(r1, 6) LKMC_ASSERT_EQ(r1, 6)
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Disassembles as: /* Disassembles as:
* *
* .... * ....
@@ -29,4 +29,4 @@ ENTRY
/* And there are other nops as well? Disassembles as `and`. */ /* And there are other nops as well? Disassembles as `and`. */
and r0, r0, r0 and r0, r0, r0
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Save sp before push. */ /* Save sp before push. */
mov r4, sp mov r4, sp
@@ -19,13 +19,13 @@ ENTRY
mov r7, 0 mov r7, 0
mov r8, 0 mov r8, 0
pop {r7, r8} pop {r7, r8}
ASSERT_EQ(r7, 1) LKMC_ASSERT_EQ(r7, 1)
ASSERT_EQ(r8, 2) LKMC_ASSERT_EQ(r8, 2)
/* Check that stack pointer moved down by 8 bytes /* Check that stack pointer moved down by 8 bytes
* (2 registers x 4 bytes each). * (2 registers x 4 bytes each).
*/ */
sub r4, r5 sub r4, r5
ASSERT_EQ(r4, 8) LKMC_ASSERT_EQ(r4, 8)
EXIT LKMC_EXIT

View File

@@ -5,8 +5,8 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ldr r0, =0b00000001001000110100010101100101 ldr r0, =0b00000001001000110100010101100101
rbit r1, r0 rbit r1, r0
ASSERT_EQ(r1, 0b10100110101000101100010010000000) LKMC_ASSERT_EQ(r1, 0b10100110101000101100010010000000)
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 13 general purpose registers. */ /* 13 general purpose registers. */
mov r0, 0 mov r0, 0
@@ -39,12 +39,12 @@ ENTRY
* https://stackoverflow.com/questions/32304646/arm-assembly-branch-to-address-inside-register-or-memory/54145818#54145818 * https://stackoverflow.com/questions/32304646/arm-assembly-branch-to-address-inside-register-or-memory/54145818#54145818
*/ */
ldr pc, =10f ldr pc, =10f
FAIL LKMC_FAIL
10: 10:
/* Same with r15, which is the same as pc. */ /* Same with r15, which is the same as pc. */
ldr r15, =10f ldr r15, =10f
FAIL LKMC_FAIL
10: 10:
/* Another example with mov reading from pc. */ /* Another example with mov reading from pc. */
@@ -60,10 +60,10 @@ pc_addr:
b 1f b 1f
.word 0x12345678 .word 0x12345678
1: 1:
ASSERT_EQ(r0, 0x12345678) LKMC_ASSERT_EQ(r0, 0x12345678)
/* We can also use fp in GNU GAS assembly. */ /* We can also use fp in GNU GAS assembly. */
mov r11, 0 mov r11, 0
mov fp, 1 mov fp, 1
ASSERT_EQ(r11, 1) LKMC_ASSERT_EQ(r11, 1)
EXIT LKMC_EXIT

View File

@@ -5,14 +5,14 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* All bytes in register. */ /* All bytes in register. */
ldr r0, =0x11223344 ldr r0, =0x11223344
rev r1, r0 rev r1, r0
ASSERT_EQ(r1, 0x44332211) LKMC_ASSERT_EQ(r1, 0x44332211)
/* Groups of 16-bits. */ /* Groups of 16-bits. */
ldr r0, =0x11223344 ldr r0, =0x11223344
rev16 r1, r0 rev16 r1, r0
ASSERT_EQ(r1, 0x22114433) LKMC_ASSERT_EQ(r1, 0x22114433)
EXIT LKMC_EXIT

View File

@@ -2,34 +2,34 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Result is 0, set beq. */ /* Result is 0, set beq. */
movs r0, 0 movs r0, 0
ASSERT(beq) LKMC_ASSERT(beq)
/* The opposite. */ /* The opposite. */
movs r0, 1 movs r0, 1
ASSERT(bne) LKMC_ASSERT(bne)
/* mov without s does not set the status. */ /* mov without s does not set the status. */
movs r0, 0 movs r0, 0
mov r0, 1 mov r0, 1
ASSERT(beq) LKMC_ASSERT(beq)
/* movs still moves... */ /* movs still moves... */
mov r0, 0 mov r0, 0
movs r0, 1 movs r0, 1
ASSERT_EQ(r0, 1) LKMC_ASSERT_EQ(r0, 1)
/* add: the result is 0. */ /* add: the result is 0. */
mov r0, 1 mov r0, 1
adds r0, -1 adds r0, -1
ASSERT(beq) LKMC_ASSERT(beq)
/* add: result non 0. */ /* add: result non 0. */
mov r0, 1 mov r0, 1
adds r0, 1 adds r0, 1
ASSERT(bne) LKMC_ASSERT(bne)
EXIT LKMC_EXIT

View File

@@ -2,37 +2,37 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* lsr */ /* lsr */
ldr r0, =0xFFF00FFF ldr r0, =0xFFF00FFF
mov r1, r0, lsl 8 mov r1, r0, lsl 8
ldr r2, =0xF00FFF00 ldr r2, =0xF00FFF00
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* lsl */ /* lsl */
ldr r0, =0xFFF00FFF ldr r0, =0xFFF00FFF
mov r1, r0, lsr 8 mov r1, r0, lsr 8
ldr r2, =0x00FFF00F ldr r2, =0x00FFF00F
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* ror */ /* ror */
ldr r0, =0xFFF00FFF ldr r0, =0xFFF00FFF
mov r1, r0, ror 8 mov r1, r0, ror 8
ldr r2, =0xFFFFF00F ldr r2, =0xFFFFF00F
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* asr negative */ /* asr negative */
ldr r0, =0x80000008 ldr r0, =0x80000008
mov r1, r0, asr 1 mov r1, r0, asr 1
ldr r2, =0xC0000004 ldr r2, =0xC0000004
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* asr positive */ /* asr positive */
ldr r0, =0x40000008 ldr r0, =0x40000008
mov r1, r0, asr 1 mov r1, r0, asr 1
ldr r2, =0x20000004 ldr r2, =0x20000004
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* There are also direct shift mnemonics for the mov shifts. /* There are also direct shift mnemonics for the mov shifts.
* *
@@ -41,7 +41,7 @@ ENTRY
ldr r0, =0xFFF00FFF ldr r0, =0xFFF00FFF
lsl r1, r0, 8 lsl r1, r0, 8
ldr r2, =0xF00FFF00 ldr r2, =0xF00FFF00
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* If used with the `mov` instruction, it results in a pure shift, /* If used with the `mov` instruction, it results in a pure shift,
* but the suffixes also exist for all the other data processing instructions. * but the suffixes also exist for all the other data processing instructions.
@@ -56,7 +56,7 @@ ENTRY
ldr r1, =0x100 ldr r1, =0x100
add r1, r1, r0, lsl 1 add r1, r1, r0, lsl 1
ldr r2, =0x00000120 ldr r2, =0x00000120
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* The shift takes up the same encoding slot as the immediate, /* The shift takes up the same encoding slot as the immediate,
* therefore it is not possible to both use an immediate and shift. * therefore it is not possible to both use an immediate and shift.
@@ -74,6 +74,6 @@ ENTRY
ldr r1, =0x100 ldr r1, =0x100
add r1, r1, (0x10 << 1) add r1, r1, (0x10 << 1)
ldr r2, =0x00000120 ldr r2, =0x00000120
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
EXIT LKMC_EXIT

View File

@@ -7,13 +7,13 @@
myvar: myvar:
.word 0x12345678 .word 0x12345678
ENTRY LKMC_ENTRY
/* Sanity check. */ /* Sanity check. */
ldr r0, =myvar ldr r0, =myvar
ldr r1, [r0] ldr r1, [r0]
movw r2, 0x5678 movw r2, 0x5678
movt r2, 0x1234 movt r2, 0x1234
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* Modify the value. */ /* Modify the value. */
ldr r0, =myvar ldr r0, =myvar
@@ -26,7 +26,7 @@ ENTRY
ldr r1, [r0] ldr r1, [r0]
movw r2, 0xDEF0 movw r2, 0xDEF0
movt r2, 0x9ABC movt r2, 0x9ABC
ASSERT_EQ_REG(r1, r2) LKMC_ASSERT_EQ_REG(r1, r2)
/* Cannot use PC relative addressing to a different segment, /* Cannot use PC relative addressing to a different segment,
* or else it fails with: * or else it fails with:
@@ -57,4 +57,4 @@ var_in_same_section:
str r1, =myvar str r1, =myvar
#endif #endif
EXIT LKMC_EXIT

View File

@@ -5,10 +5,10 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 3 - 2 == 1 , register version.*/ /* 3 - 2 == 1 , register version.*/
mov r0, 3 mov r0, 3
mov r1, 2 mov r1, 2
sub r0, r0, r1 sub r0, r0, r1
ASSERT_EQ(r0, 1) LKMC_ASSERT_EQ(r0, 1)
EXIT LKMC_EXIT

View File

@@ -5,18 +5,18 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* 0x0F && 0xF0 == 0x00, so beq. */ /* 0x0F && 0xF0 == 0x00, so beq. */
mov r0, 0x0F mov r0, 0x0F
tst r0, 0xF0 tst r0, 0xF0
ASSERT(beq) LKMC_ASSERT(beq)
/* bne */ /* bne */
mov r0, 0xFF mov r0, 0xFF
tst r0, 0x0F tst r0, 0x0F
ASSERT(bne) LKMC_ASSERT(bne)
# r0 was not modified. # r0 was not modified.
ASSERT_EQ(r0, 0xFF) LKMC_ASSERT_EQ(r0, 0xFF)
EXIT LKMC_EXIT

View File

@@ -2,6 +2,6 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
udf 0 udf 0
EXIT LKMC_EXIT

View File

@@ -3,7 +3,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* Minimal single precision floating point example. /* Minimal single precision floating point example.
* TODO: floating point representation constraints due to 4-byte instruction? * TODO: floating point representation constraints due to 4-byte instruction?
*/ */
@@ -18,7 +18,7 @@ ENTRY
/* Move the nzcv bits from fpscr to apsr */ /* Move the nzcv bits from fpscr to apsr */
vmrs apsr_nzcv, fpscr vmrs apsr_nzcv, fpscr
/* This branch uses the Z bit of apsr, which was set accordingly. */ /* This branch uses the Z bit of apsr, which was set accordingly. */
ASSERT(beq) LKMC_ASSERT(beq)
/* Now the same from memory with vldr and vstr. */ /* Now the same from memory with vldr and vstr. */
.data .data
@@ -39,7 +39,7 @@ my_float_sum:
vadd.f32 s2, s0, s1 vadd.f32 s2, s0, s1
ldr r0, =my_float_sum ldr r0, =my_float_sum
vstr.f32 s2, [r0] vstr.f32 s2, [r0]
ASSERT_MEMCMP(my_float_sum, my_float_sum_expect, 4) LKMC_ASSERT_MEMCMP(my_float_sum, my_float_sum_expect, 4)
#if 0 #if 0
/* We can't do pseudo vldr as for ldr, fails with: /* We can't do pseudo vldr as for ldr, fails with:
@@ -56,7 +56,7 @@ my_float_sum:
vmov.f64 d3, 4.0 vmov.f64 d3, 4.0
vcmp.f64 d2, d3 vcmp.f64 d2, d3
vmrs apsr_nzcv, fpscr vmrs apsr_nzcv, fpscr
ASSERT(beq) LKMC_ASSERT(beq)
/* vmov can also move to general purpose registers. /* vmov can also move to general purpose registers.
* *
@@ -68,5 +68,5 @@ my_float_sum:
vmov s0, r0 vmov s0, r0
vmov s1, s0 vmov s1, s0
vmov r1, s1 vmov r1, s1
ASSERT_EQ_REG(r0, r1) LKMC_ASSERT_EQ_REG(r0, r1)
EXIT LKMC_EXIT

View File

@@ -4,7 +4,7 @@
.bss .bss
output: .skip 16 output: .skip 16
ENTRY LKMC_ENTRY
/* Integer. */ /* Integer. */
.data .data
input0_u: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4 input0_u: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
@@ -20,7 +20,7 @@ ENTRY
vadd.u ## size q2, q0, q1; \ vadd.u ## size q2, q0, q1; \
ldr r0, =output; \ ldr r0, =output; \
vst1.u ## size {q2}, [r0]; \ vst1.u ## size {q2}, [r0]; \
ASSERT_MEMCMP(output, expect_u_ ## size, 0x10) LKMC_ASSERT_MEMCMP(output, expect_u_ ## size, 0x10)
/* vadd.u32 /* vadd.u32
* *
@@ -54,7 +54,7 @@ ENTRY
vadd.f ## size q2, q0, q1; \ vadd.f ## size q2, q0, q1; \
ldr r0, =output; \ ldr r0, =output; \
vst1. ## size {q2}, [r0]; \ vst1. ## size {q2}, [r0]; \
ASSERT_MEMCMP(output, expect_f_ ## size, 0x10) LKMC_ASSERT_MEMCMP(output, expect_f_ ## size, 0x10)
/* 4x 32-bit. */ /* 4x 32-bit. */
TEST(32) TEST(32)
@@ -68,4 +68,4 @@ ENTRY
TEST(64) TEST(64)
#endif #endif
#undef TEST #undef TEST
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* SIMD positive. */ /* SIMD positive. */
.data .data
vcvt_positive_0: .float 1.25, 2.5, 3.75, 4.0 vcvt_positive_0: .float 1.25, 2.5, 3.75, 4.0
@@ -15,7 +15,7 @@ ENTRY
vcvt.u32.f32 q1, q0 vcvt.u32.f32 q1, q0
ldr r0, =vcvt_positive_result ldr r0, =vcvt_positive_result
vst1.32 {q1}, [r0] vst1.32 {q1}, [r0]
ASSERT_MEMCMP(vcvt_positive_result, vcvt_positive_expect, 0x10) LKMC_ASSERT_MEMCMP(vcvt_positive_result, vcvt_positive_expect, 0x10)
/* SIMD negative. */ /* SIMD negative. */
.data .data
@@ -29,7 +29,7 @@ ENTRY
vcvt.s32.f32 q1, q0 vcvt.s32.f32 q1, q0
ldr r0, =vcvt_negative_result ldr r0, =vcvt_negative_result
vst1.32 {q1}, [r0] vst1.32 {q1}, [r0]
ASSERT_MEMCMP(vcvt_negative_result, vcvt_negative_expect, 0x10) LKMC_ASSERT_MEMCMP(vcvt_negative_result, vcvt_negative_expect, 0x10)
/* Floating point. */ /* Floating point. */
.data .data
@@ -44,7 +44,7 @@ ENTRY
vcvt.u32.f32 s0, s0 vcvt.u32.f32 s0, s0
ldr r0, =vcvt_positive_float_result ldr r0, =vcvt_positive_float_result
vst1.32 {d0}, [r0] vst1.32 {d0}, [r0]
ASSERT_MEMCMP(vcvt_positive_float_result, vcvt_positive_float_expect, 0x8) LKMC_ASSERT_MEMCMP(vcvt_positive_float_result, vcvt_positive_float_expect, 0x8)
/* Floating point but with immediates. /* Floating point but with immediates.
* *
@@ -63,12 +63,12 @@ ENTRY
vmov.i32 d1, 1 vmov.i32 d1, 1
vcmp.f32 s0, s2 vcmp.f32 s0, s2
vmrs apsr_nzcv, fpscr vmrs apsr_nzcv, fpscr
ASSERT(beq) LKMC_ASSERT(beq)
/* Check that s1 wasn't modified by vcvt. */ /* Check that s1 wasn't modified by vcvt. */
vmov.f32 s2, 1.5 vmov.f32 s2, 1.5
vcmp.f32 s1, s2 vcmp.f32 s1, s2
vmrs apsr_nzcv, fpscr vmrs apsr_nzcv, fpscr
ASSERT(beq) LKMC_ASSERT(beq)
/* Floating point double precision. */ /* Floating point double precision. */
.data .data
@@ -82,9 +82,9 @@ ENTRY
vcvt.u32.f64 s0, d0 vcvt.u32.f64 s0, d0
ldr r0, =vcvt_positive_double_result ldr r0, =vcvt_positive_double_result
vst1.32 {d0}, [r0] vst1.32 {d0}, [r0]
ASSERT_MEMCMP( LKMC_ASSERT_MEMCMP(
vcvt_positive_double_result, vcvt_positive_double_result,
vcvt_positive_double_expect, vcvt_positive_double_expect,
0x4 0x4
) )
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
/* SIMD positive. */ /* SIMD positive. */
.data .data
vcvta_positive_0: .float 1.25, 2.5, 3.75, 4.0 vcvta_positive_0: .float 1.25, 2.5, 3.75, 4.0
@@ -15,7 +15,7 @@ ENTRY
vcvta.u32.f32 q1, q0 vcvta.u32.f32 q1, q0
ldr r0, =vcvta_positive_result ldr r0, =vcvta_positive_result
vst1.32 {q1}, [r0] vst1.32 {q1}, [r0]
ASSERT_MEMCMP( LKMC_ASSERT_MEMCMP(
vcvta_positive_result, vcvta_positive_result,
vcvta_positive_expect, vcvta_positive_expect,
0x10 0x10
@@ -33,9 +33,9 @@ ENTRY
vcvta.s32.f32 q1, q0 vcvta.s32.f32 q1, q0
ldr r0, =vcvta_negative_result ldr r0, =vcvta_negative_result
vst1.32 {q1}, [r0] vst1.32 {q1}, [r0]
ASSERT_MEMCMP( LKMC_ASSERT_MEMCMP(
vcvta_negative_result, vcvta_negative_result,
vcvta_negative_expect, vcvta_negative_expect,
0x10 0x10
) )
EXIT LKMC_EXIT

View File

@@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.data .data
vcvtr_0: .float 1.25, 2.5, 3.75, 4.0 vcvtr_0: .float 1.25, 2.5, 3.75, 4.0
vcvtr_expect_zero: .word 1, 2, 3, 4 vcvtr_expect_zero: .word 1, 2, 3, 4
@@ -21,7 +21,7 @@ ENTRY
vcvtr.u32.f32 q1, q0 vcvtr.u32.f32 q1, q0
ldr r0, =vcvtr_result_zero ldr r0, =vcvtr_result_zero
vst1.32 {q1}, [r0] vst1.32 {q1}, [r0]
ASSERT_MEMCMP( LKMC_ASSERT_MEMCMP(
vcvtr_result_zero, vcvtr_result_zero,
vcvtr_expect_zero, vcvtr_expect_zero,
0x10 0x10
@@ -37,10 +37,10 @@ ENTRY
vcvtr.u32.f32 q1, q0 vcvtr.u32.f32 q1, q0
ldr r0, =vcvtr_result_plus_infinity ldr r0, =vcvtr_result_plus_infinity
vst1.32 {q1}, [r0] vst1.32 {q1}, [r0]
ASSERT_MEMCMP( LKMC_ASSERT_MEMCMP(
vcvtr_result_plus_infinity, vcvtr_result_plus_infinity,
vcvtr_expect_plus_infinity, vcvtr_expect_plus_infinity,
0x10 0x10
) )
#endif #endif
EXIT LKMC_EXIT

View File

@@ -15,17 +15,17 @@
; ;
/* Assert that the given branch instruction is taken. */ /* Assert that the given branch instruction is taken. */
#define ASSERT(branch_if_pass) \ #define LKMC_ASSERT(branch_if_pass) \
branch_if_pass 1f; \ branch_if_pass 1f; \
FAIL; \ LKMC_FAIL; \
1: \ 1: \
; ;
#ifndef ASSERT_EQ_REG #ifndef LKMC_ASSERT_EQ_REG
/* Assert that a register equals another register. */ /* Assert that a register equals another register. */
#define ASSERT_EQ_REG(reg1, reg2) \ #define LKMC_ASSERT_EQ_REG(reg1, reg2) \
cmp reg1, reg2; \ cmp reg1, reg2; \
ASSERT(beq); \ LKMC_ASSERT(beq); \
; ;
#endif #endif

View File

@@ -4,5 +4,5 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
EXIT LKMC_EXIT

View File

@@ -1,9 +1,9 @@
/* See what happens on test failure with FAIL. /* See what happens on test failure with LKMC_FAIL.
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly
*/ */
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
FAIL LKMC_FAIL
EXIT LKMC_EXIT

View File

@@ -2,15 +2,14 @@
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library
*/ */
#include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <lkmc.h>
int asm_main(uint32_t *line); int asm_main(uint32_t *line);
#define ASSERT_EQ_DEFINE(bits) \ #define ASSERT_EQ_DEFINE(bits) \
int assert_eq_ ## bits(uint ## bits ## _t val1, uint ## bits ## _t val2) { \ int lkmc_assert_eq_ ## bits(uint ## bits ## _t val1, uint ## bits ## _t val2) { \
if (val1 != val2) { \ if (val1 != val2) { \
printf("%s failed\n", __func__); \ printf("%s failed\n", __func__); \
printf("val1 0x%" PRIX ## bits "\n", val1); \ printf("val1 0x%" PRIX ## bits "\n", val1); \
@@ -19,11 +18,11 @@ int asm_main(uint32_t *line);
} \ } \
return 0; \ return 0; \
} }
ASSERT_EQ_DEFINE(32) ASSERT_EQ_DEFINE(32)
ASSERT_EQ_DEFINE(64) ASSERT_EQ_DEFINE(64)
#undef ASSERT_EQ_DEFINE
int assert_memcmp(const void *s1, const void *s2, size_t n) { int lkmc_assert_memcmp(const void *s1, const void *s2, size_t n) {
int ret; int ret;
size_t i; size_t i;
uint8_t *s1b, *s2b; uint8_t *s1b, *s2b;

View File

@@ -2,8 +2,8 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov $1, %rax mov $1, %rax
add $2, %rax add $2, %rax
ASSERT_EQ(%rax, $3) LKMC_ASSERT_EQ(%rax, $3)
EXIT LKMC_EXIT

View File

@@ -5,7 +5,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.bss .bss
output: .skip 16 output: .skip 16
.data .data
@@ -21,11 +21,11 @@ ENTRY
movups addp ## size ## _input1, %xmm1; \ movups addp ## size ## _input1, %xmm1; \
addp ## size %xmm1, %xmm0; \ addp ## size %xmm1, %xmm0; \
movups %xmm0, output; \ movups %xmm0, output; \
ASSERT_MEMCMP(output, addp ## size ## _expect, $0x10) LKMC_ASSERT_MEMCMP(output, addp ## size ## _expect, $0x10)
/* 4x 32-bit */ /* 4x 32-bit */
TEST(s) TEST(s)
/* 2x 64-bit */ /* 2x 64-bit */
TEST(d) TEST(d)
#undef TEST #undef TEST
EXIT LKMC_EXIT

View File

@@ -5,32 +5,32 @@
/* This and other macros may make C function calls, and therefore can destroy /* This and other macros may make C function calls, and therefore can destroy
* non-callee saved registers. */ * non-callee saved registers. */
#define ASSERT_EQ(general1, general2) \ #define LKMC_ASSERT_EQ(general1, general2) \
mov general2, %rdi; \ mov general2, %rdi; \
push %rdi; \ push %rdi; \
mov general1, %rdi; \ mov general1, %rdi; \
pop %rsi; \ pop %rsi; \
ASSERT_EQ_DO(64); \ LKMC_ASSERT_EQ_DO(64); \
; ;
#define ASSERT_EQ_DO(bits) \ #define LKMC_ASSERT_EQ_DO(bits) \
call assert_eq_ ## bits; \ call lkmc_assert_eq_ ## bits; \
cmp $0, %rax; \ cmp $0, %rax; \
ASSERT(je); \ LKMC_ASSERT(je); \
; ;
#define ASSERT_MEMCMP(label1, label2, const_size) \ #define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
lea label1(%rip), %rdi; \ lea label1(%rip), %rdi; \
lea label2(%rip), %rsi; \ lea label2(%rip), %rsi; \
mov const_size, %rdx; \ mov const_size, %rdx; \
call assert_memcmp; \ call lkmc_assert_memcmp; \
cmp $0, %rax; \ cmp $0, %rax; \
ASSERT(je); \ LKMC_ASSERT(je); \
; ;
/* Program entry point. /* Program entry point.
* *
* Return with EXIT. * Return with LKMC_EXIT.
* *
* Basically implements an x86_64 prologue: * Basically implements an x86_64 prologue:
* *
@@ -38,7 +38,7 @@
* x86_64 explained at: https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call/55207335#55207335 * 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 * - save register arguments for later usage
*/ */
#define ENTRY \ #define LKMC_ENTRY \
.text; \ .text; \
.global asm_main; \ .global asm_main; \
asm_main: \ asm_main: \
@@ -54,13 +54,13 @@ asm_main: \
asm_main_after_prologue: \ asm_main_after_prologue: \
; ;
/* Meant to be called at the end of ENTRY.* /* Meant to be called at the end of LKMC_ENTRY.*
* *
* Branching to "fail" makes tests fail with exit status 1. * Branching to "fail" makes tests fail with exit status 1.
* *
* If EXIT is reached, the program ends successfully. * If LKMC_EXIT is reached, the program ends successfully.
*/ */
#define EXIT \ #define LKMC_EXIT \
mov $0, %rax; \ mov $0, %rax; \
jmp pass; \ jmp pass; \
fail: \ fail: \
@@ -79,7 +79,7 @@ pass: \
ret; \ ret; \
; ;
#define FAIL \ #define LKMC_FAIL \
mov $__LINE__, %eax; \ mov $__LINE__, %eax; \
jmp fail; \ jmp fail; \
; ;

View File

@@ -2,12 +2,12 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
#define ASSERT_DIFF(label1, label2, result) \ #define ASSERT_DIFF(label1, label2, result) \
lea label2(%rip), %rax; \ lea label2(%rip), %rax; \
lea label1(%rip), %rbx; \ lea label1(%rip), %rbx; \
sub %rbx, %rax; \ sub %rbx, %rax; \
ASSERT_EQ(%rax, $result) LKMC_ASSERT_EQ(%rax, $result)
ASSERT_DIFF(mybyte, myword, 1) ASSERT_DIFF(mybyte, myword, 1)
ASSERT_DIFF(myword, mylong, 2) ASSERT_DIFF(myword, mylong, 2)
@@ -15,7 +15,7 @@ ENTRY
ASSERT_DIFF(myquad, myocta, 8) ASSERT_DIFF(myquad, myocta, 8)
ASSERT_DIFF(myocta, theend, 16) ASSERT_DIFF(myocta, theend, 16)
#undef ASSERT_DIF #undef ASSERT_DIF
EXIT LKMC_EXIT
mybyte: mybyte:
.byte 0x12 .byte 0x12
myword: myword:

View File

@@ -2,15 +2,15 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
mov $0x123456789ABCDEF0, %r12 mov $0x123456789ABCDEF0, %r12
mov $0x123456789ABCDEF0, %r13 mov $0x123456789ABCDEF0, %r13
ASSERT_EQ(%r12, $0x123456789ABCDEF0) LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF0)
ASSERT_EQ(%r12, %r13) LKMC_ASSERT_EQ(%r12, %r13)
ASSERT_EQ(%r12, myvar) LKMC_ASSERT_EQ(%r12, myvar)
ASSERT_EQ($0x123456789ABCDEF0, %r12) LKMC_ASSERT_EQ($0x123456789ABCDEF0, %r12)
ASSERT_EQ(%r13, %r12) LKMC_ASSERT_EQ(%r13, %r12)
ASSERT_EQ(myvar, %r12) LKMC_ASSERT_EQ(myvar, %r12)
ASSERT_EQ(%r12, $0x123456789ABCDEF1) LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF1)
EXIT LKMC_EXIT
myvar: .quad 0x123456789ABCDEF0 myvar: .quad 0x123456789ABCDEF0

View File

@@ -2,10 +2,10 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
ASSERT_MEMCMP(var0, var1, $0x10) LKMC_ASSERT_MEMCMP(var0, var1, $0x10)
ASSERT_MEMCMP(var0, var2, $0x10) LKMC_ASSERT_MEMCMP(var0, var2, $0x10)
EXIT LKMC_EXIT
var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444 var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444

View File

@@ -7,7 +7,7 @@
#include "common.h" #include "common.h"
ENTRY LKMC_ENTRY
.data .data
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4 input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515 input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
@@ -23,7 +23,7 @@ ENTRY
movups input0, %xmm0; \ movups input0, %xmm0; \
padd ## size %xmm1, %xmm0; \ padd ## size %xmm1, %xmm0; \
movups %xmm0, output; \ movups %xmm0, output; \
ASSERT_MEMCMP(output, padd ## size ## _expect, $0x10) LKMC_ASSERT_MEMCMP(output, padd ## size ## _expect, $0x10)
/* 16x 8-bit */ /* 16x 8-bit */
TEST(b) TEST(b)
@@ -35,4 +35,4 @@ ENTRY
/* 2x 16-bit */ /* 2x 16-bit */
TEST(q) TEST(q)
#undef TEST #undef TEST
EXIT LKMC_EXIT