]> git.sesse.net Git - pistorm/blob - m68kmake.c
Add Meson build files.
[pistorm] / m68kmake.c
1 /* ======================================================================== */
2 /* ========================= LICENSING & COPYRIGHT ======================== */
3 /* ======================================================================== */
4 /*
5  *                                  MUSASHI
6  *                                Version 4.60
7  *
8  * A portable Motorola M680x0 processor emulation engine.
9  * Copyright Karl Stenerud.  All rights reserved.
10  * FPU and MMU by R. Belmont.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28  * THE SOFTWARE.
29  */
30
31
32
33 /* ======================================================================== */
34 /* ============================ CODE GENERATOR ============================ */
35 /* ======================================================================== */
36 /*
37  * This is the code generator program which will generate the opcode table
38  * and the final opcode handlers.
39  *
40  * It requires an input file to function (default m68k_in.c), but you can
41  * specify your own like so:
42  *
43  * m68kmake <output path> <input file>
44  *
45  * where output path is the path where the output files should be placed, and
46  * input file is the file to use for input.
47  *
48  * If you modify the input file greatly from its released form, you may have
49  * to tweak the configuration section a bit since I'm using static allocation
50  * to keep things simple.
51  *
52  *
53  * TODO: - build a better code generator for the move instruction.
54  *       - Add callm and rtm instructions
55  *       - Fix RTE to handle other format words
56  *       - Add address error (and bus error?) handling
57  */
58
59
60 static const char g_version[] = "4.60";
61
62 /* ======================================================================== */
63 /* =============================== INCLUDES =============================== */
64 /* ======================================================================== */
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <ctype.h>
70 #include <stdarg.h>
71
72
73
74 /* ======================================================================== */
75 /* ============================= CONFIGURATION ============================ */
76 /* ======================================================================== */
77
78 #define M68K_MAX_PATH 1024
79 #define M68K_MAX_DIR  1024
80
81 #define MAX_LINE_LENGTH                 200     /* length of 1 line */
82 #define MAX_BODY_LENGTH                 300     /* Number of lines in 1 function */
83 #define MAX_REPLACE_LENGTH               30     /* Max number of replace strings */
84 #define MAX_INSERT_LENGTH              5000     /* Max size of insert piece */
85 #define MAX_NAME_LENGTH                  30     /* Max length of ophandler name */
86 #define MAX_SPEC_PROC_LENGTH              4     /* Max length of special processing str */
87 #define MAX_SPEC_EA_LENGTH                5     /* Max length of specified EA str */
88 #define EA_ALLOWED_LENGTH                11     /* Max length of ea allowed str */
89 #define MAX_OPCODE_INPUT_TABLE_LENGTH  1000     /* Max length of opcode handler tbl */
90 #define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000     /* Max length of opcode handler tbl */
91
92 /* Default filenames */
93 #define FILENAME_INPUT      "m68k_in.c"
94 #define FILENAME_PROTOTYPE  "m68kops.h"
95 #define FILENAME_TABLE      "m68kops.c"
96
97
98 /* Identifier sequences recognized by this program */
99
100 #define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
101
102 #define ID_BASE                 "M68KMAKE"
103 #define ID_PROTOTYPE_HEADER     ID_BASE "_PROTOTYPE_HEADER"
104 #define ID_PROTOTYPE_FOOTER     ID_BASE "_PROTOTYPE_FOOTER"
105 #define ID_TABLE_HEADER         ID_BASE "_TABLE_HEADER"
106 #define ID_TABLE_FOOTER         ID_BASE "_TABLE_FOOTER"
107 #define ID_TABLE_BODY           ID_BASE "_TABLE_BODY"
108 #define ID_TABLE_START          ID_BASE "_TABLE_START"
109 #define ID_OPHANDLER_HEADER     ID_BASE "_OPCODE_HANDLER_HEADER"
110 #define ID_OPHANDLER_FOOTER     ID_BASE "_OPCODE_HANDLER_FOOTER"
111 #define ID_OPHANDLER_BODY       ID_BASE "_OPCODE_HANDLER_BODY"
112 #define ID_END                  ID_BASE "_END"
113
114 #define ID_OPHANDLER_NAME       ID_BASE "_OP"
115 #define ID_OPHANDLER_EA_AY_8    ID_BASE "_GET_EA_AY_8"
116 #define ID_OPHANDLER_EA_AY_16   ID_BASE "_GET_EA_AY_16"
117 #define ID_OPHANDLER_EA_AY_32   ID_BASE "_GET_EA_AY_32"
118 #define ID_OPHANDLER_OPER_AY_8  ID_BASE "_GET_OPER_AY_8"
119 #define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16"
120 #define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32"
121 #define ID_OPHANDLER_CC         ID_BASE "_CC"
122 #define ID_OPHANDLER_NOT_CC     ID_BASE "_NOT_CC"
123
124
125 #ifndef DECL_SPEC
126 #define DECL_SPEC
127 #endif /* DECL_SPEC */
128
129
130
131 /* ======================================================================== */
132 /* ============================== PROTOTYPES ============================== */
133 /* ======================================================================== */
134
135 enum {
136     CPU_TYPE_000=0,
137     CPU_TYPE_010,
138     CPU_TYPE_020,
139     CPU_TYPE_030,
140     CPU_TYPE_040,
141     NUM_CPUS
142 };
143
144 #define UNSPECIFIED "."
145 #define UNSPECIFIED_CH '.'
146
147 #define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0)
148 #define HAS_EA_AI(A)   ((A)[0] == 'A')
149 #define HAS_EA_PI(A)   ((A)[1] == '+')
150 #define HAS_EA_PD(A)   ((A)[2] == '-')
151 #define HAS_EA_DI(A)   ((A)[3] == 'D')
152 #define HAS_EA_IX(A)   ((A)[4] == 'X')
153 #define HAS_EA_AW(A)   ((A)[5] == 'W')
154 #define HAS_EA_AL(A)   ((A)[6] == 'L')
155 #define HAS_EA_PCDI(A) ((A)[7] == 'd')
156 #define HAS_EA_PCIX(A) ((A)[8] == 'x')
157 #define HAS_EA_I(A)    ((A)[9] == 'I')
158
159 enum
160 {
161         EA_MODE_NONE,   /* No special addressing mode */
162         EA_MODE_AI,             /* Address register indirect */
163         EA_MODE_PI,             /* Address register indirect with postincrement */
164         EA_MODE_PI7,    /* Address register 7 indirect with postincrement */
165         EA_MODE_PD,             /* Address register indirect with predecrement */
166         EA_MODE_PD7,    /* Address register 7 indirect with predecrement */
167         EA_MODE_DI,             /* Address register indirect with displacement */
168         EA_MODE_IX,             /* Address register indirect with index */
169         EA_MODE_AW,             /* Absolute word */
170         EA_MODE_AL,             /* Absolute long */
171         EA_MODE_PCDI,   /* Program counter indirect with displacement */
172         EA_MODE_PCIX,   /* Program counter indirect with index */
173         EA_MODE_I               /* Immediate */
174 };
175
176
177 /* Everything we need to know about an opcode */
178 typedef struct
179 {
180         char name[MAX_NAME_LENGTH];           /* opcode handler name */
181         unsigned char size;                   /* Size of operation */
182         char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */
183         char spec_ea[MAX_SPEC_EA_LENGTH];     /* Specified effective addressing mode */
184         unsigned char bits;                   /* Number of significant bits (used for sorting the table) */
185         unsigned short op_mask;               /* Mask to apply for matching an opcode to a handler */
186         unsigned short op_match;              /* Value to match after masking */
187         char ea_allowed[EA_ALLOWED_LENGTH];   /* Effective addressing modes allowed */
188         char cpu_mode[NUM_CPUS];              /* User or supervisor mode */
189         char cpus[NUM_CPUS+1];                /* Allowed CPUs */
190         unsigned char cycles[NUM_CPUS];       /* cycles for 000, 010, 020, 030, 040 */
191 } opcode_struct;
192
193
194 /* All modifications necessary for a specific EA mode of an instruction */
195 typedef struct
196 {
197         char* fname_add;
198         char* ea_add;
199         unsigned int mask_add;
200         unsigned int match_add;
201 } ea_info_struct;
202
203
204 /* Holds the body of a function */
205 typedef struct
206 {
207         char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1];
208         int length;
209 } body_struct;
210
211
212 /* Holds a sequence of search / replace strings */
213 typedef struct
214 {
215         char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1];
216         int length;
217 } replace_struct;
218
219
220 /* Function Prototypes */
221 void error_exit(char* fmt, ...);
222 void perror_exit(char* fmt, ...);
223 int check_strsncpy(char* dst, char* src, int maxlength);
224 int check_atoi(char* str, int *result);
225 int skip_spaces(char* str);
226 int num_bits(int value);
227 int atoh(char* buff);
228 int fgetline(char* buff, int nchars, FILE* file);
229 int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type);
230 opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea);
231 opcode_struct* find_illegal_opcode(void);
232 int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea);
233 void add_replace_string(replace_struct* replace, char* search_str, char* replace_str);
234 void write_body(FILE* filep, body_struct* body, replace_struct* replace);
235 void get_base_name(char* base_name, opcode_struct* op);
236 void write_function_name(FILE* filep, char* base_name);
237 void add_opcode_output_table_entry(opcode_struct* op, char* name);
238 static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr);
239 void print_opcode_output_table(FILE* filep);
240 void write_table_entry(FILE* filep, opcode_struct* op);
241 void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode);
242 void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode);
243 void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op);
244 void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset);
245 void process_opcode_handlers(FILE* filep);
246 void populate_table(void);
247 void read_insert(char* insert);
248
249
250
251 /* ======================================================================== */
252 /* ================================= DATA ================================= */
253 /* ======================================================================== */
254
255 /* Name of the input file */
256 char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT;
257
258 /* File handles */
259 FILE* g_input_file = NULL;
260 FILE* g_prototype_file = NULL;
261 FILE* g_table_file = NULL;
262
263 int g_num_functions = 0;  /* Number of functions processed */
264 int g_num_primitives = 0; /* Number of function primitives read */
265 int g_line_number = 1;    /* Current line number */
266
267 /* Opcode handler table */
268 opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];
269
270 opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH];
271 int g_opcode_output_table_length = 0;
272
273 const ea_info_struct g_ea_info_table[13] =
274 {/* fname    ea        mask  match */
275         {"",     "",       0x00, 0x00}, /* EA_MODE_NONE */
276         {"ai",   "AY_AI",  0x38, 0x10}, /* EA_MODE_AI   */
277         {"pi",   "AY_PI",  0x38, 0x18}, /* EA_MODE_PI   */
278         {"pi7",  "A7_PI",  0x3f, 0x1f}, /* EA_MODE_PI7  */
279         {"pd",   "AY_PD",  0x38, 0x20}, /* EA_MODE_PD   */
280         {"pd7",  "A7_PD",  0x3f, 0x27}, /* EA_MODE_PD7  */
281         {"di",   "AY_DI",  0x38, 0x28}, /* EA_MODE_DI   */
282         {"ix",   "AY_IX",  0x38, 0x30}, /* EA_MODE_IX   */
283         {"aw",   "AW",     0x3f, 0x38}, /* EA_MODE_AW   */
284         {"al",   "AL",     0x3f, 0x39}, /* EA_MODE_AL   */
285         {"pcdi", "PCDI",   0x3f, 0x3a}, /* EA_MODE_PCDI */
286         {"pcix", "PCIX",   0x3f, 0x3b}, /* EA_MODE_PCIX */
287         {"i",    "I",      0x3f, 0x3c}, /* EA_MODE_I    */
288 };
289
290
291 const char *const g_cc_table[16][2] =
292 {
293         { "t",  "T"}, /* 0000 */
294         { "f",  "F"}, /* 0001 */
295         {"hi", "HI"}, /* 0010 */
296         {"ls", "LS"}, /* 0011 */
297         {"cc", "CC"}, /* 0100 */
298         {"cs", "CS"}, /* 0101 */
299         {"ne", "NE"}, /* 0110 */
300         {"eq", "EQ"}, /* 0111 */
301         {"vc", "VC"}, /* 1000 */
302         {"vs", "VS"}, /* 1001 */
303         {"pl", "PL"}, /* 1010 */
304         {"mi", "MI"}, /* 1011 */
305         {"ge", "GE"}, /* 1100 */
306         {"lt", "LT"}, /* 1101 */
307         {"gt", "GT"}, /* 1110 */
308         {"le", "LE"}, /* 1111 */
309 };
310
311 /* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */
312 const int g_size_select_table[33] =
313 {
314         0,                                                                                              /* unsized */
315         0, 0, 0, 0, 0, 0, 0, 1,                                                 /*    8    */
316         0, 0, 0, 0, 0, 0, 0, 1,                                                 /*   16    */
317         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2  /*   32    */
318 };
319
320 /* Extra cycles required for certain EA modes */
321 /* TODO: correct timings for 030, 040 */
322 const int g_ea_cycle_table[13][NUM_CPUS][3] =
323 {/*       000           010           020           030           040  */
324         {{ 0,  0,  0}, { 0,  0,  0}, { 0,  0,  0}, { 0,  0,  0}, { 0,  0,  0}}, /* EA_MODE_NONE */
325         {{ 0,  4,  8}, { 0,  4,  8}, { 0,  4,  4}, { 0,  4,  4}, { 0,  4,  4}}, /* EA_MODE_AI   */
326         {{ 0,  4,  8}, { 0,  4,  8}, { 0,  4,  4}, { 0,  4,  4}, { 0,  4,  4}}, /* EA_MODE_PI   */
327         {{ 0,  4,  8}, { 0,  4,  8}, { 0,  4,  4}, { 0,  4,  4}, { 0,  4,  4}}, /* EA_MODE_PI7  */
328         {{ 0,  6, 10}, { 0,  6, 10}, { 0,  5,  5}, { 0,  5,  5}, { 0,  5,  5}}, /* EA_MODE_PD   */
329         {{ 0,  6, 10}, { 0,  6, 10}, { 0,  5,  5}, { 0,  5,  5}, { 0,  5,  5}}, /* EA_MODE_PD7  */
330         {{ 0,  8, 12}, { 0,  8, 12}, { 0,  5,  5}, { 0,  5,  5}, { 0,  5,  5}}, /* EA_MODE_DI   */
331         {{ 0, 10, 14}, { 0, 10, 14}, { 0,  7,  7}, { 0,  7,  7}, { 0,  7,  7}}, /* EA_MODE_IX   */
332         {{ 0,  8, 12}, { 0,  8, 12}, { 0,  4,  4}, { 0,  4,  4}, { 0,  4,  4}}, /* EA_MODE_AW   */
333         {{ 0, 12, 16}, { 0, 12, 16}, { 0,  4,  4}, { 0,  4,  4}, { 0,  4,  4}}, /* EA_MODE_AL   */
334         {{ 0,  8, 12}, { 0,  8, 12}, { 0,  5,  5}, { 0,  5,  5}, { 0,  5,  5}}, /* EA_MODE_PCDI */
335         {{ 0, 10, 14}, { 0, 10, 14}, { 0,  7,  7}, { 0,  7,  7}, { 0,  7,  7}}, /* EA_MODE_PCIX */
336         {{ 0,  4,  8}, { 0,  4,  8}, { 0,  2,  4}, { 0,  2,  4}, { 0,  2,  4}}, /* EA_MODE_I    */
337 };
338
339 /* Extra cycles for JMP instruction (000, 010) */
340 const int g_jmp_cycle_table[13] =
341 {
342          0, /* EA_MODE_NONE */
343          4, /* EA_MODE_AI   */
344          0, /* EA_MODE_PI   */
345          0, /* EA_MODE_PI7  */
346          0, /* EA_MODE_PD   */
347          0, /* EA_MODE_PD7  */
348          6, /* EA_MODE_DI   */
349          10, /* EA_MODE_IX   */
350          6, /* EA_MODE_AW   */
351          8, /* EA_MODE_AL   */
352          6, /* EA_MODE_PCDI */
353         10, /* EA_MODE_PCIX */
354          0, /* EA_MODE_I    */
355 };
356
357 /* Extra cycles for JSR instruction (000, 010) */
358 const int g_jsr_cycle_table[13] =
359 {
360          0, /* EA_MODE_NONE */
361          4, /* EA_MODE_AI   */
362          0, /* EA_MODE_PI   */
363          0, /* EA_MODE_PI7  */
364          0, /* EA_MODE_PD   */
365          0, /* EA_MODE_PD7  */
366          6, /* EA_MODE_DI   */
367         10, /* EA_MODE_IX   */
368          6, /* EA_MODE_AW   */
369          8, /* EA_MODE_AL   */
370          6, /* EA_MODE_PCDI */
371         10, /* EA_MODE_PCIX */
372          0, /* EA_MODE_I    */
373 };
374
375 /* Extra cycles for LEA instruction (000, 010) */
376 const int g_lea_cycle_table[13] =
377 {
378          0, /* EA_MODE_NONE */
379          4, /* EA_MODE_AI   */
380          0, /* EA_MODE_PI   */
381          0, /* EA_MODE_PI7  */
382          0, /* EA_MODE_PD   */
383          0, /* EA_MODE_PD7  */
384          8, /* EA_MODE_DI   */
385         12, /* EA_MODE_IX   */
386          8, /* EA_MODE_AW   */
387         12, /* EA_MODE_AL   */
388          8, /* EA_MODE_PCDI */
389         12, /* EA_MODE_PCIX */
390          0, /* EA_MODE_I    */
391 };
392
393 /* Extra cycles for PEA instruction (000, 010) */
394 const int g_pea_cycle_table[13] =
395 {
396          0, /* EA_MODE_NONE */
397          6, /* EA_MODE_AI   */
398          0, /* EA_MODE_PI   */
399          0, /* EA_MODE_PI7  */
400          0, /* EA_MODE_PD   */
401          0, /* EA_MODE_PD7  */
402         10, /* EA_MODE_DI   */
403         14, /* EA_MODE_IX   */
404         10, /* EA_MODE_AW   */
405         14, /* EA_MODE_AL   */
406         10, /* EA_MODE_PCDI */
407         14, /* EA_MODE_PCIX */
408          0, /* EA_MODE_I    */
409 };
410
411 /* Extra cycles for MOVEM instruction (000, 010) */
412 const int g_movem_cycle_table[13] =
413 {
414          0, /* EA_MODE_NONE */
415          0, /* EA_MODE_AI   */
416          0, /* EA_MODE_PI   */
417          0, /* EA_MODE_PI7  */
418          0, /* EA_MODE_PD   */
419          0, /* EA_MODE_PD7  */
420          4, /* EA_MODE_DI   */
421          6, /* EA_MODE_IX   */
422          4, /* EA_MODE_AW   */
423          8, /* EA_MODE_AL   */
424          0, /* EA_MODE_PCDI */
425          0, /* EA_MODE_PCIX */
426          0, /* EA_MODE_I    */
427 };
428
429 /* Extra cycles for MOVES instruction (010) */
430 const int g_moves_cycle_table[13][3] =
431 {
432         { 0,  0,  0}, /* EA_MODE_NONE */
433         { 0,  4,  6}, /* EA_MODE_AI   */
434         { 0,  4,  6}, /* EA_MODE_PI   */
435         { 0,  4,  6}, /* EA_MODE_PI7  */
436         { 0,  6, 12}, /* EA_MODE_PD   */
437         { 0,  6, 12}, /* EA_MODE_PD7  */
438         { 0, 12, 16}, /* EA_MODE_DI   */
439         { 0, 16, 20}, /* EA_MODE_IX   */
440         { 0, 12, 16}, /* EA_MODE_AW   */
441         { 0, 16, 20}, /* EA_MODE_AL   */
442         { 0,  0,  0}, /* EA_MODE_PCDI */
443         { 0,  0,  0}, /* EA_MODE_PCIX */
444         { 0,  0,  0}, /* EA_MODE_I    */
445 };
446
447 /* Extra cycles for CLR instruction (010) */
448 const int g_clr_cycle_table[13][3] =
449 {
450         { 0,  0,  0}, /* EA_MODE_NONE */
451         { 0,  4,  6}, /* EA_MODE_AI   */
452         { 0,  4,  6}, /* EA_MODE_PI   */
453         { 0,  4,  6}, /* EA_MODE_PI7  */
454         { 0,  6,  8}, /* EA_MODE_PD   */
455         { 0,  6,  8}, /* EA_MODE_PD7  */
456         { 0,  8, 10}, /* EA_MODE_DI   */
457         { 0, 10, 14}, /* EA_MODE_IX   */
458         { 0,  8, 10}, /* EA_MODE_AW   */
459         { 0, 10, 14}, /* EA_MODE_AL   */
460         { 0,  0,  0}, /* EA_MODE_PCDI */
461         { 0,  0,  0}, /* EA_MODE_PCIX */
462         { 0,  0,  0}, /* EA_MODE_I    */
463 };
464
465
466
467 /* ======================================================================== */
468 /* =========================== UTILITY FUNCTIONS ========================== */
469 /* ======================================================================== */
470
471 /* Print an error message and exit with status error */
472 void error_exit(char* fmt, ...)
473 {
474         va_list args;
475         fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number);
476         va_start(args, fmt);
477         vfprintf(stderr, fmt, args);
478         va_end(args);
479         fprintf(stderr, "\n");
480
481         if(g_prototype_file) fclose(g_prototype_file);
482         if(g_table_file) fclose(g_table_file);
483         if(g_input_file) fclose(g_input_file);
484
485         exit(EXIT_FAILURE);
486 }
487
488 /* Print an error message, call perror(), and exit with status error */
489 void perror_exit(char* fmt, ...)
490 {
491         va_list args;
492         va_start(args, fmt);
493         vfprintf(stderr, fmt, args);
494         va_end(args);
495         perror("");
496
497         if(g_prototype_file) fclose(g_prototype_file);
498         if(g_table_file) fclose(g_table_file);
499         if(g_input_file) fclose(g_input_file);
500
501         exit(EXIT_FAILURE);
502 }
503
504
505 /* copy until 0 or space and exit with error if we read too far */
506 int check_strsncpy(char* dst, char* src, int maxlength)
507 {
508         char* p = dst;
509         while(*src && *src != ' ')
510         {
511                 *p++ = *src++;
512                 if(p - dst > maxlength)
513                         error_exit("Field too long");
514         }
515         *p = 0;
516         return p - dst;
517 }
518
519 /* copy until 0 or specified character and exit with error if we read too far */
520 int check_strcncpy(char* dst, char* src, char delim, int maxlength)
521 {
522         char* p = dst;
523         while(*src && *src != delim)
524         {
525                 *p++ = *src++;
526                 if(p - dst > maxlength)
527                         error_exit("Field too long");
528         }
529         *p = 0;
530         return p - dst;
531 }
532
533 /* convert ascii to integer and exit with error if we find invalid data */
534 int check_atoi(char* str, int *result)
535 {
536         int accum = 0;
537         char* p = str;
538         while(*p >= '0' && *p <= '9')
539         {
540                 accum *= 10;
541                 accum += *p++ - '0';
542         }
543         if(*p != ' ' && *p != 0)
544                 error_exit("Malformed integer value (%c)", *p);
545         *result = accum;
546         return p - str;
547 }
548
549 /* Skip past spaces in a string */
550 int skip_spaces(char* str)
551 {
552         char* p = str;
553
554         while(*p == ' ')
555                 p++;
556
557         return p - str;
558 }
559
560 /* Count the number of set bits in a value */
561 int num_bits(int value)
562 {
563     value = ((value & 0xaaaa) >> 1) + (value & 0x5555);
564     value = ((value & 0xcccc) >> 2) + (value & 0x3333);
565     value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f);
566     value = ((value & 0xff00) >> 8) + (value & 0x00ff);
567         return value;
568 }
569
570 /* Convert a hex value written in ASCII */
571 int atoh(char* buff)
572 {
573         int accum = 0;
574
575         for(;;buff++)
576         {
577                 if(*buff >= '0' && *buff <= '9')
578                 {
579                         accum <<= 4;
580                         accum += *buff - '0';
581                 }
582                 else if(*buff >= 'a' && *buff <= 'f')
583                 {
584                         accum <<= 4;
585                         accum += *buff - 'a' + 10;
586                 }
587                 else break;
588         }
589         return accum;
590 }
591
592 /* Get a line of text from a file, discarding any end-of-line characters */
593 int fgetline(char* buff, int nchars, FILE* file)
594 {
595         int length;
596
597         if(fgets(buff, nchars, file) == NULL)
598                 return -1;
599         if(buff[0] == '\r')
600                 memmove(buff, buff + 1, nchars - 1);
601
602         length = strlen(buff);
603         while(length && (buff[length-1] == '\r' || buff[length-1] == '\n'))
604                 length--;
605         buff[length] = 0;
606         g_line_number++;
607
608         return length;
609 }
610
611
612
613 /* ======================================================================== */
614 /* =========================== HELPER FUNCTIONS =========================== */
615 /* ======================================================================== */
616
617 /* Calculate the number of cycles an opcode requires */
618 int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type)
619 {
620         int size = g_size_select_table[op->size];
621
622         if(op->cpus[cpu_type] == '.')
623                 return 0;
624
625         if(cpu_type < CPU_TYPE_020)
626         {
627                 if(cpu_type == CPU_TYPE_010)
628                 {
629                         if(strcmp(op->name, "moves") == 0)
630                                 return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size];
631                         if(strcmp(op->name, "clr") == 0)
632                                 return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size];
633                 }
634
635                 /* ASG: added these cases -- immediate modes take 2 extra cycles here */
636                 if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I &&
637                    ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) ||
638                         strcmp(op->name, "adda")   == 0                                    ||
639                         (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) ||
640                         (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0)  ||
641                         (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) ||
642                         strcmp(op->name, "suba")   == 0))
643                         return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
644
645                 if(strcmp(op->name, "jmp") == 0)
646                         return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode];
647                 if(strcmp(op->name, "jsr") == 0)
648                         return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode];
649                 if(strcmp(op->name, "lea") == 0)
650                         return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode];
651                 if(strcmp(op->name, "pea") == 0)
652                         return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode];
653                 if(strcmp(op->name, "movem") == 0)
654                         return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode];
655         }
656         return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size];
657 }
658
659 /* Find an opcode in the opcode handler list */
660 opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea)
661 {
662         opcode_struct* op;
663
664
665         for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++)
666         {
667                 if(     strcmp(name, op->name) == 0 &&
668                         (size == op->size) &&
669                         strcmp(spec_proc, op->spec_proc) == 0 &&
670                         strcmp(spec_ea, op->spec_ea) == 0)
671                                 return op;
672         }
673         return NULL;
674 }
675
676 /* Specifically find the illegal opcode in the list */
677 opcode_struct* find_illegal_opcode(void)
678 {
679         opcode_struct* op;
680
681         for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++)
682         {
683                 if(strcmp(op->name, "illegal") == 0)
684                         return op;
685         }
686         return NULL;
687 }
688
689 /* Parse an opcode handler name */
690 int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea)
691 {
692         char* ptr = strstr(src, ID_OPHANDLER_NAME);
693
694         if(ptr == NULL)
695                 return 0;
696
697         ptr += strlen(ID_OPHANDLER_NAME) + 1;
698
699         ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH);
700         if(*ptr != ',') return 0;
701         ptr++;
702         ptr += skip_spaces(ptr);
703
704         *size = atoi(ptr);
705         ptr = strstr(ptr, ",");
706         if(ptr == NULL) return 0;
707     ptr++;
708         ptr += skip_spaces(ptr);
709
710         ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH);
711         if(*ptr != ',') return 0;
712         ptr++;
713         ptr += skip_spaces(ptr);
714
715         ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH);
716         if(*ptr != ')') return 0;
717         ptr++;
718         ptr += skip_spaces(ptr);
719
720         return 1;
721 }
722
723
724 /* Add a search/replace pair to a replace structure */
725 void add_replace_string(replace_struct* replace, char* search_str, char* replace_str)
726 {
727         if(replace->length >= MAX_REPLACE_LENGTH)
728                 error_exit("overflow in replace structure");
729
730         strcpy(replace->replace[replace->length][0], search_str);
731         strcpy(replace->replace[replace->length++][1], replace_str);
732 }
733
734 /* Write a function body while replacing any selected strings */
735 void write_body(FILE* filep, body_struct* body, replace_struct* replace)
736 {
737         int i;
738         int j;
739         char* ptr;
740         char output[MAX_LINE_LENGTH+1];
741         char temp_buff[MAX_LINE_LENGTH+1];
742         int found;
743
744         for(i=0;i<body->length;i++)
745         {
746                 strcpy(output, body->body[i]);
747                 /* Check for the base directive header */
748                 if(strstr(output, ID_BASE) != NULL)
749                 {
750                         /* Search for any text we need to replace */
751                         found = 0;
752                         for(j=0;j<replace->length;j++)
753                         {
754                                 ptr = strstr(output, replace->replace[j][0]);
755                                 if(ptr)
756                                 {
757                                         /* We found something to replace */
758                                         found = 1;
759                                         strcpy(temp_buff, ptr+strlen(replace->replace[j][0]));
760                                         strcpy(ptr, replace->replace[j][1]);
761                                         strcat(ptr, temp_buff);
762                                 }
763                         }
764                         /* Found a directive with no matching replace string */
765                         if(!found)
766                                 error_exit("Unknown " ID_BASE " directive [%s]", output);
767                 }
768                 fprintf(filep, "%s\n", output);
769         }
770         fprintf(filep, "\n\n");
771 }
772
773 /* Generate a base function name from an opcode struct */
774 void get_base_name(char* base_name, opcode_struct* op)
775 {
776         sprintf(base_name, "m68k_op_%s", op->name);
777         if(op->size > 0)
778                 sprintf(base_name+strlen(base_name), "_%d", op->size);
779         if(strcmp(op->spec_proc, UNSPECIFIED) != 0)
780                 sprintf(base_name+strlen(base_name), "_%s", op->spec_proc);
781         if(strcmp(op->spec_ea, UNSPECIFIED) != 0)
782                 sprintf(base_name+strlen(base_name), "_%s", op->spec_ea);
783 }
784
785 /* Write the name of an opcode handler function */
786 void write_function_name(FILE* filep, char* base_name)
787 {
788         fprintf(filep, "static void %s(m68ki_cpu_core *state)\n", base_name);
789 }
790
791 void add_opcode_output_table_entry(opcode_struct* op, char* name)
792 {
793         opcode_struct* ptr;
794         if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH)
795                 error_exit("Opcode output table overflow");
796
797         ptr = g_opcode_output_table + g_opcode_output_table_length++;
798
799         *ptr = *op;
800         strcpy(ptr->name, name);
801         ptr->bits = num_bits(ptr->op_mask);
802 }
803
804 /*
805  * Comparison function for qsort()
806  * For entries with an equal number of set bits in
807  * the mask compare the match values
808  */
809 static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr)
810 {
811         const opcode_struct *a = aptr, *b = bptr;
812         if(a->bits != b->bits)
813                 return a->bits - b->bits;
814         if(a->op_mask != b->op_mask)
815                 return a->op_mask - b->op_mask;
816         return a->op_match - b->op_match;
817 }
818
819 void print_opcode_output_table(FILE* filep)
820 {
821         int i;
822         qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits);
823
824         for(i=0;i<g_opcode_output_table_length;i++)
825                 write_table_entry(filep, g_opcode_output_table+i);
826 }
827
828 /* Write an entry in the opcode handler table */
829 void write_table_entry(FILE* filep, opcode_struct* op)
830 {
831         int i;
832
833         fprintf(filep, "\t{%-28s, 0x%04x, 0x%04x, {",
834                 op->name, op->op_mask, op->op_match);
835
836         for(i=0;i<NUM_CPUS;i++)
837         {
838                 fprintf(filep, "%3d", op->cycles[i]);
839                 if(i < NUM_CPUS-1)
840                         fprintf(filep, ", ");
841         }
842
843         fprintf(filep, "}},\n");
844 }
845
846 /* Fill out an opcode struct with a specific addressing mode of the source opcode struct */
847 void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode)
848 {
849         int i;
850
851         *dst = *src;
852
853         for(i=0;i<NUM_CPUS;i++)
854                 dst->cycles[i] = get_oper_cycles(dst, ea_mode, i);
855         if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE)
856                 sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add);
857         dst->op_mask |= g_ea_info_table[ea_mode].mask_add;
858         dst->op_match |= g_ea_info_table[ea_mode].match_add;
859 }
860
861
862 /* Generate a final opcode handler from the provided data */
863 void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode)
864 {
865         char str[MAX_LINE_LENGTH+1];
866         opcode_struct* op = malloc(sizeof(opcode_struct));
867
868         /* Set the opcode structure and write the tables, prototypes, etc */
869         set_opcode_struct(opinfo, op, ea_mode);
870         get_base_name(str, op);
871         add_opcode_output_table_entry(op, str);
872         write_function_name(filep, str);
873
874         /* Add any replace strings needed */
875         if(ea_mode != EA_MODE_NONE)
876         {
877                 sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add);
878                 add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str);
879                 sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add);
880                 add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str);
881                 sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add);
882                 add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str);
883                 sprintf(str, "OPER_%s_8(state)", g_ea_info_table[ea_mode].ea_add);
884                 add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str);
885                 sprintf(str, "OPER_%s_16(state)", g_ea_info_table[ea_mode].ea_add);
886                 add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str);
887                 sprintf(str, "OPER_%s_32(state)", g_ea_info_table[ea_mode].ea_add);
888                 add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str);
889         }
890
891         /* Now write the function body with the selected replace strings */
892         write_body(filep, body, replace);
893         g_num_functions++;
894         free(op);
895 }
896
897 /* Generate opcode variants based on available addressing modes */
898 void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op)
899 {
900         int old_length = replace->length;
901
902         /* No ea modes available for this opcode */
903         if(HAS_NO_EA_MODE(op->ea_allowed))
904         {
905                 generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE);
906                 return;
907         }
908
909         /* Check for and create specific opcodes for each available addressing mode */
910         if(HAS_EA_AI(op->ea_allowed))
911                 generate_opcode_handler(filep, body, replace, op, EA_MODE_AI);
912         replace->length = old_length;
913         if(HAS_EA_PI(op->ea_allowed))
914         {
915                 generate_opcode_handler(filep, body, replace, op, EA_MODE_PI);
916                 replace->length = old_length;
917                 if(op->size == 8)
918                         generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7);
919         }
920         replace->length = old_length;
921         if(HAS_EA_PD(op->ea_allowed))
922         {
923                 generate_opcode_handler(filep, body, replace, op, EA_MODE_PD);
924                 replace->length = old_length;
925                 if(op->size == 8)
926                         generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7);
927         }
928         replace->length = old_length;
929         if(HAS_EA_DI(op->ea_allowed))
930                 generate_opcode_handler(filep, body, replace, op, EA_MODE_DI);
931         replace->length = old_length;
932         if(HAS_EA_IX(op->ea_allowed))
933                 generate_opcode_handler(filep, body, replace, op, EA_MODE_IX);
934         replace->length = old_length;
935         if(HAS_EA_AW(op->ea_allowed))
936                 generate_opcode_handler(filep, body, replace, op, EA_MODE_AW);
937         replace->length = old_length;
938         if(HAS_EA_AL(op->ea_allowed))
939                 generate_opcode_handler(filep, body, replace, op, EA_MODE_AL);
940         replace->length = old_length;
941         if(HAS_EA_PCDI(op->ea_allowed))
942                 generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI);
943         replace->length = old_length;
944         if(HAS_EA_PCIX(op->ea_allowed))
945                 generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX);
946         replace->length = old_length;
947         if(HAS_EA_I(op->ea_allowed))
948                 generate_opcode_handler(filep, body, replace, op, EA_MODE_I);
949         replace->length = old_length;
950 }
951
952 /* Generate variants of condition code opcodes */
953 void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset)
954 {
955         char repl[20];
956         char replnot[20];
957         int i;
958         int old_length = replace->length;
959         opcode_struct* op = malloc(sizeof(opcode_struct));
960
961         *op = *op_in;
962
963         op->op_mask |= 0x0f00;
964
965         /* Do all condition codes except t and f */
966         for(i=2;i<16;i++)
967         {
968                 /* Add replace strings for this condition code */
969                 sprintf(repl, "COND_%s()", g_cc_table[i][1]);
970                 sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]);
971
972                 add_replace_string(replace, ID_OPHANDLER_CC, repl);
973                 add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot);
974
975                 /* Set the new opcode info */
976                 strcpy(op->name+offset, g_cc_table[i][0]);
977
978                 op->op_match = (op->op_match & 0xf0ff) | (i<<8);
979
980                 /* Generate all opcode variants for this modified opcode */
981                 generate_opcode_ea_variants(filep, body, replace, op);
982                 /* Remove the above replace strings */
983                 replace->length = old_length;
984         }
985         free(op);
986 }
987
988 /* Process the opcode handlers section of the input file */
989 void process_opcode_handlers(FILE* filep)
990 {
991         FILE* input_file = g_input_file;
992         char func_name[MAX_LINE_LENGTH+1];
993         char oper_name[MAX_LINE_LENGTH+1];
994         int  oper_size;
995         char oper_spec_proc[MAX_LINE_LENGTH+1];
996         char oper_spec_ea[MAX_LINE_LENGTH+1];
997         opcode_struct* opinfo;
998         replace_struct* replace = malloc(sizeof(replace_struct));
999         body_struct* body = malloc(sizeof(body_struct));
1000
1001         for(;;)
1002         {
1003                 /* Find the first line of the function */
1004                 func_name[0] = 0;
1005                 while(strstr(func_name, ID_OPHANDLER_NAME) == NULL)
1006                 {
1007                         if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0)
1008                         {
1009                                 free(replace);
1010                                 free(body);
1011                                 return; /* all done */
1012                         }
1013                         if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0)
1014                                 error_exit("Premature end of file when getting function name");
1015                 }
1016                 /* Get the rest of the function */
1017                 for(body->length=0;;body->length++)
1018                 {
1019                         if(body->length > MAX_BODY_LENGTH)
1020                                 error_exit("Function too long");
1021
1022                         if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0)
1023                                 error_exit("Premature end of file when getting function body");
1024
1025                         if(body->body[body->length][0] == '}')
1026                         {
1027                                 body->length++;
1028                                 break;
1029                         }
1030                 }
1031
1032                 g_num_primitives++;
1033
1034                 /* Extract the function name information */
1035                 if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea))
1036                         error_exit("Invalid " ID_OPHANDLER_NAME " format");
1037
1038                 /* Find the corresponding table entry */
1039                 opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea);
1040                 if(opinfo == NULL)
1041                         error_exit("Unable to find matching table entry for %s", func_name);
1042
1043                 replace->length = 0;
1044
1045                 /* Generate opcode variants */
1046                 if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0)
1047                         generate_opcode_cc_variants(filep, body, replace, opinfo, 1);
1048                 else if(strcmp(opinfo->name, "dbcc") == 0)
1049                         generate_opcode_cc_variants(filep, body, replace, opinfo, 2);
1050                 else if(strcmp(opinfo->name, "trapcc") == 0)
1051                         generate_opcode_cc_variants(filep, body, replace, opinfo, 4);
1052                 else
1053                         generate_opcode_ea_variants(filep, body, replace, opinfo);
1054         }
1055
1056         free(replace);
1057         free(body);
1058 }
1059
1060
1061 /* Populate the opcode handler table from the input file */
1062 void populate_table(void)
1063 {
1064         char* ptr;
1065         char bitpattern[17];
1066         opcode_struct* op;
1067         char buff[MAX_LINE_LENGTH];
1068         int i;
1069         int temp;
1070
1071         buff[0] = 0;
1072
1073         /* Find the start of the table */
1074         while(strcmp(buff, ID_TABLE_START) != 0)
1075                 if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
1076                         error_exit("(table_start) Premature EOF while reading table");
1077
1078         /* Process the entire table */
1079         for(op = g_opcode_input_table;;op++)
1080         {
1081                 if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
1082                         error_exit("(inline) Premature EOF while reading table");
1083                 if(strlen(buff) == 0)
1084                         continue;
1085                 /* We finish when we find an input separator */
1086                 if(strcmp(buff, ID_INPUT_SEPARATOR) == 0)
1087                         break;
1088
1089                 /* Extract the info from the table */
1090                 ptr = buff;
1091
1092                 /* Name */
1093                 ptr += skip_spaces(ptr);
1094                 ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH);
1095
1096                 /* Size */
1097                 ptr += skip_spaces(ptr);
1098                 ptr += check_atoi(ptr, &temp);
1099                 op->size = (unsigned char)temp;
1100
1101                 /* Special processing */
1102                 ptr += skip_spaces(ptr);
1103                 ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH);
1104
1105                 /* Specified EA Mode */
1106                 ptr += skip_spaces(ptr);
1107                 ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH);
1108
1109                 /* Bit Pattern (more processing later) */
1110                 ptr += skip_spaces(ptr);
1111                 ptr += check_strsncpy(bitpattern, ptr, 17);
1112
1113                 /* Allowed Addressing Mode List */
1114                 ptr += skip_spaces(ptr);
1115                 ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH);
1116
1117                 /* CPU operating mode (U = user or supervisor, S = supervisor only */
1118                 ptr += skip_spaces(ptr);
1119                 for(i=0;i<NUM_CPUS;i++)
1120                 {
1121                         op->cpu_mode[i] = *ptr++;
1122                         ptr += skip_spaces(ptr);
1123                 }
1124
1125                 /* Allowed CPUs for this instruction */
1126                 for(i=0;i<NUM_CPUS;i++)
1127                 {
1128                         ptr += skip_spaces(ptr);
1129                         if(*ptr == UNSPECIFIED_CH)
1130                         {
1131                                 op->cpus[i] = UNSPECIFIED_CH;
1132                                 op->cycles[i] = 0;
1133                                 ptr++;
1134                         }
1135                         else
1136                         {
1137                                 op->cpus[i] = '0' + i;
1138                                 ptr += check_atoi(ptr, &temp);
1139                                 op->cycles[i] = (unsigned char)temp;
1140                         }
1141                 }
1142
1143                 /* generate mask and match from bitpattern */
1144                 op->op_mask = 0;
1145                 op->op_match = 0;
1146                 for(i=0;i<16;i++)
1147                 {
1148                         op->op_mask |= (bitpattern[i] != '.') << (15-i);
1149                         op->op_match |= (bitpattern[i] == '1') << (15-i);
1150                 }
1151         }
1152         /* Terminate the list */
1153         op->name[0] = 0;
1154 }
1155
1156 /* Read a header or footer insert from the input file */
1157 void read_insert(char* insert)
1158 {
1159         char* ptr = insert;
1160         char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH;
1161         int length;
1162         char* first_blank = NULL;
1163
1164         first_blank = NULL;
1165
1166         /* Skip any leading blank lines */
1167         for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file))
1168                 if(ptr >= overflow)
1169                         error_exit("Buffer overflow reading inserts");
1170         if(length < 0)
1171                 error_exit("Premature EOF while reading inserts");
1172
1173         /* Advance and append newline */
1174         ptr += length;
1175         strcpy(ptr++, "\n");
1176
1177         /* Read until next separator */
1178         for(;;)
1179         {
1180                 /* Read a new line */
1181                 if(ptr >= overflow)
1182                         error_exit("Buffer overflow reading inserts");
1183                 if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0)
1184                         error_exit("Premature EOF while reading inserts");
1185
1186                 /* Stop if we read a separator */
1187                 if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0)
1188                         break;
1189
1190                 /* keep track in case there are trailing blanks */
1191                 if(length == 0)
1192                 {
1193                         if(first_blank == NULL)
1194                                 first_blank = ptr;
1195                 }
1196                 else
1197                         first_blank = NULL;
1198
1199                 /* Advance and append newline */
1200                 ptr += length;
1201                 strcpy(ptr++, "\n");
1202         }
1203
1204         /* kill any trailing blank lines */
1205         if(first_blank)
1206                 ptr = first_blank;
1207         *ptr++ = 0;
1208 }
1209
1210
1211
1212 /* ======================================================================== */
1213 /* ============================= MAIN FUNCTION ============================ */
1214 /* ======================================================================== */
1215
1216 int main(int argc, char **argv)
1217 {
1218         /* File stuff */
1219         char output_path[M68K_MAX_DIR] = "";
1220         char filename[M68K_MAX_PATH*2];
1221         /* Section identifier */
1222         char section_id[MAX_LINE_LENGTH+1];
1223         /* Inserts */
1224         char temp_insert[MAX_INSERT_LENGTH+1];
1225         char prototype_footer_insert[MAX_INSERT_LENGTH+1];
1226         char table_header_insert[MAX_INSERT_LENGTH+1];
1227         char table_footer_insert[MAX_INSERT_LENGTH+1];
1228         char ophandler_header_insert[MAX_INSERT_LENGTH+1];
1229         char ophandler_footer_insert[MAX_INSERT_LENGTH+1];
1230         /* Flags if we've processed certain parts already */
1231         int prototype_header_read = 0;
1232         int prototype_footer_read = 0;
1233         int table_header_read = 0;
1234         int table_footer_read = 0;
1235         int ophandler_header_read = 0;
1236         int ophandler_footer_read = 0;
1237         int table_body_read = 0;
1238         int ophandler_body_read = 0;
1239
1240         printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, 68040 emulator\n", g_version);
1241         printf("\t\tCopyright Karl Stenerud (kstenerud@gmail.com)\n\n");
1242
1243         /* Check if output path and source for the input file are given */
1244     if(argc > 1)
1245         {
1246                 char *ptr;
1247                 strcpy(output_path, argv[1]);
1248
1249                 for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\'))
1250                         *ptr = '/';
1251         if(output_path[strlen(output_path)-1] != '/')
1252                         strcat(output_path, "/");
1253                 if(argc > 2)
1254                         strcpy(g_input_filename, argv[2]);
1255         }
1256
1257
1258         /* Open the files we need */
1259         sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE);
1260         if((g_prototype_file = fopen(filename, "wt")) == NULL)
1261                 perror_exit("Unable to create prototype file (%s)\n", filename);
1262
1263         sprintf(filename, "%s%s", output_path, FILENAME_TABLE);
1264         if((g_table_file = fopen(filename, "wt")) == NULL)
1265                 perror_exit("Unable to create table file (%s)\n", filename);
1266
1267         if((g_input_file=fopen(g_input_filename, "rt")) == NULL)
1268                 perror_exit("can't open %s for input", g_input_filename);
1269
1270
1271         /* Get to the first section of the input file */
1272         section_id[0] = 0;
1273         while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0)
1274                 if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
1275                         error_exit("Premature EOF while reading input file");
1276
1277         /* Now process all sections */
1278         for(;;)
1279         {
1280                 if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
1281                         error_exit("Premature EOF while reading input file");
1282                 if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0)
1283                 {
1284                         if(prototype_header_read)
1285                                 error_exit("Duplicate prototype header");
1286                         read_insert(temp_insert);
1287                         fprintf(g_prototype_file, "%s\n\n", temp_insert);
1288                         prototype_header_read = 1;
1289                 }
1290                 else if(strcmp(section_id, ID_TABLE_HEADER) == 0)
1291                 {
1292                         if(table_header_read)
1293                                 error_exit("Duplicate table header");
1294                         read_insert(table_header_insert);
1295                         table_header_read = 1;
1296                 }
1297                 else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0)
1298                 {
1299                         if(ophandler_header_read)
1300                                 error_exit("Duplicate opcode handler header");
1301                         read_insert(ophandler_header_insert);
1302                         ophandler_header_read = 1;
1303                 }
1304                 else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0)
1305                 {
1306                         if(prototype_footer_read)
1307                                 error_exit("Duplicate prototype footer");
1308                         read_insert(prototype_footer_insert);
1309                         prototype_footer_read = 1;
1310                 }
1311                 else if(strcmp(section_id, ID_TABLE_FOOTER) == 0)
1312                 {
1313                         if(table_footer_read)
1314                                 error_exit("Duplicate table footer");
1315                         read_insert(table_footer_insert);
1316                         table_footer_read = 1;
1317                 }
1318                 else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0)
1319                 {
1320                         if(ophandler_footer_read)
1321                                 error_exit("Duplicate opcode handler footer");
1322                         read_insert(ophandler_footer_insert);
1323                         ophandler_footer_read = 1;
1324                 }
1325                 else if(strcmp(section_id, ID_TABLE_BODY) == 0)
1326                 {
1327                         if(!prototype_header_read)
1328                                 error_exit("Table body encountered before prototype header");
1329                         if(!table_header_read)
1330                                 error_exit("Table body encountered before table header");
1331                         if(!ophandler_header_read)
1332                                 error_exit("Table body encountered before opcode handler header");
1333
1334                         if(table_body_read)
1335                                 error_exit("Duplicate table body");
1336
1337                         populate_table();
1338                         table_body_read = 1;
1339                 }
1340                 else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0)
1341                 {
1342                         if(!prototype_header_read)
1343                                 error_exit("Opcode handlers encountered before prototype header");
1344                         if(!table_header_read)
1345                                 error_exit("Opcode handlers encountered before table header");
1346                         if(!ophandler_header_read)
1347                                 error_exit("Opcode handlers encountered before opcode handler header");
1348                         if(!table_body_read)
1349                                 error_exit("Opcode handlers encountered before table body");
1350
1351                         if(ophandler_body_read)
1352                                 error_exit("Duplicate opcode handler section");
1353
1354                         fprintf(g_table_file, "%s\n\n", ophandler_header_insert);
1355                         process_opcode_handlers(g_table_file);
1356                         fprintf(g_table_file, "%s\n\n", ophandler_footer_insert);
1357
1358                         ophandler_body_read = 1;
1359                 }
1360                 else if(strcmp(section_id, ID_END) == 0)
1361                 {
1362                         /* End of input file.  Do a sanity check and then write footers */
1363                         if(!prototype_header_read)
1364                                 error_exit("Missing prototype header");
1365                         if(!prototype_footer_read)
1366                                 error_exit("Missing prototype footer");
1367                         if(!table_header_read)
1368                                 error_exit("Missing table header");
1369                         if(!table_footer_read)
1370                                 error_exit("Missing table footer");
1371                         if(!table_body_read)
1372                                 error_exit("Missing table body");
1373                         if(!ophandler_header_read)
1374                                 error_exit("Missing opcode handler header");
1375                         if(!ophandler_footer_read)
1376                                 error_exit("Missing opcode handler footer");
1377                         if(!ophandler_body_read)
1378                                 error_exit("Missing opcode handler body");
1379
1380                         fprintf(g_table_file, "%s\n\n", table_header_insert);
1381                         print_opcode_output_table(g_table_file);
1382                         fprintf(g_table_file, "%s\n\n", table_footer_insert);
1383
1384                         fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert);
1385
1386                         break;
1387                 }
1388                 else
1389                 {
1390                         error_exit("Unknown section identifier: %s", section_id);
1391                 }
1392         }
1393
1394         /* Close all files and exit */
1395         fclose(g_prototype_file);
1396         fclose(g_table_file);
1397         fclose(g_input_file);
1398
1399         printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives);
1400
1401         return 0;
1402 }
1403
1404
1405
1406 /* ======================================================================== */
1407 /* ============================== END OF FILE ============================= */
1408 /* ======================================================================== */