diff --git a/src/alu.c b/src/alu.c index b6bc7ac..50fa765 100644 --- a/src/alu.c +++ b/src/alu.c @@ -186,8 +186,8 @@ enum alu_state { }; static enum alu_state alu_state; // deterministic finite automaton // predefined stuff -static struct ronode *op_tree = NULL; // tree to hold operators -static struct ronode op_list[] = { +static struct ronode op_tree[] = { + PREDEF_START, PREDEFNODE("asr", &ops_asr), PREDEFNODE("lsr", &ops_lsr), PREDEFNODE("asl", &ops_shift_left), @@ -197,11 +197,11 @@ static struct ronode op_list[] = { PREDEFNODE("and", &ops_and), PREDEFNODE("or", &ops_or), PREDEFNODE("eor", &ops_eor), // FIXME - remove - PREDEFLAST("xor", &ops_xor), + PREDEF_END("xor", &ops_xor), // ^^^^ this marks the last element }; -static struct ronode *function_tree = NULL; // tree to hold functions -static struct ronode function_list[] = { +static struct ronode function_tree[] = { + PREDEF_START, PREDEFNODE("addr", &ops_addr), PREDEFNODE("address", &ops_addr), PREDEFNODE("int", &ops_int), @@ -215,7 +215,7 @@ static struct ronode function_list[] = { PREDEFNODE("arctan", &ops_arctan), PREDEFNODE("sin", &ops_sin), PREDEFNODE("cos", &ops_cos), - PREDEFLAST("tan", &ops_tan), + PREDEF_END("tan", &ops_tan), // ^^^^ this marks the last element }; @@ -269,8 +269,6 @@ void ALU_init(void) { errormsg_dyna_buf = DynaBuf_create(ERRORMSG_DYNABUF_INITIALSIZE); function_dyna_buf = DynaBuf_create(FUNCTION_DYNABUF_INITIALSIZE); - Tree_add_table(&op_tree, op_list); - Tree_add_table(&function_tree, function_list); enlarge_operator_stack(); enlarge_argument_stack(); } diff --git a/src/cpu.c b/src/cpu.c index 837b64f..33d8657 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -71,8 +71,8 @@ static struct cpu_type cpu_type_m65 = { // variables // predefined stuff -static struct ronode *cputype_tree = NULL; -static struct ronode cputype_list[] = { +static struct ronode cputype_tree[] = { + PREDEF_START, #define KNOWN_TYPES "'6502', 'nmos6502', '6510', '65c02', 'r65c02', 'w65c02', '65816', '65ce02', '4502', 'm65', 'c64dtv2'" // shown in CLI error message for unknown types // PREDEFNODE("z80", &cpu_type_Z80), PREDEFNODE("6502", &cpu_type_6502), @@ -85,7 +85,7 @@ static struct ronode cputype_list[] = { PREDEFNODE("65ce02", &cpu_type_65ce02), PREDEFNODE("4502", &cpu_type_4502), PREDEFNODE("m65", &cpu_type_m65), - PREDEFLAST("c64dtv2", &cpu_type_c64dtv2), + PREDEF_END("c64dtv2", &cpu_type_c64dtv2), // ^^^^ this marks the last element }; const char cputype_names[] = KNOWN_TYPES; // string to show if cputype_find() returns NULL @@ -95,9 +95,6 @@ const struct cpu_type *cputype_find(void) { void *node_body; - // make sure tree is initialised - if (cputype_tree == NULL) - Tree_add_table(&cputype_tree, cputype_list); // perform lookup if (!Tree_easy_scan(cputype_tree, &node_body, GlobalDynaBuf)) return NULL; diff --git a/src/encoding.c b/src/encoding.c index da409b0..8966e90 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -83,12 +83,12 @@ const struct encoder encoder_file = { // keywords for "!convtab" pseudo opcode -static struct ronode *encoder_tree = NULL; // tree to hold encoders -static struct ronode encoder_list[] = { +static struct ronode encoder_tree[] = { + PREDEF_START, //no! PREDEFNODE("file", &encoder_file), "!ct file" is not needed; just use {} after initial loading of table! PREDEFNODE("pet", &encoder_pet), PREDEFNODE("raw", &encoder_raw), - PREDEFLAST("scr", &encoder_scr), + PREDEF_END("scr", &encoder_scr), // ^^^^ this marks the last element }; @@ -120,9 +120,6 @@ const struct encoder *encoding_find(void) { void *node_body; - // make sure tree is initialised - if (encoder_tree == NULL) - Tree_add_table(&encoder_tree, encoder_list); // perform lookup if (!Tree_easy_scan(encoder_tree, &node_body, GlobalDynaBuf)) { Throw_error("Unknown encoding."); diff --git a/src/mnemo.c b/src/mnemo.c index 2a134e0..4c2676b 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -148,19 +148,6 @@ static const char exception_oversized_addrmode[] = "Using oversized addressing m // Variables static struct dynabuf *mnemo_dyna_buf; // dynamic buffer for mnemonics -// predefined stuff -static struct ronode *mnemo_6502_tree = NULL; // 6502 mnemonics -static struct ronode *mnemo_6502undoc1_tree = NULL; // 6502 undocumented ("illegal") opcodes supported by DTV2 -static struct ronode *mnemo_6502undoc2_tree = NULL; // remaining 6502 undocumented ("illegal") opcodes (currently ANC only, maybe more will get moved) -static struct ronode *mnemo_c64dtv2_tree = NULL; // C64DTV2 extensions (BRA/SAC/SIR) -static struct ronode *mnemo_65c02_tree = NULL; // 65c02 extensions -static struct ronode *mnemo_bitmanips_tree = NULL; // Rockwell's bit manipulation extensions -static struct ronode *mnemo_stp_wai_tree = NULL; // WDC's "stp" and "wai" instructions -static struct ronode *mnemo_65816_tree = NULL; // WDC 65816 extensions -static struct ronode *mnemo_65ce02_tree = NULL; // CSG 65ce02/4502 extensions -static struct ronode *mnemo_aug_tree = NULL; // CSG 65ce02's "aug" instruction -static struct ronode *mnemo_map_eom_tree = NULL; // CSG 4502's "map" and "eom" instructions -static struct ronode *mnemo_m65_tree = NULL; // MEGA65 extensions // mnemonic's code, flags and group values are stored together in a single integer. // ("code" is either a table index or the opcode itself, depending on group value) @@ -181,7 +168,9 @@ static struct ronode *mnemo_m65_tree = NULL; // MEGA65 extensions #define MERGE(g, v) (((g) << 12) | (v)) #define GROUP(v) ((v) >> 12) -static struct ronode mnemos_6502[] = { +// 6502 mnemonics +static struct ronode mnemo_6502_tree[] = { + PREDEF_START, PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX_ORA)), PREDEFNODE("and", MERGE(GROUP_ACCU, IDX_AND)), PREDEFNODE("eor", MERGE(GROUP_ACCU, IDX_EOR)), @@ -237,12 +226,13 @@ static struct ronode mnemos_6502[] = { PREDEFNODE("cld", MERGE(GROUP_IMPLIEDONLY, 0xd8)), PREDEFNODE("inx", MERGE(GROUP_IMPLIEDONLY, 0xe8)), PREDEFNODE("nop", MERGE(GROUP_IMPLIEDONLY, 0xea)), - PREDEFLAST("sed", MERGE(GROUP_IMPLIEDONLY, 0xf8)), + PREDEF_END("sed", MERGE(GROUP_IMPLIEDONLY, 0xf8)), // ^^^^ this marks the last element }; // undocumented opcodes of the NMOS 6502 that are also supported by c64dtv2: -static struct ronode mnemos_6502undoc1[] = { +static struct ronode mnemo_6502undoc1_tree[] = { + PREDEF_START, PREDEFNODE("slo", MERGE(GROUP_ACCU, IDXuSLO)), // ASL + ORA (aka ASO) PREDEFNODE("rla", MERGE(GROUP_ACCU, IDXuRLA)), // ROL + AND (aka RLN) PREDEFNODE("sre", MERGE(GROUP_ACCU, IDXuSRE)), // LSR + EOR (aka LSE) @@ -265,26 +255,30 @@ static struct ronode mnemos_6502undoc1[] = { PREDEFNODE("top", MERGE(GROUP_MISC, IDXuTOP)), // "triple nop" (skip next word) PREDEFNODE("ane", MERGE(GROUP_MISC, IDXuANE)), // A = (A | ??) & X & arg (aka XAA/AXM) PREDEFNODE("lxa", MERGE(GROUP_MISC, IDXuLXA)), // A,X = (A | ??) & arg (aka LAX/ATX/OAL) - PREDEFLAST("jam", MERGE(GROUP_IMPLIEDONLY, 0x02)), // jam/crash/kill/halt-and-catch-fire + PREDEF_END("jam", MERGE(GROUP_IMPLIEDONLY, 0x02)), // jam/crash/kill/halt-and-catch-fire // ^^^^ this marks the last element }; // undocumented opcodes of the NMOS 6502 that are _not_ supported by c64dtv2: -static struct ronode mnemos_6502undoc2[] = { - PREDEFLAST("anc", MERGE(GROUP_MISC, IDXuANC)), // A = A & arg, then C=N (aka ANA, ANB) +// (currently ANC only, maybe more will get moved) +static struct ronode mnemo_6502undoc2_tree[] = { + PREDEF_START, + PREDEF_END("anc", MERGE(GROUP_MISC, IDXuANC)), // A = A & arg, then C=N (aka ANA, ANB) // ^^^^ this marks the last element }; // additional opcodes of c64dtv2: -static struct ronode mnemos_c64dtv2[] = { +static struct ronode mnemo_c64dtv2_tree[] = { + PREDEF_START, PREDEFNODE("bra", MERGE(GROUP_RELATIVE8, 0x12)), // branch always PREDEFNODE("sac", MERGE(GROUP_MISC, IDX_SAC)), // set accumulator mapping - PREDEFLAST("sir", MERGE(GROUP_MISC, IDX_SIR)), // set index register mapping + PREDEF_END("sir", MERGE(GROUP_MISC, IDX_SIR)), // set index register mapping // ^^^^ this marks the last element }; // new stuff in CMOS re-design: -static struct ronode mnemos_65c02[] = { +static struct ronode mnemo_65c02_tree[] = { + PREDEF_START, // more addressing modes for some mnemonics: PREDEFNODE("ora", MERGE(GROUP_ACCU, IDXcORA)), PREDEFNODE("and", MERGE(GROUP_ACCU, IDXcAND)), @@ -306,12 +300,13 @@ static struct ronode mnemos_65c02[] = { PREDEFNODE("plx", MERGE(GROUP_IMPLIEDONLY, 0xfa)), PREDEFNODE("tsb", MERGE(GROUP_MISC, IDXcTSB)), PREDEFNODE("trb", MERGE(GROUP_MISC, IDXcTRB)), - PREDEFLAST("stz", MERGE(GROUP_MISC, IDXcSTZ)), + PREDEF_END("stz", MERGE(GROUP_MISC, IDXcSTZ)), // ^^^^ this marks the last element }; // bit-manipulation extensions (by Rockwell?) -static struct ronode mnemos_bitmanips[] = { +static struct ronode mnemo_bitmanips_tree[] = { + PREDEF_START, PREDEFNODE("rmb0", MERGE(GROUP_ZPONLY, 0x07)), PREDEFNODE("rmb1", MERGE(GROUP_ZPONLY, 0x17)), PREDEFNODE("rmb2", MERGE(GROUP_ZPONLY, 0x27)), @@ -343,19 +338,21 @@ static struct ronode mnemos_bitmanips[] = { PREDEFNODE("bbs4", MERGE(GROUP_BITBRANCH, 0xcf)), PREDEFNODE("bbs5", MERGE(GROUP_BITBRANCH, 0xdf)), PREDEFNODE("bbs6", MERGE(GROUP_BITBRANCH, 0xef)), - PREDEFLAST("bbs7", MERGE(GROUP_BITBRANCH, 0xff)), + PREDEF_END("bbs7", MERGE(GROUP_BITBRANCH, 0xff)), // ^^^^ this marks the last element }; // "stp" and "wai" extensions by WDC: -static struct ronode mnemos_stp_wai[] = { +static struct ronode mnemo_stp_wai_tree[] = { + PREDEF_START, PREDEFNODE("wai", MERGE(GROUP_IMPLIEDONLY, 0xcb)), - PREDEFLAST("stp", MERGE(GROUP_IMPLIEDONLY, 0xdb)), + PREDEF_END("stp", MERGE(GROUP_IMPLIEDONLY, 0xdb)), // ^^^^ this marks the last element }; // the 65816 stuff -static struct ronode mnemos_65816[] = { +static struct ronode mnemo_65816_tree[] = { + PREDEF_START, // CAUTION - these use 6502/65c02 indices, because the opcodes are the same - but I need flags for immediate mode! PREDEFNODE("ldy", MERGE(GROUP_MISC, IDX_LDY | IM_INDEXREGS)), PREDEFNODE("ldx", MERGE(GROUP_MISC, IDX_LDX | IM_INDEXREGS)), @@ -401,12 +398,13 @@ static struct ronode mnemos_65816[] = { // 0xdb is STP PREDEFNODE("xba", MERGE(GROUP_IMPLIEDONLY, 0xeb)), PREDEFNODE("xce", MERGE(GROUP_IMPLIEDONLY, 0xfb)), - PREDEFLAST("wdm", MERGE(GROUP_IMPLIEDONLY, 0x42)), + PREDEF_END("wdm", MERGE(GROUP_IMPLIEDONLY, 0x42)), // ^^^^ this marks the last element }; // 65ce02 has 46 new opcodes and a few changes: -static struct ronode mnemos_65ce02[] = { +static struct ronode mnemo_65ce02_tree[] = { + PREDEF_START, // 65ce02 changes (zp) addressing of 65c02 to (zp),z addressing: PREDEFNODE("ora", MERGE(GROUP_ACCU, IDXeORA)), PREDEFNODE("and", MERGE(GROUP_ACCU, IDXeAND)), @@ -455,25 +453,28 @@ static struct ronode mnemos_65ce02[] = { PREDEFNODE("tza", MERGE(GROUP_IMPLIEDONLY, 0x6b)), PREDEFNODE("tba", MERGE(GROUP_IMPLIEDONLY, 0x7b)), PREDEFNODE("phz", MERGE(GROUP_IMPLIEDONLY, 0xdb)), - PREDEFLAST("plz", MERGE(GROUP_IMPLIEDONLY, 0xfb)), + PREDEF_END("plz", MERGE(GROUP_IMPLIEDONLY, 0xfb)), // ^^^^ this marks the last element }; // 65ce02's "aug" opcode: -static struct ronode mnemos_aug[] = { - PREDEFLAST("aug", MERGE(GROUP_IMPLIEDONLY, 0x5c)), // actually a "4-byte NOP reserved for future expansion" +static struct ronode mnemo_aug_tree[] = { + PREDEF_START, + PREDEF_END("aug", MERGE(GROUP_IMPLIEDONLY, 0x5c)), // actually a "4-byte NOP reserved for future expansion" // ^^^^ this marks the last element }; // 4502's "map" and "eom" opcodes: -static struct ronode mnemos_map_eom[] = { +static struct ronode mnemo_map_eom_tree[] = { + PREDEF_START, PREDEFNODE("map", MERGE(GROUP_IMPLIEDONLY, 0x5c)), // change memory mapping - PREDEFLAST("eom", MERGE(GROUP_IMPLIEDONLY, 0xea)), // actually the NOP opcode + PREDEF_END("eom", MERGE(GROUP_IMPLIEDONLY, 0xea)), // actually the NOP opcode // ^^^^ this marks the last element }; // m65 has a few extensions using prefix codes: -static struct ronode mnemos_m65[] = { +static struct ronode mnemo_m65_tree[] = { + PREDEF_START, // extension 1: // a NOP prefix changes ($ff),z addressing from using 16-bit pointers to // using 32-bit pointers. I chose "[$ff],z" to indicate this. @@ -523,7 +524,7 @@ static struct ronode mnemos_m65[] = { PREDEFNODE("bitq", MERGE(GROUP_MISC, IDXmBITQ | PREFIX_NEGNEG)), PREDEFNODE("asrq", MERGE(GROUP_MISC, IDXeASR | PREFIX_NEGNEG)), // because the NOP opcode is used as a prefix code, the mnemonic was disabled: - PREDEFLAST("nop", MERGE(GROUP_PREFIX, 0xea)), + PREDEF_END("nop", MERGE(GROUP_PREFIX, 0xea)), // ^^^^ this marks the last element }; @@ -533,18 +534,6 @@ static struct ronode mnemos_m65[] = { void Mnemo_init(void) { mnemo_dyna_buf = DynaBuf_create(MNEMO_DYNABUF_INITIALSIZE); - Tree_add_table(&mnemo_6502_tree, mnemos_6502); - Tree_add_table(&mnemo_6502undoc1_tree, mnemos_6502undoc1); - Tree_add_table(&mnemo_6502undoc2_tree, mnemos_6502undoc2); - Tree_add_table(&mnemo_c64dtv2_tree, mnemos_c64dtv2); - Tree_add_table(&mnemo_65c02_tree, mnemos_65c02); - Tree_add_table(&mnemo_bitmanips_tree, mnemos_bitmanips); - Tree_add_table(&mnemo_stp_wai_tree, mnemos_stp_wai); - Tree_add_table(&mnemo_65816_tree, mnemos_65816); - Tree_add_table(&mnemo_65ce02_tree, mnemos_65ce02); - Tree_add_table(&mnemo_aug_tree, mnemos_aug); - Tree_add_table(&mnemo_map_eom_tree, mnemos_map_eom); - Tree_add_table(&mnemo_m65_tree, mnemos_m65); } diff --git a/src/output.c b/src/output.c index a8bd28e..723d64b 100644 --- a/src/output.c +++ b/src/output.c @@ -72,13 +72,14 @@ enum output_format { OUTPUT_FORMAT_PLAIN // code only }; // predefined stuff -static struct ronode *file_format_tree = NULL; // tree to hold output formats (FIXME - a tree for three items, really?) -static struct ronode file_format_list[] = { +// tree to hold output formats (FIXME - a tree for three items, really?) +static struct ronode file_format_tree[] = { + PREDEF_START, #define KNOWN_FORMATS "'plain', 'cbm', 'apple'" // shown in CLI error message for unknown formats PREDEFNODE("apple", OUTPUT_FORMAT_APPLE), PREDEFNODE("cbm", OUTPUT_FORMAT_CBM), // PREDEFNODE("o65", OUTPUT_FORMAT_O65), - PREDEFLAST("plain", OUTPUT_FORMAT_PLAIN), + PREDEF_END("plain", OUTPUT_FORMAT_PLAIN), // ^^^^ this marks the last element }; // chosen file format @@ -239,9 +240,6 @@ int outputfile_set_format(void) { void *node_body; - // make sure tree is initialised - if (file_format_tree == NULL) - Tree_add_table(&file_format_tree, file_format_list); // perform lookup if (!Tree_easy_scan(file_format_tree, &node_body, GlobalDynaBuf)) return 1; diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index 53b457c..e584680 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -35,10 +35,6 @@ enum eos { static const char exception_unknown_pseudo_opcode[] = "Unknown pseudo opcode."; -// variables -static struct ronode *pseudo_opcode_tree = NULL; // tree to hold pseudo opcodes - - // this is not really a pseudo opcode, but similar enough to be put here: // called when "*= EXPRESSION" is parsed, to set the program counter void notreallypo_setpc(void) // GotByte is '*' @@ -1295,7 +1291,8 @@ static enum eos po_endoffile(void) } // pseudo opcode table -static struct ronode pseudo_opcode_list[] = { +static struct ronode pseudo_opcode_tree[] = { + PREDEF_START, PREDEFNODE("initmem", po_initmem), PREDEFNODE("xor", po_xor), PREDEFNODE("to", po_to), @@ -1365,7 +1362,7 @@ static struct ronode pseudo_opcode_list[] = { PREDEFNODE("error", po_error), PREDEFNODE("serious", po_serious), PREDEFNODE("eof", po_endoffile), - PREDEFLAST("endoffile", po_endoffile), + PREDEF_END("endoffile", po_endoffile), // ^^^^ this marks the last element }; @@ -1374,7 +1371,6 @@ static struct ronode pseudo_opcode_list[] = { void pseudoopcodes_init(void) { user_message = DynaBuf_create(USERMSG_DYNABUF_INITIALSIZE); - Tree_add_table(&pseudo_opcode_tree, pseudo_opcode_list); } diff --git a/src/tree.c b/src/tree.c index c004112..8b60f7f 100644 --- a/src/tree.c +++ b/src/tree.c @@ -28,14 +28,15 @@ hash_t make_hash(struct ronode *node) { } // Link a predefined data set to a tree -void add_node_to_tree(struct ronode **tree, struct ronode *node_to_add) +static void add_node_to_tree(struct ronode **tree, struct ronode *node_to_add) { hash_t hash; // compute hash value hash = make_hash(node_to_add); + // search for NULL pointer to replace while (*tree) { - // compare HashValue + // decide which way to go if (hash > (*tree)->hash_value) tree = &((*tree)->greater_than); else @@ -48,10 +49,11 @@ void add_node_to_tree(struct ronode **tree, struct ronode *node_to_add) // fields. } -// Add predefined tree items to given tree. The PREDEF* macros set HashValue -// to 1 in all entries but the last. The last entry contains 0. -void Tree_add_table(struct ronode **tree, struct ronode *table_to_add) +// Add predefined tree items to given tree. The PREDEF* macros set the hash +// to 1 in all entries but the last, and to 0 in the last entry. +static void tree_from_list(struct ronode **tree, struct ronode *table_to_add) { + //printf("Building tree from list.\n"); // Caution when trying to optimise this. :) while (table_to_add->hash_value) add_node_to_tree(tree, table_to_add++); @@ -72,6 +74,15 @@ int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_b b2; hash_t hash; + // check if tree is actually ready to use. if not, build it from list. + // (list's first item does not contain real data, so "greater_than" is + // used to hold pointer to tree root) + if (tree->greater_than == NULL) + tree_from_list(&tree->greater_than, tree + 1); // real data starts at next list item + tree = tree->greater_than; // go from list head to tree root + // ok, we're done with this setup stuff. + // from now on, "greater_than" really means "greater_than"! + wanted.id_string = dyna_buf->buffer; hash = make_hash(&wanted); while (tree) { diff --git a/src/tree.h b/src/tree.h index e5d5756..f171ca3 100644 --- a/src/tree.h +++ b/src/tree.h @@ -12,9 +12,9 @@ // macros for pre-defining tree node tables +#define PREDEF_START {NULL, NULL, 0, NULL, NULL} // this is used to determine if list has been made into tree yet #define PREDEFNODE(s, v) {NULL, NULL, 1, s, (void *) (v)} -#define PREDEFLAST(s, v) {NULL, NULL, 0, s, (void *) (v)} -// TODO: add macro to define tree struct as "pointer-to-root (initially NULL) and pointer-to-init-table" combination +#define PREDEF_END(s, v) {NULL, NULL, 0, s, (void *) (v)} // type definitions @@ -42,12 +42,8 @@ struct rwnode { // prototypes -// Add predefined tree items to given tree. -// TODO: change this to an internal function. convert table to tree on first lookup. -extern void Tree_add_table(struct ronode **tree, struct ronode *table_to_add); // Search for a given ID string in a given tree. Store "body" component in // node_body and return TRUE. Return FALSE if no matching item found. -// TODO: change tree passing from "pointer to root" to "pointer to struct containing pointer to root and pointer to table", so first lookup can create tree. struct dynabuf; extern int Tree_easy_scan(struct ronode *tree, void **node_body, struct dynabuf *dyna_buf); // Search for a "RAM tree" item. Save pointer to found tree item in given diff --git a/src/version.h b/src/version.h index d20ef28..d16507f 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ #define RELEASE "0.97" // update before release FIXME #define CODENAME "Zem" // update before release -#define CHANGE_DATE "12 Aug" // update before release FIXME +#define CHANGE_DATE "15 Aug" // update before release FIXME #define CHANGE_YEAR "2020" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME