1 /*
2 * Copyright (C) 2021 Collabora, Ltd.
3 * Copyright (C) 2019 Ryan Houdek <[email protected]>
4 * Copyright (C) 2014 Rob Clark <[email protected]>
5 * Copyright © 2015 Red Hat
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27 #include <getopt.h>
28 #include <string.h>
29 #include "bifrost/disassemble.h"
30 #include "util/macros.h"
31 #include "valhall/disassemble.h"
32
33 unsigned gpu_id = 0x7212;
34 int verbose = 0;
35
36 #define BI_FOURCC(ch0, ch1, ch2, ch3) \
37 ((uint32_t)(ch0) | (uint32_t)(ch1) << 8 | (uint32_t)(ch2) << 16 | \
38 (uint32_t)(ch3) << 24)
39
40 static void
disassemble(const char * filename)41 disassemble(const char *filename)
42 {
43 FILE *fp = fopen(filename, "rb");
44 assert(fp);
45
46 fseek(fp, 0, SEEK_END);
47 unsigned filesize = ftell(fp);
48 rewind(fp);
49
50 uint32_t *code = malloc(filesize);
51 unsigned res = fread(code, 1, filesize, fp);
52 if (res != filesize) {
53 printf("Couldn't read full file\n");
54 }
55
56 fclose(fp);
57
58 void *entrypoint = code;
59
60 if (filesize && code[0] == BI_FOURCC('M', 'B', 'S', '2')) {
61 for (int i = 0; i < filesize / 4; ++i) {
62 if (code[i] != BI_FOURCC('O', 'B', 'J', 'C'))
63 continue;
64
65 unsigned size = code[i + 1];
66 unsigned offset = i + 2;
67
68 entrypoint = code + offset;
69 filesize = size;
70 }
71 }
72
73 if ((gpu_id >> 12) >= 9)
74 disassemble_valhall(stdout, entrypoint, filesize, verbose);
75 else
76 disassemble_bifrost(stdout, entrypoint, filesize, verbose);
77
78 free(code);
79 }
80
81 int
main(int argc,char ** argv)82 main(int argc, char **argv)
83 {
84 int c;
85
86 if (argc < 2) {
87 printf("Pass a command\n");
88 exit(1);
89 }
90
91 static struct option longopts[] = {
92 {"id", optional_argument, NULL, 'i'},
93 {"gpu", optional_argument, NULL, 'g'},
94 {"verbose", no_argument, &verbose, 'v'},
95 {NULL, 0, NULL, 0},
96 };
97
98 static struct {
99 const char *name;
100 unsigned major, minor;
101 } gpus[] = {
102 {"G71", 6, 0}, {"G72", 6, 2}, {"G51", 7, 0}, {"G76", 7, 1},
103 {"G52", 7, 2}, {"G31", 7, 3}, {"G77", 9, 0}, {"G57", 9, 1},
104 {"G78", 9, 2}, {"G57", 9, 3}, {"G68", 9, 4}, {"G78AE", 9, 5},
105 };
106
107 while ((c = getopt_long(argc, argv, "v:", longopts, NULL)) != -1) {
108
109 switch (c) {
110 case 'i':
111 gpu_id = atoi(optarg);
112
113 if (!gpu_id) {
114 fprintf(stderr, "Expected GPU ID, got %s\n", optarg);
115 return 1;
116 }
117
118 break;
119 case 'g':
120 gpu_id = 0;
121
122 /* Compatibility with the Arm compiler */
123 if (strncmp(optarg, "Mali-", 5) == 0)
124 optarg += 5;
125
126 for (unsigned i = 0; i < ARRAY_SIZE(gpus); ++i) {
127 if (strcmp(gpus[i].name, optarg))
128 continue;
129
130 unsigned major = gpus[i].major;
131 unsigned minor = gpus[i].minor;
132
133 gpu_id = (major << 12) | (minor << 8);
134 break;
135 }
136
137 if (!gpu_id) {
138 fprintf(stderr, "Unknown GPU %s\n", optarg);
139 return 1;
140 }
141
142 break;
143 default:
144 break;
145 }
146 }
147
148 disassemble(argv[optind + 1]);
149 return 0;
150 }
151