m68kmake.c 44 KB

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