Zhi An Ng | 109a5eb | 2022-01-20 09:35:12 -0800 | [diff] [blame] | 1 | // Copyright 2022 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 | |
| 6 | #include <xnnpack/aarch64-assembler.h> |
| 7 | #include <xnnpack/allocator.h> |
| 8 | #include <xnnpack/common.h> |
| 9 | |
Zhi An Ng | 0ba29e7 | 2022-01-20 11:26:01 -0800 | [diff] [blame] | 10 | #include "assembler-helpers.h" |
Zhi An Ng | 109a5eb | 2022-01-20 09:35:12 -0800 | [diff] [blame] | 11 | #include <gtest/gtest.h> |
| 12 | |
| 13 | namespace xnnpack { |
| 14 | namespace aarch64 { |
| 15 | |
| 16 | TEST(AArch64Assembler, Initialization) { |
| 17 | xnn_code_buffer b; |
| 18 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 19 | Assembler a(&b); |
| 20 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 21 | } |
| 22 | |
Zhi An Ng | 65ccb13 | 2022-01-20 16:16:47 -0800 | [diff] [blame] | 23 | TEST(AArch64Assembler, BaseInstructionEncoding) { |
| 24 | xnn_code_buffer b; |
| 25 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 26 | Assembler a(&b); |
| 27 | |
Zhi An Ng | 4915509 | 2022-01-21 16:32:57 -0800 | [diff] [blame] | 28 | CHECK_ENCODING(0x91008041, a.add(x1, x2, 32)); |
| 29 | CHECK_ENCODING(0x913FFC41, a.add(x1, x2, 4095)); |
| 30 | EXPECT_ERROR(Error::kInvalidOperand, a.add(x1, x2, 4096)); |
| 31 | |
Zhi An Ng | 658a67d | 2022-01-25 10:55:43 -0800 | [diff] [blame] | 32 | CHECK_ENCODING(0x8B040069, a.add(x9, x3, x4)); |
| 33 | |
Zhi An Ng | 80eac62 | 2022-01-25 10:51:12 -0800 | [diff] [blame] | 34 | CHECK_ENCODING(0xF100081F, a.cmp(x0, 2)); |
| 35 | EXPECT_ERROR(Error::kInvalidOperand, a.cmp(x0, 4096)); |
| 36 | |
Zhi An Ng | 9e51ad6 | 2022-02-03 09:09:59 -0800 | [diff] [blame] | 37 | CHECK_ENCODING(0xEB0C02DF, a.cmp(x22, x12)); |
| 38 | |
Zhi An Ng | 8709ac9 | 2022-01-25 14:52:21 -0800 | [diff] [blame] | 39 | CHECK_ENCODING(0x9A8F322E, a.csel(x14, x17, x15, kLO)); |
| 40 | |
Zhi An Ng | 65ccb13 | 2022-01-20 16:16:47 -0800 | [diff] [blame] | 41 | CHECK_ENCODING(0xA9403FEE, a.ldp(x14, x15, mem[sp])); |
| 42 | CHECK_ENCODING(0xA8C13FEE, a.ldp(x14, x15, mem[sp], 16)); |
| 43 | CHECK_ENCODING(0xA9413FEE, a.ldp(x14, x15, mem[sp, 16])); |
| 44 | CHECK_ENCODING(0xA9603FEE, a.ldp(x14, x15, mem[sp, -512])); |
| 45 | CHECK_ENCODING(0xA95FBFEE, a.ldp(x14, x15, mem[sp, 504])); |
| 46 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(x14, x15, mem[sp], 15)); |
| 47 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(x14, x15, mem[sp], -520)); |
| 48 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(x14, x15, mem[sp], 512)); |
| 49 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(x14, x15, mem[sp, 16], 16)); |
| 50 | |
| 51 | CHECK_ENCODING(0xF9400BE8, a.ldr(x8, mem[sp, 16])); |
| 52 | CHECK_ENCODING(0xF97FFFE8, a.ldr(x8, mem[sp, 32760])); |
| 53 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(x8, mem[sp, -8])); |
| 54 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(x8, mem[sp, 7])); |
| 55 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(x8, mem[sp, 32768])); |
| 56 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(x8, MemOperand(sp, 16, AddressingMode::kPostIndex))); |
| 57 | |
Zhi An Ng | 1738f11 | 2022-02-03 16:08:31 -0800 | [diff] [blame] | 58 | CHECK_ENCODING(0xF8408488, a.ldr(x8, mem[x4], 8)); |
| 59 | CHECK_ENCODING(0xF84FF488, a.ldr(x8, mem[x4], 255)); |
| 60 | CHECK_ENCODING(0xF8500488, a.ldr(x8, mem[x4], -256)); |
| 61 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(x8, mem[x4], 256)); |
| 62 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(x8, mem[x4], -257)); |
| 63 | |
Zhi An Ng | 4decc8e | 2022-02-03 09:32:44 -0800 | [diff] [blame] | 64 | CHECK_ENCODING(0xAA0303E9, a.mov(x9, x3)); |
| 65 | |
Zhi An Ng | c2e2da8 | 2022-01-25 16:51:58 -0800 | [diff] [blame] | 66 | CHECK_ENCODING(0xF98000A0, a.prfm(kPLDL1KEEP, mem[x5])); |
Zhi An Ng | fc67a86 | 2022-01-27 09:12:34 -0800 | [diff] [blame] | 67 | CHECK_ENCODING(0xF98020A0, a.prfm(kPLDL1KEEP, mem[x5, 64])); |
Zhi An Ng | c2e2da8 | 2022-01-25 16:51:58 -0800 | [diff] [blame] | 68 | EXPECT_ERROR(Error::kInvalidOperand, a.prfm(kPLDL1KEEP, mem[x5, -8])); |
| 69 | EXPECT_ERROR(Error::kInvalidOperand, a.prfm(kPLDL1KEEP, mem[x5, 32761])); |
Zhi An Ng | 234d6b4 | 2022-01-20 16:31:33 -0800 | [diff] [blame] | 70 | |
Zhi An Ng | cdfff79 | 2022-01-21 15:01:00 -0800 | [diff] [blame] | 71 | CHECK_ENCODING(0xD65F03C0, a.ret()); |
| 72 | |
Zhi An Ng | 3176868 | 2022-01-21 14:52:05 -0800 | [diff] [blame] | 73 | CHECK_ENCODING(0xCB020083, a.sub(x3, x4, x2)); |
| 74 | |
Zhi An Ng | 8ceeebe | 2022-02-03 09:20:28 -0800 | [diff] [blame] | 75 | CHECK_ENCODING(0xA90457F4, a.stp(x20, x21, mem[sp, 64])); |
| 76 | CHECK_ENCODING(0xA98457F4, a.stp(x20, x21, mem[sp, 64]++)); |
| 77 | CHECK_ENCODING(0xA91FD7F4, a.stp(x20, x21, mem[sp, 504])); |
| 78 | CHECK_ENCODING(0xA92057F4, a.stp(x20, x21, mem[sp, -512])); |
| 79 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(x20, x21, mem[sp, 3])); |
| 80 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(x20, x21, mem[sp, 512])); |
| 81 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(x20, x21, mem[sp, -520])); |
| 82 | |
Zhi An Ng | e2dc2ec | 2022-01-20 17:05:33 -0800 | [diff] [blame] | 83 | CHECK_ENCODING(0xF1008040, a.subs(x0, x2, 32)); |
| 84 | CHECK_ENCODING(0xF13FFC40, a.subs(x0, x2, 4095)); |
| 85 | EXPECT_ERROR(Error::kInvalidOperand, a.subs(x0, x2, -32)); |
| 86 | EXPECT_ERROR(Error::kInvalidOperand, a.subs(x0, x2, 4096)); |
| 87 | |
Zhi An Ng | 3cec451 | 2022-01-25 15:03:42 -0800 | [diff] [blame] | 88 | CHECK_ENCODING(0xF240043F, a.tst(x1, 3)); |
| 89 | CHECK_ENCODING(0xF2400C3F, a.tst(x1, 15)); |
| 90 | CHECK_ENCODING(0xF240103F, a.tst(x1, 31)); |
| 91 | EXPECT_ERROR(Error::kUnimplemented, a.tst(x1, 32)); |
| 92 | |
Zhi An Ng | 65ccb13 | 2022-01-20 16:16:47 -0800 | [diff] [blame] | 93 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 94 | } |
| 95 | |
| 96 | TEST(AArch64Assembler, SIMDInstructionEncoding) { |
Zhi An Ng | 0ba29e7 | 2022-01-20 11:26:01 -0800 | [diff] [blame] | 97 | xnn_code_buffer b; |
| 98 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 99 | Assembler a(&b); |
| 100 | |
Zhi An Ng | 2f24c3e | 2022-01-21 17:14:03 -0800 | [diff] [blame] | 101 | CHECK_ENCODING(0x5E180610, a.dup(d16, v16.d()[1])); |
| 102 | EXPECT_ERROR(Error::kInvalidOperand, a.dup(d16, v16.d()[2])); |
| 103 | EXPECT_ERROR(Error::kInvalidOperand, a.dup(d16, v16.s()[1])); |
| 104 | |
Zhi An Ng | ecfb1f0 | 2022-01-21 14:14:38 -0800 | [diff] [blame] | 105 | CHECK_ENCODING(0x4E25D690, a.fadd(v16.v4s(), v20.v4s(), v5.v4s())); |
| 106 | EXPECT_ERROR(Error::kInvalidOperand, a.fadd(v16.v4s(), v20.v4s(), v5.v2s())); |
| 107 | |
Zhi An Ng | 544d73d | 2022-01-21 14:21:52 -0800 | [diff] [blame] | 108 | CHECK_ENCODING(0x4E30F7E3, a.fmax(v3.v4s(), v31.v4s(), v16.v4s())); |
| 109 | EXPECT_ERROR(Error::kInvalidOperand, a.fmax(v3.v8h(), v31.v4s(), v16.v4s())); |
| 110 | |
| 111 | CHECK_ENCODING(0x4EB1F7C2, a.fmin(v2.v4s(), v30.v4s(), v17.v4s())); |
| 112 | EXPECT_ERROR(Error::kInvalidOperand, a.fmin(v2.v4s(), v30.v16b(), v17.v4s())); |
| 113 | |
Zhi An Ng | 6a1151b | 2022-01-21 13:18:31 -0800 | [diff] [blame] | 114 | CHECK_ENCODING(0x4F801290, a.fmla(v16.v4s(), v20.v4s(), v0.s()[0])); |
| 115 | EXPECT_ERROR(Error::kInvalidOperand, a.fmla(v16.v4s(), v20.v2s(), v0.s()[0])); |
| 116 | EXPECT_ERROR(Error::kInvalidOperand, a.fmla(v16.v2d(), v20.v2d(), v0.s()[0])); |
| 117 | EXPECT_ERROR(Error::kInvalidLaneIndex, a.fmla(v16.v4s(), v20.v4s(), v0.s()[4])); |
| 118 | |
Zhi An Ng | 6e68f54 | 2022-01-20 15:18:57 -0800 | [diff] [blame] | 119 | CHECK_ENCODING(0x0CDF7060, a.ld1({v0.v8b()}, mem[x3], 8)); |
| 120 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v0.v8b()}, mem[x3], 16)); |
| 121 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v0.v16b()}, mem[x3], 8)); |
| 122 | |
| 123 | CHECK_ENCODING(0x0CDFA060, a.ld1({v0.v8b(), v1.v8b()}, mem[x3], 16)); |
| 124 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v0.v8b(), v1.v8b()}, mem[x3], 32)); |
| 125 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v0.v16b(), v1.v16b()}, mem[x3], 16)); |
| 126 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v0.v8b(), v2.v8b()}, mem[x3], 16)); |
| 127 | |
| 128 | CHECK_ENCODING(0x4CDF61F0, a.ld1({v16.v16b(), v17.v16b(), v18.v16b()}, mem[x15], 48)); |
| 129 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v16.v8b(), v17.v16b(), v18.v16b()}, mem[x15], 48)); |
| 130 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v16.v16b(), v17.v16b(), v18.v8b()}, mem[x15], 48)); |
| 131 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v16.v16b(), v17.v16b(), v18.v16b()}, mem[x15], 24)); |
| 132 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1({v16.v8b(), v17.v8b(), v18.v8b()}, mem[x15], 48)); |
| 133 | |
Zhi An Ng | 4a1c6a8 | 2022-01-25 16:05:44 -0800 | [diff] [blame] | 134 | CHECK_ENCODING(0x6D433FEE, a.ldp(d14, d15, mem[sp, 48])); |
| 135 | CHECK_ENCODING(0x6DC33FEE, a.ldp(d14, d15, mem[sp, 48]++)); |
| 136 | CHECK_ENCODING(0x6CC427E8, a.ldp(d8, d9, mem[sp], 64)); |
| 137 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(d14, d15, mem[sp, 7])); |
| 138 | |
Zhi An Ng | 157b0f4 | 2022-01-21 11:30:49 -0800 | [diff] [blame] | 139 | CHECK_ENCODING(0xACC154B4, a.ldp(q20, q21, mem[x5], 32)); |
| 140 | CHECK_ENCODING(0xACE054B4, a.ldp(q20, q21, mem[x5], -1024)); |
| 141 | CHECK_ENCODING(0xACDFD4B4, a.ldp(q20, q21, mem[x5], 1008)); |
| 142 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(q20, q21, mem[x5], 15)); |
| 143 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(q20, q21, mem[x5], -1040)); |
| 144 | EXPECT_ERROR(Error::kInvalidOperand, a.ldp(q20, q21, mem[x5], 1024)); |
| 145 | |
Zhi An Ng | 491e9e0 | 2022-01-24 14:52:37 -0800 | [diff] [blame] | 146 | CHECK_ENCODING(0xFC408460, a.ldr(d0, mem[x3], 8)); |
| 147 | CHECK_ENCODING(0xBC404460, a.ldr(s0, mem[x3], 4)); |
| 148 | |
Zhi An Ng | 157b0f4 | 2022-01-21 11:30:49 -0800 | [diff] [blame] | 149 | CHECK_ENCODING(0x3CC10460, a.ldr(q0, mem[x3], 16)); |
| 150 | CHECK_ENCODING(0x3CCFF460, a.ldr(q0, mem[x3], 255)); |
| 151 | CHECK_ENCODING(0x3CD00460, a.ldr(q0, mem[x3], -256)); |
| 152 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(q0, mem[x3], -257)); |
| 153 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(q0, mem[x3], 256)); |
| 154 | EXPECT_ERROR(Error::kInvalidOperand, a.ldr(q0, mem[x3, 16], 16)); |
| 155 | |
Zhi An Ng | eb7256b | 2022-02-03 16:02:54 -0800 | [diff] [blame] | 156 | CHECK_ENCODING(0x4D40C904, a.ld1r({v4.v4s()}, mem[x8])); |
| 157 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1r({v4.v4s(), v5.v4s()}, mem[x8])); |
| 158 | EXPECT_ERROR(Error::kInvalidOperand, a.ld1r({v4.v4s()}, mem[x8, 16])); |
| 159 | |
Zhi An Ng | 5702efb | 2022-01-20 14:04:20 -0800 | [diff] [blame] | 160 | CHECK_ENCODING(0x4D60C902, a.ld2r({v2.v4s(), v3.v4s()}, mem[x8])); |
| 161 | EXPECT_ERROR(Error::kInvalidOperand, a.ld2r({v2.v4s(), v3.v4s()}, mem[x8, 16])); |
| 162 | EXPECT_ERROR(Error::kInvalidOperand, a.ld2r({v2.v4s(), v4.v4s()}, mem[x8, 16])); |
Zhi An Ng | 6e68f54 | 2022-01-20 15:18:57 -0800 | [diff] [blame] | 163 | EXPECT_ERROR(Error::kInvalidOperand, a.ld2r({v2.v4s(), v3.v8b()}, mem[x8])); |
Zhi An Ng | 5702efb | 2022-01-20 14:04:20 -0800 | [diff] [blame] | 164 | |
Zhi An Ng | 5a5c9e1 | 2022-01-21 16:47:09 -0800 | [diff] [blame] | 165 | CHECK_ENCODING(0x4EB21E50, a.mov(v16.v16b(), v18.v16b())); |
| 166 | CHECK_ENCODING(0x0EB21E50, a.mov(v16.v8b(), v18.v8b())); |
| 167 | EXPECT_ERROR(Error::kInvalidOperand, a.mov(v16.v16b(), v18.v8b())); |
| 168 | |
Zhi An Ng | 65ccb13 | 2022-01-20 16:16:47 -0800 | [diff] [blame] | 169 | CHECK_ENCODING(0x4F000405, a.movi(v5.v4s(), 0)); |
| 170 | CHECK_ENCODING(0x4F008405, a.movi(v5.v8h(), 0)); |
| 171 | CHECK_ENCODING(0x4F00E405, a.movi(v5.v16b(), 0)); |
| 172 | EXPECT_ERROR(Error::kUnimplemented, a.movi(v5.v16b(), 0xFF)); |
Zhi An Ng | 04cdc41 | 2022-01-20 11:37:49 -0800 | [diff] [blame] | 173 | |
Zhi An Ng | 3f34299 | 2022-01-21 14:27:45 -0800 | [diff] [blame] | 174 | CHECK_ENCODING(0x4C82746F, a.st1({v15.v8h()}, mem[x3], x2)); |
| 175 | |
| 176 | CHECK_ENCODING(0x4C95AA8F, a.st1({v15.v4s(), v16.v4s()}, mem[x20], x21)); |
| 177 | EXPECT_ERROR(Error::kInvalidOperand, a.st1({v15.v4s(), v17.v4s()}, mem[x20], x21)); |
| 178 | EXPECT_ERROR(Error::kInvalidOperand, a.st1({v15.v4s(), v16.v8h()}, mem[x20], x21)); |
| 179 | |
| 180 | CHECK_ENCODING(0x4C8E60D0, a.st1({v16.v16b(), v17.v16b(), v18.v16b() }, mem[x6], x14)); |
| 181 | EXPECT_ERROR(Error::kInvalidOperand, a.st1({v15.v16b(), v17.v16b(), v18.v16b()}, mem[x6], x14)); |
| 182 | EXPECT_ERROR(Error::kInvalidOperand, a.st1({v16.v16b(), v17.v16b(), v18.v4s()}, mem[x6], x14)); |
| 183 | |
| 184 | CHECK_ENCODING(0x4C812FB4, a.st1({v20.v2d(), v21.v2d(), v22.v2d(), v23.v2d()}, mem[x29], x1)); |
| 185 | EXPECT_ERROR(Error::kInvalidOperand, a.st1({v20.v2d(), v21.v2d(), v22.v2d(), v23.v2s()}, mem[x29], x1)); |
| 186 | EXPECT_ERROR(Error::kInvalidOperand, a.st1({v20.v2d(), v21.v2d(), v22.v2d(), v27.v2d()}, mem[x29], x1)); |
| 187 | |
Zhi An Ng | 35d8e68 | 2022-01-25 11:40:06 -0800 | [diff] [blame] | 188 | CHECK_ENCODING(0x6D012FEA, a.stp(d10, d11, mem[sp, 16])); |
| 189 | CHECK_ENCODING(0x6D202FEA, a.stp(d10, d11, mem[sp, -512])); |
| 190 | CHECK_ENCODING(0x6D1FAFEA, a.stp(d10, d11, mem[sp, 504])); |
| 191 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(d10, d11, mem[sp, -520])); |
| 192 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(d10, d11, mem[sp, 512])); |
| 193 | |
| 194 | CHECK_ENCODING(0x6D812FEA, a.stp(d10, d11, mem[sp, 16]++)); |
| 195 | |
Zhi An Ng | 048704d | 2022-01-25 15:14:15 -0800 | [diff] [blame] | 196 | CHECK_ENCODING(0xAD0075BC, a.stp(q28, q29, mem[x13])); |
| 197 | CHECK_ENCODING(0xAD80F5BC, a.stp(q28, q29, mem[x13, 16]++)); |
| 198 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(q28, q28, mem[x13, 7])); |
| 199 | |
Zhi An Ng | 5e31395 | 2022-01-21 16:35:36 -0800 | [diff] [blame] | 200 | CHECK_ENCODING(0xAC8144D0, a.stp(q16, q17, mem[x6], 32)); |
| 201 | CHECK_ENCODING(0xAC9FC4D0, a.stp(q16, q17, mem[x6], 1008)); |
| 202 | CHECK_ENCODING(0xACA044D0, a.stp(q16, q17, mem[x6], -1024)); |
| 203 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(q16, q17, mem[x6], 34)); |
| 204 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(q16, q17, mem[x6], 1024)); |
| 205 | EXPECT_ERROR(Error::kInvalidOperand, a.stp(q16, q17, mem[x6], -1040)); |
| 206 | |
Zhi An Ng | 491e9e0 | 2022-01-24 14:52:37 -0800 | [diff] [blame] | 207 | CHECK_ENCODING(0xFC0084D0, a.str(d16, mem[x6], 8)); |
Zhi An Ng | f761632 | 2022-01-21 17:06:31 -0800 | [diff] [blame] | 208 | CHECK_ENCODING(0x3C8104D0, a.str(q16, mem[x6], 16)); |
| 209 | CHECK_ENCODING(0x3C8FF4D0, a.str(q16, mem[x6], 255)); |
| 210 | CHECK_ENCODING(0x3C9004D0, a.str(q16, mem[x6], -256)); |
| 211 | EXPECT_ERROR(Error::kInvalidOperand, a.str(q16, mem[x6], 256)); |
| 212 | EXPECT_ERROR(Error::kInvalidOperand, a.str(q16, mem[x6], -257)); |
| 213 | |
| 214 | CHECK_ENCODING(0xBD0000D0, a.str(s16, mem[x6])); |
| 215 | CHECK_ENCODING(0xBD3FFCD0, a.str(s16, mem[x6, 16380])); |
| 216 | EXPECT_ERROR(Error::kInvalidOperand, a.str(s16, mem[x6, 3])); |
| 217 | EXPECT_ERROR(Error::kInvalidOperand, a.str(s16, mem[x6, -4])); |
| 218 | EXPECT_ERROR(Error::kInvalidOperand, a.str(s16, mem[x6, 16384])); |
| 219 | |
Zhi An Ng | f672851 | 2022-02-03 16:19:49 -0800 | [diff] [blame] | 220 | CHECK_ENCODING(0xBC0044D0, a.str(s16, mem[x6], 4)); |
| 221 | CHECK_ENCODING(0xBC0FF4D0, a.str(s16, mem[x6], 255)); |
| 222 | CHECK_ENCODING(0xBC1004D0, a.str(s16, mem[x6], -256)); |
| 223 | EXPECT_ERROR(Error::kInvalidOperand, a.str(s16, mem[x6], 256)); |
| 224 | EXPECT_ERROR(Error::kInvalidOperand, a.str(s16, mem[x6], -257)); |
| 225 | |
Zhi An Ng | 0ba29e7 | 2022-01-20 11:26:01 -0800 | [diff] [blame] | 226 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 227 | } |
| 228 | |
Zhi An Ng | f67f1be | 2022-01-21 10:06:54 -0800 | [diff] [blame] | 229 | TEST(AArch64Assembler, Label) { |
| 230 | xnn_code_buffer b; |
| 231 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 232 | Assembler a(&b); |
| 233 | |
| 234 | Label l1; |
| 235 | a.movi(v0.v4s(), 0); |
| 236 | |
| 237 | // Branch to unbound label. |
| 238 | auto b1 = a.offset<uint32_t*>(); |
| 239 | a.b_eq(l1); |
| 240 | |
| 241 | a.movi(v1.v4s(), 0); |
| 242 | |
| 243 | auto b2 = a.offset<uint32_t*>(); |
| 244 | a.b_ne(l1); |
| 245 | |
| 246 | a.movi(v2.v4s(), 0); |
| 247 | |
| 248 | a.bind(l1); |
| 249 | |
| 250 | // Check that b1 and b2 are both patched after binding l1. |
| 251 | EXPECT_INSTR(0x54000080, *b1); |
| 252 | EXPECT_INSTR(0x54000041, *b2); |
| 253 | |
| 254 | a.movi(v3, 0); |
| 255 | |
| 256 | // Branch to bound label. |
| 257 | auto b3 = a.offset<uint32_t*>(); |
| 258 | a.b_hi(l1); |
| 259 | auto b4 = a.offset<uint32_t*>(); |
| 260 | a.b_hs(l1); |
| 261 | auto b5 = a.offset<uint32_t*>(); |
| 262 | a.b_lo(l1); |
| 263 | |
| 264 | EXPECT_INSTR(0x54FFFFE8, *b3); |
| 265 | EXPECT_INSTR(0x54FFFFC2, *b4); |
| 266 | EXPECT_INSTR(0x54FFFFA3, *b5); |
| 267 | |
| 268 | // Binding a bound label is an error. |
| 269 | a.bind(l1); |
| 270 | EXPECT_ERROR(Error::kLabelAlreadyBound, a.bind(l1)); |
| 271 | |
| 272 | // Check for bind failure due to too many users of label. |
| 273 | Label lfail; |
| 274 | a.reset(); |
| 275 | // Arbitrary high number of users that we probably won't support. |
| 276 | for (int i = 0; i < 1000; i++) { |
| 277 | a.b_eq(lfail); |
| 278 | } |
| 279 | EXPECT_EQ(Error::kLabelHasTooManyUsers, a.error()); |
| 280 | |
| 281 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 282 | } |
| 283 | |
Zhi An Ng | 0981080 | 2022-01-21 13:46:39 -0800 | [diff] [blame] | 284 | TEST(AArch64Assembler, Tbnz) { |
| 285 | xnn_code_buffer b; |
| 286 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 287 | Assembler a(&b); |
| 288 | |
| 289 | Label l1; |
| 290 | a.movi(v0.v4s(), 0); |
| 291 | |
| 292 | // Branch to unbound label. |
| 293 | auto b1 = a.offset<uint32_t*>(); |
| 294 | a.tbnz(x0, 4, l1); |
| 295 | |
| 296 | a.movi(v1.v4s(), 0); |
| 297 | a.bind(l1); |
| 298 | |
| 299 | EXPECT_INSTR(0x37200040, *b1); |
| 300 | |
| 301 | a.movi(v2.v4s(), 0); |
| 302 | |
| 303 | // Branch to bound label. |
| 304 | auto b2 = a.offset<uint32_t*>(); |
| 305 | a.tbnz(x1, 6, l1); |
| 306 | |
| 307 | EXPECT_INSTR(0x3737FFE1, *b2); |
| 308 | |
| 309 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 310 | } |
| 311 | |
Zhi An Ng | 56e8b91 | 2022-01-21 15:06:20 -0800 | [diff] [blame] | 312 | TEST(AArch64Assembler, Tbz) { |
| 313 | xnn_code_buffer b; |
| 314 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 315 | Assembler a(&b); |
| 316 | |
| 317 | Label l1; |
| 318 | a.movi(v0.v4s(), 0); |
| 319 | |
| 320 | // Branch to unbound label. |
| 321 | auto b1 = a.offset<uint32_t*>(); |
| 322 | a.tbz(x0, 4, l1); |
| 323 | |
| 324 | a.movi(v1.v4s(), 0); |
| 325 | a.bind(l1); |
| 326 | |
| 327 | EXPECT_INSTR(0x36200040, *b1); |
| 328 | |
| 329 | a.movi(v2.v4s(), 0); |
| 330 | |
| 331 | // Branch to bound label. |
| 332 | auto b2 = a.offset<uint32_t*>(); |
| 333 | a.tbz(x1, 6, l1); |
| 334 | |
| 335 | EXPECT_INSTR(0x3637FFE1, *b2); |
| 336 | |
| 337 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 338 | } |
| 339 | |
Zhi An Ng | b10677e | 2022-01-21 16:24:26 -0800 | [diff] [blame] | 340 | TEST(AArch64Assembler, UnconditionalBranch) { |
| 341 | xnn_code_buffer b; |
| 342 | xnn_allocate_code_memory(&b, XNN_DEFAULT_CODE_BUFFER_SIZE); |
| 343 | Assembler a(&b); |
| 344 | |
| 345 | Label l1; |
| 346 | a.movi(v0.v4s(), 0); |
| 347 | |
| 348 | // Branch to unbound label. |
| 349 | auto b1 = a.offset<uint32_t*>(); |
| 350 | a.b(l1); |
| 351 | |
| 352 | a.movi(v1.v4s(), 0); |
| 353 | a.bind(l1); |
| 354 | |
| 355 | EXPECT_INSTR(0x14000002, *b1); |
| 356 | |
| 357 | a.movi(v2.v4s(), 0); |
| 358 | |
| 359 | // Branch to bound label. |
| 360 | auto b2 = a.offset<uint32_t*>(); |
| 361 | a.b(l1); |
| 362 | |
| 363 | EXPECT_INSTR(0x17FFFFFF, *b2); |
| 364 | |
| 365 | ASSERT_EQ(xnn_status_success, xnn_release_code_memory(&b)); |
| 366 | } |
| 367 | |
Zhi An Ng | 109a5eb | 2022-01-20 09:35:12 -0800 | [diff] [blame] | 368 | } // namespace aarch64 |
| 369 | } // namespace xnnpack |