199461Sobrien/* s390-mkopc.c -- Generates opcode table out of s390-opc.txt 2218822Sdim Copyright 2000, 2001, 2003 Free Software Foundation, Inc. 399461Sobrien Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). 499461Sobrien 599461Sobrien This file is part of GDB, GAS, and the GNU binutils. 699461Sobrien 799461Sobrien This program is free software; you can redistribute it and/or modify 899461Sobrien it under the terms of the GNU General Public License as published by 999461Sobrien the Free Software Foundation; either version 2 of the License, or 1099461Sobrien (at your option) any later version. 1199461Sobrien 1299461Sobrien This program is distributed in the hope that it will be useful, 1399461Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1499461Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1599461Sobrien GNU General Public License for more details. 1699461Sobrien 1799461Sobrien You should have received a copy of the GNU General Public License 1899461Sobrien along with this program; if not, write to the Free Software 19218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim 02110-1301, USA. */ 2199461Sobrien 2299461Sobrien#include <stdio.h> 2399461Sobrien#include <stdlib.h> 2499461Sobrien#include <string.h> 2599461Sobrien 26130561Sobrien/* Taken from opcodes/s390.h */ 27130561Sobrienenum s390_opcode_mode_val 28130561Sobrien { 29130561Sobrien S390_OPCODE_ESA = 0, 30130561Sobrien S390_OPCODE_ZARCH 31130561Sobrien }; 3299461Sobrien 33130561Sobrienenum s390_opcode_cpu_val 34130561Sobrien { 35130561Sobrien S390_OPCODE_G5 = 0, 36130561Sobrien S390_OPCODE_G6, 37130561Sobrien S390_OPCODE_Z900, 38218822Sdim S390_OPCODE_Z990, 39218822Sdim S390_OPCODE_Z9_109, 40218822Sdim S390_OPCODE_Z9_EC 41130561Sobrien }; 42130561Sobrien 4399461Sobrienstruct op_struct 4499461Sobrien { 4599461Sobrien char opcode[16]; 4699461Sobrien char mnemonic[16]; 4799461Sobrien char format[16]; 48130561Sobrien int mode_bits; 49130561Sobrien int min_cpu; 50130561Sobrien 5199461Sobrien unsigned long long sort_value; 5299461Sobrien int no_nibbles; 5399461Sobrien }; 5499461Sobrien 5599461Sobrienstruct op_struct *op_array; 5699461Sobrienint max_ops; 5799461Sobrienint no_ops; 5899461Sobrien 5999461Sobrienstatic void 6099461SobriencreateTable (void) 6199461Sobrien{ 6299461Sobrien max_ops = 256; 6399461Sobrien op_array = malloc (max_ops * sizeof (struct op_struct)); 6499461Sobrien no_ops = 0; 6599461Sobrien} 6699461Sobrien 6799461Sobrien/* `insertOpcode': insert an op_struct into sorted opcode array. */ 6899461Sobrien 6999461Sobrienstatic void 70130561SobrieninsertOpcode (char *opcode, char *mnemonic, char *format, 71130561Sobrien int min_cpu, int mode_bits) 7299461Sobrien{ 7399461Sobrien char *str; 7499461Sobrien unsigned long long sort_value; 7599461Sobrien int no_nibbles; 7699461Sobrien int ix, k; 7799461Sobrien 7899461Sobrien while (no_ops >= max_ops) 7999461Sobrien { 8099461Sobrien max_ops = max_ops * 2; 8199461Sobrien op_array = realloc (op_array, max_ops * sizeof (struct op_struct)); 8299461Sobrien } 8399461Sobrien 8499461Sobrien sort_value = 0; 8599461Sobrien str = opcode; 8699461Sobrien for (ix = 0; ix < 16; ix++) 8799461Sobrien { 8899461Sobrien if (*str >= '0' && *str <= '9') 8999461Sobrien sort_value = (sort_value << 4) + (*str - '0'); 9099461Sobrien else if (*str >= 'a' && *str <= 'f') 9199461Sobrien sort_value = (sort_value << 4) + (*str - 'a' + 10); 9299461Sobrien else if (*str >= 'A' && *str <= 'F') 9399461Sobrien sort_value = (sort_value << 4) + (*str - 'A' + 10); 9499461Sobrien else if (*str == '?') 9599461Sobrien sort_value <<= 4; 9699461Sobrien else 9799461Sobrien break; 9899461Sobrien str ++; 9999461Sobrien } 10099461Sobrien sort_value <<= 4*(16 - ix); 101130561Sobrien sort_value += (min_cpu << 8) + mode_bits; 10299461Sobrien no_nibbles = ix; 10399461Sobrien for (ix = 0; ix < no_ops; ix++) 10499461Sobrien if (sort_value > op_array[ix].sort_value) 10599461Sobrien break; 10699461Sobrien for (k = no_ops; k > ix; k--) 10799461Sobrien op_array[k] = op_array[k-1]; 10899461Sobrien strcpy(op_array[ix].opcode, opcode); 10999461Sobrien strcpy(op_array[ix].mnemonic, mnemonic); 11099461Sobrien strcpy(op_array[ix].format, format); 11199461Sobrien op_array[ix].sort_value = sort_value; 11299461Sobrien op_array[ix].no_nibbles = no_nibbles; 113130561Sobrien op_array[ix].min_cpu = min_cpu; 114130561Sobrien op_array[ix].mode_bits = mode_bits; 11599461Sobrien no_ops++; 11699461Sobrien} 11799461Sobrien 11899461Sobrienstatic char file_header[] = 11999461Sobrien "/* The opcode table. This file was generated by s390-mkopc.\n\n" 12099461Sobrien " The format of the opcode table is:\n\n" 12199461Sobrien " NAME OPCODE MASK OPERANDS\n\n" 12299461Sobrien " Name is the name of the instruction.\n" 12399461Sobrien " OPCODE is the instruction opcode.\n" 12499461Sobrien " MASK is the opcode mask; this is used to tell the disassembler\n" 12599461Sobrien " which bits in the actual opcode must match OPCODE.\n" 12699461Sobrien " OPERANDS is the list of operands.\n\n" 12799461Sobrien " The disassembler reads the table in order and prints the first\n" 12899461Sobrien " instruction which matches. */\n\n" 12999461Sobrien "const struct s390_opcode s390_opcodes[] =\n {\n"; 13099461Sobrien 13199461Sobrien/* `dumpTable': write opcode table. */ 13299461Sobrien 13399461Sobrienstatic void 13499461SobriendumpTable (void) 13599461Sobrien{ 13699461Sobrien char *str; 13799461Sobrien int ix; 13899461Sobrien 13999461Sobrien /* Write hash table entries (slots). */ 14099461Sobrien printf (file_header); 14199461Sobrien 14299461Sobrien for (ix = 0; ix < no_ops; ix++) 14399461Sobrien { 14499461Sobrien printf (" { \"%s\", ", op_array[ix].mnemonic); 14599461Sobrien for (str = op_array[ix].opcode; *str != 0; str++) 14699461Sobrien if (*str == '?') 14799461Sobrien *str = '0'; 14899461Sobrien printf ("OP%i(0x%sLL), ", 14999461Sobrien op_array[ix].no_nibbles*4, op_array[ix].opcode); 15099461Sobrien printf ("MASK_%s, INSTR_%s, ", 15199461Sobrien op_array[ix].format, op_array[ix].format); 152130561Sobrien printf ("%i, ", op_array[ix].mode_bits); 153130561Sobrien printf ("%i}", op_array[ix].min_cpu); 15499461Sobrien if (ix < no_ops-1) 15599461Sobrien printf (",\n"); 15699461Sobrien else 15799461Sobrien printf ("\n"); 15899461Sobrien } 15999461Sobrien printf ("};\n\n"); 16099461Sobrien printf ("const int s390_num_opcodes =\n"); 16199461Sobrien printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n"); 16299461Sobrien} 16399461Sobrien 16499461Sobrienint 16599461Sobrienmain (void) 16699461Sobrien{ 16799461Sobrien char currentLine[256]; 16899461Sobrien 16999461Sobrien createTable (); 17099461Sobrien 17199461Sobrien /* Read opcode descriptions from `stdin'. For each mnemonic, 17299461Sobrien make an entry into the opcode table. */ 17399461Sobrien while (fgets (currentLine, sizeof (currentLine), stdin) != NULL) 17499461Sobrien { 17599461Sobrien char opcode[16]; 17699461Sobrien char mnemonic[16]; 17799461Sobrien char format[16]; 17899461Sobrien char description[64]; 179130561Sobrien char cpu_string[16]; 180130561Sobrien char modes_string[16]; 181130561Sobrien int min_cpu; 182130561Sobrien int mode_bits; 183130561Sobrien char *str; 18499461Sobrien 18599461Sobrien if (currentLine[0] == '#') 18699461Sobrien continue; 18799461Sobrien memset (opcode, 0, 8); 188130561Sobrien if (sscanf (currentLine, "%15s %15s %15s \"%[^\"]\" %15s %15s", 189130561Sobrien opcode, mnemonic, format, description, 190130561Sobrien cpu_string, modes_string) == 6) 19199461Sobrien { 192130561Sobrien if (strcmp (cpu_string, "g5") == 0) 193130561Sobrien min_cpu = S390_OPCODE_G5; 194130561Sobrien else if (strcmp (cpu_string, "g6") == 0) 195130561Sobrien min_cpu = S390_OPCODE_G6; 196130561Sobrien else if (strcmp (cpu_string, "z900") == 0) 197130561Sobrien min_cpu = S390_OPCODE_Z900; 198130561Sobrien else if (strcmp (cpu_string, "z990") == 0) 199130561Sobrien min_cpu = S390_OPCODE_Z990; 200218822Sdim else if (strcmp (cpu_string, "z9-109") == 0) 201218822Sdim min_cpu = S390_OPCODE_Z9_109; 202218822Sdim else if (strcmp (cpu_string, "z9-ec") == 0) 203218822Sdim min_cpu = S390_OPCODE_Z9_EC; 204130561Sobrien else { 205130561Sobrien fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string); 206130561Sobrien exit (1); 207130561Sobrien } 208130561Sobrien 209130561Sobrien str = modes_string; 210130561Sobrien mode_bits = 0; 211130561Sobrien do { 212130561Sobrien if (strncmp (str, "esa", 3) == 0 213130561Sobrien && (str[3] == 0 || str[3] == ',')) { 214130561Sobrien mode_bits |= 1 << S390_OPCODE_ESA; 215130561Sobrien str += 3; 216130561Sobrien } else if (strncmp (str, "zarch", 5) == 0 217130561Sobrien && (str[5] == 0 || str[5] == ',')) { 218130561Sobrien mode_bits |= 1 << S390_OPCODE_ZARCH; 219130561Sobrien str += 5; 220130561Sobrien } else { 221130561Sobrien fprintf (stderr, "Couldn't parse modes string %s\n", 222130561Sobrien modes_string); 223130561Sobrien exit (1); 224130561Sobrien } 225130561Sobrien if (*str == ',') 226130561Sobrien str++; 227130561Sobrien } while (*str != 0); 228130561Sobrien insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits); 22999461Sobrien } 23099461Sobrien else 23199461Sobrien fprintf (stderr, "Couldn't scan line %s\n", currentLine); 23299461Sobrien } 23399461Sobrien 23499461Sobrien dumpTable (); 23599461Sobrien return 0; 23699461Sobrien} 237