1/* 2 * Copyright © 2019 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <fcntl.h> 25#include <string.h> 26#include <xf86drm.h> 27 28#include <gtest/gtest.h> 29 30#include "dev/gen_device_info.h" 31#include "drm-uapi/i915_drm.h" 32#include "genxml/gen_macros.h" 33#include "util/macros.h" 34 35class gen_mi_builder_test; 36 37struct address { 38 uint32_t gem_handle; 39 uint32_t offset; 40}; 41 42#define __gen_address_type struct address 43#define __gen_user_data ::gen_mi_builder_test 44 45uint64_t __gen_combine_address(gen_mi_builder_test *test, void *location, 46 struct address addr, uint32_t delta); 47void * __gen_get_batch_dwords(gen_mi_builder_test *test, unsigned num_dwords); 48 49struct address 50__gen_address_offset(address addr, uint64_t offset) 51{ 52 addr.offset += offset; 53 return addr; 54} 55 56#if GEN_GEN >= 8 || GEN_IS_HASWELL 57#define RSVD_TEMP_REG 0x2678 /* MI_ALU_REG15 */ 58#else 59#define RSVD_TEMP_REG 0x2430 /* GEN7_3DPRIM_START_VERTEX */ 60#endif 61#define GEN_MI_BUILDER_NUM_ALLOC_GPRS 15 62#define INPUT_DATA_OFFSET 0 63#define OUTPUT_DATA_OFFSET 2048 64 65#include "genxml/genX_pack.h" 66#include "gen_mi_builder.h" 67 68#include <vector> 69 70class gen_mi_builder_test : public ::testing::Test { 71public: 72 gen_mi_builder_test(); 73 ~gen_mi_builder_test(); 74 75 void SetUp(); 76 77 void *emit_dwords(int num_dwords); 78 void submit_batch(); 79 80 inline address in_addr(uint32_t offset) 81 { 82 address addr; 83 addr.gem_handle = data_bo_handle; 84 addr.offset = INPUT_DATA_OFFSET + offset; 85 return addr; 86 } 87 88 inline address out_addr(uint32_t offset) 89 { 90 address addr; 91 addr.gem_handle = data_bo_handle; 92 addr.offset = OUTPUT_DATA_OFFSET + offset; 93 return addr; 94 } 95 96 inline gen_mi_value in_mem64(uint32_t offset) 97 { 98 return gen_mi_mem64(in_addr(offset)); 99 } 100 101 inline gen_mi_value in_mem32(uint32_t offset) 102 { 103 return gen_mi_mem32(in_addr(offset)); 104 } 105 106 inline gen_mi_value out_mem64(uint32_t offset) 107 { 108 return gen_mi_mem64(out_addr(offset)); 109 } 110 111 inline gen_mi_value out_mem32(uint32_t offset) 112 { 113 return gen_mi_mem32(out_addr(offset)); 114 } 115 116 int fd; 117 gen_device_info devinfo; 118 119 uint32_t batch_bo_handle; 120 uint32_t batch_offset; 121 void *batch_map; 122 123 std::vector<drm_i915_gem_relocation_entry> relocs; 124 125 uint32_t data_bo_handle; 126 void *data_map; 127 char *input; 128 char *output; 129 uint64_t canary; 130 131 gen_mi_builder b; 132}; 133 134gen_mi_builder_test::gen_mi_builder_test() : 135 fd(-1) 136{ } 137 138gen_mi_builder_test::~gen_mi_builder_test() 139{ 140 close(fd); 141} 142 143// 1 MB of batch should be enough for anyone, right? 144#define BATCH_BO_SIZE (256 * 4096) 145#define DATA_BO_SIZE 4096 146 147void 148gen_mi_builder_test::SetUp() 149{ 150 drmDevicePtr devices[8]; 151 int max_devices = drmGetDevices2(0, devices, 8); 152 153 int i; 154 for (i = 0; i < max_devices; i++) { 155 if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER && 156 devices[i]->bustype == DRM_BUS_PCI && 157 devices[i]->deviceinfo.pci->vendor_id == 0x8086) { 158 fd = open(devices[i]->nodes[DRM_NODE_RENDER], O_RDWR | O_CLOEXEC); 159 if (fd < 0) 160 continue; 161 162 /* We don't really need to do this when running on hardware because 163 * we can just pull it from the drmDevice. However, without doing 164 * this, intel_dump_gpu gets a bit of heartburn and we can't use the 165 * --device option with it. 166 */ 167 int device_id; 168 drm_i915_getparam getparam = drm_i915_getparam(); 169 getparam.param = I915_PARAM_CHIPSET_ID; 170 getparam.value = &device_id; 171 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, 172 (void *)&getparam), 0) << strerror(errno); 173 174 ASSERT_TRUE(gen_get_device_info(device_id, &devinfo)); 175 if (devinfo.gen != GEN_GEN || devinfo.is_haswell != GEN_IS_HASWELL) { 176 close(fd); 177 fd = -1; 178 continue; 179 } 180 181 182 /* Found a device! */ 183 break; 184 } 185 } 186 ASSERT_TRUE(i < max_devices) << "Failed to find a DRM device"; 187 188 // Create the batch buffer 189 drm_i915_gem_create gem_create = drm_i915_gem_create(); 190 gem_create.size = BATCH_BO_SIZE; 191 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, 192 (void *)&gem_create), 0) << strerror(errno); 193 batch_bo_handle = gem_create.handle; 194 195 drm_i915_gem_caching gem_caching = drm_i915_gem_caching(); 196 gem_caching.handle = batch_bo_handle; 197 gem_caching.caching = I915_CACHING_CACHED; 198 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_CACHING, 199 (void *)&gem_caching), 0) << strerror(errno); 200 201 drm_i915_gem_mmap gem_mmap = drm_i915_gem_mmap(); 202 gem_mmap.handle = batch_bo_handle; 203 gem_mmap.offset = 0; 204 gem_mmap.size = BATCH_BO_SIZE; 205 gem_mmap.flags = 0; 206 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP, 207 (void *)&gem_mmap), 0) << strerror(errno); 208 batch_map = (void *)(uintptr_t)gem_mmap.addr_ptr; 209 210 // Start the batch at zero 211 batch_offset = 0; 212 213 // Create the data buffer 214 gem_create = drm_i915_gem_create(); 215 gem_create.size = DATA_BO_SIZE; 216 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, 217 (void *)&gem_create), 0) << strerror(errno); 218 data_bo_handle = gem_create.handle; 219 220 gem_caching = drm_i915_gem_caching(); 221 gem_caching.handle = data_bo_handle; 222 gem_caching.caching = I915_CACHING_CACHED; 223 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_CACHING, 224 (void *)&gem_caching), 0) << strerror(errno); 225 226 gem_mmap = drm_i915_gem_mmap(); 227 gem_mmap.handle = data_bo_handle; 228 gem_mmap.offset = 0; 229 gem_mmap.size = DATA_BO_SIZE; 230 gem_mmap.flags = 0; 231 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP, 232 (void *)&gem_mmap), 0) << strerror(errno); 233 data_map = (void *)(uintptr_t)gem_mmap.addr_ptr; 234 input = (char *)data_map + INPUT_DATA_OFFSET; 235 output = (char *)data_map + OUTPUT_DATA_OFFSET; 236 237 // Fill the test data with garbage 238 memset(data_map, 139, DATA_BO_SIZE); 239 memset(&canary, 139, sizeof(canary)); 240 241 gen_mi_builder_init(&b, this); 242} 243 244void * 245gen_mi_builder_test::emit_dwords(int num_dwords) 246{ 247 void *ptr = (void *)((char *)batch_map + batch_offset); 248 batch_offset += num_dwords * 4; 249 assert(batch_offset < BATCH_BO_SIZE); 250 return ptr; 251} 252 253void 254gen_mi_builder_test::submit_batch() 255{ 256 gen_mi_builder_emit(&b, GENX(MI_BATCH_BUFFER_END), bbe); 257 258 // Round batch up to an even number of dwords. 259 if (batch_offset & 4) 260 gen_mi_builder_emit(&b, GENX(MI_NOOP), noop); 261 262 drm_i915_gem_exec_object2 objects[2]; 263 memset(objects, 0, sizeof(objects)); 264 265 objects[0].handle = data_bo_handle; 266 objects[0].relocation_count = 0; 267 objects[0].relocs_ptr = 0; 268 objects[0].flags = EXEC_OBJECT_WRITE; 269 objects[0].offset = -1; 270 if (GEN_GEN >= 8) 271 objects[0].flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 272 273 objects[1].handle = batch_bo_handle; 274 objects[1].relocation_count = relocs.size(); 275 objects[1].relocs_ptr = (uintptr_t)(void *)&relocs[0]; 276 objects[1].flags = 0; 277 objects[1].offset = -1; 278 if (GEN_GEN >= 8) 279 objects[1].flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 280 281 drm_i915_gem_execbuffer2 execbuf = drm_i915_gem_execbuffer2(); 282 execbuf.buffers_ptr = (uintptr_t)(void *)objects; 283 execbuf.buffer_count = 2; 284 execbuf.batch_start_offset = 0; 285 execbuf.batch_len = batch_offset; 286 execbuf.flags = I915_EXEC_HANDLE_LUT | I915_EXEC_RENDER; 287 288 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, 289 (void *)&execbuf), 0) << strerror(errno); 290 291 drm_i915_gem_wait gem_wait = drm_i915_gem_wait(); 292 gem_wait.bo_handle = batch_bo_handle; 293 gem_wait.timeout_ns = INT64_MAX; 294 ASSERT_EQ(drmIoctl(fd, DRM_IOCTL_I915_GEM_WAIT, 295 (void *)&gem_wait), 0) << strerror(errno); 296} 297 298uint64_t 299__gen_combine_address(gen_mi_builder_test *test, void *location, 300 address addr, uint32_t delta) 301{ 302 drm_i915_gem_relocation_entry reloc = drm_i915_gem_relocation_entry(); 303 reloc.target_handle = addr.gem_handle == test->data_bo_handle ? 0 : 1; 304 reloc.delta = addr.offset + delta; 305 reloc.offset = (char *)location - (char *)test->batch_map; 306 reloc.presumed_offset = -1; 307 test->relocs.push_back(reloc); 308 309 return reloc.delta; 310} 311 312void * 313__gen_get_batch_dwords(gen_mi_builder_test *test, unsigned num_dwords) 314{ 315 return test->emit_dwords(num_dwords); 316} 317 318#include "genxml/genX_pack.h" 319#include "gen_mi_builder.h" 320 321TEST_F(gen_mi_builder_test, imm_mem) 322{ 323 const uint64_t value = 0x0123456789abcdef; 324 325 gen_mi_store(&b, out_mem64(0), gen_mi_imm(value)); 326 gen_mi_store(&b, out_mem32(8), gen_mi_imm(value)); 327 328 submit_batch(); 329 330 // 64 -> 64 331 EXPECT_EQ(*(uint64_t *)(output + 0), value); 332 333 // 64 -> 32 334 EXPECT_EQ(*(uint32_t *)(output + 8), (uint32_t)value); 335 EXPECT_EQ(*(uint32_t *)(output + 12), (uint32_t)canary); 336} 337 338/* mem -> mem copies are only supported on HSW+ */ 339#if GEN_GEN >= 8 || GEN_IS_HASWELL 340TEST_F(gen_mi_builder_test, mem_mem) 341{ 342 const uint64_t value = 0x0123456789abcdef; 343 *(uint64_t *)input = value; 344 345 gen_mi_store(&b, out_mem64(0), in_mem64(0)); 346 gen_mi_store(&b, out_mem32(8), in_mem64(0)); 347 gen_mi_store(&b, out_mem32(16), in_mem32(0)); 348 gen_mi_store(&b, out_mem64(24), in_mem32(0)); 349 350 submit_batch(); 351 352 // 64 -> 64 353 EXPECT_EQ(*(uint64_t *)(output + 0), value); 354 355 // 64 -> 32 356 EXPECT_EQ(*(uint32_t *)(output + 8), (uint32_t)value); 357 EXPECT_EQ(*(uint32_t *)(output + 12), (uint32_t)canary); 358 359 // 32 -> 32 360 EXPECT_EQ(*(uint32_t *)(output + 16), (uint32_t)value); 361 EXPECT_EQ(*(uint32_t *)(output + 20), (uint32_t)canary); 362 363 // 32 -> 64 364 EXPECT_EQ(*(uint64_t *)(output + 24), (uint64_t)(uint32_t)value); 365} 366#endif 367 368TEST_F(gen_mi_builder_test, imm_reg) 369{ 370 const uint64_t value = 0x0123456789abcdef; 371 372 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(canary)); 373 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(value)); 374 gen_mi_store(&b, out_mem64(0), gen_mi_reg64(RSVD_TEMP_REG)); 375 376 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(canary)); 377 gen_mi_store(&b, gen_mi_reg32(RSVD_TEMP_REG), gen_mi_imm(value)); 378 gen_mi_store(&b, out_mem64(8), gen_mi_reg64(RSVD_TEMP_REG)); 379 380 submit_batch(); 381 382 // 64 -> 64 383 EXPECT_EQ(*(uint64_t *)(output + 0), value); 384 385 // 64 -> 32 386 EXPECT_EQ(*(uint32_t *)(output + 8), (uint32_t)value); 387 EXPECT_EQ(*(uint32_t *)(output + 12), (uint32_t)canary); 388} 389 390TEST_F(gen_mi_builder_test, mem_reg) 391{ 392 const uint64_t value = 0x0123456789abcdef; 393 *(uint64_t *)input = value; 394 395 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(canary)); 396 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), in_mem64(0)); 397 gen_mi_store(&b, out_mem64(0), gen_mi_reg64(RSVD_TEMP_REG)); 398 399 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(canary)); 400 gen_mi_store(&b, gen_mi_reg32(RSVD_TEMP_REG), in_mem64(0)); 401 gen_mi_store(&b, out_mem64(8), gen_mi_reg64(RSVD_TEMP_REG)); 402 403 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(canary)); 404 gen_mi_store(&b, gen_mi_reg32(RSVD_TEMP_REG), in_mem32(0)); 405 gen_mi_store(&b, out_mem64(16), gen_mi_reg64(RSVD_TEMP_REG)); 406 407 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), gen_mi_imm(canary)); 408 gen_mi_store(&b, gen_mi_reg64(RSVD_TEMP_REG), in_mem32(0)); 409 gen_mi_store(&b, out_mem64(24), gen_mi_reg64(RSVD_TEMP_REG)); 410 411 submit_batch(); 412 413 // 64 -> 64 414 EXPECT_EQ(*(uint64_t *)(output + 0), value); 415 416 // 64 -> 32 417 EXPECT_EQ(*(uint32_t *)(output + 8), (uint32_t)value); 418 EXPECT_EQ(*(uint32_t *)(output + 12), (uint32_t)canary); 419 420 // 32 -> 32 421 EXPECT_EQ(*(uint32_t *)(output + 16), (uint32_t)value); 422 EXPECT_EQ(*(uint32_t *)(output + 20), (uint32_t)canary); 423 424 // 32 -> 64 425 EXPECT_EQ(*(uint64_t *)(output + 24), (uint64_t)(uint32_t)value); 426} 427 428TEST_F(gen_mi_builder_test, memset) 429{ 430 const unsigned memset_size = 256; 431 432 gen_mi_memset(&b, out_addr(0), 0xdeadbeef, memset_size); 433 434 submit_batch(); 435 436 uint32_t *out_u32 = (uint32_t *)output; 437 for (unsigned i = 0; i < memset_size / sizeof(*out_u32); i++) 438 EXPECT_EQ(out_u32[i], 0xdeadbeef); 439} 440 441TEST_F(gen_mi_builder_test, memcpy) 442{ 443 const unsigned memcpy_size = 256; 444 445 uint8_t *in_u8 = (uint8_t *)input; 446 for (unsigned i = 0; i < memcpy_size; i++) 447 in_u8[i] = i; 448 449 gen_mi_memcpy(&b, out_addr(0), in_addr(0), 256); 450 451 submit_batch(); 452 453 uint8_t *out_u8 = (uint8_t *)output; 454 for (unsigned i = 0; i < memcpy_size; i++) 455 EXPECT_EQ(out_u8[i], i); 456} 457 458/* Start of MI_MATH section */ 459#if GEN_GEN >= 8 || GEN_IS_HASWELL 460 461/* Test adding of immediates of all kinds including 462 * 463 * - All zeroes 464 * - All ones 465 * - inverted constants 466 */ 467TEST_F(gen_mi_builder_test, add_imm) 468{ 469 const uint64_t value = 0x0123456789abcdef; 470 const uint64_t add = 0xdeadbeefac0ffee2; 471 memcpy(input, &value, sizeof(value)); 472 473 gen_mi_store(&b, out_mem64(0), 474 gen_mi_iadd(&b, in_mem64(0), gen_mi_imm(0))); 475 gen_mi_store(&b, out_mem64(8), 476 gen_mi_iadd(&b, in_mem64(0), gen_mi_imm(-1))); 477 gen_mi_store(&b, out_mem64(16), 478 gen_mi_iadd(&b, in_mem64(0), gen_mi_inot(&b, gen_mi_imm(0)))); 479 gen_mi_store(&b, out_mem64(24), 480 gen_mi_iadd(&b, in_mem64(0), gen_mi_inot(&b, gen_mi_imm(-1)))); 481 gen_mi_store(&b, out_mem64(32), 482 gen_mi_iadd(&b, in_mem64(0), gen_mi_imm(add))); 483 gen_mi_store(&b, out_mem64(40), 484 gen_mi_iadd(&b, in_mem64(0), gen_mi_inot(&b, gen_mi_imm(add)))); 485 gen_mi_store(&b, out_mem64(48), 486 gen_mi_iadd(&b, gen_mi_imm(0), in_mem64(0))); 487 gen_mi_store(&b, out_mem64(56), 488 gen_mi_iadd(&b, gen_mi_imm(-1), in_mem64(0))); 489 gen_mi_store(&b, out_mem64(64), 490 gen_mi_iadd(&b, gen_mi_inot(&b, gen_mi_imm(0)), in_mem64(0))); 491 gen_mi_store(&b, out_mem64(72), 492 gen_mi_iadd(&b, gen_mi_inot(&b, gen_mi_imm(-1)), in_mem64(0))); 493 gen_mi_store(&b, out_mem64(80), 494 gen_mi_iadd(&b, gen_mi_imm(add), in_mem64(0))); 495 gen_mi_store(&b, out_mem64(88), 496 gen_mi_iadd(&b, gen_mi_inot(&b, gen_mi_imm(add)), in_mem64(0))); 497 498 // And som add_imm just for good measure 499 gen_mi_store(&b, out_mem64(96), gen_mi_iadd_imm(&b, in_mem64(0), 0)); 500 gen_mi_store(&b, out_mem64(104), gen_mi_iadd_imm(&b, in_mem64(0), add)); 501 502 submit_batch(); 503 504 EXPECT_EQ(*(uint64_t *)(output + 0), value); 505 EXPECT_EQ(*(uint64_t *)(output + 8), value - 1); 506 EXPECT_EQ(*(uint64_t *)(output + 16), value - 1); 507 EXPECT_EQ(*(uint64_t *)(output + 24), value); 508 EXPECT_EQ(*(uint64_t *)(output + 32), value + add); 509 EXPECT_EQ(*(uint64_t *)(output + 40), value + ~add); 510 EXPECT_EQ(*(uint64_t *)(output + 48), value); 511 EXPECT_EQ(*(uint64_t *)(output + 56), value - 1); 512 EXPECT_EQ(*(uint64_t *)(output + 64), value - 1); 513 EXPECT_EQ(*(uint64_t *)(output + 72), value); 514 EXPECT_EQ(*(uint64_t *)(output + 80), value + add); 515 EXPECT_EQ(*(uint64_t *)(output + 88), value + ~add); 516 EXPECT_EQ(*(uint64_t *)(output + 96), value); 517 EXPECT_EQ(*(uint64_t *)(output + 104), value + add); 518} 519 520TEST_F(gen_mi_builder_test, ilt_uge) 521{ 522 uint64_t values[8] = { 523 0x0123456789abcdef, 524 0xdeadbeefac0ffee2, 525 (uint64_t)-1, 526 1, 527 0, 528 1049571, 529 (uint64_t)-240058, 530 20204184, 531 }; 532 memcpy(input, values, sizeof(values)); 533 534 for (unsigned i = 0; i < ARRAY_SIZE(values); i++) { 535 for (unsigned j = 0; j < ARRAY_SIZE(values); j++) { 536 gen_mi_store(&b, out_mem32(i * 64 + j * 8 + 0), 537 gen_mi_ult(&b, in_mem64(i * 8), in_mem64(j * 8))); 538 gen_mi_store(&b, out_mem32(i * 64 + j * 8 + 4), 539 gen_mi_uge(&b, in_mem64(i * 8), in_mem64(j * 8))); 540 } 541 } 542 543 submit_batch(); 544 545 for (unsigned i = 0; i < ARRAY_SIZE(values); i++) { 546 for (unsigned j = 0; j < ARRAY_SIZE(values); j++) { 547 uint32_t *out_u32 = (uint32_t *)(output + i * 64 + j * 8); 548 EXPECT_EQ(out_u32[0], values[i] < values[j] ? ~0u : 0u); 549 EXPECT_EQ(out_u32[1], values[i] >= values[j] ? ~0u : 0u); 550 } 551 } 552} 553 554TEST_F(gen_mi_builder_test, iand) 555{ 556 const uint64_t values[2] = { 557 0x0123456789abcdef, 558 0xdeadbeefac0ffee2, 559 }; 560 memcpy(input, values, sizeof(values)); 561 562 gen_mi_store(&b, out_mem64(0), gen_mi_iand(&b, in_mem64(0), in_mem64(8))); 563 564 submit_batch(); 565 566 EXPECT_EQ(*(uint64_t *)output, values[0] & values[1]); 567} 568 569TEST_F(gen_mi_builder_test, imul_imm) 570{ 571 uint64_t lhs[2] = { 572 0x0123456789abcdef, 573 0xdeadbeefac0ffee2, 574 }; 575 memcpy(input, lhs, sizeof(lhs)); 576 577 /* Some random 32-bit unsigned integers. The first four have been 578 * hand-chosen just to ensure some good low integers; the rest were 579 * generated with a python script. 580 */ 581 uint32_t rhs[20] = { 582 1, 2, 3, 5, 583 10800, 193, 64, 40, 584 3796, 256, 88, 473, 585 1421, 706, 175, 850, 586 39, 38985, 1941, 17, 587 }; 588 589 for (unsigned i = 0; i < ARRAY_SIZE(lhs); i++) { 590 for (unsigned j = 0; j < ARRAY_SIZE(rhs); j++) { 591 gen_mi_store(&b, out_mem64(i * 160 + j * 8), 592 gen_mi_imul_imm(&b, in_mem64(i * 8), rhs[j])); 593 } 594 } 595 596 submit_batch(); 597 598 for (unsigned i = 0; i < ARRAY_SIZE(lhs); i++) { 599 for (unsigned j = 0; j < ARRAY_SIZE(rhs); j++) { 600 EXPECT_EQ(*(uint64_t *)(output + i * 160 + j * 8), lhs[i] * rhs[j]); 601 } 602 } 603} 604 605TEST_F(gen_mi_builder_test, ishl_imm) 606{ 607 const uint64_t value = 0x0123456789abcdef; 608 memcpy(input, &value, sizeof(value)); 609 610 const unsigned max_shift = 64; 611 612 for (unsigned i = 0; i <= max_shift; i++) 613 gen_mi_store(&b, out_mem64(i * 8), gen_mi_ishl_imm(&b, in_mem64(0), i)); 614 615 submit_batch(); 616 617 for (unsigned i = 0; i <= max_shift; i++) { 618 if (i >= 64) { 619 EXPECT_EQ(*(uint64_t *)(output + i * 8), 0); 620 } else { 621 EXPECT_EQ(*(uint64_t *)(output + i * 8), value << i); 622 } 623 } 624} 625 626TEST_F(gen_mi_builder_test, ushr32_imm) 627{ 628 const uint64_t value = 0x0123456789abcdef; 629 memcpy(input, &value, sizeof(value)); 630 631 const unsigned max_shift = 64; 632 633 for (unsigned i = 0; i <= max_shift; i++) 634 gen_mi_store(&b, out_mem64(i * 8), gen_mi_ushr32_imm(&b, in_mem64(0), i)); 635 636 submit_batch(); 637 638 for (unsigned i = 0; i <= max_shift; i++) { 639 if (i >= 64) { 640 EXPECT_EQ(*(uint64_t *)(output + i * 8), 0); 641 } else { 642 EXPECT_EQ(*(uint64_t *)(output + i * 8), (value >> i) & UINT32_MAX); 643 } 644 } 645} 646 647TEST_F(gen_mi_builder_test, udiv32_imm) 648{ 649 /* Some random 32-bit unsigned integers. The first four have been 650 * hand-chosen just to ensure some good low integers; the rest were 651 * generated with a python script. 652 */ 653 uint32_t values[20] = { 654 1, 2, 3, 5, 655 10800, 193, 64, 40, 656 3796, 256, 88, 473, 657 1421, 706, 175, 850, 658 39, 38985, 1941, 17, 659 }; 660 memcpy(input, values, sizeof(values)); 661 662 for (unsigned i = 0; i < ARRAY_SIZE(values); i++) { 663 for (unsigned j = 0; j < ARRAY_SIZE(values); j++) { 664 gen_mi_store(&b, out_mem32(i * 80 + j * 4), 665 gen_mi_udiv32_imm(&b, in_mem32(i * 4), values[j])); 666 } 667 } 668 669 submit_batch(); 670 671 for (unsigned i = 0; i < ARRAY_SIZE(values); i++) { 672 for (unsigned j = 0; j < ARRAY_SIZE(values); j++) { 673 EXPECT_EQ(*(uint32_t *)(output + i * 80 + j * 4), 674 values[i] / values[j]); 675 } 676 } 677} 678 679#endif /* GEN_GEN >= 8 || GEN_IS_HASWELL */ 680