This source file includes following definitions.
- insn_format_to_type
- read_instructions
- cmpformat
- print_formats
- cmp_long_insn
- print_long_insn
- print_opcode
- add_to_group
- cmpopcode
- print_opcode_table
- print_opcode_table_offsets
- main
1
2
3
4
5
6
7
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13
14 #define STRING_SIZE_MAX 20
15
16 struct insn_type {
17 unsigned char byte;
18 unsigned char mask;
19 char **format;
20 };
21
22 struct insn {
23 struct insn_type *type;
24 char opcode[STRING_SIZE_MAX];
25 char name[STRING_SIZE_MAX];
26 char upper[STRING_SIZE_MAX];
27 char format[STRING_SIZE_MAX];
28 unsigned int name_len;
29 };
30
31 struct insn_group {
32 struct insn_type *type;
33 int offset;
34 int count;
35 char opcode[2];
36 };
37
38 struct insn_format {
39 char *format;
40 int type;
41 };
42
43 struct gen_opcode {
44 struct insn *insn;
45 int nr;
46 struct insn_group *group;
47 int nr_groups;
48 };
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 static struct insn_type insn_type_table[] = {
67 {
68 .byte = 0,
69 .mask = 0xff,
70 .format = (char *[]) {
71 "MII",
72 "RR",
73 "RS",
74 "RSI",
75 "RX",
76 "SI",
77 "SMI",
78 "SS",
79 NULL,
80 },
81 },
82 {
83 .byte = 1,
84 .mask = 0x0f,
85 .format = (char *[]) {
86 "RI",
87 "RIL",
88 "SSF",
89 NULL,
90 },
91 },
92 {
93 .byte = 1,
94 .mask = 0xff,
95 .format = (char *[]) {
96 "E",
97 "IE",
98 "RRE",
99 "RRF",
100 "RRR",
101 "S",
102 "SIL",
103 "SSE",
104 NULL,
105 },
106 },
107 {
108 .byte = 5,
109 .mask = 0xff,
110 .format = (char *[]) {
111 "RIE",
112 "RIS",
113 "RRS",
114 "RSE",
115 "RSL",
116 "RSY",
117 "RXE",
118 "RXF",
119 "RXY",
120 "SIY",
121 "VRI",
122 "VRR",
123 "VRS",
124 "VRV",
125 "VRX",
126 "VSI",
127 NULL,
128 },
129 },
130 };
131
132 static struct insn_type *insn_format_to_type(char *format)
133 {
134 char tmp[STRING_SIZE_MAX];
135 char *base_format, **ptr;
136 int i;
137
138 strcpy(tmp, format);
139 base_format = tmp;
140 base_format = strsep(&base_format, "_");
141 for (i = 0; i < sizeof(insn_type_table) / sizeof(insn_type_table[0]); i++) {
142 ptr = insn_type_table[i].format;
143 while (*ptr) {
144 if (!strcmp(base_format, *ptr))
145 return &insn_type_table[i];
146 ptr++;
147 }
148 }
149 exit(EXIT_FAILURE);
150 }
151
152 static void read_instructions(struct gen_opcode *desc)
153 {
154 struct insn insn;
155 int rc, i;
156
157 while (1) {
158 rc = scanf("%s %s %s", insn.opcode, insn.name, insn.format);
159 if (rc == EOF)
160 break;
161 if (rc != 3)
162 exit(EXIT_FAILURE);
163 insn.type = insn_format_to_type(insn.format);
164 insn.name_len = strlen(insn.name);
165 for (i = 0; i <= insn.name_len; i++)
166 insn.upper[i] = toupper((unsigned char)insn.name[i]);
167 desc->nr++;
168 desc->insn = realloc(desc->insn, desc->nr * sizeof(*desc->insn));
169 if (!desc->insn)
170 exit(EXIT_FAILURE);
171 desc->insn[desc->nr - 1] = insn;
172 }
173 }
174
175 static int cmpformat(const void *a, const void *b)
176 {
177 return strcmp(((struct insn *)a)->format, ((struct insn *)b)->format);
178 }
179
180 static void print_formats(struct gen_opcode *desc)
181 {
182 char *format;
183 int i, count;
184
185 qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmpformat);
186 format = "";
187 count = 0;
188 printf("enum {\n");
189 for (i = 0; i < desc->nr; i++) {
190 if (!strcmp(format, desc->insn[i].format))
191 continue;
192 count++;
193 format = desc->insn[i].format;
194 printf("\tINSTR_%s,\n", format);
195 }
196 printf("}; /* %d */\n\n", count);
197 }
198
199 static int cmp_long_insn(const void *a, const void *b)
200 {
201 return strcmp(((struct insn *)a)->name, ((struct insn *)b)->name);
202 }
203
204 static void print_long_insn(struct gen_opcode *desc)
205 {
206 struct insn *insn;
207 int i, count;
208
209 qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmp_long_insn);
210 count = 0;
211 printf("enum {\n");
212 for (i = 0; i < desc->nr; i++) {
213 insn = &desc->insn[i];
214 if (insn->name_len < 6)
215 continue;
216 printf("\tLONG_INSN_%s,\n", insn->upper);
217 count++;
218 }
219 printf("}; /* %d */\n\n", count);
220
221 printf("#define LONG_INSN_INITIALIZER { \\\n");
222 for (i = 0; i < desc->nr; i++) {
223 insn = &desc->insn[i];
224 if (insn->name_len < 6)
225 continue;
226 printf("\t[LONG_INSN_%s] = \"%s\", \\\n", insn->upper, insn->name);
227 }
228 printf("}\n\n");
229 }
230
231 static void print_opcode(struct insn *insn, int nr)
232 {
233 char *opcode;
234
235 opcode = insn->opcode;
236 if (insn->type->byte != 0)
237 opcode += 2;
238 printf("\t[%4d] = { .opfrag = 0x%s, .format = INSTR_%s, ", nr, opcode, insn->format);
239 if (insn->name_len < 6)
240 printf(".name = \"%s\" ", insn->name);
241 else
242 printf(".offset = LONG_INSN_%s ", insn->upper);
243 printf("}, \\\n");
244 }
245
246 static void add_to_group(struct gen_opcode *desc, struct insn *insn, int offset)
247 {
248 struct insn_group *group;
249
250 group = desc->group ? &desc->group[desc->nr_groups - 1] : NULL;
251 if (group && (!strncmp(group->opcode, insn->opcode, 2) || group->type->byte == 0)) {
252 group->count++;
253 return;
254 }
255 desc->nr_groups++;
256 desc->group = realloc(desc->group, desc->nr_groups * sizeof(*desc->group));
257 if (!desc->group)
258 exit(EXIT_FAILURE);
259 group = &desc->group[desc->nr_groups - 1];
260 memcpy(group->opcode, insn->opcode, 2);
261 group->type = insn->type;
262 group->offset = offset;
263 group->count = 1;
264 }
265
266 static int cmpopcode(const void *a, const void *b)
267 {
268 return strcmp(((struct insn *)a)->opcode, ((struct insn *)b)->opcode);
269 }
270
271 static void print_opcode_table(struct gen_opcode *desc)
272 {
273 char opcode[2] = "";
274 struct insn *insn;
275 int i, offset;
276
277 qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmpopcode);
278 printf("#define OPCODE_TABLE_INITIALIZER { \\\n");
279 offset = 0;
280 for (i = 0; i < desc->nr; i++) {
281 insn = &desc->insn[i];
282 if (insn->type->byte == 0)
283 continue;
284 add_to_group(desc, insn, offset);
285 if (strncmp(opcode, insn->opcode, 2)) {
286 memcpy(opcode, insn->opcode, 2);
287 printf("\t/* %.2s */ \\\n", opcode);
288 }
289 print_opcode(insn, offset);
290 offset++;
291 }
292 printf("\t/* 1-byte opcode instructions */ \\\n");
293 for (i = 0; i < desc->nr; i++) {
294 insn = &desc->insn[i];
295 if (insn->type->byte != 0)
296 continue;
297 add_to_group(desc, insn, offset);
298 print_opcode(insn, offset);
299 offset++;
300 }
301 printf("}\n\n");
302 }
303
304 static void print_opcode_table_offsets(struct gen_opcode *desc)
305 {
306 struct insn_group *group;
307 int i;
308
309 printf("#define OPCODE_OFFSET_INITIALIZER { \\\n");
310 for (i = 0; i < desc->nr_groups; i++) {
311 group = &desc->group[i];
312 printf("\t{ .opcode = 0x%.2s, .mask = 0x%02x, .byte = %d, .offset = %d, .count = %d }, \\\n",
313 group->opcode, group->type->mask, group->type->byte, group->offset, group->count);
314 }
315 printf("}\n\n");
316 }
317
318 int main(int argc, char **argv)
319 {
320 struct gen_opcode _desc = { 0 };
321 struct gen_opcode *desc = &_desc;
322
323 read_instructions(desc);
324 printf("#ifndef __S390_GENERATED_DIS_DEFS_H__\n");
325 printf("#define __S390_GENERATED_DIS_DEFS_H__\n");
326 printf("/*\n");
327 printf(" * DO NOT MODIFY.\n");
328 printf(" *\n");
329 printf(" * This file was generated by %s\n", __FILE__);
330 printf(" */\n\n");
331 print_formats(desc);
332 print_long_insn(desc);
333 print_opcode_table(desc);
334 print_opcode_table_offsets(desc);
335 printf("#endif\n");
336 exit(EXIT_SUCCESS);
337 }