Skip to content

Commit ce6febc

Browse files
committed
[Compiler-rt] Implement AEABI Unaligned Read/Write Helpers in compiler-rt
This patch adds implementations for the __aeabi_uread and __aeabi_uwrite helper functions to compiler-rt..
1 parent 1618e49 commit ce6febc

File tree

6 files changed

+180
-0
lines changed

6 files changed

+180
-0
lines changed

compiler-rt/lib/builtins/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ set(arm_EABI_RT_SOURCES
470470
arm/aeabi_ldivmod.S
471471
arm/aeabi_uidivmod.S
472472
arm/aeabi_uldivmod.S
473+
arm/aeabi_uread4.c
474+
arm/aeabi_uread8.c
475+
arm/aeabi_uwrite4.c
476+
arm/aeabi_uwrite8.c
473477
)
474478

475479
set(arm_EABI_CLIB_SOURCES
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- aeabi_uread4.c - ARM EABI Helper — Unaligned 4-Byte Memory Read --===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===-----------------------------------------------------------------------------===//
8+
9+
typedef struct {
10+
char v[4];
11+
} v4;
12+
13+
int __aeabi_uread4(void *p) {
14+
union {
15+
v4 v;
16+
int u;
17+
} u;
18+
19+
u.v = *(v4 *)p;
20+
return u.u;
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- aeabi_uread8.c - ARM EABI Helper — Unaligned 8-Byte Memory Read --===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===-----------------------------------------------------------------------------===//
8+
9+
typedef struct {
10+
char v[8];
11+
} v8;
12+
13+
long long __aeabi_uread8(void *p) {
14+
union {
15+
v8 v;
16+
long long u;
17+
} u;
18+
19+
u.v = *(v8 *)p;
20+
return u.u;
21+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- aeabi_uread8.c - ARM EABI Helper — Unaligned 4-Byte Memory Write --===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===-----------------------------------------------------------------------------===//
8+
9+
typedef struct {
10+
char v[4];
11+
} v4;
12+
13+
int __aeabi_uwrite4(int val, void *p) {
14+
union {
15+
v4 v;
16+
int u;
17+
} u;
18+
19+
u.u = val;
20+
*(v4 *)p = u.v;
21+
22+
return val;
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- aeabi_uread8.c - ARM EABI Helper — Unaligned 8-Byte Memory Write --===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===-----------------------------------------------------------------------------===//
8+
9+
typedef struct {
10+
char v[8];
11+
} v8;
12+
13+
long long __aeabi_uwrite8(long long val, void *p) {
14+
union {
15+
v8 v;
16+
long long u;
17+
} u;
18+
19+
u.u = val;
20+
*(v8 *)p = u.v;
21+
22+
return val;
23+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// REQUIRES: arm-target-arch || armv6m-target-arch
2+
// RUN: %clang_builtins %s %librt -o %t && %run %t
3+
4+
#include <stdint.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
8+
extern int __aeabi_uread4(void *);
9+
extern int __aeabi_uwrite4(int, void *);
10+
extern long long __aeabi_uread8(void *);
11+
extern long long __aeabi_uwrite8(long long, void *);
12+
13+
#define lenof(x) (sizeof((x)) / sizeof(*(x)))
14+
15+
int test_unaligned(void) {
16+
long long target8;
17+
int target4;
18+
const char source[] = "abcdefghijklmno";
19+
static char dest1[lenof(source)], dest2[lenof(source)];
20+
int i, j;
21+
22+
for (i = 0; i < 7; i++) {
23+
memcpy(&target8, source + i, 8);
24+
if (__aeabi_uread8(source + i) != target8) {
25+
printf("error in __aeabi_uread8 => output = %llx, expected %llx\n",
26+
__aeabi_uread8(source + i), target8);
27+
return 1;
28+
}
29+
30+
memcpy(dest1, source, lenof(source));
31+
memcpy(dest2, source, lenof(source));
32+
target8 = 0x4142434445464748ULL;
33+
if (__aeabi_uwrite8(target8, dest1 + i) != target8) {
34+
printf("error in __aeabi_uwrite8 => output = %llx, expected %llx\n",
35+
__aeabi_uwrite8(target8, dest1 + i), target8);
36+
return 1;
37+
}
38+
memcpy(dest2 + i, &target8, 8);
39+
if (memcmp(dest1, dest2, lenof(source)) != 0) {
40+
int pos = -1;
41+
printf("error in __aeabi_uwrite8: memcmp failed: buffers differ!\n");
42+
for (int j = 0; j < 8; ++j) {
43+
if (dest1[j] != dest2[j]) {
44+
pos = j;
45+
break;
46+
}
47+
}
48+
printf("error: 8-byte write mismatch at offset %d\n", pos);
49+
return 1;
50+
}
51+
52+
memcpy(&target4, source + i, 4);
53+
if (__aeabi_uread4(source + i) != target4) {
54+
printf("error in __aeabi_uread4 => output = %x, expected %x\n",
55+
__aeabi_uread4(source + i), target4);
56+
return 1;
57+
}
58+
59+
memcpy(dest1, source, lenof(source));
60+
memcpy(dest2, source, lenof(source));
61+
target4 = 0x414243444;
62+
if (__aeabi_uwrite4(target4, dest1 + i) != target4) {
63+
printf("error in __aeabi_uwrite4 => output = %x, expected %x\n",
64+
__aeabi_uwrite4(target4, dest1 + i), target4);
65+
return 1;
66+
}
67+
memcpy(dest2 + i, &target4, 4);
68+
if (memcmp(dest1, dest2, lenof(source)) != 0) {
69+
int pos = -1;
70+
printf("error in __aeabi_uwrite4: memcmp failed: buffers differ!\n");
71+
for (int j = 0; j < 4; ++j) {
72+
if (dest1[j] != dest2[j]) {
73+
pos = j;
74+
break;
75+
}
76+
}
77+
printf("error: 4-byte write mismatch at offset %d\n", pos);
78+
return 1;
79+
}
80+
}
81+
return 0;
82+
}
83+
84+
int main() {
85+
if (test_unaligned())
86+
return 1;
87+
return 0;
88+
}

0 commit comments

Comments
 (0)