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