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