1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gtest/gtest.h"
18 
19 #include <link.h>
20 
21 #include <cstdint>
22 #include <cstdio>
23 
24 // Dummy function for LinkerExidx test.
arm_tests()25 int arm_tests() {
26   return 0;
27 }
28 
read_exidx_func(int32_t * entry)29 uintptr_t read_exidx_func(int32_t* entry) {
30   int32_t offset = *entry;
31   // sign-extend from int31 to int32.
32   if ((offset & 0x40000000) != 0) {
33     offset += -0x7fffffff - 1;
34   }
35   return reinterpret_cast<uintptr_t>(entry) + offset;
36 }
37 
TEST(ARM,LinkerExidx)38 TEST(ARM, LinkerExidx) {
39   int count;
40   int32_t* entries;
41   entries = reinterpret_cast<int32_t*>(
42       dl_unwind_find_exidx(reinterpret_cast<uintptr_t>(read_exidx_func), &count));
43   ASSERT_TRUE(entries);
44   ASSERT_GT(count, 0);
45   // Sanity checks
46   uintptr_t func = reinterpret_cast<uintptr_t>(arm_tests);
47   bool found = false;
48   for (int i = 0; i < count; i++) {
49     // Entries must have 31 bit set to zero.
50     ASSERT_GE(entries[2 * i], 0);
51     uintptr_t exidx_func = read_exidx_func(&entries[2 * i]);
52     // If our function is compiled to thumb, exception table contains our
53     // address - 1.
54     if (func == exidx_func || func == exidx_func + 1) {
55       found = true;
56     }
57     // Entries must be sorted. Some addresses may appear twice if function
58     // is compiled to arm.
59     if (i > 0) {
60       ASSERT_GE(exidx_func, read_exidx_func(&entries[2 * (i - 1)]));
61     }
62   }
63   ASSERT_TRUE(found);
64 }
65 
TEST(ARM,LSL0)66 TEST(ARM, LSL0) {
67   int result;
68 
69   asm volatile(
70       "mov %0, #-2\n"
71       "mov r1, #0\n"
72       "lsl %0, r1\n"
73       : "=r"(result)::"r1");
74   EXPECT_EQ(result, -2);
75 
76   asm volatile(
77       "mov r1, #-2\n"
78       "mov r2, #0\n"
79       "lsl %0, r1, r2\n"
80       : "=r"(result)::"r1", "r2");
81   EXPECT_EQ(result, -2);
82 
83   asm volatile(
84       "mov r1, #-2\n"
85       "lsl %0, r1, #0\n"
86       : "=r"(result)::"r1");
87   EXPECT_EQ(result, -2);
88 }
89 
TEST(ARM,LSL32)90 TEST(ARM, LSL32) {
91   int result;
92   int flag;
93 
94   asm volatile(
95       "mov %0, #-1\n"
96       "mov r1, #32\n"
97       "lsls %0, r1\n"
98       "sbc %1, r1, r1\n"
99       : "=r"(result), "=r"(flag)::"r1");
100   EXPECT_EQ(result, 0);
101   EXPECT_EQ(flag, 0);
102 
103   asm volatile(
104       "mov r1, #-1\n"
105       "mov r2, #32\n"
106       "lsls %0, r1, r2\n"
107       "sbc %1, r1, r1\n"
108       : "=r"(result), "=r"(flag)::"r1", "r2");
109   EXPECT_EQ(result, 0);
110   EXPECT_EQ(flag, 0);
111 }
112 
TEST(ARM,LSL33)113 TEST(ARM, LSL33) {
114   int result;
115   int flag;
116 
117   asm volatile(
118       "mov %0, #-1\n"
119       "mov r1, #33\n"
120       "lsls %0, r1\n"
121       "sbc %1, r1, r1\n"
122       : "=r"(result), "=r"(flag)::"r1");
123   EXPECT_EQ(result, 0);
124   EXPECT_EQ(flag, -1);
125 
126   asm volatile(
127       "mov r1, #-1\n"
128       "mov r2, #33\n"
129       "lsls %0, r1, r2\n"
130       "sbc %1, r1, r1\n"
131       : "=r"(result), "=r"(flag)::"r1", "r2");
132   EXPECT_EQ(result, 0);
133   EXPECT_EQ(flag, -1);
134 }
135 
TEST(ARM,LSL256)136 TEST(ARM, LSL256) {
137   int result;
138 
139   asm volatile(
140       "mov %0, #-2\n"
141       "mov r1, #256\n"
142       "lsl %0, r1\n"
143       : "=r"(result)::"r1");
144   EXPECT_EQ(result, -2);
145 
146   asm volatile(
147       "mov r1, #-2\n"
148       "mov r2, #256\n"
149       "lsl %0, r1, r2\n"
150       : "=r"(result)::"r1", "r2");
151   EXPECT_EQ(result, -2);
152 }
153 
TEST(ARM,LSR0)154 TEST(ARM, LSR0) {
155   int result;
156 
157   asm volatile(
158       "mov %0, #-2\n"
159       "mov r1, #0\n"
160       "lsr %0, r1\n"
161       : "=r"(result)::"r1");
162   EXPECT_EQ(result, -2);
163 
164   asm volatile(
165       "mov r1, #-2\n"
166       "mov r2, #0\n"
167       "lsr %0, r1, r2\n"
168       : "=r"(result)::"r1", "r2");
169   EXPECT_EQ(result, -2);
170 }
171 
TEST(ARM,LSR32)172 TEST(ARM, LSR32) {
173   int result;
174   int flag;
175 
176   asm volatile(
177       "mov %0, #-1\n"
178       "mov r1, #32\n"
179       "lsrs %0, r1\n"
180       "sbc %1, r1, r1\n"
181       : "=r"(result), "=r"(flag)::"r1");
182   EXPECT_EQ(result, 0);
183   EXPECT_EQ(flag, 0);
184 
185   asm volatile(
186       "mov r1, #-1\n"
187       "mov r2, #32\n"
188       "lsrs %0, r1, r2\n"
189       "sbc %1, r1, r1\n"
190       : "=r"(result), "=r"(flag)::"r1", "r2");
191   EXPECT_EQ(result, 0);
192   EXPECT_EQ(flag, 0);
193 
194   asm volatile(
195       "mov r1, #-1\n"
196       "lsrs %0, r1, #32\n"
197       "sbc %1, r1, r1\n"
198       : "=r"(result), "=r"(flag)::"r1");
199   EXPECT_EQ(result, 0);
200   EXPECT_EQ(flag, 0);
201 }
202 
TEST(ARM,LSR33)203 TEST(ARM, LSR33) {
204   int result;
205   int flag;
206 
207   asm volatile(
208       "mov %0, #-1\n"
209       "mov r1, #33\n"
210       "lsrs %0, r1\n"
211       "sbc %1, r1, r1\n"
212       : "=r"(result), "=r"(flag)::"r1");
213   EXPECT_EQ(result, 0);
214   EXPECT_EQ(flag, -1);
215 
216   asm volatile(
217       "mov r1, #-1\n"
218       "mov r2, #33\n"
219       "lsrs %0, r1, r2\n"
220       "sbc %1, r1, r1\n"
221       : "=r"(result), "=r"(flag)::"r1", "r2");
222   EXPECT_EQ(result, 0);
223   EXPECT_EQ(flag, -1);
224 }
225 
TEST(ARM,LSR256)226 TEST(ARM, LSR256) {
227   int result;
228 
229   asm volatile(
230       "mov %0, #-2\n"
231       "mov r1, #256\n"
232       "lsr %0, r1\n"
233       : "=r"(result)::"r1");
234   EXPECT_EQ(result, -2);
235 
236   asm volatile(
237       "mov r1, #-2\n"
238       "mov r2, #256\n"
239       "lsr %0, r1, r2\n"
240       : "=r"(result)::"r1", "r2");
241   EXPECT_EQ(result, -2);
242 }
243 
TEST(ARM,ASR0)244 TEST(ARM, ASR0) {
245   int result;
246 
247   asm volatile(
248       "mov %0, #-2\n"
249       "mov r1, #0\n"
250       "asr %0, r1\n"
251       : "=r"(result)::"r1");
252   EXPECT_EQ(result, -2);
253 
254   asm volatile(
255       "mov r1, #-2\n"
256       "mov r2, #0\n"
257       "asr %0, r1, r2\n"
258       : "=r"(result)::"r1", "r2");
259   EXPECT_EQ(result, -2);
260 }
261 
TEST(ARM,ASR32)262 TEST(ARM, ASR32) {
263   int result;
264   int flag;
265 
266   asm volatile(
267       "mov %0, #-1\n"
268       "mov r1, #32\n"
269       "asrs %0, r1\n"
270       "sbc %1, r1, r1\n"
271       : "=r"(result), "=r"(flag)::"r1");
272   EXPECT_EQ(result, -1);
273   EXPECT_EQ(flag, 0);
274 
275   asm volatile(
276       "mov r1, #-1\n"
277       "mov r2, #32\n"
278       "asrs %0, r1, r2\n"
279       "sbc %1, r1, r1\n"
280       : "=r"(result), "=r"(flag)::"r1", "r2");
281   EXPECT_EQ(result, -1);
282   EXPECT_EQ(flag, 0);
283 
284   asm volatile(
285       "mov r1, #-1\n"
286       "asrs %0, r1, #32\n"
287       "sbc %1, r1, r1\n"
288       : "=r"(result), "=r"(flag)::"r1");
289   EXPECT_EQ(result, -1);
290   EXPECT_EQ(flag, 0);
291 }
292 
TEST(ARM,ASR33)293 TEST(ARM, ASR33) {
294   int result;
295   int flag;
296 
297   asm volatile(
298       "mov %0, #-1\n"
299       "mov r1, #33\n"
300       "asrs %0, r1\n"
301       "sbc %1, r1, r1\n"
302       : "=r"(result), "=r"(flag)::"r1");
303   EXPECT_EQ(result, -1);
304   EXPECT_EQ(flag, 0);
305 
306   asm volatile(
307       "mov r1, #-1\n"
308       "mov r2, #33\n"
309       "asrs %0, r1, r2\n"
310       "sbc %1, r1, r1\n"
311       : "=r"(result), "=r"(flag)::"r1", "r2");
312   EXPECT_EQ(result, -1);
313   EXPECT_EQ(flag, 0);
314 }
315 
TEST(ARM,ASR256)316 TEST(ARM, ASR256) {
317   int result;
318 
319   asm volatile(
320       "mov %0, #-2\n"
321       "mov r1, #256\n"
322       "asr %0, r1\n"
323       : "=r"(result)::"r1");
324   EXPECT_EQ(result, -2);
325 
326   asm volatile(
327       "mov r1, #-2\n"
328       "mov r2, #256\n"
329       "asr %0, r1, r2\n"
330       : "=r"(result)::"r1", "r2");
331   EXPECT_EQ(result, -2);
332 }
333