101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2012 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include <stdlib.h>
2501e04c3fSmrg#include <stdio.h>
2601e04c3fSmrg#include <stdbool.h>
2701e04c3fSmrg#include "util/ralloc.h"
2801e04c3fSmrg#include "brw_eu.h"
2901e04c3fSmrg
307ec681f3Smrg#include <gtest/gtest.h>
317ec681f3Smrg
327ec681f3Smrgstruct CompactParams {
337ec681f3Smrg   unsigned verx10;
347ec681f3Smrg   unsigned align;
357ec681f3Smrg};
367ec681f3Smrg
377ec681f3Smrgstd::string
387ec681f3Smrgget_compact_params_name(const testing::TestParamInfo<CompactParams> p)
397ec681f3Smrg{
407ec681f3Smrg   CompactParams params = p.param;
417ec681f3Smrg   std::stringstream ss;
427ec681f3Smrg   ss << params.verx10 << "_";
437ec681f3Smrg   switch (params.align) {
447ec681f3Smrg   case BRW_ALIGN_1:
457ec681f3Smrg      ss << "Align_1";
467ec681f3Smrg      break;
477ec681f3Smrg   case BRW_ALIGN_16:
487ec681f3Smrg      ss << "Align_16";
497ec681f3Smrg      break;
507ec681f3Smrg   default:
517ec681f3Smrg      unreachable("invalid align");
527ec681f3Smrg   }
537ec681f3Smrg   return ss.str();
547ec681f3Smrg}
557ec681f3Smrg
5601e04c3fSmrgstatic bool
5701e04c3fSmrgtest_compact_instruction(struct brw_codegen *p, brw_inst src)
5801e04c3fSmrg{
5901e04c3fSmrg   brw_compact_inst dst;
6001e04c3fSmrg   memset(&dst, 0xd0, sizeof(dst));
6101e04c3fSmrg
6201e04c3fSmrg   if (brw_try_compact_instruction(p->devinfo, &dst, &src)) {
6301e04c3fSmrg      brw_inst uncompacted;
6401e04c3fSmrg
6501e04c3fSmrg      brw_uncompact_instruction(p->devinfo, &uncompacted, &dst);
6601e04c3fSmrg      if (memcmp(&uncompacted, &src, sizeof(src))) {
6701e04c3fSmrg	 brw_debug_compact_uncompact(p->devinfo, &src, &uncompacted);
6801e04c3fSmrg	 return false;
6901e04c3fSmrg      }
7001e04c3fSmrg   } else {
7101e04c3fSmrg      brw_compact_inst unchanged;
7201e04c3fSmrg      memset(&unchanged, 0xd0, sizeof(unchanged));
7301e04c3fSmrg      /* It's not supposed to change dst unless it compacted. */
7401e04c3fSmrg      if (memcmp(&unchanged, &dst, sizeof(dst))) {
7501e04c3fSmrg	 fprintf(stderr, "Failed to compact, but dst changed\n");
7601e04c3fSmrg	 fprintf(stderr, "  Instruction: ");
777ec681f3Smrg	 brw_disassemble_inst(stderr, p->devinfo, &src, false, 0, NULL);
7801e04c3fSmrg	 return false;
7901e04c3fSmrg      }
8001e04c3fSmrg   }
8101e04c3fSmrg
8201e04c3fSmrg   return true;
8301e04c3fSmrg}
8401e04c3fSmrg
8501e04c3fSmrg/**
8601e04c3fSmrg * When doing fuzz testing, pad bits won't round-trip.
8701e04c3fSmrg *
8801e04c3fSmrg * This sort of a superset of skip_bit, which is testing for changing bits that
8901e04c3fSmrg * aren't worth testing for fuzzing.  We also just want to clear bits that
9001e04c3fSmrg * become meaningless once fuzzing twiddles a related bit.
9101e04c3fSmrg */
9201e04c3fSmrgstatic void
937ec681f3Smrgclear_pad_bits(const struct intel_device_info *devinfo, brw_inst *inst)
9401e04c3fSmrg{
9501e04c3fSmrg   if (brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SEND &&
9601e04c3fSmrg       brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SENDC &&
9701e04c3fSmrg       brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE &&
9801e04c3fSmrg       brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
9901e04c3fSmrg      brw_inst_set_bits(inst, 127, 111, 0);
10001e04c3fSmrg   }
10101e04c3fSmrg
1027ec681f3Smrg   if (devinfo->ver == 8 && !devinfo->is_cherryview &&
1037ec681f3Smrg       is_3src(devinfo, brw_inst_opcode(devinfo, inst))) {
10401e04c3fSmrg      brw_inst_set_bits(inst, 105, 105, 0);
10501e04c3fSmrg      brw_inst_set_bits(inst, 84, 84, 0);
10601e04c3fSmrg      brw_inst_set_bits(inst, 36, 35, 0);
10701e04c3fSmrg   }
10801e04c3fSmrg}
10901e04c3fSmrg
11001e04c3fSmrgstatic bool
1117ec681f3Smrgskip_bit(const struct intel_device_info *devinfo, brw_inst *src, int bit)
11201e04c3fSmrg{
11301e04c3fSmrg   /* pad bit */
11401e04c3fSmrg   if (bit == 7)
11501e04c3fSmrg      return true;
11601e04c3fSmrg
11701e04c3fSmrg   /* The compact bit -- uncompacted can't have it set. */
11801e04c3fSmrg   if (bit == 29)
11901e04c3fSmrg      return true;
12001e04c3fSmrg
1217ec681f3Smrg   if (is_3src(devinfo, brw_inst_opcode(devinfo, src))) {
1227ec681f3Smrg      if (devinfo->ver >= 9 || devinfo->is_cherryview) {
12301e04c3fSmrg         if (bit == 127)
12401e04c3fSmrg            return true;
12501e04c3fSmrg      } else {
12601e04c3fSmrg         if (bit >= 126 && bit <= 127)
12701e04c3fSmrg            return true;
12801e04c3fSmrg
12901e04c3fSmrg         if (bit == 105)
13001e04c3fSmrg            return true;
13101e04c3fSmrg
13201e04c3fSmrg         if (bit == 84)
13301e04c3fSmrg            return true;
13401e04c3fSmrg
13501e04c3fSmrg         if (bit >= 35 && bit <= 36)
13601e04c3fSmrg            return true;
13701e04c3fSmrg      }
13801e04c3fSmrg   } else {
13901e04c3fSmrg      if (bit == 47)
14001e04c3fSmrg         return true;
14101e04c3fSmrg
1427ec681f3Smrg      if (devinfo->ver >= 8) {
14301e04c3fSmrg         if (bit == 11)
14401e04c3fSmrg            return true;
14501e04c3fSmrg
14601e04c3fSmrg         if (bit == 95)
14701e04c3fSmrg            return true;
14801e04c3fSmrg      } else {
1497ec681f3Smrg         if (devinfo->ver < 7 && bit == 90)
15001e04c3fSmrg            return true;
15101e04c3fSmrg
15201e04c3fSmrg         if (bit >= 91 && bit <= 95)
15301e04c3fSmrg            return true;
15401e04c3fSmrg      }
15501e04c3fSmrg   }
15601e04c3fSmrg
15701e04c3fSmrg   /* sometimes these are pad bits. */
15801e04c3fSmrg   if (brw_inst_opcode(devinfo, src) != BRW_OPCODE_SEND &&
15901e04c3fSmrg       brw_inst_opcode(devinfo, src) != BRW_OPCODE_SENDC &&
16001e04c3fSmrg       brw_inst_src0_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
16101e04c3fSmrg       brw_inst_src1_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
16201e04c3fSmrg       bit >= 121) {
16301e04c3fSmrg      return true;
16401e04c3fSmrg   }
16501e04c3fSmrg
16601e04c3fSmrg   return false;
16701e04c3fSmrg}
16801e04c3fSmrg
16901e04c3fSmrgstatic bool
17001e04c3fSmrgtest_fuzz_compact_instruction(struct brw_codegen *p, brw_inst src)
17101e04c3fSmrg{
17201e04c3fSmrg   for (int bit0 = 0; bit0 < 128; bit0++) {
17301e04c3fSmrg      if (skip_bit(p->devinfo, &src, bit0))
17401e04c3fSmrg	 continue;
17501e04c3fSmrg
17601e04c3fSmrg      for (int bit1 = 0; bit1 < 128; bit1++) {
17701e04c3fSmrg         brw_inst instr = src;
17801e04c3fSmrg	 uint64_t *bits = instr.data;
17901e04c3fSmrg
18001e04c3fSmrg         if (skip_bit(p->devinfo, &src, bit1))
18101e04c3fSmrg	    continue;
18201e04c3fSmrg
18301e04c3fSmrg	 bits[bit0 / 64] ^= (1ull << (bit0 & 63));
18401e04c3fSmrg	 bits[bit1 / 64] ^= (1ull << (bit1 & 63));
18501e04c3fSmrg
18601e04c3fSmrg         clear_pad_bits(p->devinfo, &instr);
18701e04c3fSmrg
1887ec681f3Smrg         if (!brw_validate_instruction(p->devinfo, &instr, 0, NULL))
1897ec681f3Smrg            continue;
1907ec681f3Smrg
19101e04c3fSmrg	 if (!test_compact_instruction(p, instr)) {
19201e04c3fSmrg	    printf("  twiddled bits for fuzzing %d, %d\n", bit0, bit1);
19301e04c3fSmrg	    return false;
19401e04c3fSmrg	 }
19501e04c3fSmrg      }
19601e04c3fSmrg   }
19701e04c3fSmrg
19801e04c3fSmrg   return true;
19901e04c3fSmrg}
20001e04c3fSmrg
2017ec681f3Smrgclass CompactTestFixture : public testing::TestWithParam<CompactParams> {
2027ec681f3Smrgprotected:
2037ec681f3Smrg   virtual void SetUp() {
2047ec681f3Smrg      CompactParams params = GetParam();
2057ec681f3Smrg      mem_ctx = ralloc_context(NULL);
2067ec681f3Smrg      devinfo = rzalloc(mem_ctx, intel_device_info);
2077ec681f3Smrg      p = rzalloc(mem_ctx, brw_codegen);
2087ec681f3Smrg
2097ec681f3Smrg      devinfo->verx10 = params.verx10;
2107ec681f3Smrg      devinfo->ver = devinfo->verx10 / 10;
2117ec681f3Smrg
2127ec681f3Smrg      brw_init_codegen(devinfo, p, p);
2137ec681f3Smrg      brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
2147ec681f3Smrg      brw_set_default_access_mode(p, params.align);
2157ec681f3Smrg   };
2167ec681f3Smrg
2177ec681f3Smrg   virtual void TearDown() {
2187ec681f3Smrg      EXPECT_EQ(p->nr_insn, 1);
2197ec681f3Smrg      EXPECT_TRUE(test_compact_instruction(p, p->store[0]));
2207ec681f3Smrg      EXPECT_TRUE(test_fuzz_compact_instruction(p, p->store[0]));
2217ec681f3Smrg
2227ec681f3Smrg      ralloc_free(mem_ctx);
2237ec681f3Smrg   };
2247ec681f3Smrg
2257ec681f3Smrg   void *mem_ctx;
2267ec681f3Smrg   intel_device_info *devinfo;
2277ec681f3Smrg   brw_codegen *p;
2287ec681f3Smrg};
2297ec681f3Smrg
2307ec681f3Smrgclass Instructions : public CompactTestFixture {};
2317ec681f3Smrg
2327ec681f3SmrgINSTANTIATE_TEST_CASE_P(
2337ec681f3Smrg   CompactTest,
2347ec681f3Smrg   Instructions,
2357ec681f3Smrg   testing::Values(
2367ec681f3Smrg      CompactParams{ 50,  BRW_ALIGN_1 }, CompactParams{ 50, BRW_ALIGN_16 },
2377ec681f3Smrg      CompactParams{ 60,  BRW_ALIGN_1 }, CompactParams{ 60, BRW_ALIGN_16 },
2387ec681f3Smrg      CompactParams{ 70,  BRW_ALIGN_1 }, CompactParams{ 70, BRW_ALIGN_16 },
2397ec681f3Smrg      CompactParams{ 75,  BRW_ALIGN_1 }, CompactParams{ 75, BRW_ALIGN_16 },
2407ec681f3Smrg      CompactParams{ 80,  BRW_ALIGN_1 }, CompactParams{ 80, BRW_ALIGN_16 },
2417ec681f3Smrg      CompactParams{ 90,  BRW_ALIGN_1 }, CompactParams{ 90, BRW_ALIGN_16 },
2427ec681f3Smrg      CompactParams{ 110, BRW_ALIGN_1 },
2437ec681f3Smrg      CompactParams{ 120, BRW_ALIGN_1 },
2447ec681f3Smrg      CompactParams{ 125, BRW_ALIGN_1 }
2457ec681f3Smrg   ),
2467ec681f3Smrg   get_compact_params_name);
2477ec681f3Smrg
2487ec681f3Smrgclass InstructionsBeforeIvyBridge : public CompactTestFixture {};
2497ec681f3Smrg
2507ec681f3SmrgINSTANTIATE_TEST_CASE_P(
2517ec681f3Smrg   CompactTest,
2527ec681f3Smrg   InstructionsBeforeIvyBridge,
2537ec681f3Smrg   testing::Values(
2547ec681f3Smrg      CompactParams{ 50,  BRW_ALIGN_1 }, CompactParams{ 50, BRW_ALIGN_16 },
2557ec681f3Smrg      CompactParams{ 60,  BRW_ALIGN_1 }, CompactParams{ 60, BRW_ALIGN_16 }
2567ec681f3Smrg   ),
2577ec681f3Smrg   get_compact_params_name);
2587ec681f3Smrg
2597ec681f3Smrg
2607ec681f3SmrgTEST_P(Instructions, ADD_GRF_GRF_GRF)
26101e04c3fSmrg{
26201e04c3fSmrg   struct brw_reg g0 = brw_vec8_grf(0, 0);
26301e04c3fSmrg   struct brw_reg g2 = brw_vec8_grf(2, 0);
26401e04c3fSmrg   struct brw_reg g4 = brw_vec8_grf(4, 0);
26501e04c3fSmrg
26601e04c3fSmrg   brw_ADD(p, g0, g2, g4);
26701e04c3fSmrg}
26801e04c3fSmrg
2697ec681f3SmrgTEST_P(Instructions, ADD_GRF_GRF_IMM)
27001e04c3fSmrg{
27101e04c3fSmrg   struct brw_reg g0 = brw_vec8_grf(0, 0);
27201e04c3fSmrg   struct brw_reg g2 = brw_vec8_grf(2, 0);
27301e04c3fSmrg
27401e04c3fSmrg   brw_ADD(p, g0, g2, brw_imm_f(1.0));
27501e04c3fSmrg}
27601e04c3fSmrg
2777ec681f3SmrgTEST_P(Instructions, ADD_GRF_GRF_IMM_d)
27801e04c3fSmrg{
27901e04c3fSmrg   struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
28001e04c3fSmrg   struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
28101e04c3fSmrg
28201e04c3fSmrg   brw_ADD(p, g0, g2, brw_imm_d(1));
28301e04c3fSmrg}
28401e04c3fSmrg
2857ec681f3SmrgTEST_P(Instructions, MOV_GRF_GRF)
28601e04c3fSmrg{
28701e04c3fSmrg   struct brw_reg g0 = brw_vec8_grf(0, 0);
28801e04c3fSmrg   struct brw_reg g2 = brw_vec8_grf(2, 0);
28901e04c3fSmrg
29001e04c3fSmrg   brw_MOV(p, g0, g2);
29101e04c3fSmrg}
29201e04c3fSmrg
2937ec681f3SmrgTEST_P(InstructionsBeforeIvyBridge, ADD_MRF_GRF_GRF)
29401e04c3fSmrg{
29501e04c3fSmrg   struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
29601e04c3fSmrg   struct brw_reg g2 = brw_vec8_grf(2, 0);
29701e04c3fSmrg   struct brw_reg g4 = brw_vec8_grf(4, 0);
29801e04c3fSmrg
29901e04c3fSmrg   brw_ADD(p, m6, g2, g4);
30001e04c3fSmrg}
30101e04c3fSmrg
3027ec681f3SmrgTEST_P(Instructions, ADD_vec1_GRF_GRF_GRF)
30301e04c3fSmrg{
30401e04c3fSmrg   struct brw_reg g0 = brw_vec1_grf(0, 0);
30501e04c3fSmrg   struct brw_reg g2 = brw_vec1_grf(2, 0);
30601e04c3fSmrg   struct brw_reg g4 = brw_vec1_grf(4, 0);
30701e04c3fSmrg
30801e04c3fSmrg   brw_ADD(p, g0, g2, g4);
30901e04c3fSmrg}
31001e04c3fSmrg
3117ec681f3SmrgTEST_P(InstructionsBeforeIvyBridge, PLN_MRF_GRF_GRF)
31201e04c3fSmrg{
31301e04c3fSmrg   struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
31401e04c3fSmrg   struct brw_reg interp = brw_vec1_grf(2, 0);
31501e04c3fSmrg   struct brw_reg g4 = brw_vec8_grf(4, 0);
31601e04c3fSmrg
31701e04c3fSmrg   brw_PLN(p, m6, interp, g4);
31801e04c3fSmrg}
31901e04c3fSmrg
3207ec681f3SmrgTEST_P(Instructions, f0_0_MOV_GRF_GRF)
32101e04c3fSmrg{
32201e04c3fSmrg   struct brw_reg g0 = brw_vec8_grf(0, 0);
32301e04c3fSmrg   struct brw_reg g2 = brw_vec8_grf(2, 0);
32401e04c3fSmrg
32501e04c3fSmrg   brw_push_insn_state(p);
3267ec681f3Smrg   brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
32701e04c3fSmrg   brw_MOV(p, g0, g2);
32801e04c3fSmrg   brw_pop_insn_state(p);
32901e04c3fSmrg}
33001e04c3fSmrg
3317ec681f3Smrg/* The handling of f0.1 vs f0.0 changes between gfx6 and gfx7.  Explicitly test
33201e04c3fSmrg * it, so that we run the fuzzing can run over all the other bits that might
33301e04c3fSmrg * interact with it.
33401e04c3fSmrg */
3357ec681f3SmrgTEST_P(Instructions, f0_1_MOV_GRF_GRF)
33601e04c3fSmrg{
33701e04c3fSmrg   struct brw_reg g0 = brw_vec8_grf(0, 0);
33801e04c3fSmrg   struct brw_reg g2 = brw_vec8_grf(2, 0);
33901e04c3fSmrg
34001e04c3fSmrg   brw_push_insn_state(p);
3417ec681f3Smrg   brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
34201e04c3fSmrg   brw_inst *mov = brw_MOV(p, g0, g2);
34301e04c3fSmrg   brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1);
34401e04c3fSmrg   brw_pop_insn_state(p);
34501e04c3fSmrg}
346