Commit | Line | Data |
---|---|---|
a85d7ed0 | 1 | /* s390-mkopc.c -- Generates opcode table out of s390-opc.txt |
060d22b0 | 2 | Copyright 2000, 2001 Free Software Foundation, Inc. |
a85d7ed0 NC |
3 | Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). |
4 | ||
5 | This file is part of GDB, GAS, and the GNU binutils. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
20 | 02111-1307, USA. */ | |
21 | ||
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | ||
26 | /* ARCHBITS_ESA and ARCH_ESAME correspond to the bit numbers defined | |
27 | by s390_opcode_arch_val in include/opcode/s390.h: | |
28 | ARCHBITS_ESAONLY = (1<<S390_OPCODE_ESA) | |
29 | ARCHBITS_ESA = (1<<S390_OPCODE_ESA) + (1<<S390_OPCODE_ESAME) | |
30 | ARCHBITS_ESA = (1<<S390_OPCODE_ESAME). */ | |
31 | #define ARCHBITS_ESAONLY 1 | |
32 | #define ARCHBITS_ESA 3 | |
33 | #define ARCHBITS_ESAME 2 | |
34 | ||
b6849f55 NC |
35 | struct op_struct |
36 | { | |
37 | char opcode[16]; | |
38 | char mnemonic[16]; | |
39 | char format[16]; | |
40 | int archbits; | |
41 | unsigned long long sort_value; | |
42 | int no_nibbles; | |
43 | }; | |
a85d7ed0 NC |
44 | |
45 | struct op_struct *op_array; | |
46 | int max_ops; | |
47 | int no_ops; | |
48 | ||
49 | static void | |
b6849f55 | 50 | createTable (void) |
a85d7ed0 | 51 | { |
b6849f55 NC |
52 | max_ops = 256; |
53 | op_array = malloc (max_ops * sizeof (struct op_struct)); | |
54 | no_ops = 0; | |
a85d7ed0 NC |
55 | } |
56 | ||
b6849f55 NC |
57 | /* `insertOpcode': insert an op_struct into sorted opcode array. */ |
58 | ||
a85d7ed0 | 59 | static void |
b6849f55 | 60 | insertOpcode (char *opcode, char *mnemonic, char *format, int archbits) |
a85d7ed0 | 61 | { |
b6849f55 NC |
62 | char *str; |
63 | unsigned long long sort_value; | |
64 | int no_nibbles; | |
65 | int ix, k; | |
66 | ||
67 | while (no_ops >= max_ops) | |
68 | { | |
69 | max_ops = max_ops * 2; | |
70 | op_array = realloc (op_array, max_ops * sizeof (struct op_struct)); | |
a85d7ed0 | 71 | } |
b6849f55 NC |
72 | |
73 | sort_value = 0; | |
74 | str = opcode; | |
75 | for (ix = 0; ix < 16; ix++) | |
76 | { | |
a85d7ed0 NC |
77 | if (*str >= '0' && *str <= '9') |
78 | sort_value = (sort_value << 4) + (*str - '0'); | |
79 | else if (*str >= 'a' && *str <= 'f') | |
80 | sort_value = (sort_value << 4) + (*str - 'a' + 10); | |
81 | else if (*str >= 'A' && *str <= 'F') | |
82 | sort_value = (sort_value << 4) + (*str - 'A' + 10); | |
83 | else if (*str == '?') | |
84 | sort_value <<= 4; | |
85 | else | |
86 | break; | |
b6849f55 | 87 | str ++; |
a85d7ed0 | 88 | } |
b6849f55 NC |
89 | sort_value <<= 4*(16 - ix); |
90 | no_nibbles = ix; | |
91 | for (ix = 0; ix < no_ops; ix++) | |
92 | if (sort_value > op_array[ix].sort_value) | |
93 | break; | |
94 | for (k = no_ops; k > ix; k--) | |
95 | op_array[k] = op_array[k-1]; | |
96 | strcpy(op_array[ix].opcode, opcode); | |
97 | strcpy(op_array[ix].mnemonic, mnemonic); | |
98 | strcpy(op_array[ix].format, format); | |
99 | op_array[ix].sort_value = sort_value; | |
100 | op_array[ix].no_nibbles = no_nibbles; | |
101 | op_array[ix].archbits = archbits; | |
102 | no_ops++; | |
a85d7ed0 NC |
103 | } |
104 | ||
b6849f55 NC |
105 | static char file_header[] = |
106 | "/* The opcode table. This file was generated by s390-mkopc.\n\n" | |
107 | " The format of the opcode table is:\n\n" | |
108 | " NAME OPCODE MASK OPERANDS\n\n" | |
109 | " Name is the name of the instruction.\n" | |
110 | " OPCODE is the instruction opcode.\n" | |
111 | " MASK is the opcode mask; this is used to tell the disassembler\n" | |
112 | " which bits in the actual opcode must match OPCODE.\n" | |
113 | " OPERANDS is the list of operands.\n\n" | |
114 | " The disassembler reads the table in order and prints the first\n" | |
115 | " instruction which matches. */\n\n" | |
116 | "const struct s390_opcode s390_opcodes[] =\n {\n"; | |
117 | ||
118 | /* `dumpTable': write opcode table. */ | |
a85d7ed0 | 119 | |
a85d7ed0 | 120 | static void |
b6849f55 | 121 | dumpTable (void) |
a85d7ed0 | 122 | { |
b6849f55 NC |
123 | char *str; |
124 | int ix; | |
a85d7ed0 | 125 | |
b6849f55 NC |
126 | /* Write hash table entries (slots). */ |
127 | printf (file_header); | |
128 | ||
129 | for (ix = 0; ix < no_ops; ix++) | |
130 | { | |
131 | printf (" { \"%s\", ", op_array[ix].mnemonic); | |
a85d7ed0 NC |
132 | for (str = op_array[ix].opcode; *str != 0; str++) |
133 | if (*str == '?') | |
134 | *str = '0'; | |
b6849f55 NC |
135 | printf ("OP%i(0x%sLL), ", |
136 | op_array[ix].no_nibbles*4, op_array[ix].opcode); | |
137 | printf ("MASK_%s, INSTR_%s, ", | |
138 | op_array[ix].format, op_array[ix].format); | |
139 | printf ("%i}", op_array[ix].archbits); | |
a85d7ed0 | 140 | if (ix < no_ops-1) |
b6849f55 | 141 | printf (",\n"); |
a85d7ed0 | 142 | else |
b6849f55 | 143 | printf ("\n"); |
a85d7ed0 | 144 | } |
b6849f55 NC |
145 | printf ("};\n\n"); |
146 | printf ("const int s390_num_opcodes =\n"); | |
147 | printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n"); | |
a85d7ed0 NC |
148 | } |
149 | ||
a85d7ed0 | 150 | int |
b6849f55 | 151 | main (void) |
a85d7ed0 | 152 | { |
b6849f55 NC |
153 | char currentLine[256]; |
154 | ||
155 | createTable (); | |
156 | ||
157 | /* Read opcode descriptions from `stdin'. For each mnemonic, | |
158 | make an entry into the opcode table. */ | |
159 | while (fgets (currentLine, sizeof (currentLine), stdin) != NULL) | |
160 | { | |
a85d7ed0 NC |
161 | char opcode[16]; |
162 | char mnemonic[16]; | |
163 | char format[16]; | |
164 | char description[64]; | |
165 | char archtag[16]; | |
166 | int archbits; | |
167 | ||
168 | if (currentLine[0] == '#') | |
169 | continue; | |
b6849f55 NC |
170 | memset (opcode, 0, 8); |
171 | if (sscanf (currentLine, "%15s %15s %15s \"%[^\"]\" %15s", | |
172 | opcode, mnemonic, format, description, archtag) == 5) | |
173 | { | |
174 | if (strcmp (archtag, "esaonly") == 0) | |
175 | archbits = ARCHBITS_ESAONLY; | |
176 | else if (strcmp (archtag, "esa") == 0) | |
177 | archbits = ARCHBITS_ESA; | |
178 | else if (strcmp (archtag, "esame") == 0) | |
179 | archbits = ARCHBITS_ESAME; | |
180 | else | |
181 | archbits = 0; | |
182 | insertOpcode (opcode, mnemonic, format, archbits); | |
183 | } | |
184 | else | |
185 | fprintf (stderr, "Couldn't scan line %s\n", currentLine); | |
a85d7ed0 NC |
186 | } |
187 | ||
b6849f55 NC |
188 | dumpTable (); |
189 | return 0; | |
a85d7ed0 | 190 | } |