1/* This file is part of the program psim. 2 3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 21 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <fcntl.h> 25#include <getopt.h> 26#include <stdio.h> 27#include <ctype.h> 28#include <stdarg.h> 29 30#include "config.h" 31#include "misc.h" 32#include "lf.h" 33#include "table.h" 34 35#ifdef HAVE_UNISTD_H 36#include <unistd.h> 37#endif 38 39#ifdef HAVE_STDLIB_H 40#include <stdlib.h> 41#endif 42 43#ifdef HAVE_STRING_H 44#include <string.h> 45#else 46#ifdef HAVE_STRINGS_H 47#include <strings.h> 48#endif 49#endif 50 51/****************************************************************/ 52 53int spreg_lookup_table = 1; 54enum { 55 nr_of_sprs = 1024, 56}; 57 58/****************************************************************/ 59 60 61typedef enum { 62 spreg_name, 63 spreg_reg_nr, 64 spreg_readonly, 65 spreg_length, 66 nr_spreg_fields, 67} spreg_fields; 68 69typedef struct _spreg_table_entry spreg_table_entry; 70struct _spreg_table_entry { 71 char *name; 72 int spreg_nr; 73 int is_readonly; 74 int length; 75 table_entry *entry; 76 spreg_table_entry *next; 77}; 78 79typedef struct _spreg_table spreg_table; 80struct _spreg_table { 81 spreg_table_entry *sprs; 82}; 83 84static void 85spreg_table_insert(spreg_table *table, table_entry *entry) 86{ 87 /* create a new spr entry */ 88 spreg_table_entry *new_spr = ZALLOC(spreg_table_entry); 89 new_spr->next = NULL; 90 new_spr->entry = entry; 91 new_spr->spreg_nr = atoi(entry->fields[spreg_reg_nr]); 92 new_spr->is_readonly = (entry->fields[spreg_readonly] 93 ? atoi(entry->fields[spreg_readonly]) 94 : 0); 95 new_spr->length = atoi(entry->fields[spreg_length]); 96 new_spr->name = (char*)zalloc(strlen(entry->fields[spreg_name]) + 1); 97 ASSERT(new_spr->name != NULL); 98 { 99 int i; 100 for (i = 0; entry->fields[spreg_name][i] != '\0'; i++) { 101 if (isupper(entry->fields[spreg_name][i])) 102 new_spr->name[i] = tolower(entry->fields[spreg_name][i]); 103 else 104 new_spr->name[i] = entry->fields[spreg_name][i]; 105 } 106 } 107 108 /* insert, by spreg_nr order */ 109 { 110 spreg_table_entry **ptr_to_spreg_entry = &table->sprs; 111 spreg_table_entry *spreg_entry = *ptr_to_spreg_entry; 112 while (spreg_entry != NULL && spreg_entry->spreg_nr < new_spr->spreg_nr) { 113 ptr_to_spreg_entry = &spreg_entry->next; 114 spreg_entry = *ptr_to_spreg_entry; 115 } 116 ASSERT(spreg_entry == NULL || spreg_entry->spreg_nr != new_spr->spreg_nr); 117 *ptr_to_spreg_entry = new_spr; 118 new_spr->next = spreg_entry; 119 } 120 121} 122 123 124static spreg_table * 125spreg_table_load(char *file_name) 126{ 127 table *file = table_open(file_name, nr_spreg_fields, 0); 128 spreg_table *table = ZALLOC(spreg_table); 129 130 { 131 table_entry *entry; 132 while ((entry = table_entry_read(file)) != NULL) { 133 spreg_table_insert(table, entry); 134 } 135 } 136 137 return table; 138} 139 140 141/****************************************************************/ 142 143char *spreg_attributes[] = { 144 "is_valid", 145 "is_readonly", 146 "name", 147 "index", 148 "length", 149 0 150}; 151 152static void 153gen_spreg_h(spreg_table *table, lf *file) 154{ 155 spreg_table_entry *entry; 156 char **attribute; 157 158 lf_print__gnu_copyleft(file); 159 lf_printf(file, "\n"); 160 lf_printf(file, "#ifndef _SPREG_H_\n"); 161 lf_printf(file, "#define _SPREG_H_\n"); 162 lf_printf(file, "\n"); 163 lf_printf(file, "typedef unsigned_word spreg;\n"); 164 lf_printf(file, "\n"); 165 lf_printf(file, "typedef enum {\n"); 166 167 for (entry = table->sprs; 168 entry != NULL ; 169 entry = entry->next) { 170 lf_printf(file, " spr_%s = %d,\n", entry->name, entry->spreg_nr); 171 } 172 173 lf_printf(file, " nr_of_sprs = %d\n", nr_of_sprs); 174 lf_printf(file, "} sprs;\n"); 175 lf_printf(file, "\n"); 176 for (attribute = spreg_attributes; 177 *attribute != NULL; 178 attribute++) { 179 if (strcmp(*attribute, "name") == 0) { 180 lf_print_function_type(file, "const char *", "INLINE_SPREG", " "); 181 lf_printf(file, "spr_%s(sprs spr);\n", *attribute); 182 } 183 else { 184 lf_print_function_type(file, "int", "INLINE_SPREG", " "); 185 lf_printf(file, "spr_%s(sprs spr);\n", *attribute); 186 } 187 } 188 lf_printf(file, "\n"); 189 lf_printf(file, "#endif /* _SPREG_H_ */\n"); 190} 191 192 193static void 194gen_spreg_c(spreg_table *table, lf *file) 195{ 196 spreg_table_entry *entry; 197 char **attribute; 198 int spreg_nr; 199 200 lf_print__gnu_copyleft(file); 201 lf_printf(file, "\n"); 202 lf_printf(file, "#ifndef _SPREG_C_\n"); 203 lf_printf(file, "#define _SPREG_C_\n"); 204 lf_printf(file, "\n"); 205 lf_printf(file, "#include \"basics.h\"\n"); 206 lf_printf(file, "#include \"spreg.h\"\n"); 207 208 lf_printf(file, "\n"); 209 lf_printf(file, "typedef struct _spreg_info {\n"); 210 lf_printf(file, " char *name;\n"); 211 lf_printf(file, " int is_valid;\n"); 212 lf_printf(file, " int length;\n"); 213 lf_printf(file, " int is_readonly;\n"); 214 lf_printf(file, " int index;\n"); 215 lf_printf(file, "} spreg_info;\n"); 216 lf_printf(file, "\n"); 217 lf_printf(file, "static spreg_info spr_info[nr_of_sprs+1] = {\n"); 218 entry = table->sprs; 219 for (spreg_nr = 0; spreg_nr < nr_of_sprs+1; spreg_nr++) { 220 if (entry == NULL || spreg_nr < entry->spreg_nr) 221 lf_printf(file, " { 0, 0, 0, 0, %d},\n", spreg_nr); 222 else { 223 lf_printf(file, " { \"%s\", %d, %d, %d, spr_%s /*%d*/ },\n", 224 entry->name, 1, entry->length, entry->is_readonly, 225 entry->name, entry->spreg_nr); 226 entry = entry->next; 227 } 228 } 229 lf_printf(file, "};\n"); 230 231 for (attribute = spreg_attributes; 232 *attribute != NULL; 233 attribute++) { 234 lf_printf(file, "\n"); 235 if (strcmp(*attribute, "name") == 0) { 236 lf_print_function_type(file, "const char *", "INLINE_SPREG", "\n"); 237 } 238 else { 239 lf_print_function_type(file, "int", "INLINE_SPREG", "\n"); 240 } 241 lf_printf(file, "spr_%s(sprs spr)\n", *attribute); 242 lf_printf(file, "{\n"); 243 if (spreg_lookup_table 244 || strcmp(*attribute, "name") == 0 245 || strcmp(*attribute, "index") == 0) 246 lf_printf(file, " return spr_info[spr].%s;\n", 247 *attribute); 248 else { 249 spreg_table_entry *entry; 250 lf_printf(file, " switch (spr) {\n"); 251 for (entry = table->sprs; entry != NULL; entry = entry->next) { 252 lf_printf(file, " case %d:\n", entry->spreg_nr); 253 if (strcmp(*attribute, "is_valid") == 0) 254 lf_printf(file, " return 1;\n"); 255 else if (strcmp(*attribute, "is_readonly") == 0) 256 lf_printf(file, " return %d;\n", entry->is_readonly); 257 else if (strcmp(*attribute, "length") == 0) 258 lf_printf(file, " return %d;\n", entry->length); 259 else 260 ASSERT(0); 261 } 262 lf_printf(file, " default:\n"); 263 lf_printf(file, " return 0;\n"); 264 lf_printf(file, " }\n"); 265 } 266 lf_printf(file, "}\n"); 267 } 268 269 lf_printf(file, "\n"); 270 lf_printf(file, "#endif /* _SPREG_C_ */\n"); 271} 272 273 274 275/****************************************************************/ 276 277 278int 279main(int argc, 280 char **argv, 281 char **envp) 282{ 283 lf_file_references file_references = lf_include_references; 284 spreg_table *sprs = NULL; 285 char *real_file_name = NULL; 286 int is_header = 0; 287 int ch; 288 289 if (argc <= 1) { 290 printf("Usage: dgen ...\n"); 291 printf("-s Use switch instead of table\n"); 292 printf("-n <file-name> Use this as cpp line numbering name\n"); 293 printf("-h Output header file\n"); 294 printf("-p <spreg-file> Output spreg.h(P) or spreg.c(p)\n"); 295 printf("-L Suppress cpp line numbering in output files\n"); 296 } 297 298 299 while ((ch = getopt(argc, argv, "hLsn:r:p:")) != -1) { 300 fprintf(stderr, "\t-%c %s\n", ch, ( optarg ? optarg : "")); 301 switch(ch) { 302 case 's': 303 spreg_lookup_table = 0; 304 break; 305 case 'r': 306 sprs = spreg_table_load(optarg); 307 break; 308 case 'n': 309 real_file_name = strdup(optarg); 310 break; 311 case 'L': 312 file_references = lf_omit_references; 313 break; 314 case 'h': 315 is_header = 1; 316 break; 317 case 'p': 318 { 319 lf *file = lf_open(optarg, real_file_name, file_references, 320 (is_header ? lf_is_h : lf_is_c), 321 argv[0]); 322 if (is_header) 323 gen_spreg_h(sprs, file); 324 else 325 gen_spreg_c(sprs, file); 326 lf_close(file); 327 is_header = 0; 328 } 329 real_file_name = NULL; 330 break; 331 default: 332 error("unknown option\n"); 333 } 334 } 335 return 0; 336} 337