Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/tools/i965_asm.c
4547 views
1
/*
2
* Copyright © 2018 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 FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
* SOFTWARE.
22
*
23
*/
24
25
#include <stdio.h>
26
#include <getopt.h>
27
#include "i965_asm.h"
28
29
enum opt_output_type {
30
OPT_OUTPUT_HEX,
31
OPT_OUTPUT_C_LITERAL,
32
OPT_OUTPUT_BIN,
33
};
34
35
extern FILE *yyin;
36
struct brw_codegen *p;
37
static enum opt_output_type output_type = OPT_OUTPUT_BIN;
38
char *input_filename = NULL;
39
int errors;
40
41
struct list_head instr_labels;
42
struct list_head target_labels;
43
44
static void
45
print_help(const char *progname, FILE *file)
46
{
47
fprintf(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"
57
"Example:\n"
58
" i965_asm -g kbl input.asm -t hex -o output\n",
59
progname);
60
}
61
62
static uint32_t
63
get_dword(const brw_inst *inst, int idx)
64
{
65
uint32_t dword;
66
memcpy(&dword, (char *)inst + 4 * idx, sizeof(dword));
67
return dword;
68
}
69
70
static void
71
print_instruction(FILE *output, bool compact, const brw_inst *instruction)
72
{
73
int byte_limit;
74
75
byte_limit = (compact == true) ? 8 : 16;
76
77
switch (output_type) {
78
case OPT_OUTPUT_HEX: {
79
fprintf(output, "%02x", ((unsigned char *)instruction)[0]);
80
81
for (unsigned i = 1; i < byte_limit; i++) {
82
fprintf(output, " %02x", ((unsigned char *)instruction)[i]);
83
}
84
break;
85
}
86
case OPT_OUTPUT_C_LITERAL: {
87
fprintf(output, "\t0x%08x,", get_dword(instruction, 0));
88
89
for (unsigned i = 1; i < byte_limit / 4; i++)
90
fprintf(output, " 0x%08x,", get_dword(instruction, i));
91
92
break;
93
}
94
case OPT_OUTPUT_BIN:
95
fwrite(instruction, 1, byte_limit, output);
96
break;
97
}
98
99
if (output_type != OPT_OUTPUT_BIN) {
100
fprintf(output, "\n");
101
}
102
}
103
104
static struct intel_device_info *
105
i965_disasm_init(uint16_t pci_id)
106
{
107
struct intel_device_info *devinfo;
108
109
devinfo = malloc(sizeof *devinfo);
110
if (devinfo == NULL)
111
return NULL;
112
113
if (!intel_get_device_info_from_pci_id(pci_id, devinfo)) {
114
fprintf(stderr, "can't find device information: pci_id=0x%x\n",
115
pci_id);
116
free(devinfo);
117
return NULL;
118
}
119
120
return devinfo;
121
}
122
123
static bool
124
i965_postprocess_labels()
125
{
126
if (p->devinfo->ver < 6) {
127
return true;
128
}
129
130
void *store = p->store;
131
132
struct target_label *tlabel;
133
struct instr_label *ilabel, *s;
134
135
const unsigned to_bytes_scale = brw_jump_scale(p->devinfo);
136
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;
141
142
int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst);
143
relative_offset *= to_bytes_scale;
144
145
unsigned opcode = brw_inst_opcode(p->devinfo, inst);
146
147
if (ilabel->type == INSTR_LABEL_JIP) {
148
switch (opcode) {
149
case BRW_OPCODE_IF:
150
case BRW_OPCODE_ELSE:
151
case BRW_OPCODE_ENDIF:
152
case BRW_OPCODE_WHILE:
153
if (p->devinfo->ver >= 7) {
154
brw_inst_set_jip(p->devinfo, inst, relative_offset);
155
} else if (p->devinfo->ver == 6) {
156
brw_inst_set_gfx6_jump_count(p->devinfo, inst, relative_offset);
157
}
158
break;
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);
163
break;
164
default:
165
fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode);
166
return false;
167
}
168
} else {
169
switch (opcode) {
170
case BRW_OPCODE_IF:
171
case BRW_OPCODE_ELSE:
172
if (p->devinfo->ver > 7) {
173
brw_inst_set_uip(p->devinfo, inst, relative_offset);
174
} else if (p->devinfo->ver == 7) {
175
brw_inst_set_uip(p->devinfo, inst, relative_offset);
176
} else if (p->devinfo->ver == 6) {
177
// Nothing
178
}
179
break;
180
case BRW_OPCODE_WHILE:
181
case BRW_OPCODE_ENDIF:
182
fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n");
183
return false;
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);
188
break;
189
default:
190
fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode);
191
return false;
192
}
193
}
194
195
list_del(&ilabel->link);
196
}
197
}
198
}
199
200
LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) {
201
fprintf(stderr, "Unknown label '%s'\n", ilabel->name);
202
}
203
204
return list_is_empty(&instr_labels);
205
}
206
207
int main(int argc, char **argv)
208
{
209
char *output_file = NULL;
210
char c;
211
FILE *output = stdout;
212
bool help = false, compact = false;
213
void *store;
214
uint64_t pci_id = 0;
215
int offset = 0, err;
216
int start_offset = 0;
217
struct disasm_info *disasm_info;
218
struct intel_device_info *devinfo = NULL;
219
int result = EXIT_FAILURE;
220
list_inithead(&instr_labels);
221
list_inithead(&target_labels);
222
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 },
229
{ NULL, 0, NULL, 0 }
230
};
231
232
while ((c = getopt_long(argc, argv, ":t:g:o:h", i965_asm_opts, NULL)) != -1) {
233
switch (c) {
234
case 'g': {
235
const int id = intel_device_name_to_pci_device_id(optarg);
236
if (id < 0) {
237
fprintf(stderr, "can't parse gen: '%s', expected 3 letter "
238
"platform name\n", optarg);
239
goto end;
240
} else {
241
pci_id = id;
242
}
243
break;
244
}
245
case 'h':
246
help = true;
247
print_help(argv[0], stderr);
248
goto end;
249
case 't': {
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;
256
} else {
257
fprintf(stderr, "invalid value for --type: %s\n", optarg);
258
goto end;
259
}
260
break;
261
}
262
case 'o':
263
output_file = strdup(optarg);
264
break;
265
case 0:
266
break;
267
case ':':
268
fprintf(stderr, "%s: option `-%c' requires an argument\n",
269
argv[0], optopt);
270
goto end;
271
case '?':
272
default:
273
fprintf(stderr, "%s: option `-%c' is invalid: ignored\n",
274
argv[0], optopt);
275
goto end;
276
}
277
}
278
279
if (help || !pci_id) {
280
print_help(argv[0], stderr);
281
goto end;
282
}
283
284
if (!argv[optind]) {
285
fprintf(stderr, "Please specify input file\n");
286
goto end;
287
}
288
289
input_filename = strdup(argv[optind]);
290
yyin = fopen(input_filename, "r");
291
if (!yyin) {
292
fprintf(stderr, "Unable to read input file : %s\n",
293
input_filename);
294
goto end;
295
}
296
297
if (output_file) {
298
output = fopen(output_file, "w");
299
if (!output) {
300
fprintf(stderr, "Couldn't open output file\n");
301
goto end;
302
}
303
}
304
305
devinfo = i965_disasm_init(pci_id);
306
if (!devinfo) {
307
fprintf(stderr, "Unable to allocate memory for "
308
"intel_device_info struct instance.\n");
309
goto end;
310
}
311
312
p = rzalloc(NULL, struct brw_codegen);
313
brw_init_codegen(devinfo, p, p);
314
p->automatic_exec_sizes = false;
315
316
err = yyparse();
317
if (err || errors)
318
goto end;
319
320
if (!i965_postprocess_labels())
321
goto end;
322
323
store = p->store;
324
325
disasm_info = disasm_initialize(p->devinfo, NULL);
326
if (!disasm_info) {
327
fprintf(stderr, "Unable to initialize disasm_info struct instance\n");
328
goto end;
329
}
330
331
if (output_type == OPT_OUTPUT_C_LITERAL)
332
fprintf(output, "{\n");
333
334
brw_validate_instructions(p->devinfo, p->store, 0,
335
p->next_insn_offset, disasm_info);
336
337
const int nr_insn = (p->next_insn_offset - start_offset) / 16;
338
339
if (compact)
340
brw_compact_instructions(p, start_offset, disasm_info);
341
342
for (int i = 0; i < nr_insn; i++) {
343
const brw_inst *insn = store + offset;
344
bool compacted = false;
345
346
if (compact && brw_inst_cmpt_control(p->devinfo, insn)) {
347
offset += 8;
348
compacted = true;
349
} else {
350
offset += 16;
351
}
352
353
print_instruction(output, compacted, insn);
354
}
355
356
ralloc_free(disasm_info);
357
358
if (output_type == OPT_OUTPUT_C_LITERAL)
359
fprintf(output, "}");
360
361
result = EXIT_SUCCESS;
362
goto end;
363
364
end:
365
free(input_filename);
366
free(output_file);
367
368
if (yyin)
369
fclose(yyin);
370
371
if (output)
372
fclose(output);
373
374
if (p)
375
ralloc_free(p);
376
377
if (devinfo)
378
free(devinfo);
379
380
exit(result);
381
}
382
383