internal cleanup: keyword trees are now only built when needed.

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@290 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-08-15 14:55:22 +00:00
parent aa8d766e6c
commit 2be25080aa
9 changed files with 76 additions and 94 deletions

View File

@ -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();
}

View File

@ -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;

View File

@ -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.");

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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

View File

@ -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