xref: /aosp_15_r20/external/mesa3d/src/etnaviv/isa/assembler.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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