2 * Copyright © 2018 Intel Corporation
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:
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
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 enum opt_output_type
{
36 struct brw_codegen
*p
;
37 static enum opt_output_type output_type
= OPT_OUTPUT_BIN
;
38 char *input_filename
= NULL
;
41 struct list_head instr_labels
;
42 struct list_head target_labels
;
45 print_help(const char *progname
, FILE *file
)
48 "Usage: %s [OPTION] inputfile\n"
49 "Assemble i965 instructions from input file.\n\n"
50 " -h, --help display this help and exit\n"
51 " -t, --type=OUTPUT_TYPE OUTPUT_TYPE can be 'bin' (default if omitted),\n"
52 " 'c_literal', or 'hex'\n"
53 " -o, --output specify output file\n"
54 " --compact print compacted instructions\n"
55 " -g, --gen=platform assemble instructions for given \n"
56 " platform (3 letter platform name)\n"
58 " i965_asm -g kbl input.asm -t hex -o output\n",
63 get_dword(const brw_inst
*inst
, int idx
)
66 memcpy(&dword
, (char *)inst
+ 4 * idx
, sizeof(dword
));
71 print_instruction(FILE *output
, bool compact
, const brw_inst
*instruction
)
75 byte_limit
= (compact
== true) ? 8 : 16;
77 switch (output_type
) {
78 case OPT_OUTPUT_HEX
: {
79 fprintf(output
, "%02x", ((unsigned char *)instruction
)[0]);
81 for (unsigned i
= 1; i
< byte_limit
; i
++) {
82 fprintf(output
, " %02x", ((unsigned char *)instruction
)[i
]);
86 case OPT_OUTPUT_C_LITERAL
: {
87 fprintf(output
, "\t0x%08x,", get_dword(instruction
, 0));
89 for (unsigned i
= 1; i
< byte_limit
/ 4; i
++)
90 fprintf(output
, " 0x%08x,", get_dword(instruction
, i
));
95 fwrite(instruction
, 1, byte_limit
, output
);
99 if (output_type
!= OPT_OUTPUT_BIN
) {
100 fprintf(output
, "\n");
104 static struct gen_device_info
*
105 i965_disasm_init(uint16_t pci_id
)
107 struct gen_device_info
*devinfo
;
109 devinfo
= malloc(sizeof *devinfo
);
113 if (!gen_get_device_info_from_pci_id(pci_id
, devinfo
)) {
114 fprintf(stderr
, "can't find device information: pci_id=0x%x\n",
124 i965_postprocess_labels()
126 if (p
->devinfo
->gen
< 6) {
130 void *store
= p
->store
;
132 struct target_label
*tlabel
;
133 struct instr_label
*ilabel
, *s
;
135 const unsigned to_bytes_scale
= brw_jump_scale(p
->devinfo
);
137 LIST_FOR_EACH_ENTRY(tlabel
, &target_labels
, link
) {
138 LIST_FOR_EACH_ENTRY_SAFE(ilabel
, s
, &instr_labels
, link
) {
139 if (!strcmp(tlabel
->name
, ilabel
->name
)) {
140 brw_inst
*inst
= store
+ ilabel
->offset
;
142 int relative_offset
= (tlabel
->offset
- ilabel
->offset
) / sizeof(brw_inst
);
143 relative_offset
*= to_bytes_scale
;
145 unsigned opcode
= brw_inst_opcode(p
->devinfo
, inst
);
147 if (ilabel
->type
== INSTR_LABEL_JIP
) {
150 case BRW_OPCODE_ELSE
:
151 case BRW_OPCODE_ENDIF
:
152 case BRW_OPCODE_WHILE
:
153 if (p
->devinfo
->gen
>= 7) {
154 brw_inst_set_jip(p
->devinfo
, inst
, relative_offset
);
155 } else if (p
->devinfo
->gen
== 6) {
156 brw_inst_set_gen6_jump_count(p
->devinfo
, inst
, relative_offset
);
159 case BRW_OPCODE_BREAK
:
160 case BRW_OPCODE_HALT
:
161 case BRW_OPCODE_CONTINUE
:
162 brw_inst_set_jip(p
->devinfo
, inst
, relative_offset
);
165 fprintf(stderr
, "Unknown opcode %d with JIP label\n", opcode
);
171 case BRW_OPCODE_ELSE
:
172 if (p
->devinfo
->gen
> 7) {
173 brw_inst_set_uip(p
->devinfo
, inst
, relative_offset
);
174 } else if (p
->devinfo
->gen
== 7) {
175 brw_inst_set_uip(p
->devinfo
, inst
, relative_offset
);
176 } else if (p
->devinfo
->gen
== 6) {
180 case BRW_OPCODE_WHILE
:
181 case BRW_OPCODE_ENDIF
:
182 fprintf(stderr
, "WHILE/ENDIF cannot have UIP offset\n");
184 case BRW_OPCODE_BREAK
:
185 case BRW_OPCODE_CONTINUE
:
186 case BRW_OPCODE_HALT
:
187 brw_inst_set_uip(p
->devinfo
, inst
, relative_offset
);
190 fprintf(stderr
, "Unknown opcode %d with UIP label\n", opcode
);
195 list_del(&ilabel
->link
);
200 LIST_FOR_EACH_ENTRY(ilabel
, &instr_labels
, link
) {
201 fprintf(stderr
, "Unknown label '%s'\n", ilabel
->name
);
204 return list_is_empty(&instr_labels
);
207 int main(int argc
, char **argv
)
209 char *output_file
= NULL
;
211 FILE *output
= stdout
;
212 bool help
= false, compact
= false;
216 int start_offset
= 0;
217 struct disasm_info
*disasm_info
;
218 struct gen_device_info
*devinfo
= NULL
;
219 int result
= EXIT_FAILURE
;
220 list_inithead(&instr_labels
);
221 list_inithead(&target_labels
);
223 const struct option i965_asm_opts
[] = {
224 { "help", no_argument
, (int *) &help
, true },
225 { "type", required_argument
, NULL
, 't' },
226 { "gen", required_argument
, NULL
, 'g' },
227 { "output", required_argument
, NULL
, 'o' },
228 { "compact", no_argument
, (int *) &compact
, true },
232 while ((c
= getopt_long(argc
, argv
, ":t:g:o:h", i965_asm_opts
, NULL
)) != -1) {
235 const int id
= gen_device_name_to_pci_device_id(optarg
);
237 fprintf(stderr
, "can't parse gen: '%s', expected 3 letter "
238 "platform name\n", optarg
);
247 print_help(argv
[0], stderr
);
250 if (strcmp(optarg
, "hex") == 0) {
251 output_type
= OPT_OUTPUT_HEX
;
252 } else if (strcmp(optarg
, "c_literal") == 0) {
253 output_type
= OPT_OUTPUT_C_LITERAL
;
254 } else if (strcmp(optarg
, "bin") == 0) {
255 output_type
= OPT_OUTPUT_BIN
;
257 fprintf(stderr
, "invalid value for --type: %s\n", optarg
);
263 output_file
= strdup(optarg
);
268 fprintf(stderr
, "%s: option `-%c' requires an argument\n",
273 fprintf(stderr
, "%s: option `-%c' is invalid: ignored\n",
279 if (help
|| !pci_id
) {
280 print_help(argv
[0], stderr
);
285 fprintf(stderr
, "Please specify input file\n");
289 input_filename
= strdup(argv
[optind
]);
290 yyin
= fopen(input_filename
, "r");
292 fprintf(stderr
, "Unable to read input file : %s\n",
298 output
= fopen(output_file
, "w");
300 fprintf(stderr
, "Couldn't open output file\n");
305 devinfo
= i965_disasm_init(pci_id
);
307 fprintf(stderr
, "Unable to allocate memory for "
308 "gen_device_info struct instance.\n");
312 p
= rzalloc(NULL
, struct brw_codegen
);
313 brw_init_codegen(devinfo
, p
, p
);
314 p
->automatic_exec_sizes
= false;
320 if (!i965_postprocess_labels())
325 disasm_info
= disasm_initialize(p
->devinfo
, NULL
);
327 fprintf(stderr
, "Unable to initialize disasm_info struct instance\n");
331 if (output_type
== OPT_OUTPUT_C_LITERAL
)
332 fprintf(output
, "{\n");
334 brw_validate_instructions(p
->devinfo
, p
->store
, 0,
335 p
->next_insn_offset
, disasm_info
);
337 const int nr_insn
= (p
->next_insn_offset
- start_offset
) / 16;
340 brw_compact_instructions(p
, start_offset
, disasm_info
);
342 for (int i
= 0; i
< nr_insn
; i
++) {
343 const brw_inst
*insn
= store
+ offset
;
344 bool compacted
= false;
346 if (compact
&& brw_inst_cmpt_control(p
->devinfo
, insn
)) {
353 print_instruction(output
, compacted
, insn
);
356 ralloc_free(disasm_info
);
358 if (output_type
== OPT_OUTPUT_C_LITERAL
)
359 fprintf(output
, "}");
361 result
= EXIT_SUCCESS
;
365 free(input_filename
);