1/*
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6#include "native_client/src/include/arm_sandbox.h"
7#include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
8#include "native_client/src/trusted/service_runtime/nacl_config.h"
9
10/* the macros below are used with movw/movt and absolute values */
11/* llvm-mc does not like the use of :lower16:/:upper16: with absolute values */
12/* c.f.: http://llvm.org/bugs/show_bug.cgi?id=8721 */
13#define lower_16(x) ((x) & 0xffff)
14#define upper_16(x) (((x) >> 16) & 0xffff)
15
16
17        /*
18         * Code to test various address layout boundary conditions.
19         * This is a translation from the x86-{32,64} code, and is
20         * not intended to be super efficent, just good enough to
21         * print out the values that are designed, while maintaining
22         * strict control over the address space layout.
23         */
24
25        .text
26start_of_text:
27        /*
28         * write_num_10 omitted.  __aeabi_udivmod is too long/complex
29         * to replicate, we cannot link against glibc to get _udivsi3.o
30         * and pick up transitive dependencies.  Plus, we don't actually
31         * use decimal output (yet).
32         *
33         * One alternative would be to link using:
34         *
35         * ${LD} --native-client -e _start -Ttext 0x20000 -o ${TARGET} \
36         *  ${SOURCES} ${GLIBC} ${TEXT_EXTEND}
37         *
38         * i.e., to load the text pad as a separate .o *after* external
39         * references are resolved from glibc, with link-time
40         * expansion/computation of the (TEXT_EXTEND - (. - start_of_text))/4
41         * fill expression (is that possible?).
42         */
43
44        /*
45         * write_num_16.  Write an unsigned value in hex.
46         * r0 is descriptor number, r1 is unsigned value to write.
47         */
48        .p2align 4
49write_num_16:
50        push {r4, lr}
51        mov r3, sp
52        /* r12 is caller-saved: use it as a temporary register */
53        sub r12, sp, #0x10
54        bic sp, r12, #0xc0000000
55
56        mov r2, #0
57do_digit_16:
58        sub r3, r3, #1
59        add r2, r2, #1
60        and r4, r1, #0xf
61
62        add r4, r4, #'0'
63        cmp r4, #'9'
64        ble do_digit_not_upper
65        add r4, r4, #('a'-'0'-10)
66
67do_digit_not_upper:
68        bic r3, r3, #0xc0000000
69        strb r4, [r3]
70        lsrs r1, r1, #4
71        bne do_digit_16
72
73        mov r1, r3
74        movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_write))
75        movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_write))
76        nop
77
78        nop
79        nop
80        bic r3, r3, #0xc000000f
81        blx r3
82
83        /* r12 is caller-saved: use it as a temporary register */
84        add r12, sp, #0x10
85        bic sp, r12, #0xc0000000
86        pop {r4, lr}
87        nop
88
89        bic lr, lr, #0xc000000f
90        bx lr
91
92        .p2align 4
93        /*
94         * r0 is descriptor number, r1 is character to write
95         */
96write_char:
97        push {lr}
98        /* r12 is caller-saved: use it as a temporary register */
99        sub r12, sp, #0x10
100        bic sp, r12, #0xc0000000
101        strb r1, [sp]
102
103        mov r1, sp
104        mov r2, #1
105        movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_write))
106        movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_write))
107
108        nop
109        nop
110        bic r3, r3, #0xc000000f
111        blx r3
112
113        /* r12 is caller-saved: use it as a temporary register */
114        add r12, sp, #0x10
115        bic sp, r12, #0xc0000000
116        pop {lr}
117        nop
118
119        bic lr, lr, #0xc000000f
120        bx lr
121
122        .p2align 4
123        .globl _start
124_start:
125        /* basic I/O test */
126        mov r0, #1
127        movw r1, #0xbeef
128        movt r1, #0xdead
129        bl write_num_16
130
131        mov r0, #1
132        mov r1, #'\n'
133        nop
134        bl write_char
135
136        movw r1, :lower16:(end_of_text)
137        movt r1, :upper16:(end_of_text)
138        mov r0, #1
139        bl write_num_16
140
141        mov r0, #1
142        mov r1, #'\n'
143        nop
144        bl write_char
145
146        mov r0, #0
147        movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_brk))
148        movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_brk))
149        nop
150
151        nop
152        nop
153        bic r3, r3, #0xc000000f
154        blx r3
155
156        mov r4, r0  /* save a copy of break addr */
157        mov r1, r0
158        mov r0, #1
159        bl write_num_16
160
161        mov r0, #1
162        mov r1, #'\n'
163        nop
164        bl write_char
165
166        mov r5, #0  /* r5 holds eventual exit status */
167        movw r1, lower_16(EXPECTED_BREAK)
168        movt r1, upper_16(EXPECTED_BREAK)
169        cmp r1, r4
170
171        movne r5, #1
172        mov r0, #1  /* r1 still has EXPECTED_BREAK */
173        nop
174        bl write_num_16
175
176        mov r1, #'\n'
177        mov r0, #1
178        nop
179        bl write_char
180
181#if defined(EXPECTED_RODATA)
182        mov r2, #12
183        movw r1, :lower16:(ro_str)
184        movt r1, :upper16:(ro_str)
185        mov r0, #1
186
187        movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_write))
188        movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_write))
189        bic r3, r3, #0xc000000f
190        blx r3
191
192        /* Truncate the address to page boundary for comparison. */
193        movw r4, #0
194        movt r4, :upper16:(ro_str)
195        nop
196        nop
197
198        mov r0, #1
199        mov r1, r4
200        nop
201        bl write_num_16
202
203        mov r1, #'\n'
204        mov r0, #1
205        nop
206        bl write_char
207
208        movw r1, lower_16(EXPECTED_RODATA)
209        movt r1, upper_16(EXPECTED_RODATA)
210        nop
211        nop
212
213        cmp r1, r4
214        movne r5, #2
215        mov r0, #1  /* r1 still has EXPECTED_RODATA */
216        bl write_num_16
217
218        mov r1, #'\n'
219        mov r0, #2
220        nop
221        bl write_char
222#endif
223
224        movw r3, lower_16(NACL_SYSCALL_ADDR(NACL_sys_exit))
225        movt r3, upper_16(NACL_SYSCALL_ADDR(NACL_sys_exit))
226        mov r0, r5
227        nop
228
229        nop
230        nop
231        bic r3, r3, #0xc000000f
232        blx r3
233#if defined(PNACL_AS)
234/* NOTE: unlike x86 the alignment directive on ARM takes
235   the logarithm of the alignment */
236#define POW2_BIGGER_THAN_DOT 14
237        .align32 POW2_BIGGER_THAN_DOT, NACL_INSTR_ARM_HALT_FILL
238        .fill (TEXT_EXTEND - (1 << POW2_BIGGER_THAN_DOT))/4, 4, \
239              NACL_INSTR_ARM_HALT_FILL
240#else
241        .fill (TEXT_EXTEND - (. - start_of_text))/4, 4, \
242              NACL_INSTR_ARM_HALT_FILL
243#endif
244
245end_of_text:
246
247#if defined(EXPECTED_RODATA)
248        .section .rodata
249ro_str: .ascii "Hello world\n"
250        /*      123456789012 */
251#endif
252