1 /* s390-mkopc.c -- Generates opcode table out of s390-opc.txt 2 Copyright 2000, 2001, 2003 Free Software Foundation, Inc. 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., 51 Franklin Street - Fifth Floor, Boston, MA 20 02110-1301, USA. */ 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 /* Taken from opcodes/s390.h */ 27 enum s390_opcode_mode_val 28 { 29 S390_OPCODE_ESA = 0, 30 S390_OPCODE_ZARCH 31 }; 32 33 enum s390_opcode_cpu_val 34 { 35 S390_OPCODE_G5 = 0, 36 S390_OPCODE_G6, 37 S390_OPCODE_Z900, 38 S390_OPCODE_Z990, 39 S390_OPCODE_Z9_109 40 }; 41 42 struct op_struct 43 { 44 char opcode[16]; 45 char mnemonic[16]; 46 char format[16]; 47 int mode_bits; 48 int min_cpu; 49 50 unsigned long long sort_value; 51 int no_nibbles; 52 }; 53 54 struct op_struct *op_array; 55 int max_ops; 56 int no_ops; 57 58 static void 59 createTable (void) 60 { 61 max_ops = 256; 62 op_array = malloc (max_ops * sizeof (struct op_struct)); 63 no_ops = 0; 64 } 65 66 /* `insertOpcode': insert an op_struct into sorted opcode array. */ 67 68 static void 69 insertOpcode (char *opcode, char *mnemonic, char *format, 70 int min_cpu, int mode_bits) 71 { 72 char *str; 73 unsigned long long sort_value; 74 int no_nibbles; 75 int ix, k; 76 77 while (no_ops >= max_ops) 78 { 79 max_ops = max_ops * 2; 80 op_array = realloc (op_array, max_ops * sizeof (struct op_struct)); 81 } 82 83 sort_value = 0; 84 str = opcode; 85 for (ix = 0; ix < 16; ix++) 86 { 87 if (*str >= '0' && *str <= '9') 88 sort_value = (sort_value << 4) + (*str - '0'); 89 else if (*str >= 'a' && *str <= 'f') 90 sort_value = (sort_value << 4) + (*str - 'a' + 10); 91 else if (*str >= 'A' && *str <= 'F') 92 sort_value = (sort_value << 4) + (*str - 'A' + 10); 93 else if (*str == '?') 94 sort_value <<= 4; 95 else 96 break; 97 str ++; 98 } 99 sort_value <<= 4*(16 - ix); 100 sort_value += (min_cpu << 8) + mode_bits; 101 no_nibbles = ix; 102 for (ix = 0; ix < no_ops; ix++) 103 if (sort_value > op_array[ix].sort_value) 104 break; 105 for (k = no_ops; k > ix; k--) 106 op_array[k] = op_array[k-1]; 107 strcpy(op_array[ix].opcode, opcode); 108 strcpy(op_array[ix].mnemonic, mnemonic); 109 strcpy(op_array[ix].format, format); 110 op_array[ix].sort_value = sort_value; 111 op_array[ix].no_nibbles = no_nibbles; 112 op_array[ix].min_cpu = min_cpu; 113 op_array[ix].mode_bits = mode_bits; 114 no_ops++; 115 } 116 117 static char file_header[] = 118 "/* The opcode table. This file was generated by s390-mkopc.\n\n" 119 " The format of the opcode table is:\n\n" 120 " NAME OPCODE MASK OPERANDS\n\n" 121 " Name is the name of the instruction.\n" 122 " OPCODE is the instruction opcode.\n" 123 " MASK is the opcode mask; this is used to tell the disassembler\n" 124 " which bits in the actual opcode must match OPCODE.\n" 125 " OPERANDS is the list of operands.\n\n" 126 " The disassembler reads the table in order and prints the first\n" 127 " instruction which matches. */\n\n" 128 "const struct s390_opcode s390_opcodes[] =\n {\n"; 129 130 /* `dumpTable': write opcode table. */ 131 132 static void 133 dumpTable (void) 134 { 135 char *str; 136 int ix; 137 138 /* Write hash table entries (slots). */ 139 printf (file_header); 140 141 for (ix = 0; ix < no_ops; ix++) 142 { 143 printf (" { \"%s\", ", op_array[ix].mnemonic); 144 for (str = op_array[ix].opcode; *str != 0; str++) 145 if (*str == '?') 146 *str = '0'; 147 printf ("OP%i(0x%sLL), ", 148 op_array[ix].no_nibbles*4, op_array[ix].opcode); 149 printf ("MASK_%s, INSTR_%s, ", 150 op_array[ix].format, op_array[ix].format); 151 printf ("%i, ", op_array[ix].mode_bits); 152 printf ("%i}", op_array[ix].min_cpu); 153 if (ix < no_ops-1) 154 printf (",\n"); 155 else 156 printf ("\n"); 157 } 158 printf ("};\n\n"); 159 printf ("const int s390_num_opcodes =\n"); 160 printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n"); 161 } 162 163 int 164 main (void) 165 { 166 char currentLine[256]; 167 168 createTable (); 169 170 /* Read opcode descriptions from `stdin'. For each mnemonic, 171 make an entry into the opcode table. */ 172 while (fgets (currentLine, sizeof (currentLine), stdin) != NULL) 173 { 174 char opcode[16]; 175 char mnemonic[16]; 176 char format[16]; 177 char description[64]; 178 char cpu_string[16]; 179 char modes_string[16]; 180 int min_cpu; 181 int mode_bits; 182 char *str; 183 184 if (currentLine[0] == '#') 185 continue; 186 memset (opcode, 0, 8); 187 if (sscanf (currentLine, "%15s %15s %15s \"%[^\"]\" %15s %15s", 188 opcode, mnemonic, format, description, 189 cpu_string, modes_string) == 6) 190 { 191 if (strcmp (cpu_string, "g5") == 0) 192 min_cpu = S390_OPCODE_G5; 193 else if (strcmp (cpu_string, "g6") == 0) 194 min_cpu = S390_OPCODE_G6; 195 else if (strcmp (cpu_string, "z900") == 0) 196 min_cpu = S390_OPCODE_Z900; 197 else if (strcmp (cpu_string, "z990") == 0) 198 min_cpu = S390_OPCODE_Z990; 199 else if (strcmp (cpu_string, "z9-109") == 0) 200 min_cpu = S390_OPCODE_Z9_109; 201 else { 202 fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string); 203 exit (1); 204 } 205 206 str = modes_string; 207 mode_bits = 0; 208 do { 209 if (strncmp (str, "esa", 3) == 0 210 && (str[3] == 0 || str[3] == ',')) { 211 mode_bits |= 1 << S390_OPCODE_ESA; 212 str += 3; 213 } else if (strncmp (str, "zarch", 5) == 0 214 && (str[5] == 0 || str[5] == ',')) { 215 mode_bits |= 1 << S390_OPCODE_ZARCH; 216 str += 5; 217 } else { 218 fprintf (stderr, "Couldn't parse modes string %s\n", 219 modes_string); 220 exit (1); 221 } 222 if (*str == ',') 223 str++; 224 } while (*str != 0); 225 insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits); 226 } 227 else 228 fprintf (stderr, "Couldn't scan line %s\n", currentLine); 229 } 230 231 dumpTable (); 232 return 0; 233 } 234