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 size_t check_strsncpy(char* dst, char* src, int maxlength);
222 size_t check_atoi(char* str, int *result);
223 size_t 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 */
error_exit(char * fmt,...)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 */
perror_exit(char * fmt,...)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 */
check_strsncpy(char * dst,char * src,int maxlength)495 size_t 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 */
check_strcncpy(char * dst,char * src,char delim,int maxlength)509 size_t 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 */
check_atoi(char * str,int * result)523 size_t 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 */
skip_spaces(char * str)539 size_t 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 */
num_bits(int 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 */
atoh(char * buff)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 */
fgetline(char * buff,int nchars,FILE * file)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 = (int)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 */
get_oper_cycles(opcode_struct * op,int ea_mode,int cpu_type)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 */
find_opcode(char * name,int size,char * spec_proc,char * spec_ea)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; strlen(op->name) != 0;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 */
find_illegal_opcode(void)664 opcode_struct* find_illegal_opcode(void)
665 {
666 	opcode_struct* op;
667 
668 	for(op = g_opcode_input_table;strlen(op->name) != 0;op++)
669 	{
670 		if(strcmp(op->name, "illegal") == 0)
671 			return op;
672 	}
673 	return NULL;
674 }
675 
676 /* Parse an opcode handler name */
extract_opcode_info(char * src,char * name,int * size,char * spec_proc,char * spec_ea)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 */
add_replace_string(replace_struct * replace,char * search_str,char * replace_str)712 void add_replace_string(replace_struct* replace, char* search_str, char* replace_str)
713 {
714 	size_t search_str_len = strlen(search_str);
715 	size_t replace_str_len = strlen(replace_str);
716 
717 	if(search_str_len >= 201)
718 		error_exit("search_str was too long");
719 
720 	if (replace_str_len >= 201)
721 		error_exit("replace_str was too long");
722 
723 	if(replace->length >= MAX_REPLACE_LENGTH)
724 		error_exit("overflow in replace structure");
725 
726 	strcpy(replace->replace[replace->length][0], search_str);
727 	strcpy(replace->replace[replace->length++][1], replace_str);
728 }
729 
730 /* Write a function body while replacing any selected strings */
write_body(FILE * filep,body_struct * body,replace_struct * replace)731 void write_body(FILE* filep, body_struct* body, replace_struct* replace)
732 {
733 	int i;
734 	int j;
735 	char* ptr;
736 	char output[MAX_LINE_LENGTH+1];
737 	char temp_buff[MAX_LINE_LENGTH+1];
738 	int found;
739 
740 	for(i=0;i<body->length;i++)
741 	{
742 		strcpy(output, body->body[i]);
743 		/* Check for the base directive header */
744 		if(strstr(output, ID_BASE) != NULL)
745 		{
746 			/* Search for any text we need to replace */
747 			found = 0;
748 			for(j=0;j<replace->length;j++)
749 			{
750 				ptr = strstr(output, replace->replace[j][0]);
751 				if(ptr)
752 				{
753 					size_t replace_len = strlen(ptr + strlen(replace->replace[j][0]));
754 					if(replace_len >= 201)
755 						error_exit("write_body: replace_len was too long");
756 					/* We found something to replace */
757 					found = 1;
758 					strcpy(temp_buff, ptr+strlen(replace->replace[j][0]));
759 					strcpy(ptr, replace->replace[j][1]);
760 					strcat(ptr, temp_buff);
761 				}
762 			}
763 			/* Found a directive with no matching replace string */
764 			if(!found)
765 				error_exit("Unknown " ID_BASE " directive");
766 		}
767 		fprintf(filep, "%s\n", output);
768 	}
769 	fprintf(filep, "\n\n");
770 }
771 
772 /* Generate a base function name from an opcode struct */
get_base_name(char * base_name,opcode_struct * op)773 void get_base_name(char* base_name, opcode_struct* op)
774 {
775 	sprintf(base_name, "m68k_op_%s", op->name);
776 	if(op->size > 0)
777 		sprintf(base_name+strlen(base_name), "_%d", op->size);
778 	if(strcmp(op->spec_proc, UNSPECIFIED) != 0)
779 		sprintf(base_name+strlen(base_name), "_%s", op->spec_proc);
780 	if(strcmp(op->spec_ea, UNSPECIFIED) != 0)
781 		sprintf(base_name+strlen(base_name), "_%s", op->spec_ea);
782 }
783 
784 /* Write the prototype of an opcode handler function */
write_prototype(FILE * filep,char * base_name)785 void write_prototype(FILE* filep, char* base_name)
786 {
787 	fprintf(filep, "void %s(void);\n", base_name);
788 }
789 
790 /* Write the name of an opcode handler function */
write_function_name(FILE * filep,char * base_name)791 void write_function_name(FILE* filep, char* base_name)
792 {
793 	fprintf(filep, "void %s(void)\n", base_name);
794 }
795 
add_opcode_output_table_entry(opcode_struct * op,char * name)796 void add_opcode_output_table_entry(opcode_struct* op, char* name)
797 {
798 	opcode_struct* ptr;
799 	size_t name_len = strlen(name);
800 
801 	if(name_len >= 30)
802 		error_exit("Opcode output name too long");
803 
804 	if(g_opcode_output_table_length >= MAX_OPCODE_OUTPUT_TABLE_LENGTH)
805 		error_exit("Opcode output table overflow");
806 
807 	ptr = g_opcode_output_table + g_opcode_output_table_length++;
808 
809 	*ptr = *op;
810 	strcpy(ptr->name, name);
811 	ptr->bits = num_bits(ptr->op_mask);
812 }
813 
814 /*
815  * Comparison function for qsort()
816  * For entries with an equal number of set bits in
817  * the mask compare the match values
818  */
compare_nof_true_bits(const void * aptr,const void * bptr)819 static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr)
820 {
821 	const opcode_struct *a = aptr, *b = bptr;
822 	if(a->bits != b->bits)
823 		return a->bits - b->bits;
824 	if(a->op_mask != b->op_mask)
825 		return a->op_mask - b->op_mask;
826 	return a->op_match - b->op_match;
827 }
828 
print_opcode_output_table(FILE * filep)829 void print_opcode_output_table(FILE* filep)
830 {
831 	int i;
832 	qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits);
833 
834 	for(i=0;i<g_opcode_output_table_length;i++)
835 		write_table_entry(filep, g_opcode_output_table+i);
836 }
837 
838 /* Write an entry in the opcode handler table */
write_table_entry(FILE * filep,opcode_struct * op)839 void write_table_entry(FILE* filep, opcode_struct* op)
840 {
841 	int i;
842 
843 	fprintf(filep, "\t{%-28s, 0x%04x, 0x%04x, {",
844 		op->name, op->op_mask, op->op_match);
845 
846 	for(i=0;i<NUM_CPUS;i++)
847 	{
848 		fprintf(filep, "%3d", op->cycles[i]);
849 		if(i < NUM_CPUS-1)
850 			fprintf(filep, ", ");
851 	}
852 
853 	fprintf(filep, "}},\n");
854 }
855 
856 /* Fill out an opcode struct with a specific addressing mode of the source opcode struct */
set_opcode_struct(opcode_struct * src,opcode_struct * dst,int ea_mode)857 void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode)
858 {
859 	int i;
860 
861 	*dst = *src;
862 
863 	for(i=0;i<NUM_CPUS;i++)
864 		dst->cycles[i] = get_oper_cycles(dst, ea_mode, i);
865 	if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE)
866 		sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add);
867 	dst->op_mask |= g_ea_info_table[ea_mode].mask_add;
868 	dst->op_match |= g_ea_info_table[ea_mode].match_add;
869 }
870 
871 
872 /* Generate a final opcode handler from the provided data */
generate_opcode_handler(FILE * filep,body_struct * body,replace_struct * replace,opcode_struct * opinfo,int ea_mode)873 void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode)
874 {
875 	char str[MAX_LINE_LENGTH+1];
876 	opcode_struct* op = malloc(sizeof(opcode_struct));
877 
878 	/* Set the opcode structure and write the tables, prototypes, etc */
879 	set_opcode_struct(opinfo, op, ea_mode);
880 	get_base_name(str, op);
881 	write_prototype(g_prototype_file, str);
882 	add_opcode_output_table_entry(op, str);
883 	write_function_name(filep, str);
884 
885 	/* Add any replace strings needed */
886 	if(ea_mode != EA_MODE_NONE)
887 	{
888 		sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add);
889 		add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str);
890 		sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add);
891 		add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str);
892 		sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add);
893 		add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str);
894 		sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add);
895 		add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str);
896 		sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add);
897 		add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str);
898 		sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add);
899 		add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str);
900 	}
901 
902 	/* Now write the function body with the selected replace strings */
903 	write_body(filep, body, replace);
904 	g_num_functions++;
905 	free(op);
906 }
907 
908 /* Generate opcode variants based on available addressing modes */
generate_opcode_ea_variants(FILE * filep,body_struct * body,replace_struct * replace,opcode_struct * op)909 void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op)
910 {
911 	int old_length = replace->length;
912 
913 	/* No ea modes available for this opcode */
914 	if(HAS_NO_EA_MODE(op->ea_allowed))
915 	{
916 		generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE);
917 		return;
918 	}
919 
920 	/* Check for and create specific opcodes for each available addressing mode */
921 	if(HAS_EA_AI(op->ea_allowed))
922 		generate_opcode_handler(filep, body, replace, op, EA_MODE_AI);
923 	replace->length = old_length;
924 	if(HAS_EA_PI(op->ea_allowed))
925 	{
926 		generate_opcode_handler(filep, body, replace, op, EA_MODE_PI);
927 		replace->length = old_length;
928 		if(op->size == 8)
929 			generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7);
930 	}
931 	replace->length = old_length;
932 	if(HAS_EA_PD(op->ea_allowed))
933 	{
934 		generate_opcode_handler(filep, body, replace, op, EA_MODE_PD);
935 		replace->length = old_length;
936 		if(op->size == 8)
937 			generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7);
938 	}
939 	replace->length = old_length;
940 	if(HAS_EA_DI(op->ea_allowed))
941 		generate_opcode_handler(filep, body, replace, op, EA_MODE_DI);
942 	replace->length = old_length;
943 	if(HAS_EA_IX(op->ea_allowed))
944 		generate_opcode_handler(filep, body, replace, op, EA_MODE_IX);
945 	replace->length = old_length;
946 	if(HAS_EA_AW(op->ea_allowed))
947 		generate_opcode_handler(filep, body, replace, op, EA_MODE_AW);
948 	replace->length = old_length;
949 	if(HAS_EA_AL(op->ea_allowed))
950 		generate_opcode_handler(filep, body, replace, op, EA_MODE_AL);
951 	replace->length = old_length;
952 	if(HAS_EA_PCDI(op->ea_allowed))
953 		generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI);
954 	replace->length = old_length;
955 	if(HAS_EA_PCIX(op->ea_allowed))
956 		generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX);
957 	replace->length = old_length;
958 	if(HAS_EA_I(op->ea_allowed))
959 		generate_opcode_handler(filep, body, replace, op, EA_MODE_I);
960 	replace->length = old_length;
961 }
962 
963 /* Generate variants of condition code opcodes */
generate_opcode_cc_variants(FILE * filep,body_struct * body,replace_struct * replace,opcode_struct * op_in,int offset)964 void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset)
965 {
966 	char repl[20];
967 	char replnot[20];
968 	int i;
969 	int old_length = replace->length;
970 	opcode_struct* op = malloc(sizeof(opcode_struct));
971 
972 	*op = *op_in;
973 
974 	op->op_mask |= 0x0f00;
975 
976 	/* Do all condition codes except t and f */
977 	for(i=2;i<16;i++)
978 	{
979 		/* Add replace strings for this condition code */
980 		sprintf(repl, "COND_%s()", g_cc_table[i][1]);
981 		sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]);
982 
983 		add_replace_string(replace, ID_OPHANDLER_CC, repl);
984 		add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot);
985 
986 		/* Set the new opcode info */
987 		strcpy(op->name+offset, g_cc_table[i][0]);
988 
989 		op->op_match = (op->op_match & 0xf0ff) | (i<<8);
990 
991 		/* Generate all opcode variants for this modified opcode */
992 		generate_opcode_ea_variants(filep, body, replace, op);
993 		/* Remove the above replace strings */
994 		replace->length = old_length;
995 	}
996 	free(op);
997 }
998 
999 /* Process the opcode handlers section of the input file */
process_opcode_handlers(void)1000 void process_opcode_handlers(void)
1001 {
1002 	FILE* input_file = g_input_file;
1003 	FILE* output_file;
1004 	char func_name[MAX_LINE_LENGTH+1];
1005 	char oper_name[MAX_LINE_LENGTH+1];
1006 	int  oper_size;
1007 	char oper_spec_proc[MAX_LINE_LENGTH+1];
1008 	char oper_spec_ea[MAX_LINE_LENGTH+1];
1009 	opcode_struct* opinfo;
1010 	replace_struct* replace = malloc(sizeof(replace_struct));
1011 	body_struct* body = malloc(sizeof(body_struct));
1012 
1013 
1014 	output_file = g_ops_ac_file;
1015 
1016 	for(;;)
1017 	{
1018 		/* Find the first line of the function */
1019 		func_name[0] = 0;
1020 		while(strstr(func_name, ID_OPHANDLER_NAME) == NULL)
1021 		{
1022 			if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0)
1023 			{
1024 				free(replace);
1025 				free(body);
1026 				return; /* all done */
1027 			}
1028 			if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0)
1029 				error_exit("Premature end of file when getting function name");
1030 		}
1031 		/* Get the rest of the function */
1032 		for(body->length=0;;body->length++)
1033 		{
1034 			if(body->length > MAX_BODY_LENGTH)
1035 				error_exit("Function too long");
1036 
1037 			if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0)
1038 				error_exit("Premature end of file when getting function body");
1039 
1040 			if(body->body[body->length][0] == '}')
1041 			{
1042 				body->length++;
1043 				break;
1044 			}
1045 		}
1046 
1047 		g_num_primitives++;
1048 
1049 		/* Extract the function name information */
1050 		if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea))
1051 			error_exit("Invalid " ID_OPHANDLER_NAME " format");
1052 
1053 		/* Find the corresponding table entry */
1054 		opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea);
1055 		if(opinfo == NULL)
1056 			error_exit("Unable to find matching table entry for %s", func_name);
1057 
1058         /* Change output files if we pass 'c' or 'n' */
1059 		if(output_file == g_ops_ac_file && oper_name[0] > 'c')
1060 			output_file = g_ops_dm_file;
1061 		else if(output_file == g_ops_dm_file && oper_name[0] > 'm')
1062 			output_file = g_ops_nz_file;
1063 
1064 		replace->length = 0;
1065 
1066 		/* Generate opcode variants */
1067 		if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0)
1068 			generate_opcode_cc_variants(output_file, body, replace, opinfo, 1);
1069 		else if(strcmp(opinfo->name, "dbcc") == 0)
1070 			generate_opcode_cc_variants(output_file, body, replace, opinfo, 2);
1071 		else if(strcmp(opinfo->name, "trapcc") == 0)
1072 			generate_opcode_cc_variants(output_file, body, replace, opinfo, 4);
1073 		else
1074 			generate_opcode_ea_variants(output_file, body, replace, opinfo);
1075 	}
1076 
1077 	free(replace);
1078 	free(body);
1079 }
1080 
1081 
1082 /* Populate the opcode handler table from the input file */
populate_table(void)1083 void populate_table(void)
1084 {
1085 	char* ptr;
1086 	char bitpattern[17];
1087 	opcode_struct* op;
1088 	char buff[MAX_LINE_LENGTH];
1089 	int i;
1090 	int temp;
1091 
1092 	buff[0] = 0;
1093 
1094 	/* Find the start of the table */
1095 	while(strcmp(buff, ID_TABLE_START) != 0)
1096 		if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
1097 			error_exit("Premature EOF while reading table");
1098 
1099 	/* Process the entire table */
1100 	for(op = g_opcode_input_table;;op++)
1101 	{
1102 		if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
1103 			error_exit("Premature EOF while reading table");
1104 		if(strlen(buff) == 0)
1105 			continue;
1106 		/* We finish when we find an input separator */
1107 		if(strcmp(buff, ID_INPUT_SEPARATOR) == 0)
1108 			break;
1109 
1110 		/* Extract the info from the table */
1111 		ptr = buff;
1112 
1113 		/* Name */
1114 		ptr += skip_spaces(ptr);
1115 		ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH);
1116 
1117 		/* Size */
1118 		ptr += skip_spaces(ptr);
1119 		ptr += check_atoi(ptr, &temp);
1120 		op->size = (unsigned char)temp;
1121 
1122 		/* Special processing */
1123 		ptr += skip_spaces(ptr);
1124 		ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH);
1125 
1126 		/* Specified EA Mode */
1127 		ptr += skip_spaces(ptr);
1128 		ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH);
1129 
1130 		/* Bit Pattern (more processing later) */
1131 		ptr += skip_spaces(ptr);
1132 		ptr += check_strsncpy(bitpattern, ptr, 17);
1133 
1134 		/* Allowed Addressing Mode List */
1135 		ptr += skip_spaces(ptr);
1136 		ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH);
1137 
1138 		/* CPU operating mode (U = user or supervisor, S = supervisor only */
1139 		ptr += skip_spaces(ptr);
1140 		for(i=0;i<NUM_CPUS;i++)
1141 		{
1142 			op->cpu_mode[i] = *ptr++;
1143 			ptr += skip_spaces(ptr);
1144 		}
1145 
1146 		/* Allowed CPUs for this instruction */
1147 		for(i=0;i<NUM_CPUS;i++)
1148 		{
1149 			ptr += skip_spaces(ptr);
1150 			if(*ptr == UNSPECIFIED_CH)
1151 			{
1152 				op->cpus[i] = UNSPECIFIED_CH;
1153 				op->cycles[i] = 0;
1154 				ptr++;
1155 			}
1156 			else
1157 			{
1158 				op->cpus[i] = '0' + i;
1159 				ptr += check_atoi(ptr, &temp);
1160 				op->cycles[i] = (unsigned char)temp;
1161 			}
1162 		}
1163 
1164 		/* generate mask and match from bitpattern */
1165 		op->op_mask = 0;
1166 		op->op_match = 0;
1167 		for(i=0;i<16;i++)
1168 		{
1169 			op->op_mask |= (bitpattern[i] != '.') << (15-i);
1170 			op->op_match |= (bitpattern[i] == '1') << (15-i);
1171 		}
1172 	}
1173 	/* Terminate the list */
1174 	op->name[0] = 0;
1175 }
1176 
1177 /* Read a header or footer insert from the input file */
read_insert(char * insert)1178 void read_insert(char* insert)
1179 {
1180 	char* ptr = insert;
1181 	char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH;
1182 	int length;
1183 	char* first_blank = NULL;
1184 
1185 	first_blank = NULL;
1186 
1187 	/* Skip any leading blank lines */
1188 	for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file))
1189 		if(ptr >= overflow)
1190 			error_exit("Buffer overflow reading inserts");
1191 	if(length < 0)
1192 		error_exit("Premature EOF while reading inserts");
1193 
1194 	/* Advance and append newline */
1195 	ptr += length;
1196 	strcpy(ptr++, "\n");
1197 
1198 	/* Read until next separator */
1199 	for(;;)
1200 	{
1201 		/* Read a new line */
1202 		if(ptr >= overflow)
1203 			error_exit("Buffer overflow reading inserts");
1204 		if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0)
1205 			error_exit("Premature EOF while reading inserts");
1206 
1207 		/* Stop if we read a separator */
1208 		if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0)
1209 			break;
1210 
1211 		/* keep track in case there are trailing blanks */
1212 		if(length == 0)
1213 		{
1214 			if(first_blank == NULL)
1215 				first_blank = ptr;
1216 		}
1217 		else
1218 			first_blank = NULL;
1219 
1220 		/* Advance and append newline */
1221 		ptr += length;
1222 		strcpy(ptr++, "\n");
1223 	}
1224 
1225 	/* kill any trailing blank lines */
1226 	if(first_blank)
1227 		ptr = first_blank;
1228 	*ptr++ = 0;
1229 }
1230 
1231 
1232 
1233 /* ======================================================================== */
1234 /* ============================= MAIN FUNCTION ============================ */
1235 /* ======================================================================== */
1236 
main(int argc,char ** argv)1237 int main(int argc, char **argv)
1238 {
1239 	/* File stuff */
1240 	char output_path[M68K_MAX_DIR] = "";
1241 	char filename[M68K_MAX_PATH];
1242 	/* Section identifier */
1243 	char section_id[MAX_LINE_LENGTH+1];
1244 	/* Inserts */
1245 	char temp_insert[MAX_INSERT_LENGTH+1];
1246 	char prototype_footer_insert[MAX_INSERT_LENGTH+1];
1247 	char table_footer_insert[MAX_INSERT_LENGTH+1];
1248 	char ophandler_footer_insert[MAX_INSERT_LENGTH+1];
1249 	/* Flags if we've processed certain parts already */
1250 	int prototype_header_read = 0;
1251 	int prototype_footer_read = 0;
1252 	int table_header_read = 0;
1253 	int table_footer_read = 0;
1254 	int ophandler_header_read = 0;
1255 	int ophandler_footer_read = 0;
1256 	int table_body_read = 0;
1257 	int ophandler_body_read = 0;
1258 
1259 	printf("\n\t\tMusashi v%s 68000, 68010, 68EC020, 68020 emulator\n", g_version);
1260 	printf("\t\tCopyright 1998-2000 Karl Stenerud (karl@mame.net)\n\n");
1261 
1262 	/* Check if output path and source for the input file are given */
1263     if(argc > 1)
1264 	{
1265 		char *ptr;
1266 		size_t argv_len = strlen(argv[1]);
1267 
1268 		if(argv_len >= 1024)
1269 			perror_exit("Argument was too long (%s)\n", argv[1]);
1270 
1271 		strcpy(output_path, argv[1]);
1272 
1273 		for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\'))
1274 			*ptr = '/';
1275         if(output_path[strlen(output_path)-1] != '/')
1276 			strcat(output_path, "/");
1277         if (argc > 2)
1278         {
1279            if (strlen(argv[2]) >= 1024)
1280               perror_exit("Argument 2 was too long (%s)\n", argv[2]);
1281 
1282            strcpy(g_input_filename, argv[2]);
1283         }
1284 	}
1285 
1286 
1287 	/* Open the files we need */
1288 	sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE);
1289 	if((g_prototype_file = fopen(filename, "wt")) == NULL)
1290 		perror_exit("Unable to create prototype file (%s)\n", filename);
1291 
1292 	sprintf(filename, "%s%s", output_path, FILENAME_TABLE);
1293 	if((g_table_file = fopen(filename, "wt")) == NULL)
1294 		perror_exit("Unable to create table file (%s)\n", filename);
1295 
1296 	sprintf(filename, "%s%s", output_path, FILENAME_OPS_AC);
1297 	if((g_ops_ac_file = fopen(filename, "wt")) == NULL)
1298 		perror_exit("Unable to create ops ac file (%s)\n", filename);
1299 
1300 	sprintf(filename, "%s%s", output_path, FILENAME_OPS_DM);
1301 	if((g_ops_dm_file = fopen(filename, "wt")) == NULL)
1302 		perror_exit("Unable to create ops dm file (%s)\n", filename);
1303 
1304 	sprintf(filename, "%s%s", output_path, FILENAME_OPS_NZ);
1305 	if((g_ops_nz_file = fopen(filename, "wt")) == NULL)
1306 		perror_exit("Unable to create ops nz file (%s)\n", filename);
1307 
1308 	if((g_input_file=fopen(g_input_filename, "rt")) == NULL)
1309 		perror_exit("can't open %s for input", g_input_filename);
1310 
1311 
1312 	/* Get to the first section of the input file */
1313 	section_id[0] = 0;
1314 	while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0)
1315 		if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
1316 			error_exit("Premature EOF while reading input file");
1317 
1318 	/* Now process all sections */
1319 	for(;;)
1320 	{
1321 		if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
1322 			error_exit("Premature EOF while reading input file");
1323 		if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0)
1324 		{
1325 			if(prototype_header_read)
1326 				error_exit("Duplicate prototype header");
1327 			read_insert(temp_insert);
1328 			fprintf(g_prototype_file, "%s\n\n", temp_insert);
1329 			prototype_header_read = 1;
1330 		}
1331 		else if(strcmp(section_id, ID_TABLE_HEADER) == 0)
1332 		{
1333 			if(table_header_read)
1334 				error_exit("Duplicate table header");
1335 			read_insert(temp_insert);
1336 			fprintf(g_table_file, "%s", temp_insert);
1337 			table_header_read = 1;
1338 		}
1339 		else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0)
1340 		{
1341 			if(ophandler_header_read)
1342 				error_exit("Duplicate opcode handler header");
1343 			read_insert(temp_insert);
1344 			fprintf(g_ops_ac_file, "%s\n\n", temp_insert);
1345 			fprintf(g_ops_dm_file, "%s\n\n", temp_insert);
1346 			fprintf(g_ops_nz_file, "%s\n\n", temp_insert);
1347 			ophandler_header_read = 1;
1348 		}
1349 		else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0)
1350 		{
1351 			if(prototype_footer_read)
1352 				error_exit("Duplicate prototype footer");
1353 			read_insert(prototype_footer_insert);
1354 			prototype_footer_read = 1;
1355 		}
1356 		else if(strcmp(section_id, ID_TABLE_FOOTER) == 0)
1357 		{
1358 			if(table_footer_read)
1359 				error_exit("Duplicate table footer");
1360 			read_insert(table_footer_insert);
1361 			table_footer_read = 1;
1362 		}
1363 		else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0)
1364 		{
1365 			if(ophandler_footer_read)
1366 				error_exit("Duplicate opcode handler footer");
1367 			read_insert(ophandler_footer_insert);
1368 			ophandler_footer_read = 1;
1369 		}
1370 		else if(strcmp(section_id, ID_TABLE_BODY) == 0)
1371 		{
1372 			if(!prototype_header_read)
1373 				error_exit("Table body encountered before prototype header");
1374 			if(!table_header_read)
1375 				error_exit("Table body encountered before table header");
1376 			if(!ophandler_header_read)
1377 				error_exit("Table body encountered before opcode handler header");
1378 
1379 			if(table_body_read)
1380 				error_exit("Duplicate table body");
1381 
1382 			populate_table();
1383 			table_body_read = 1;
1384 		}
1385 		else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0)
1386 		{
1387 			if(!prototype_header_read)
1388 				error_exit("Opcode handlers encountered before prototype header");
1389 			if(!table_header_read)
1390 				error_exit("Opcode handlers encountered before table header");
1391 			if(!ophandler_header_read)
1392 				error_exit("Opcode handlers encountered before opcode handler header");
1393 			if(!table_body_read)
1394 				error_exit("Opcode handlers encountered before table body");
1395 
1396 			if(ophandler_body_read)
1397 				error_exit("Duplicate opcode handler section");
1398 
1399 			process_opcode_handlers();
1400 
1401 			ophandler_body_read = 1;
1402 		}
1403 		else if(strcmp(section_id, ID_END) == 0)
1404 		{
1405 			/* End of input file.  Do a sanity check and then write footers */
1406 			if(!prototype_header_read)
1407 				error_exit("Missing prototype header");
1408 			if(!prototype_footer_read)
1409 				error_exit("Missing prototype footer");
1410 			if(!table_header_read)
1411 				error_exit("Missing table header");
1412 			if(!table_footer_read)
1413 				error_exit("Missing table footer");
1414 			if(!table_body_read)
1415 				error_exit("Missing table body");
1416 			if(!ophandler_header_read)
1417 				error_exit("Missing opcode handler header");
1418 			if(!ophandler_footer_read)
1419 				error_exit("Missing opcode handler footer");
1420 			if(!ophandler_body_read)
1421 				error_exit("Missing opcode handler body");
1422 
1423 			print_opcode_output_table(g_table_file);
1424 
1425 			fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert);
1426 			fprintf(g_table_file, "%s\n\n", table_footer_insert);
1427 			fprintf(g_ops_ac_file, "%s\n\n", ophandler_footer_insert);
1428 			fprintf(g_ops_dm_file, "%s\n\n", ophandler_footer_insert);
1429 			fprintf(g_ops_nz_file, "%s\n\n", ophandler_footer_insert);
1430 
1431 			break;
1432 		}
1433 		else
1434 		{
1435 			error_exit("Unknown section identifier: %s", section_id);
1436 		}
1437 	}
1438 
1439 	/* Close all files and exit */
1440 	fclose(g_prototype_file);
1441 	fclose(g_table_file);
1442 	fclose(g_ops_ac_file);
1443 	fclose(g_ops_dm_file);
1444 	fclose(g_ops_nz_file);
1445 	fclose(g_input_file);
1446 
1447 	printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives);
1448 
1449 	return 0;
1450 }
1451 
1452 
1453 
1454 /* ======================================================================== */
1455 /* ============================== END OF FILE ============================= */
1456 /* ======================================================================== */
1457