1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Generate opcode table initializers for the in-kernel disassembler.
5 * Copyright IBM Corp. 2017
14 #define STRING_SIZE_MAX 20
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;
32 struct insn_type *type;
46 struct insn_group *group;
51 * Table of instruction format types. Each opcode is defined with at
52 * least one byte (two nibbles), three nibbles, or two bytes (four
54 * The byte member of each instruction format type entry defines
55 * within which byte of an instruction the third (and fourth) nibble
56 * of an opcode can be found. The mask member is the and-mask that
57 * needs to be applied on this byte in order to get the third (and
58 * fourth) nibble of the opcode.
59 * The format array defines all instruction formats (as defined in the
60 * Principles of Operation) which have the same position of the opcode
62 * A special case are instruction formats with 1-byte opcodes. In this
63 * case the byte member always is zero, so that the mask is applied on
64 * the (only) byte that contains the opcode.
66 static struct insn_type insn_type_table[] = {
70 .format = (char *[]) {
85 .format = (char *[]) {
95 .format = (char *[]) {
110 .format = (char *[]) {
132 static struct insn_type *insn_format_to_type(char *format)
134 char tmp[STRING_SIZE_MAX];
135 char *base_format, **ptr;
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;
144 if (!strcmp(base_format, *ptr))
145 return &insn_type_table[i];
152 static void read_instructions(struct gen_opcode *desc)
158 rc = scanf("%s %s %s", insn.opcode, insn.name, insn.format);
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]);
168 desc->insn = realloc(desc->insn, desc->nr * sizeof(*desc->insn));
171 desc->insn[desc->nr - 1] = insn;
175 static int cmpformat(const void *a, const void *b)
177 return strcmp(((struct insn *)a)->format, ((struct insn *)b)->format);
180 static void print_formats(struct gen_opcode *desc)
185 qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmpformat);
189 for (i = 0; i < desc->nr; i++) {
190 if (!strcmp(format, desc->insn[i].format))
193 format = desc->insn[i].format;
194 printf("\tINSTR_%s,\n", format);
196 printf("}; /* %d */\n\n", count);
199 static int cmp_long_insn(const void *a, const void *b)
201 return strcmp(((struct insn *)a)->name, ((struct insn *)b)->name);
204 static void print_long_insn(struct gen_opcode *desc)
209 qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmp_long_insn);
212 for (i = 0; i < desc->nr; i++) {
213 insn = &desc->insn[i];
214 if (insn->name_len < 6)
216 printf("\tLONG_INSN_%s,\n", insn->upper);
219 printf("}; /* %d */\n\n", count);
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)
226 printf("\t[LONG_INSN_%s] = \"%s\", \\\n", insn->upper, insn->name);
231 static void print_opcode(struct insn *insn, int nr)
235 opcode = insn->opcode;
236 if (insn->type->byte != 0)
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);
242 printf(".offset = LONG_INSN_%s ", insn->upper);
246 static void add_to_group(struct gen_opcode *desc, struct insn *insn, int offset)
248 struct insn_group *group;
250 group = desc->group ? &desc->group[desc->nr_groups - 1] : NULL;
251 if (group && (!strncmp(group->opcode, insn->opcode, 2) || group->type->byte == 0)) {
256 desc->group = realloc(desc->group, desc->nr_groups * sizeof(*desc->group));
259 group = &desc->group[desc->nr_groups - 1];
260 memcpy(group->opcode, insn->opcode, 2);
261 group->type = insn->type;
262 group->offset = offset;
266 static int cmpopcode(const void *a, const void *b)
268 return strcmp(((struct insn *)a)->opcode, ((struct insn *)b)->opcode);
271 static void print_opcode_table(struct gen_opcode *desc)
277 qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmpopcode);
278 printf("#define OPCODE_TABLE_INITIALIZER { \\\n");
280 for (i = 0; i < desc->nr; i++) {
281 insn = &desc->insn[i];
282 if (insn->type->byte == 0)
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);
289 print_opcode(insn, offset);
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)
297 add_to_group(desc, insn, offset);
298 print_opcode(insn, offset);
304 static void print_opcode_table_offsets(struct gen_opcode *desc)
306 struct insn_group *group;
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);
318 int main(int argc, char **argv)
320 struct gen_opcode _desc = { 0 };
321 struct gen_opcode *desc = &_desc;
323 read_instructions(desc);
324 printf("#ifndef __S390_GENERATED_DIS_DEFS_H__\n");
325 printf("#define __S390_GENERATED_DIS_DEFS_H__\n");
327 printf(" * DO NOT MODIFY.\n");
329 printf(" * This file was generated by %s\n", __FILE__);
332 print_long_insn(desc);
333 print_opcode_table(desc);
334 print_opcode_table_offsets(desc);