Zhi An Ng | ec17e99 | 2021-12-16 13:06:37 -0800 | [diff] [blame] | 1 | // Copyright 2021 Google LLC |
| 2 | // |
| 3 | // This source code is licensed under the BSD-style license found in the |
| 4 | // LICENSE file in the root directory of this source tree. |
| 5 | |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 6 | #include <xnnpack/aarch32-assembler.h> |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 7 | #include <xnnpack/allocator.h> |
| 8 | #include <xnnpack/common.h> |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 9 | |
Zhi An Ng | d221c54 | 2021-12-07 15:55:22 -0800 | [diff] [blame] | 10 | #include <ios> |
| 11 | |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 12 | #include <gtest/gtest.h> |
| 13 | |
Zhi An Ng | 737ad01 | 2021-12-08 16:42:44 -0800 | [diff] [blame] | 14 | // clang-format off |
| 15 | #define EXPECT_INSTR(expected, actual) \ |
| 16 | EXPECT_EQ(expected, actual) << "expected = 0x" << std::hex << std::setw(8) << std::setfill('0') << expected \ |
| 17 | << std::endl << " actual = 0x" << actual; |
| 18 | // clang-format on |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 19 | |
| 20 | #define CHECK_ENCODING(expected, call) \ |
| 21 | a.reset(); \ |
| 22 | call; \ |
| 23 | EXPECT_INSTR(expected, *a.start()) |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 24 | |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 25 | #define EXPECT_ERROR(expected, call) \ |
| 26 | a.reset(); \ |
| 27 | call; \ |
| 28 | EXPECT_EQ(expected, a.error()); |
| 29 | |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 30 | namespace xnnpack { |
| 31 | namespace aarch32 { |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 32 | TEST(AArch32Assembler, InstructionEncoding) { |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 33 | xnn_code_buffer b; |
| 34 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 35 | Assembler a(&b); |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 36 | |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 37 | CHECK_ENCODING(0xE0810002, a.add(r0, r1, r2)); |
Zhi An Ng | f73e55b | 2021-12-09 10:04:38 -0800 | [diff] [blame] | 38 | CHECK_ENCODING(0xE28A9080, a.add(r9, r10, 128)); |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 39 | |
Zhi An Ng | 10475ec | 2021-12-09 14:52:46 -0800 | [diff] [blame] | 40 | CHECK_ENCODING(0xE12FFF1E, a.bx(lr)); |
| 41 | |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 42 | CHECK_ENCODING(0xE3500002, a.cmp(r0, 2)); |
Zhi An Ng | 663b4fe | 2021-12-07 14:34:54 -0800 | [diff] [blame] | 43 | |
Zhi An Ng | c9ffad7 | 2021-12-07 14:28:21 -0800 | [diff] [blame] | 44 | // Offset addressing mode. |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 45 | CHECK_ENCODING(0xE59D7060, a.ldr(r7, mem[sp, 96])); |
Zhi An Ng | c9ffad7 | 2021-12-07 14:28:21 -0800 | [diff] [blame] | 46 | // Post-indexed addressing mode. |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 47 | CHECK_ENCODING(0xE490B000, a.ldr(r11, mem[r0], 0)); |
| 48 | CHECK_ENCODING(0xE490B060, a.ldr(r11, mem[r0], 96)); |
Zhi An Ng | c9ffad7 | 2021-12-07 14:28:21 -0800 | [diff] [blame] | 49 | // Offsets out of bounds. |
| 50 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(r7, MemOperand(sp, 4096))); |
| 51 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(r7, MemOperand(sp, -4096))); |
| 52 | |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 53 | CHECK_ENCODING(0x31A0C003, a.movlo(r12, r3)); |
| 54 | CHECK_ENCODING(0x91A0A00C, a.movls(r10, r12)); |
| 55 | CHECK_ENCODING(0xE1A0A00C, a.mov(r10, r12)); |
Zhi An Ng | ff2e8b2 | 2021-12-07 15:18:33 -0800 | [diff] [blame] | 56 | |
Zhi An Ng | be4e6a5 | 2021-12-16 15:09:27 -0800 | [diff] [blame] | 57 | CHECK_ENCODING(0xE320F000, a.nop()); |
| 58 | |
Zhi An Ng | 16f3548 | 2021-12-09 14:32:31 -0800 | [diff] [blame] | 59 | CHECK_ENCODING(0xE8BD0FF0, a.pop({r4, r5, r6, r7, r8, r9, r10, r11})); |
| 60 | EXPECT_ERROR(Error::kInvalidOperand, a.pop({})); |
| 61 | EXPECT_ERROR(Error::kInvalidOperand, a.pop({r1})); |
| 62 | |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 63 | CHECK_ENCODING(0xE92D0FF0, a.push({r4, r5, r6, r7, r8, r9, r10, r11})); |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 64 | EXPECT_ERROR(Error::kInvalidOperand, a.push({})); |
| 65 | EXPECT_ERROR(Error::kInvalidOperand, a.push({r1})); |
Zhi An Ng | 4ab7b93 | 2021-12-07 15:20:54 -0800 | [diff] [blame] | 66 | |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 67 | CHECK_ENCODING(0xF5D3F000, a.pld(MemOperand(r3, 0))); |
| 68 | CHECK_ENCODING(0xF5D3F040, a.pld(MemOperand(r3, 64))); |
Zhi An Ng | 591b917 | 2021-12-07 15:38:52 -0800 | [diff] [blame] | 69 | |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 70 | CHECK_ENCODING(0xE0487002, a.sub(r7, r8, r2)); |
| 71 | CHECK_ENCODING(0xE2525010, a.subs(r5, r2, 16)); |
Zhi An Ng | 68c27d3 | 2021-12-08 10:58:34 -0800 | [diff] [blame] | 72 | |
Zhi An Ng | 2fce75b | 2021-12-09 10:40:16 -0800 | [diff] [blame] | 73 | CHECK_ENCODING(0xE315000F, a.tst(r5, 15)); |
| 74 | |
Zhi An Ng | 4a58583 | 2021-12-14 16:46:25 -0800 | [diff] [blame] | 75 | CHECK_ENCODING(0xF3FF8C4F, a.vdup_8(q12, d15[7])); |
| 76 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vdup_8(q12, d15[8])); |
| 77 | CHECK_ENCODING(0xF3FE8C4F, a.vdup_16(q12, d15[3])); |
| 78 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vdup_16(q12, d15[4])); |
| 79 | CHECK_ENCODING(0xF3FC8C4F, a.vdup_32(q12, d15[1])); |
| 80 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vdup_32(q12, d15[2])); |
| 81 | |
Zhi An Ng | 6fac719 | 2021-12-14 16:48:22 -0800 | [diff] [blame] | 82 | CHECK_ENCODING(0xF2BE04C6, a.vext_8(q0, q15, q3, 4)); |
| 83 | EXPECT_ERROR(Error::kInvalidOperand, a.vext_8(q0, q15, q3, 16)); |
| 84 | |
Zhi An Ng | a38a161 | 2021-12-14 12:07:06 -0800 | [diff] [blame] | 85 | CHECK_ENCODING(0xF423070F, a.vld1_8({d0}, mem[r3])); |
| 86 | CHECK_ENCODING(0xF423070D, a.vld1_8({d0}, mem[r3]++)); |
| 87 | |
Zhi An Ng | dfe8929 | 2021-12-08 16:48:48 -0800 | [diff] [blame] | 88 | CHECK_ENCODING(0xF42C178F, a.vld1_32({d1}, mem[r12])); |
| 89 | CHECK_ENCODING(0xF42C178D, a.vld1_32({d1}, mem[r12]++)); |
| 90 | |
| 91 | CHECK_ENCODING(0xF4A54CAF, a.vld1r_32({d4, d5}, mem[r5])); |
| 92 | CHECK_ENCODING(0xF4A54CAD, a.vld1r_32({d4, d5}, mem[r5]++)); |
| 93 | |
Zhi An Ng | 637becf | 2021-12-08 13:16:59 -0800 | [diff] [blame] | 94 | CHECK_ENCODING(0xECF90B08, a.vldm(r9, {d16, d19}, true)); |
| 95 | CHECK_ENCODING(0xEC998B08, a.vldm(r9, {d8, d11}, false)); |
| 96 | CHECK_ENCODING(0xEC998B08, a.vldm(r9, {d8, d11})); |
| 97 | CHECK_ENCODING(0xECB30A01, a.vldm(r3, {s0}, true)); |
| 98 | CHECK_ENCODING(0xEC930A01, a.vldm(r3, {s0})); |
| 99 | |
Zhi An Ng | 477bdbb | 2021-12-08 13:33:39 -0800 | [diff] [blame] | 100 | CHECK_ENCODING(0xED99FB0E, a.vldr(d15, mem[r9, 56])); |
Zhi An Ng | 737ad01 | 2021-12-08 16:42:44 -0800 | [diff] [blame] | 101 | EXPECT_ERROR(Error::kInvalidOperand, a.vldr(d15, MemOperand(r9, 56, AddressingMode::kPostIndexed))); |
Zhi An Ng | 477bdbb | 2021-12-08 13:33:39 -0800 | [diff] [blame] | 102 | EXPECT_ERROR(Error::kInvalidOperand, a.vldr(d15, mem[r9, 256])); |
| 103 | |
Zhi An Ng | 2649014 | 2021-12-14 16:02:12 -0800 | [diff] [blame] | 104 | CHECK_ENCODING(0xF20E26C6, a.vmax_s8(q1, q15, q3)); |
Zhi An Ng | ea612bc | 2021-12-09 10:42:50 -0800 | [diff] [blame] | 105 | CHECK_ENCODING(0xF24ECFC4, a.vmax_f32(q14, q15, q2)); |
| 106 | |
Zhi An Ng | 2649014 | 2021-12-14 16:02:12 -0800 | [diff] [blame] | 107 | CHECK_ENCODING(0xF20E26D6, a.vmin_s8(q1, q15, q3)); |
Zhi An Ng | ea612bc | 2021-12-09 10:42:50 -0800 | [diff] [blame] | 108 | CHECK_ENCODING(0xF220EFC6, a.vmin_f32(q7, q8, q3)); |
| 109 | |
Zhi An Ng | c9f70f7 | 2021-12-09 09:33:17 -0800 | [diff] [blame] | 110 | CHECK_ENCODING(0xF3E80140, a.vmla_f32(q8, q4, d0[0])); |
| 111 | CHECK_ENCODING(0xF3EC0160, a.vmla_f32(q8, q6, d0[1])); |
| 112 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vmla_f32(q8, q4, d0[2])); |
| 113 | |
Zhi An Ng | a38a161 | 2021-12-14 12:07:06 -0800 | [diff] [blame] | 114 | CHECK_ENCODING(0xF2D9E246, a.vmlal_s16(q15, d9, d6[0])); |
| 115 | CHECK_ENCODING(0xF2D8424A, a.vmlal_s16(q10, d8, d2[1])); |
| 116 | CHECK_ENCODING(0xF2D88264, a.vmlal_s16(q12, d8, d4[2])); |
| 117 | CHECK_ENCODING(0xF2D8626A, a.vmlal_s16(q11, d8, d2[3])); |
| 118 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vmlal_s16(q15, d9, d6[4])); |
| 119 | |
Zhi An Ng | f4beaf1 | 2021-12-08 13:27:29 -0800 | [diff] [blame] | 120 | CHECK_ENCODING(0xEEB0EA4F, a.vmov(s28, s30)); |
| 121 | CHECK_ENCODING(0xF26101B1, a.vmov(d16, d17)); |
| 122 | CHECK_ENCODING(0xEC420B1F, a.vmov(d15, r0, r2)); |
| 123 | CHECK_ENCODING(0xF26041F0, a.vmov(q10, q8)); |
| 124 | |
Zhi An Ng | a38a161 | 2021-12-14 12:07:06 -0800 | [diff] [blame] | 125 | CHECK_ENCODING(0xF2880A10, a.vmovl_s8(q0, d0)); |
| 126 | |
Zhi An Ng | 16f3548 | 2021-12-09 14:32:31 -0800 | [diff] [blame] | 127 | CHECK_ENCODING(0xECBD8B10, a.vpop({d8, d15})); |
| 128 | |
Zhi An Ng | 68c27d3 | 2021-12-08 10:58:34 -0800 | [diff] [blame] | 129 | CHECK_ENCODING(0xED2D4A08, a.vpush({s8, s15})); |
| 130 | CHECK_ENCODING(0xED2DAA04, a.vpush({s20, s23})); |
| 131 | CHECK_ENCODING(0xED2D8B10, a.vpush({d8, d15})); |
| 132 | CHECK_ENCODING(0xED6D4B08, a.vpush({d20, d23})); |
Zhi An Ng | fe4a750 | 2021-12-09 14:21:57 -0800 | [diff] [blame] | 133 | |
Zhi An Ng | 2649014 | 2021-12-14 16:02:12 -0800 | [diff] [blame] | 134 | CHECK_ENCODING(0xF25E00D2, a.vqadd_s16(q8, q15, q1)); |
| 135 | |
| 136 | CHECK_ENCODING(0xF3A82CCE, a.vqdmulh_s32(q1, q12, d14[0])); |
| 137 | CHECK_ENCODING(0xF3A82CEE, a.vqdmulh_s32(q1, q12, d14[1])); |
| 138 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vqdmulh_s32(q1, q12, d14[2])); |
| 139 | EXPECT_ERROR(Error::kInvalidOperand, a.vqdmulh_s32(q1, q12, d16[0])); |
| 140 | |
Zhi An Ng | 6fac719 | 2021-12-14 16:48:22 -0800 | [diff] [blame] | 141 | CHECK_ENCODING(0xF3F602A0, a.vqmovn_s32(d16, q8)); |
| 142 | |
Zhi An Ng | 2649014 | 2021-12-14 16:02:12 -0800 | [diff] [blame] | 143 | CHECK_ENCODING(0xF22C247E, a.vqshl_s32(q1, q15, q6)); |
| 144 | |
| 145 | CHECK_ENCODING(0xF264C560, a.vrshl_s32(q14, q8, q2)); |
| 146 | |
Zhi An Ng | 4ef8d51 | 2021-12-14 15:47:53 -0800 | [diff] [blame] | 147 | CHECK_ENCODING(0xF40B070F, a.vst1_8({d0}, mem[r11])); |
| 148 | CHECK_ENCODING(0xF40B070D, a.vst1_8({d0}, mem[r11]++)); |
Zhi An Ng | 00a929f | 2021-12-14 15:07:34 -0800 | [diff] [blame] | 149 | CHECK_ENCODING(0xF40B0707, a.vst1_8({d0}, mem[r11], r7)); |
| 150 | CHECK_ENCODING(0xF48B000F, a.vst1_8({d0[0]}, mem[r11])); |
| 151 | CHECK_ENCODING(0xF48B00EF, a.vst1_8({d0[7]}, mem[r11])); |
| 152 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vst1_8(d0[8], mem[r11])); |
| 153 | |
Zhi An Ng | 4ef8d51 | 2021-12-14 15:47:53 -0800 | [diff] [blame] | 154 | CHECK_ENCODING(0xF40B074F, a.vst1_16({d0}, mem[r11])); |
| 155 | CHECK_ENCODING(0xF40B074D, a.vst1_16({d0}, mem[r11]++)); |
| 156 | CHECK_ENCODING(0xF40B0747, a.vst1_16({d0}, mem[r11], r7)); |
| 157 | CHECK_ENCODING(0xF48B040F, a.vst1_16({d0[0]}, mem[r11])); |
| 158 | CHECK_ENCODING(0xF48B04CF, a.vst1_16({d0[3]}, mem[r11])); |
| 159 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vst1_16(d0[4], mem[r11])); |
| 160 | |
Zhi An Ng | fe4a750 | 2021-12-09 14:21:57 -0800 | [diff] [blame] | 161 | CHECK_ENCODING(0xF44B0280, a.vst1_32({d16, d19}, mem[r11], r0)); |
| 162 | EXPECT_ERROR(Error::kInvalidRegisterListLength, a.vst1_32({d0, d4}, mem[r11], r0)); |
| 163 | EXPECT_ERROR(Error::kInvalidOperand, a.vst1_32({d16, d19}, mem[r11], sp)); |
| 164 | EXPECT_ERROR(Error::kInvalidOperand, a.vst1_32({d16, d19}, mem[r11], pc)); |
| 165 | CHECK_ENCODING(0xF404168F, a.vst1_32({d1, d3}, mem[r4])); |
| 166 | CHECK_ENCODING(0xF44B0A8D, a.vst1_32({d16, d17}, mem[r11]++)); |
| 167 | CHECK_ENCODING(0xF4CB080F, a.vst1_32({d16[0]}, mem[r11])); |
| 168 | // The surrounding braces are optional, but makes it look closer to native assembly. |
| 169 | CHECK_ENCODING(0xF4CB080F, a.vst1_32(d16[0], mem[r11])); |
Zhi An Ng | 00a929f | 2021-12-14 15:07:34 -0800 | [diff] [blame] | 170 | CHECK_ENCODING(0xF4CB088F, a.vst1_32(d16[1], mem[r11])); |
Zhi An Ng | fe4a750 | 2021-12-09 14:21:57 -0800 | [diff] [blame] | 171 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.vst1_32(d16[2], mem[r11])); |
| 172 | CHECK_ENCODING(0xF4C6C80D, a.vst1_32({d28[0]}, mem[r6]++)); |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 173 | |
Zhi An Ng | 3bdbe9f | 2021-12-14 17:19:31 -0800 | [diff] [blame] | 174 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | TEST(AArch32Assembler, Label) { |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 178 | xnn_code_buffer b; |
| 179 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 180 | Assembler a(&b); |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 181 | |
| 182 | Label l1; |
| 183 | a.add(r0, r0, r0); |
| 184 | |
| 185 | // Branch to unbound label. |
| 186 | auto b1 = a.offset(); |
| 187 | a.beq(l1); |
| 188 | |
| 189 | a.add(r1, r1, r1); |
| 190 | |
| 191 | auto b2 = a.offset(); |
| 192 | a.bne(l1); |
| 193 | |
| 194 | a.add(r2, r2, r2); |
| 195 | |
| 196 | a.bind(l1); |
| 197 | |
| 198 | // Check that b1 and b2 are both patched after binding l1. |
| 199 | EXPECT_INSTR(0x0A000002, *b1); |
| 200 | EXPECT_INSTR(0x1A000000, *b2); |
| 201 | |
| 202 | a.add(r0, r1, r2); |
| 203 | |
| 204 | // Branch to bound label. |
| 205 | auto b3 = a.offset(); |
| 206 | a.bhi(l1); |
| 207 | auto b4 = a.offset(); |
| 208 | a.bhs(l1); |
| 209 | auto b5 = a.offset(); |
| 210 | a.blo(l1); |
Zhi An Ng | b63e84c | 2021-12-16 15:11:37 -0800 | [diff] [blame^] | 211 | auto b6 = a.offset(); |
| 212 | a.b(l1); |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 213 | |
| 214 | EXPECT_INSTR(0x8AFFFFFD, *b3); |
| 215 | EXPECT_INSTR(0x2AFFFFFC, *b4); |
| 216 | EXPECT_INSTR(0x3AFFFFFB, *b5); |
Zhi An Ng | b63e84c | 2021-12-16 15:11:37 -0800 | [diff] [blame^] | 217 | EXPECT_INSTR(0xEAFFFFFA, *b6); |
Zhi An Ng | 65584bd | 2021-12-08 09:30:10 -0800 | [diff] [blame] | 218 | |
| 219 | // Binding a bound label is an error. |
| 220 | a.bind(l1); |
| 221 | EXPECT_ERROR(Error::kLabelAlreadyBound, a.bind(l1)); |
| 222 | |
| 223 | // Check for bind failure due to too many users of label. |
| 224 | Label lfail; |
| 225 | a.reset(); |
| 226 | // Arbitrary high number of users that we probably won't support. |
| 227 | for (int i = 0; i < 1000; i++) { |
| 228 | a.beq(lfail); |
| 229 | } |
| 230 | EXPECT_EQ(Error::kLabelHasTooManyUsers, a.error()); |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 231 | |
Zhi An Ng | 3bdbe9f | 2021-12-14 17:19:31 -0800 | [diff] [blame] | 232 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 233 | } |
| 234 | |
Zhi An Ng | be4e6a5 | 2021-12-16 15:09:27 -0800 | [diff] [blame] | 235 | TEST(AArch32Assembler, Align) { |
| 236 | xnn_code_buffer b; |
| 237 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 238 | Assembler a(&b); |
| 239 | |
| 240 | a.add(r0, r1, r2); |
| 241 | a.align(4); |
| 242 | EXPECT_EQ(0, reinterpret_cast<uintptr_t>(a.offset()) & 0x3); |
| 243 | EXPECT_EQ(4, a.code_size_in_bytes()); |
| 244 | |
| 245 | a.align(8); |
| 246 | EXPECT_EQ(0, reinterpret_cast<uintptr_t>(a.offset()) & 0x7); |
| 247 | EXPECT_EQ(8, a.code_size_in_bytes()); |
| 248 | |
| 249 | a.add(r0, r1, r2); |
| 250 | a.align(8); |
| 251 | EXPECT_EQ(0, reinterpret_cast<uintptr_t>(a.offset()) & 0x7); |
| 252 | EXPECT_EQ(16, a.code_size_in_bytes()); |
| 253 | |
| 254 | a.add(r0, r1, r2); |
| 255 | EXPECT_EQ(20, a.code_size_in_bytes()); |
| 256 | |
| 257 | a.align(16); |
| 258 | EXPECT_EQ(0, reinterpret_cast<uintptr_t>(a.offset()) & 0xF); |
| 259 | EXPECT_EQ(32, a.code_size_in_bytes()); |
| 260 | |
| 261 | a.add(r0, r1, r2); |
| 262 | a.add(r0, r1, r2); |
| 263 | EXPECT_EQ(40, a.code_size_in_bytes()); |
| 264 | |
| 265 | a.align(16); |
| 266 | EXPECT_EQ(0, reinterpret_cast<uintptr_t>(a.offset()) & 0xF); |
| 267 | EXPECT_EQ(48, a.code_size_in_bytes()); |
| 268 | |
| 269 | // Not power-of-two. |
| 270 | EXPECT_ERROR(Error::kInvalidOperand, a.align(6)); |
| 271 | // Is power-of-two but is not a multiple of instruction size. |
| 272 | EXPECT_ERROR(Error::kInvalidOperand, a.align(2)); |
| 273 | |
| 274 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 275 | } |
| 276 | |
Zhi An Ng | 512d44b | 2021-12-06 11:42:55 -0800 | [diff] [blame] | 277 | TEST(AArch32Assembler, CoreRegisterList) { |
| 278 | EXPECT_EQ(0x3, CoreRegisterList({r0, r1})); |
| 279 | EXPECT_EQ(0xFC00, CoreRegisterList({r10, r11, r12, r13, r14, r15})); |
| 280 | |
| 281 | EXPECT_FALSE(CoreRegisterList({}).has_more_than_one_register()); |
| 282 | EXPECT_FALSE(CoreRegisterList({r0}).has_more_than_one_register()); |
| 283 | EXPECT_FALSE(CoreRegisterList({r1}).has_more_than_one_register()); |
| 284 | EXPECT_TRUE(CoreRegisterList({r0, r1}).has_more_than_one_register()); |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 285 | } |
Zhi An Ng | c9ffad7 | 2021-12-07 14:28:21 -0800 | [diff] [blame] | 286 | |
Zhi An Ng | 68c27d3 | 2021-12-08 10:58:34 -0800 | [diff] [blame] | 287 | TEST(AArch32Assembler, ConsecutiveRegisterList) { |
| 288 | SRegisterList s1 = SRegisterList(s0, s9); |
| 289 | EXPECT_EQ(s1.start, s0); |
| 290 | EXPECT_EQ(s1.length, 10); |
| 291 | |
| 292 | DRegisterList d1 = DRegisterList(d4, d5); |
| 293 | EXPECT_EQ(d1.start, d4); |
| 294 | EXPECT_EQ(d1.length, 2); |
| 295 | } |
| 296 | |
Zhi An Ng | c9ffad7 | 2021-12-07 14:28:21 -0800 | [diff] [blame] | 297 | TEST(AArch32Assembler, MemOperand) { |
| 298 | EXPECT_EQ(MemOperand(r0, 4, AddressingMode::kOffset), (mem[r0, 4])); |
| 299 | } |
Zhi An Ng | c9f70f7 | 2021-12-09 09:33:17 -0800 | [diff] [blame] | 300 | |
| 301 | TEST(AArch32Assembler, DRegisterLane) { |
| 302 | EXPECT_EQ((DRegisterLane{2, 0}), d2[0]); |
| 303 | EXPECT_EQ((DRegisterLane{2, 1}), d2[1]); |
| 304 | } |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 305 | |
| 306 | TEST(AArch32Assembler, CodeBufferOverflow) { |
| 307 | xnn_code_buffer b; |
| 308 | xnn_allocate_code_memory(&b, 4); |
| 309 | Assembler a(&b); |
| 310 | a.add(r0, r0, 2); |
| 311 | EXPECT_EQ(Error::kNoError, a.error()); |
| 312 | |
| 313 | a.bx(lr); |
| 314 | EXPECT_EQ(Error::kOutOfMemory, a.error()); |
Zhi An Ng | 3bdbe9f | 2021-12-14 17:19:31 -0800 | [diff] [blame] | 315 | |
| 316 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 317 | } |
| 318 | |
| 319 | TEST(AArch32Assembler, AllocateAndRelease) { |
| 320 | xnn_code_buffer b; |
| 321 | ASSERT_EQ(xnn_status_success, xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE)); |
| 322 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | #if XNN_ARCH_ARM |
| 326 | TEST(AArch32Assembler, JitAllocCodeBuffer) { |
| 327 | typedef uint32_t (*Func)(uint32_t); |
| 328 | |
| 329 | xnn_code_buffer b; |
| 330 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 331 | |
| 332 | Assembler a(&b); |
| 333 | a.add(r0, r0, 2).bx(lr); |
| 334 | |
| 335 | Func fn = reinterpret_cast<Func>(a.finalize()); |
| 336 | |
| 337 | ASSERT_EQ(3, fn(1)); |
| 338 | |
Zhi An Ng | 3bdbe9f | 2021-12-14 17:19:31 -0800 | [diff] [blame] | 339 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
Zhi An Ng | 6883abb | 2021-12-14 10:13:18 -0800 | [diff] [blame] | 340 | } |
| 341 | #endif |
Zhi An Ng | b559fe9 | 2021-12-06 09:25:38 -0800 | [diff] [blame] | 342 | } // namespace aarch32 |
| 343 | } // namespace xnnpack |