1 /*
2 * Copyright © 2024 Igalia S.L.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include <fcntl.h>
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <unistd.h>
10
11 #include "asm.h"
12 #include "isa.h"
13
14 #include "util/u_dynarray.h"
15
16 #include <etnaviv/isa/etnaviv-isa.h>
17
18 struct encoded_instr {
19 uint32_t word[4];
20 };
21
22 static void
pre_instr_cb(void * d,unsigned n,void * instr)23 pre_instr_cb(void *d, unsigned n, void *instr)
24 {
25 uint32_t *dwords = (uint32_t *)instr;
26 printf("%03d [%08x %08x %08x %08x] ", n, dwords[0], dwords[1], dwords[2], dwords[3]);
27 }
28
29 static void
store(const char * filename,void * data,unsigned size)30 store(const char *filename, void *data, unsigned size)
31 {
32 int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
33 if (fd == -1) {
34 fprintf(stderr, "Error opening file (%s)", filename);
35 return;
36 }
37
38 ssize_t bytes_written = write(fd, data, size);
39 if (bytes_written == -1) {
40 fprintf(stderr, "Error writing to file");
41 close(fd);
42 return;
43 }
44
45 close(fd);
46 }
47
48 static void
print_usage()49 print_usage()
50 {
51 printf("Usage: etnaviv-assembler -i FILE -o FILE -s\n");
52 }
53
54 int
main(int argc,char * argv[])55 main(int argc, char *argv[])
56 {
57 bool show_disasm = false;
58 bool dual_16_mode = false;
59 const char *in = NULL;
60 const char *out = NULL;
61
62 int opt = 0;
63 while ((opt = getopt(argc, argv, "i:o:sd")) != -1) {
64 switch (opt) {
65 case 'i':
66 in = optarg;
67 break;
68 case 'o':
69 out = optarg;
70 break;
71 case 's':
72 show_disasm = true;
73 break;
74 case 'd':
75 dual_16_mode = true;
76 break;
77 default:
78 print_usage();
79 exit(EXIT_FAILURE);
80 }
81 }
82
83 if (!in || !out) {
84 print_usage();
85
86 return EXIT_FAILURE;
87 }
88
89 struct etna_asm_result *result = isa_parse_file(in, dual_16_mode);
90
91 if (!result->success) {
92 fprintf(stderr, "Failed to parse %s\n%s\n", in, result->error);
93 isa_asm_result_destroy(result);
94
95 return EXIT_FAILURE;
96 }
97
98 struct util_dynarray bin;
99 util_dynarray_init(&bin, NULL);
100
101 for (unsigned int i = 0; i < result->num_instr; i++) {
102 struct encoded_instr encoded;
103
104 isa_assemble_instruction(encoded.word, &result->instr[i]);
105 util_dynarray_append(&bin, struct encoded_instr, encoded);
106 }
107
108 unsigned int num = util_dynarray_num_elements(&bin, struct encoded_instr);
109 unsigned int size = num * sizeof(struct encoded_instr);
110 void *data = util_dynarray_begin(&bin);
111
112 store(out, data, size);
113
114 if (show_disasm) {
115 static struct isa_decode_options options = {
116 .show_errors = true,
117 .branch_labels = true,
118 .pre_instr_cb = pre_instr_cb,
119 };
120
121 etnaviv_isa_disasm(data, size, stdout, &options);
122 }
123
124 util_dynarray_fini(&bin);
125
126 return EXIT_SUCCESS;
127 }
128