1 /* 2 * Copyright 2012 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 <stdlib.h> 25 #include <stdio.h> 26 #include <stdbool.h> 27 #include "util/ralloc.h" 28 #include "brw_context.h" 29 #include "brw_eu.h" 30 31 static bool 32 test_compact_instruction(struct brw_codegen *p, brw_inst src) 33 { 34 brw_compact_inst dst; 35 memset(&dst, 0xd0, sizeof(dst)); 36 37 if (brw_try_compact_instruction(p->devinfo, &dst, &src)) { 38 brw_inst uncompacted; 39 40 brw_uncompact_instruction(p->devinfo, &uncompacted, &dst); 41 if (memcmp(&uncompacted, &src, sizeof(src))) { 42 brw_debug_compact_uncompact(p->devinfo, &src, &uncompacted); 43 return false; 44 } 45 } else { 46 brw_compact_inst unchanged; 47 memset(&unchanged, 0xd0, sizeof(unchanged)); 48 /* It's not supposed to change dst unless it compacted. */ 49 if (memcmp(&unchanged, &dst, sizeof(dst))) { 50 fprintf(stderr, "Failed to compact, but dst changed\n"); 51 fprintf(stderr, " Instruction: "); 52 brw_disassemble_inst(stderr, p->devinfo, &src, false); 53 return false; 54 } 55 } 56 57 return true; 58 } 59 60 /** 61 * When doing fuzz testing, pad bits won't round-trip. 62 * 63 * This sort of a superset of skip_bit, which is testing for changing bits that 64 * aren't worth testing for fuzzing. We also just want to clear bits that 65 * become meaningless once fuzzing twiddles a related bit. 66 */ 67 static void 68 clear_pad_bits(const struct gen_device_info *devinfo, brw_inst *inst) 69 { 70 if (brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SEND && 71 brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SENDC && 72 brw_inst_opcode(devinfo, inst) != BRW_OPCODE_BREAK && 73 brw_inst_opcode(devinfo, inst) != BRW_OPCODE_CONTINUE && 74 brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE && 75 brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) { 76 brw_inst_set_bits(inst, 127, 111, 0); 77 } 78 } 79 80 static bool 81 skip_bit(const struct gen_device_info *devinfo, brw_inst *src, int bit) 82 { 83 /* pad bit */ 84 if (bit == 7) 85 return true; 86 87 /* The compact bit -- uncompacted can't have it set. */ 88 if (bit == 29) 89 return true; 90 91 /* pad bit */ 92 if (bit == 47) 93 return true; 94 95 /* pad bits */ 96 if (bit >= 90 && bit <= 95) 97 return true; 98 99 /* sometimes these are pad bits. */ 100 if (brw_inst_opcode(devinfo, src) != BRW_OPCODE_SEND && 101 brw_inst_opcode(devinfo, src) != BRW_OPCODE_SENDC && 102 brw_inst_opcode(devinfo, src) != BRW_OPCODE_BREAK && 103 brw_inst_opcode(devinfo, src) != BRW_OPCODE_CONTINUE && 104 brw_inst_src0_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE && 105 brw_inst_src1_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE && 106 bit >= 121) { 107 return true; 108 } 109 110 return false; 111 } 112 113 static bool 114 test_fuzz_compact_instruction(struct brw_codegen *p, brw_inst src) 115 { 116 for (int bit0 = 0; bit0 < 128; bit0++) { 117 if (skip_bit(p->devinfo, &src, bit0)) 118 continue; 119 120 for (int bit1 = 0; bit1 < 128; bit1++) { 121 brw_inst instr = src; 122 uint32_t *bits = (uint32_t *)&instr; 123 124 if (skip_bit(p->devinfo, &src, bit1)) 125 continue; 126 127 bits[bit0 / 32] ^= (1 << (bit0 & 31)); 128 bits[bit1 / 32] ^= (1 << (bit1 & 31)); 129 130 clear_pad_bits(p->devinfo, &instr); 131 132 if (!test_compact_instruction(p, instr)) { 133 printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1); 134 return false; 135 } 136 } 137 } 138 139 return true; 140 } 141 142 static void 143 gen_ADD_GRF_GRF_GRF(struct brw_codegen *p) 144 { 145 struct brw_reg g0 = brw_vec8_grf(0, 0); 146 struct brw_reg g2 = brw_vec8_grf(2, 0); 147 struct brw_reg g4 = brw_vec8_grf(4, 0); 148 149 brw_ADD(p, g0, g2, g4); 150 } 151 152 static void 153 gen_ADD_GRF_GRF_IMM(struct brw_codegen *p) 154 { 155 struct brw_reg g0 = brw_vec8_grf(0, 0); 156 struct brw_reg g2 = brw_vec8_grf(2, 0); 157 158 brw_ADD(p, g0, g2, brw_imm_f(1.0)); 159 } 160 161 static void 162 gen_ADD_GRF_GRF_IMM_d(struct brw_codegen *p) 163 { 164 struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D); 165 struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D); 166 167 brw_ADD(p, g0, g2, brw_imm_d(1)); 168 } 169 170 static void 171 gen_MOV_GRF_GRF(struct brw_codegen *p) 172 { 173 struct brw_reg g0 = brw_vec8_grf(0, 0); 174 struct brw_reg g2 = brw_vec8_grf(2, 0); 175 176 brw_MOV(p, g0, g2); 177 } 178 179 static void 180 gen_ADD_MRF_GRF_GRF(struct brw_codegen *p) 181 { 182 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0); 183 struct brw_reg g2 = brw_vec8_grf(2, 0); 184 struct brw_reg g4 = brw_vec8_grf(4, 0); 185 186 brw_ADD(p, m6, g2, g4); 187 } 188 189 static void 190 gen_ADD_vec1_GRF_GRF_GRF(struct brw_codegen *p) 191 { 192 struct brw_reg g0 = brw_vec1_grf(0, 0); 193 struct brw_reg g2 = brw_vec1_grf(2, 0); 194 struct brw_reg g4 = brw_vec1_grf(4, 0); 195 196 brw_ADD(p, g0, g2, g4); 197 } 198 199 static void 200 gen_PLN_MRF_GRF_GRF(struct brw_codegen *p) 201 { 202 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0); 203 struct brw_reg interp = brw_vec1_grf(2, 0); 204 struct brw_reg g4 = brw_vec8_grf(4, 0); 205 206 brw_PLN(p, m6, interp, g4); 207 } 208 209 static void 210 gen_f0_0_MOV_GRF_GRF(struct brw_codegen *p) 211 { 212 struct brw_reg g0 = brw_vec8_grf(0, 0); 213 struct brw_reg g2 = brw_vec8_grf(2, 0); 214 215 brw_push_insn_state(p); 216 brw_set_default_predicate_control(p, true); 217 brw_MOV(p, g0, g2); 218 brw_pop_insn_state(p); 219 } 220 221 /* The handling of f0.1 vs f0.0 changes between gen6 and gen7. Explicitly test 222 * it, so that we run the fuzzing can run over all the other bits that might 223 * interact with it. 224 */ 225 static void 226 gen_f0_1_MOV_GRF_GRF(struct brw_codegen *p) 227 { 228 struct brw_reg g0 = brw_vec8_grf(0, 0); 229 struct brw_reg g2 = brw_vec8_grf(2, 0); 230 231 brw_push_insn_state(p); 232 brw_set_default_predicate_control(p, true); 233 brw_inst *mov = brw_MOV(p, g0, g2); 234 brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1); 235 brw_pop_insn_state(p); 236 } 237 238 struct { 239 void (*func)(struct brw_codegen *p); 240 } tests[] = { 241 { gen_MOV_GRF_GRF }, 242 { gen_ADD_GRF_GRF_GRF }, 243 { gen_ADD_GRF_GRF_IMM }, 244 { gen_ADD_GRF_GRF_IMM_d }, 245 { gen_ADD_MRF_GRF_GRF }, 246 { gen_ADD_vec1_GRF_GRF_GRF }, 247 { gen_PLN_MRF_GRF_GRF }, 248 { gen_f0_0_MOV_GRF_GRF }, 249 { gen_f0_1_MOV_GRF_GRF }, 250 }; 251 252 static bool 253 run_tests(const struct gen_device_info *devinfo) 254 { 255 bool fail = false; 256 257 for (int i = 0; i < ARRAY_SIZE(tests); i++) { 258 for (int align_16 = 0; align_16 <= 1; align_16++) { 259 struct brw_codegen *p = rzalloc(NULL, struct brw_codegen); 260 brw_init_codegen(devinfo, p, p); 261 262 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 263 if (align_16) 264 brw_set_default_access_mode(p, BRW_ALIGN_16); 265 else 266 brw_set_default_access_mode(p, BRW_ALIGN_1); 267 268 tests[i].func(p); 269 assert(p->nr_insn == 1); 270 271 if (!test_compact_instruction(p, p->store[0])) { 272 fail = true; 273 continue; 274 } 275 276 if (!test_fuzz_compact_instruction(p, p->store[0])) { 277 fail = true; 278 continue; 279 } 280 281 ralloc_free(p); 282 } 283 } 284 285 return fail; 286 } 287 288 int 289 main(int argc, char **argv) 290 { 291 struct gen_device_info *devinfo = calloc(1, sizeof(*devinfo)); 292 devinfo->gen = 6; 293 bool fail = false; 294 295 for (devinfo->gen = 6; devinfo->gen <= 7; devinfo->gen++) { 296 fail |= run_tests(devinfo); 297 } 298 299 return fail; 300 } 301