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