1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444 |
- /* ======================================================================== */
- /* ========================= LICENSING & COPYRIGHT ======================== */
- /* ======================================================================== */
- /*
- * MUSASHI
- * Version 3.31
- *
- * A portable Motorola M680x0 processor emulation engine.
- * Copyright 1998-2007 Karl Stenerud. All rights reserved.
- *
- * This code may be freely used for non-commercial purposes as long as this
- * copyright notice remains unaltered in the source code and any binary files
- * containing this code in compiled form.
- *
- * All other lisencing terms must be negotiated with the author
- * (Karl Stenerud).
- *
- * The latest version of this code can be obtained at:
- * http://kstenerud.cjb.net
- */
- /*
- * Modified For OpenVMS By: Robert Alan Byer
- * byer@mail.ourservers.net
- */
- /* ======================================================================== */
- /* ============================ CODE GENERATOR ============================ */
- /* ======================================================================== */
- /*
- * This is the code generator program which will generate the opcode table
- * and the final opcode handlers.
- *
- * It requires an input file to function (default m68k_in.c), but you can
- * specify your own like so:
- *
- * m68kmake <output path> <input file>
- *
- * where output path is the path where the output files should be placed, and
- * input file is the file to use for input.
- *
- * If you modify the input file greatly from its released form, you may have
- * to tweak the configuration section a bit since I'm using static allocation
- * to keep things simple.
- *
- *
- * TODO: - build a better code generator for the move instruction.
- * - Add callm and rtm instructions
- * - Fix RTE to handle other format words
- * - Add address error (and bus error?) handling
- */
- static const char* g_version = "3.31";
- /* ======================================================================== */
- /* =============================== INCLUDES =============================== */
- /* ======================================================================== */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdarg.h>
- /* ======================================================================== */
- /* ============================= CONFIGURATION ============================ */
- /* ======================================================================== */
- #define M68K_MAX_PATH 1024
- #define M68K_MAX_DIR 1024
- #define MAX_LINE_LENGTH 200 /* length of 1 line */
- #define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */
- #define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */
- #define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */
- #define MAX_NAME_LENGTH 30 /* Max length of ophandler name */
- #define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */
- #define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */
- #define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */
- #define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */
- #define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */
- /* Default filenames */
- #define FILENAME_INPUT "m68k_in.c"
- #define FILENAME_PROTOTYPE "m68kops.h"
- #define FILENAME_TABLE "m68kops.c"
- /* Identifier sequences recognized by this program */
- #define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
- #define ID_BASE "M68KMAKE"
- #define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER"
- #define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER"
- #define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER"
- #define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER"
- #define ID_TABLE_BODY ID_BASE "_TABLE_BODY"
- #define ID_TABLE_START ID_BASE "_TABLE_START"
- #define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER"
- #define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER"
- #define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY"
- #define ID_END ID_BASE "_END"
- #define ID_OPHANDLER_NAME ID_BASE "_OP"
- #define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8"
- #define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16"
- #define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32"
- #define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8"
- #define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16"
- #define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32"
- #define ID_OPHANDLER_CC ID_BASE "_CC"
- #define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC"
- #ifndef DECL_SPEC
- #define DECL_SPEC
- #endif /* DECL_SPEC */
- #ifdef USE_LIBRETRO_VFS
- #include "file_stream_transforms.h"
- #endif
- /* ======================================================================== */
- /* ============================== PROTOTYPES ============================== */
- /* ======================================================================== */
- enum {
- CPU_TYPE_000 = 0,
- CPU_TYPE_010,
- CPU_TYPE_020,
- CPU_TYPE_040,
- NUM_CPUS
- };
- #define UNSPECIFIED "."
- #define UNSPECIFIED_CH '.'
- #define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0)
- #define HAS_EA_AI(A) ((A)[0] == 'A')
- #define HAS_EA_PI(A) ((A)[1] == '+')
- #define HAS_EA_PD(A) ((A)[2] == '-')
- #define HAS_EA_DI(A) ((A)[3] == 'D')
- #define HAS_EA_IX(A) ((A)[4] == 'X')
- #define HAS_EA_AW(A) ((A)[5] == 'W')
- #define HAS_EA_AL(A) ((A)[6] == 'L')
- #define HAS_EA_PCDI(A) ((A)[7] == 'd')
- #define HAS_EA_PCIX(A) ((A)[8] == 'x')
- #define HAS_EA_I(A) ((A)[9] == 'I')
- enum
- {
- EA_MODE_NONE, /* No special addressing mode */
- EA_MODE_AI, /* Address register indirect */
- EA_MODE_PI, /* Address register indirect with postincrement */
- EA_MODE_PI7, /* Address register 7 indirect with postincrement */
- EA_MODE_PD, /* Address register indirect with predecrement */
- EA_MODE_PD7, /* Address register 7 indirect with predecrement */
- EA_MODE_DI, /* Address register indirect with displacement */
- EA_MODE_IX, /* Address register indirect with index */
- EA_MODE_AW, /* Absolute word */
- EA_MODE_AL, /* Absolute long */
- EA_MODE_PCDI, /* Program counter indirect with displacement */
- EA_MODE_PCIX, /* Program counter indirect with index */
- EA_MODE_I /* Immediate */
- };
- /* Everything we need to know about an opcode */
- typedef struct
- {
- char name[MAX_NAME_LENGTH]; /* opcode handler name */
- unsigned char size; /* Size of operation */
- char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */
- char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */
- unsigned char bits; /* Number of significant bits (used for sorting the table) */
- unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */
- unsigned short op_match; /* Value to match after masking */
- char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */
- char cpu_mode[NUM_CPUS]; /* User or supervisor mode */
- char cpus[NUM_CPUS+1]; /* Allowed CPUs */
- unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020 */
- } opcode_struct;
- /* All modifications necessary for a specific EA mode of an instruction */
- typedef struct
- {
- const char* fname_add;
- const char* ea_add;
- unsigned int mask_add;
- unsigned int match_add;
- } ea_info_struct;
- /* Holds the body of a function */
- typedef struct
- {
- char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1];
- int length;
- } body_struct;
- /* Holds a sequence of search / replace strings */
- typedef struct
- {
- char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1];
- int length;
- } replace_struct;
- /* Function Prototypes */
- void error_exit(const char* fmt, ...);
- void perror_exit(const char* fmt, ...);
- int check_strsncpy(char* dst, char* src, int maxlength);
- int check_atoi(char* str, int *result);
- int skip_spaces(char* str);
- int num_bits(int value);
- int atoh(char* buff);
- int fgetline(char* buff, int nchars, FILE* file);
- int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type);
- opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea);
- opcode_struct* find_illegal_opcode(void);
- int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea);
- void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str);
- void write_body(FILE* filep, body_struct* body, replace_struct* replace);
- void get_base_name(char* base_name, opcode_struct* op);
- void write_prototype(FILE* filep, char* base_name);
- void write_function_name(FILE* filep, char* base_name);
- void add_opcode_output_table_entry(opcode_struct* op, char* name);
- static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr);
- void print_opcode_output_table(FILE* filep);
- void write_table_entry(FILE* filep, opcode_struct* op);
- void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode);
- void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode);
- void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op);
- void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset);
- void process_opcode_handlers(FILE* filep);
- void populate_table(void);
- void read_insert(char* insert);
- /* ======================================================================== */
- /* ================================= DATA ================================= */
- /* ======================================================================== */
- /* Name of the input file */
- char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT;
- /* File handles */
- FILE* g_input_file = NULL;
- FILE* g_prototype_file = NULL;
- FILE* g_table_file = NULL;
- int g_num_functions = 0; /* Number of functions processed */
- int g_num_primitives = 0; /* Number of function primitives read */
- int g_line_number = 1; /* Current line number */
- /* Opcode handler table */
- opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];
- opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH];
- int g_opcode_output_table_length = 0;
- ea_info_struct g_ea_info_table[13] =
- {/* fname ea mask match */
- {"", "", 0x00, 0x00}, /* EA_MODE_NONE */
- {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */
- {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */
- {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */
- {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */
- {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */
- {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */
- {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */
- {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */
- {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */
- {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */
- {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */
- {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */
- };
- const char* g_cc_table[16][2] =
- {
- { "t", "T"}, /* 0000 */
- { "f", "F"}, /* 0001 */
- {"hi", "HI"}, /* 0010 */
- {"ls", "LS"}, /* 0011 */
- {"cc", "CC"}, /* 0100 */
- {"cs", "CS"}, /* 0101 */
- {"ne", "NE"}, /* 0110 */
- {"eq", "EQ"}, /* 0111 */
- {"vc", "VC"}, /* 1000 */
- {"vs", "VS"}, /* 1001 */
- {"pl", "PL"}, /* 1010 */
- {"mi", "MI"}, /* 1011 */
- {"ge", "GE"}, /* 1100 */
- {"lt", "LT"}, /* 1101 */
- {"gt", "GT"}, /* 1110 */
- {"le", "LE"}, /* 1111 */
- };
- /* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */
- int g_size_select_table[33] =
- {
- 0, /* unsized */
- 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */
- 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */
- };
- /* Extra cycles required for certain EA modes */
- /* TODO: correct timings for 040 */
- int g_ea_cycle_table[13][NUM_CPUS][3] =
- {/* 000 010 020 040 */
- {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */
- {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AI */
- {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI */
- {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI7 */
- {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD */
- {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD7 */
- {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_DI */
- {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_IX */
- {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AW */
- {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AL */
- {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PCDI */
- {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_PCIX */
- {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}, { 0, 2, 4}}, /* EA_MODE_I */
- };
- /* Extra cycles for JMP instruction (000, 010) */
- int g_jmp_cycle_table[13] =
- {
- 0, /* EA_MODE_NONE */
- 4, /* EA_MODE_AI */
- 0, /* EA_MODE_PI */
- 0, /* EA_MODE_PI7 */
- 0, /* EA_MODE_PD */
- 0, /* EA_MODE_PD7 */
- 6, /* EA_MODE_DI */
- 10, /* EA_MODE_IX */
- 6, /* EA_MODE_AW */
- 8, /* EA_MODE_AL */
- 6, /* EA_MODE_PCDI */
- 10, /* EA_MODE_PCIX */
- 0, /* EA_MODE_I */
- };
- /* Extra cycles for JSR instruction (000, 010) */
- int g_jsr_cycle_table[13] =
- {
- 0, /* EA_MODE_NONE */
- 4, /* EA_MODE_AI */
- 0, /* EA_MODE_PI */
- 0, /* EA_MODE_PI7 */
- 0, /* EA_MODE_PD */
- 0, /* EA_MODE_PD7 */
- 6, /* EA_MODE_DI */
- 10, /* EA_MODE_IX */
- 6, /* EA_MODE_AW */
- 8, /* EA_MODE_AL */
- 6, /* EA_MODE_PCDI */
- 10, /* EA_MODE_PCIX */
- 0, /* EA_MODE_I */
- };
- /* Extra cycles for LEA instruction (000, 010) */
- int g_lea_cycle_table[13] =
- {
- 0, /* EA_MODE_NONE */
- 4, /* EA_MODE_AI */
- 0, /* EA_MODE_PI */
- 0, /* EA_MODE_PI7 */
- 0, /* EA_MODE_PD */
- 0, /* EA_MODE_PD7 */
- 8, /* EA_MODE_DI */
- 12, /* EA_MODE_IX */
- 8, /* EA_MODE_AW */
- 12, /* EA_MODE_AL */
- 8, /* EA_MODE_PCDI */
- 12, /* EA_MODE_PCIX */
- 0, /* EA_MODE_I */
- };
- /* Extra cycles for PEA instruction (000, 010) */
- int g_pea_cycle_table[13] =
- {
- 0, /* EA_MODE_NONE */
- 6, /* EA_MODE_AI */
- 0, /* EA_MODE_PI */
- 0, /* EA_MODE_PI7 */
- 0, /* EA_MODE_PD */
- 0, /* EA_MODE_PD7 */
- 10, /* EA_MODE_DI */
- 14, /* EA_MODE_IX */
- 10, /* EA_MODE_AW */
- 14, /* EA_MODE_AL */
- 10, /* EA_MODE_PCDI */
- 14, /* EA_MODE_PCIX */
- 0, /* EA_MODE_I */
- };
- /* Extra cycles for MOVEM instruction (000, 010) */
- int g_movem_cycle_table[13] =
- {
- 0, /* EA_MODE_NONE */
- 0, /* EA_MODE_AI */
- 0, /* EA_MODE_PI */
- 0, /* EA_MODE_PI7 */
- 0, /* EA_MODE_PD */
- 0, /* EA_MODE_PD7 */
- 4, /* EA_MODE_DI */
- 6, /* EA_MODE_IX */
- 4, /* EA_MODE_AW */
- 8, /* EA_MODE_AL */
- 0, /* EA_MODE_PCDI */
- 0, /* EA_MODE_PCIX */
- 0, /* EA_MODE_I */
- };
- /* Extra cycles for MOVES instruction (010) */
- int g_moves_cycle_table[13][3] =
- {
- { 0, 0, 0}, /* EA_MODE_NONE */
- { 0, 4, 6}, /* EA_MODE_AI */
- { 0, 4, 6}, /* EA_MODE_PI */
- { 0, 4, 6}, /* EA_MODE_PI7 */
- { 0, 6, 12}, /* EA_MODE_PD */
- { 0, 6, 12}, /* EA_MODE_PD7 */
- { 0, 12, 16}, /* EA_MODE_DI */
- { 0, 16, 20}, /* EA_MODE_IX */
- { 0, 12, 16}, /* EA_MODE_AW */
- { 0, 16, 20}, /* EA_MODE_AL */
- { 0, 0, 0}, /* EA_MODE_PCDI */
- { 0, 0, 0}, /* EA_MODE_PCIX */
- { 0, 0, 0}, /* EA_MODE_I */
- };
- /* Extra cycles for CLR instruction (010) */
- int g_clr_cycle_table[13][3] =
- {
- { 0, 0, 0}, /* EA_MODE_NONE */
- { 0, 4, 6}, /* EA_MODE_AI */
- { 0, 4, 6}, /* EA_MODE_PI */
- { 0, 4, 6}, /* EA_MODE_PI7 */
- { 0, 6, 8}, /* EA_MODE_PD */
- { 0, 6, 8}, /* EA_MODE_PD7 */
- { 0, 8, 10}, /* EA_MODE_DI */
- { 0, 10, 14}, /* EA_MODE_IX */
- { 0, 8, 10}, /* EA_MODE_AW */
- { 0, 10, 14}, /* EA_MODE_AL */
- { 0, 0, 0}, /* EA_MODE_PCDI */
- { 0, 0, 0}, /* EA_MODE_PCIX */
- { 0, 0, 0}, /* EA_MODE_I */
- };
- /* ======================================================================== */
- /* =========================== UTILITY FUNCTIONS ========================== */
- /* ======================================================================== */
- /* Print an error message and exit with status error */
- void error_exit(const char* fmt, ...)
- {
- va_list args;
- fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fprintf(stderr, "\n");
- if(g_prototype_file) fclose(g_prototype_file);
- if(g_table_file) fclose(g_table_file);
- if(g_input_file) fclose(g_input_file);
- exit(EXIT_FAILURE);
- }
- /* Print an error message, call perror(), and exit with status error */
- void perror_exit(const char* fmt, ...)
- {
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- perror("");
- if(g_prototype_file) fclose(g_prototype_file);
- if(g_table_file) fclose(g_table_file);
- if(g_input_file) fclose(g_input_file);
- exit(EXIT_FAILURE);
- }
- /* copy until 0 or space and exit with error if we read too far */
- int check_strsncpy(char* dst, char* src, int maxlength)
- {
- char* p = dst;
- while(*src && *src != ' ')
- {
- *p++ = *src++;
- if(p - dst > maxlength)
- error_exit("Field too long");
- }
- *p = 0;
- return p - dst;
- }
- /* copy until 0 or specified character and exit with error if we read too far */
- int check_strcncpy(char* dst, char* src, char delim, int maxlength)
- {
- char* p = dst;
- while(*src && *src != delim)
- {
- *p++ = *src++;
- if(p - dst > maxlength)
- error_exit("Field too long");
- }
- *p = 0;
- return p - dst;
- }
- /* convert ascii to integer and exit with error if we find invalid data */
- int check_atoi(char* str, int *result)
- {
- int accum = 0;
- char* p = str;
- while(*p >= '0' && *p <= '9')
- {
- accum *= 10;
- accum += *p++ - '0';
- }
- if(*p != ' ' && *p != 0)
- error_exit("Malformed integer value (%c)", *p);
- *result = accum;
- return p - str;
- }
- /* Skip past spaces in a string */
- int skip_spaces(char* str)
- {
- char* p = str;
- while(*p == ' ')
- p++;
- return p - str;
- }
- /* Count the number of set bits in a value */
- int num_bits(int value)
- {
- value = ((value & 0xaaaa) >> 1) + (value & 0x5555);
- value = ((value & 0xcccc) >> 2) + (value & 0x3333);
- value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f);
- value = ((value & 0xff00) >> 8) + (value & 0x00ff);
- return value;
- }
- /* Convert a hex value written in ASCII */
- int atoh(char* buff)
- {
- int accum = 0;
- for(;;buff++)
- {
- if(*buff >= '0' && *buff <= '9')
- {
- accum <<= 4;
- accum += *buff - '0';
- }
- else if(*buff >= 'a' && *buff <= 'f')
- {
- accum <<= 4;
- accum += *buff - 'a' + 10;
- }
- else break;
- }
- return accum;
- }
- /* Get a line of text from a file, discarding any end-of-line characters */
- int fgetline(char* buff, int nchars, FILE* file)
- {
- int length;
- if(fgets(buff, nchars, file) == NULL)
- return -1;
- if(buff[0] == '\r')
- memcpy(buff, buff + 1, nchars - 1);
- length = strlen(buff);
- while(length && (buff[length-1] == '\r' || buff[length-1] == '\n'))
- length--;
- buff[length] = 0;
- g_line_number++;
- return length;
- }
- /* ======================================================================== */
- /* =========================== HELPER FUNCTIONS =========================== */
- /* ======================================================================== */
- /* Calculate the number of cycles an opcode requires */
- int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type)
- {
- int size = g_size_select_table[op->size];
- if(op->cpus[cpu_type] == '.')
- return 0;
- if(cpu_type < CPU_TYPE_020)
- {
- if(cpu_type == CPU_TYPE_010)
- {
- if(strcmp(op->name, "moves") == 0)
- return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size];
- if(strcmp(op->name, "clr") == 0)
- return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size];
- }
- /* ASG: added these cases -- immediate modes take 2 extra cycles here */
- /* SV: but only when operating on long, and also on register direct mode */
- if(cpu_type == CPU_TYPE_000 && (ea_mode == EA_MODE_I || ea_mode == EA_MODE_NONE) && op->size == 32 &&
- ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) ||
- strcmp(op->name, "adda") == 0 ||
- (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) ||
- (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) ||
- (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) ||
- strcmp(op->name, "suba") == 0))
- return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
- if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && op->size == 8 && strcmp(op->name, "btst") == 0)
- return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
- if(strcmp(op->name, "jmp") == 0)
- return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode];
- if(strcmp(op->name, "jsr") == 0)
- return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode];
- if(strcmp(op->name, "lea") == 0)
- return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode];
- if(strcmp(op->name, "pea") == 0)
- return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode];
- if(strcmp(op->name, "movem") == 0)
- return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode];
- }
- return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size];
- }
- /* Find an opcode in the opcode handler list */
- opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea)
- {
- opcode_struct* op;
- for(op = g_opcode_input_table;op->name != NULL;op++)
- {
- if( strcmp(name, op->name) == 0 &&
- (size == op->size) &&
- strcmp(spec_proc, op->spec_proc) == 0 &&
- strcmp(spec_ea, op->spec_ea) == 0)
- return op;
- }
- return NULL;
- }
- /* Specifically find the illegal opcode in the list */
- opcode_struct* find_illegal_opcode(void)
- {
- opcode_struct* op;
- for(op = g_opcode_input_table;op->name != NULL;op++)
- {
- if(strcmp(op->name, "illegal") == 0)
- return op;
- }
- return NULL;
- }
- /* Parse an opcode handler name */
- int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea)
- {
- char* ptr = strstr(src, ID_OPHANDLER_NAME);
- if(ptr == NULL)
- return 0;
- ptr += strlen(ID_OPHANDLER_NAME) + 1;
- ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH);
- if(*ptr != ',') return 0;
- ptr++;
- ptr += skip_spaces(ptr);
- *size = atoi(ptr);
- ptr = strstr(ptr, ",");
- if(ptr == NULL) return 0;
- ptr++;
- ptr += skip_spaces(ptr);
- ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH);
- if(*ptr != ',') return 0;
- ptr++;
- ptr += skip_spaces(ptr);
- ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH);
- if(*ptr != ')') return 0;
- ptr++;
- ptr += skip_spaces(ptr);
- return 1;
- }
- /* Add a search/replace pair to a replace structure */
- void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str)
- {
- if(replace->length >= MAX_REPLACE_LENGTH)
- error_exit("overflow in replace structure");
- strcpy(replace->replace[replace->length][0], search_str);
- strcpy(replace->replace[replace->length++][1], replace_str);
- }
- /* Write a function body while replacing any selected strings */
- void write_body(FILE* filep, body_struct* body, replace_struct* replace)
- {
- int i;
- int j;
- char* ptr;
- char output[MAX_LINE_LENGTH+1];
- char temp_buff[MAX_LINE_LENGTH+1];
- int found;
- for(i=0;i<body->length;i++)
- {
- strcpy(output, body->body[i]);
- /* Check for the base directive header */
- if(strstr(output, ID_BASE) != NULL)
- {
- /* Search for any text we need to replace */
- found = 0;
- for(j=0;j<replace->length;j++)
- {
- ptr = strstr(output, replace->replace[j][0]);
- if(ptr)
- {
- /* We found something to replace */
- found = 1;
- strcpy(temp_buff, ptr+strlen(replace->replace[j][0]));
- strcpy(ptr, replace->replace[j][1]);
- strcat(ptr, temp_buff);
- }
- }
- /* Found a directive with no matching replace string */
- if(!found)
- error_exit("Unknown " ID_BASE " directive");
- }
- fprintf(filep, "%s\n", output);
- }
- fprintf(filep, "\n\n");
- }
- /* Generate a base function name from an opcode struct */
- void get_base_name(char* base_name, opcode_struct* op)
- {
- sprintf(base_name, "m68k_op_%s", op->name);
- if(op->size > 0)
- sprintf(base_name+strlen(base_name), "_%d", op->size);
- if(strcmp(op->spec_proc, UNSPECIFIED) != 0)
- sprintf(base_name+strlen(base_name), "_%s", op->spec_proc);
- if(strcmp(op->spec_ea, UNSPECIFIED) != 0)
- sprintf(base_name+strlen(base_name), "_%s", op->spec_ea);
- }
- /* Write the prototype of an opcode handler function */
- void write_prototype(FILE* filep, char* base_name)
- {
- fprintf(filep, "void %s(void);\n", base_name);
- }
- /* Write the name of an opcode handler function */
- void write_function_name(FILE* filep, char* base_name)
- {
- fprintf(filep, "void %s(void)\n", base_name);
- }
- void add_opcode_output_table_entry(opcode_struct* op, char* name)
- {
- opcode_struct* ptr;
- if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH)
- error_exit("Opcode output table overflow");
- ptr = g_opcode_output_table + g_opcode_output_table_length++;
- *ptr = *op;
- strcpy(ptr->name, name);
- ptr->bits = num_bits(ptr->op_mask);
- }
- /*
- * Comparison function for qsort()
- * For entries with an equal number of set bits in
- * the mask compare the match values
- */
- static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr)
- {
- const opcode_struct *a = aptr, *b = bptr;
- if(a->bits != b->bits)
- return a->bits - b->bits;
- if(a->op_mask != b->op_mask)
- return a->op_mask - b->op_mask;
- return a->op_match - b->op_match;
- }
- void print_opcode_output_table(FILE* filep)
- {
- int i;
- qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits);
- for(i=0;i<g_opcode_output_table_length;i++)
- write_table_entry(filep, g_opcode_output_table+i);
- }
- /* Write an entry in the opcode handler table */
- void write_table_entry(FILE* filep, opcode_struct* op)
- {
- int i;
- fprintf(filep, "\t{%-28s, 0x%04x, 0x%04x, {",
- op->name, op->op_mask, op->op_match);
- for(i=0;i<NUM_CPUS;i++)
- {
- fprintf(filep, "%3d", op->cycles[i]);
- if(i < NUM_CPUS-1)
- fprintf(filep, ", ");
- }
- fprintf(filep, "}},\n");
- }
- /* Fill out an opcode struct with a specific addressing mode of the source opcode struct */
- void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode)
- {
- int i;
- *dst = *src;
- for(i=0;i<NUM_CPUS;i++)
- dst->cycles[i] = get_oper_cycles(dst, ea_mode, i);
- if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE)
- sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add);
- dst->op_mask |= g_ea_info_table[ea_mode].mask_add;
- dst->op_match |= g_ea_info_table[ea_mode].match_add;
- }
- /* Generate a final opcode handler from the provided data */
- void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode)
- {
- char str[MAX_LINE_LENGTH+1];
- opcode_struct* op = malloc(sizeof(opcode_struct));
- /* Set the opcode structure and write the tables, prototypes, etc */
- set_opcode_struct(opinfo, op, ea_mode);
- get_base_name(str, op);
- write_prototype(g_prototype_file, str);
- add_opcode_output_table_entry(op, str);
- write_function_name(filep, str);
- /* Add any replace strings needed */
- if(ea_mode != EA_MODE_NONE)
- {
- sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add);
- add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str);
- sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add);
- add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str);
- sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add);
- add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str);
- sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add);
- add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str);
- sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add);
- add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str);
- sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add);
- add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str);
- }
- /* Now write the function body with the selected replace strings */
- write_body(filep, body, replace);
- g_num_functions++;
- free(op);
- }
- /* Generate opcode variants based on available addressing modes */
- void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op)
- {
- int old_length = replace->length;
- /* No ea modes available for this opcode */
- if(HAS_NO_EA_MODE(op->ea_allowed))
- {
- generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE);
- return;
- }
- /* Check for and create specific opcodes for each available addressing mode */
- if(HAS_EA_AI(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_AI);
- replace->length = old_length;
- if(HAS_EA_PI(op->ea_allowed))
- {
- generate_opcode_handler(filep, body, replace, op, EA_MODE_PI);
- replace->length = old_length;
- if(op->size == 8)
- generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7);
- }
- replace->length = old_length;
- if(HAS_EA_PD(op->ea_allowed))
- {
- generate_opcode_handler(filep, body, replace, op, EA_MODE_PD);
- replace->length = old_length;
- if(op->size == 8)
- generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7);
- }
- replace->length = old_length;
- if(HAS_EA_DI(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_DI);
- replace->length = old_length;
- if(HAS_EA_IX(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_IX);
- replace->length = old_length;
- if(HAS_EA_AW(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_AW);
- replace->length = old_length;
- if(HAS_EA_AL(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_AL);
- replace->length = old_length;
- if(HAS_EA_PCDI(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI);
- replace->length = old_length;
- if(HAS_EA_PCIX(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX);
- replace->length = old_length;
- if(HAS_EA_I(op->ea_allowed))
- generate_opcode_handler(filep, body, replace, op, EA_MODE_I);
- replace->length = old_length;
- }
- /* Generate variants of condition code opcodes */
- void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset)
- {
- char repl[20];
- char replnot[20];
- int i;
- int old_length = replace->length;
- opcode_struct* op = malloc(sizeof(opcode_struct));
- *op = *op_in;
- op->op_mask |= 0x0f00;
- /* Do all condition codes except t and f */
- for(i=2;i<16;i++)
- {
- /* Add replace strings for this condition code */
- sprintf(repl, "COND_%s()", g_cc_table[i][1]);
- sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]);
- add_replace_string(replace, ID_OPHANDLER_CC, repl);
- add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot);
- /* Set the new opcode info */
- strcpy(op->name+offset, g_cc_table[i][0]);
- op->op_match = (op->op_match & 0xf0ff) | (i<<8);
- /* Generate all opcode variants for this modified opcode */
- generate_opcode_ea_variants(filep, body, replace, op);
- /* Remove the above replace strings */
- replace->length = old_length;
- }
- free(op);
- }
- /* Process the opcode handlers section of the input file */
- void process_opcode_handlers(FILE* filep)
- {
- FILE* input_file = g_input_file;
- char func_name[MAX_LINE_LENGTH+1];
- char oper_name[MAX_LINE_LENGTH+1];
- int oper_size;
- char oper_spec_proc[MAX_LINE_LENGTH+1];
- char oper_spec_ea[MAX_LINE_LENGTH+1];
- opcode_struct* opinfo;
- replace_struct* replace = malloc(sizeof(replace_struct));
- body_struct* body = malloc(sizeof(body_struct));
- for(;;)
- {
- /* Find the first line of the function */
- func_name[0] = 0;
- while(strstr(func_name, ID_OPHANDLER_NAME) == NULL)
- {
- if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0)
- {
- free(replace);
- free(body);
- return; /* all done */
- }
- if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0)
- error_exit("Premature end of file when getting function name");
- }
- /* Get the rest of the function */
- for(body->length=0;;body->length++)
- {
- if(body->length > MAX_BODY_LENGTH)
- error_exit("Function too long");
- if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0)
- error_exit("Premature end of file when getting function body");
- if(body->body[body->length][0] == '}')
- {
- body->length++;
- break;
- }
- }
- g_num_primitives++;
- /* Extract the function name information */
- if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea))
- error_exit("Invalid " ID_OPHANDLER_NAME " format");
- /* Find the corresponding table entry */
- opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea);
- if(opinfo == NULL)
- error_exit("Unable to find matching table entry for %s", func_name);
- #if 1 /* PD hack: 000 only */
- if (opinfo->cpus[0] == UNSPECIFIED_CH)
- continue;
- #endif
- replace->length = 0;
- /* Generate opcode variants */
- if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0)
- generate_opcode_cc_variants(filep, body, replace, opinfo, 1);
- else if(strcmp(opinfo->name, "dbcc") == 0)
- generate_opcode_cc_variants(filep, body, replace, opinfo, 2);
- else if(strcmp(opinfo->name, "trapcc") == 0)
- generate_opcode_cc_variants(filep, body, replace, opinfo, 4);
- else
- generate_opcode_ea_variants(filep, body, replace, opinfo);
- }
- free(replace);
- free(body);
- }
- /* Populate the opcode handler table from the input file */
- void populate_table(void)
- {
- char* ptr;
- char bitpattern[17];
- opcode_struct* op;
- char buff[MAX_LINE_LENGTH];
- int i;
- int temp;
- buff[0] = 0;
- /* Find the start of the table */
- while(strcmp(buff, ID_TABLE_START) != 0)
- if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
- error_exit("Premature EOF while reading table");
- /* Process the entire table */
- for(op = g_opcode_input_table;;op++)
- {
- if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
- error_exit("Premature EOF while reading table");
- if(strlen(buff) == 0)
- continue;
- /* We finish when we find an input separator */
- if(strcmp(buff, ID_INPUT_SEPARATOR) == 0)
- break;
- /* Extract the info from the table */
- ptr = buff;
- /* Name */
- ptr += skip_spaces(ptr);
- ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH);
- /* Size */
- ptr += skip_spaces(ptr);
- ptr += check_atoi(ptr, &temp);
- op->size = (unsigned char)temp;
- /* Special processing */
- ptr += skip_spaces(ptr);
- ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH);
- /* Specified EA Mode */
- ptr += skip_spaces(ptr);
- ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH);
- /* Bit Pattern (more processing later) */
- ptr += skip_spaces(ptr);
- ptr += check_strsncpy(bitpattern, ptr, 17);
- /* Allowed Addressing Mode List */
- ptr += skip_spaces(ptr);
- ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH);
- /* CPU operating mode (U = user or supervisor, S = supervisor only */
- ptr += skip_spaces(ptr);
- for(i=0;i<NUM_CPUS;i++)
- {
- op->cpu_mode[i] = *ptr++;
- ptr += skip_spaces(ptr);
- }
- /* Allowed CPUs for this instruction */
- for(i=0;i<NUM_CPUS;i++)
- {
- ptr += skip_spaces(ptr);
- if(*ptr == UNSPECIFIED_CH)
- {
- op->cpus[i] = UNSPECIFIED_CH;
- op->cycles[i] = 0;
- ptr++;
- }
- else
- {
- op->cpus[i] = '0' + i;
- ptr += check_atoi(ptr, &temp);
- op->cycles[i] = (unsigned char)temp;
- }
- }
- /* generate mask and match from bitpattern */
- op->op_mask = 0;
- op->op_match = 0;
- for(i=0;i<16;i++)
- {
- op->op_mask |= (bitpattern[i] != '.') << (15-i);
- op->op_match |= (bitpattern[i] == '1') << (15-i);
- }
- }
- /* Terminate the list */
- op->name[0] = 0;
- }
- /* Read a header or footer insert from the input file */
- void read_insert(char* insert)
- {
- char* ptr = insert;
- char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH;
- int length;
- char* first_blank = NULL;
- first_blank = NULL;
- /* Skip any leading blank lines */
- for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file))
- if(ptr >= overflow)
- error_exit("Buffer overflow reading inserts");
- if(length < 0)
- error_exit("Premature EOF while reading inserts");
- /* Advance and append newline */
- ptr += length;
- strcpy(ptr++, "\n");
- /* Read until next separator */
- for(;;)
- {
- /* Read a new line */
- if(ptr >= overflow)
- error_exit("Buffer overflow reading inserts");
- if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0)
- error_exit("Premature EOF while reading inserts");
- /* Stop if we read a separator */
- if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0)
- break;
- /* keep track in case there are trailing blanks */
- if(length == 0)
- {
- if(first_blank == NULL)
- first_blank = ptr;
- }
- else
- first_blank = NULL;
- /* Advance and append newline */
- ptr += length;
- strcpy(ptr++, "\n");
- }
- /* kill any trailing blank lines */
- if(first_blank)
- ptr = first_blank;
- *ptr++ = 0;
- }
- /* ======================================================================== */
- /* ============================= MAIN FUNCTION ============================ */
- /* ======================================================================== */
- int main(int argc, char **argv)
- {
- /* File stuff */
- char output_path[M68K_MAX_DIR] = "";
- char filename[M68K_MAX_PATH];
- /* Section identifier */
- char section_id[MAX_LINE_LENGTH+1];
- /* Inserts */
- char temp_insert[MAX_INSERT_LENGTH+1];
- char prototype_footer_insert[MAX_INSERT_LENGTH+1];
- char table_header_insert[MAX_INSERT_LENGTH+1];
- char table_footer_insert[MAX_INSERT_LENGTH+1];
- char ophandler_header_insert[MAX_INSERT_LENGTH+1];
- char ophandler_footer_insert[MAX_INSERT_LENGTH+1];
- /* Flags if we've processed certain parts already */
- int prototype_header_read = 0;
- int prototype_footer_read = 0;
- int table_header_read = 0;
- int table_footer_read = 0;
- int ophandler_header_read = 0;
- int ophandler_footer_read = 0;
- int table_body_read = 0;
- int ophandler_body_read = 0;
- printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68040 emulator\n", g_version);
- printf("\tCopyright 1998-2007 Karl Stenerud (karl@mame.net)\n\n");
- /* Check if output path and source for the input file are given */
- if(argc > 1)
- {
- char *ptr;
- strcpy(output_path, argv[1]);
- for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\'))
- *ptr = '/';
- #if !(defined(__DECC) && defined(VMS))
- if(output_path[strlen(output_path)-1] != '/')
- strcat(output_path, "/");
- #endif
- if(argc > 2)
- strcpy(g_input_filename, argv[2]);
- }
- #if defined(__DECC) && defined(VMS)
- /* Open the files we need */
- sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE);
- if((g_prototype_file = fopen(filename, "w")) == NULL)
- perror_exit("Unable to create prototype file (%s)\n", filename);
- sprintf(filename, "%s%s", output_path, FILENAME_TABLE);
- if((g_table_file = fopen(filename, "w")) == NULL)
- perror_exit("Unable to create table file (%s)\n", filename);
- if((g_input_file=fopen(g_input_filename, "r")) == NULL)
- perror_exit("can't open %s for input", g_input_filename);
- #else
- /* Open the files we need */
- sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE);
- if((g_prototype_file = fopen(filename, "wt")) == NULL)
- perror_exit("Unable to create prototype file (%s)\n", filename);
- sprintf(filename, "%s%s", output_path, FILENAME_TABLE);
- if((g_table_file = fopen(filename, "wt")) == NULL)
- perror_exit("Unable to create table file (%s)\n", filename);
- if((g_input_file=fopen(g_input_filename, "rt")) == NULL)
- perror_exit("can't open %s for input", g_input_filename);
- #endif
- /* Get to the first section of the input file */
- section_id[0] = 0;
- while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0)
- if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
- error_exit("Premature EOF while reading input file");
- /* Now process all sections */
- for(;;)
- {
- if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
- error_exit("Premature EOF while reading input file");
- if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0)
- {
- if(prototype_header_read)
- error_exit("Duplicate prototype header");
- read_insert(temp_insert);
- fprintf(g_prototype_file, "%s\n\n", temp_insert);
- prototype_header_read = 1;
- }
- else if(strcmp(section_id, ID_TABLE_HEADER) == 0)
- {
- if(table_header_read)
- error_exit("Duplicate table header");
- read_insert(table_header_insert);
- table_header_read = 1;
- }
- else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0)
- {
- if(ophandler_header_read)
- error_exit("Duplicate opcode handler header");
- read_insert(ophandler_header_insert);
- ophandler_header_read = 1;
- }
- else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0)
- {
- if(prototype_footer_read)
- error_exit("Duplicate prototype footer");
- read_insert(prototype_footer_insert);
- prototype_footer_read = 1;
- }
- else if(strcmp(section_id, ID_TABLE_FOOTER) == 0)
- {
- if(table_footer_read)
- error_exit("Duplicate table footer");
- read_insert(table_footer_insert);
- table_footer_read = 1;
- }
- else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0)
- {
- if(ophandler_footer_read)
- error_exit("Duplicate opcode handler footer");
- read_insert(ophandler_footer_insert);
- ophandler_footer_read = 1;
- }
- else if(strcmp(section_id, ID_TABLE_BODY) == 0)
- {
- if(!prototype_header_read)
- error_exit("Table body encountered before prototype header");
- if(!table_header_read)
- error_exit("Table body encountered before table header");
- if(!ophandler_header_read)
- error_exit("Table body encountered before opcode handler header");
- if(table_body_read)
- error_exit("Duplicate table body");
- populate_table();
- table_body_read = 1;
- }
- else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0)
- {
- if(!prototype_header_read)
- error_exit("Opcode handlers encountered before prototype header");
- if(!table_header_read)
- error_exit("Opcode handlers encountered before table header");
- if(!ophandler_header_read)
- error_exit("Opcode handlers encountered before opcode handler header");
- if(!table_body_read)
- error_exit("Opcode handlers encountered before table body");
- if(ophandler_body_read)
- error_exit("Duplicate opcode handler section");
- fprintf(g_table_file, "%s\n\n", ophandler_header_insert);
- process_opcode_handlers(g_table_file);
- fprintf(g_table_file, "%s\n\n", ophandler_footer_insert);
- ophandler_body_read = 1;
- }
- else if(strcmp(section_id, ID_END) == 0)
- {
- /* End of input file. Do a sanity check and then write footers */
- if(!prototype_header_read)
- error_exit("Missing prototype header");
- if(!prototype_footer_read)
- error_exit("Missing prototype footer");
- if(!table_header_read)
- error_exit("Missing table header");
- if(!table_footer_read)
- error_exit("Missing table footer");
- if(!table_body_read)
- error_exit("Missing table body");
- if(!ophandler_header_read)
- error_exit("Missing opcode handler header");
- if(!ophandler_footer_read)
- error_exit("Missing opcode handler footer");
- if(!ophandler_body_read)
- error_exit("Missing opcode handler body");
- fprintf(g_table_file, "%s\n\n", table_header_insert);
- print_opcode_output_table(g_table_file);
- fprintf(g_table_file, "%s\n\n", table_footer_insert);
- fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert);
- break;
- }
- else
- {
- error_exit("Unknown section identifier: %s", section_id);
- }
- }
- /* Close all files and exit */
- fclose(g_prototype_file);
- fclose(g_table_file);
- fclose(g_input_file);
- printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives);
- return 0;
- }
- /* ======================================================================== */
- /* ============================== END OF FILE ============================= */
- /* ======================================================================== */
|