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