Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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