diff --git a/src/acme.c b/src/acme.c index b5d1783..bde676e 100644 --- a/src/acme.c +++ b/src/acme.c @@ -333,9 +333,9 @@ static void perform_pass(void) } } output_endofpass(); // make sure last code segment is closed - // TODO: atm "--from-to" reads two numbers. if that is changed in the - // future to two general expressions, this is the point where they would - // need to be evaluated. + // TODO: atm "--from-to" reads two number literals. if that is changed + // in the future to two general expressions, this is the point where + // they would need to be evaluated. if (config.process_verbosity > 8) printf("Found %d undefined expressions.\n", pass.undefined_count); if (pass.error_count) @@ -351,6 +351,11 @@ static void do_actual_work(void) report = &global_report; // let global pointer point to something report_init(report); // we must init struct before doing passes + + sanity.macro_recursions_left = config.sanity_limit; + sanity.source_recursions_left = config.sanity_limit; + sanity.passes_left = config.sanity_limit; + pass.complain_about_undefined = FALSE; // disable until error pass needed perform_pass(); // first pass // pretend there has been a previous pass, with one more undefined result @@ -362,6 +367,7 @@ static void do_actual_work(void) perform_pass(); if (--sanity.passes_left < 0) { // FIXME - exit with error + // ...or maybe do one additional pass where all errors are reported, including "not defined" and "value has changed". //puts("Exceeded maximum number of passes, please check your sources."); //break; } @@ -389,6 +395,7 @@ static void do_actual_work(void) perform_pass(); // perform pass, but now show "value undefined" // FIXME - perform_pass() calls exit() when there were errors, // so if controls returns here, call BUG()! + // (this can be triggered using ifdef/ifndef) } } @@ -742,10 +749,6 @@ int main(int argc, const char *argv[]) exit(EXIT_FAILURE); } - sanity.macro_recursions_left = config.sanity_limit; - sanity.source_recursions_left = config.sanity_limit; - sanity.passes_left = config.sanity_limit; - // init output buffer output_createbuffer(); // do the actual work diff --git a/src/mnemo.c b/src/mnemo.c index fb9c823..526a17d 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -159,8 +159,8 @@ static STRUCT_DYNABUF_REF(mnemo_dyna_buf, MNEMO_INITIALSIZE); // for mnemonics // immediate mode: #define IM_FORCE8 0x000 // immediate values are 8 bits (CAUTION - program relies on "no bits set" being the default!) #define IM_FORCE16 0x100 // immediate value is 16 bits (for 65ce02's PHW#) -#define IM_ACCUMULATOR 0x200 // immediate value depends on accumulator length -#define IM_INDEXREGS 0x300 // immediate value depends on index register length +#define IM_ACCU_LENGTH 0x200 // immediate value depends on accumulator length +#define IM_REGS_LENGTH 0x300 // immediate value depends on index register length #define IMMASK 0x300 // mask for immediate mode flags #define PREFIX_NEGNEG 0x400 // output NEG:NEG before actual opcode #define LI_PREFIX_NOP 0x800 // when using long indirect addressing, output NOP before actual opcode @@ -360,20 +360,20 @@ static struct ronode mnemo_stp_wai_tree[] = { 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)), - PREDEFNODE("cpy", MERGE(GROUP_MISC, IDX_CPY | IM_INDEXREGS)), - PREDEFNODE("cpx", MERGE(GROUP_MISC, IDX_CPX | IM_INDEXREGS)), - PREDEFNODE("bit", MERGE(GROUP_MISC, IDXcBIT | IM_ACCUMULATOR)), + PREDEFNODE("ldy", MERGE(GROUP_MISC, IDX_LDY | IM_REGS_LENGTH)), + PREDEFNODE("ldx", MERGE(GROUP_MISC, IDX_LDX | IM_REGS_LENGTH)), + PREDEFNODE("cpy", MERGE(GROUP_MISC, IDX_CPY | IM_REGS_LENGTH)), + PREDEFNODE("cpx", MERGE(GROUP_MISC, IDX_CPX | IM_REGS_LENGTH)), + PREDEFNODE("bit", MERGE(GROUP_MISC, IDXcBIT | IM_ACCU_LENGTH)), // more addressing modes for some mnemonics: - PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX16ORA | IM_ACCUMULATOR)), - PREDEFNODE("and", MERGE(GROUP_ACCU, IDX16AND | IM_ACCUMULATOR)), - PREDEFNODE("eor", MERGE(GROUP_ACCU, IDX16EOR | IM_ACCUMULATOR)), - PREDEFNODE("adc", MERGE(GROUP_ACCU, IDX16ADC | IM_ACCUMULATOR)), + PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX16ORA | IM_ACCU_LENGTH)), + PREDEFNODE("and", MERGE(GROUP_ACCU, IDX16AND | IM_ACCU_LENGTH)), + PREDEFNODE("eor", MERGE(GROUP_ACCU, IDX16EOR | IM_ACCU_LENGTH)), + PREDEFNODE("adc", MERGE(GROUP_ACCU, IDX16ADC | IM_ACCU_LENGTH)), PREDEFNODE("sta", MERGE(GROUP_ACCU, IDX16STA)), - PREDEFNODE("lda", MERGE(GROUP_ACCU, IDX16LDA | IM_ACCUMULATOR)), - PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDX16CMP | IM_ACCUMULATOR)), - PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDX16SBC | IM_ACCUMULATOR)), + PREDEFNODE("lda", MERGE(GROUP_ACCU, IDX16LDA | IM_ACCU_LENGTH)), + PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDX16CMP | IM_ACCU_LENGTH)), + PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDX16SBC | IM_ACCU_LENGTH)), PREDEFNODE("jmp", MERGE(GROUP_ALLJUMPS, IDX16JMP)), PREDEFNODE("jsr", MERGE(GROUP_ALLJUMPS, IDX16JSR)), // @@ -894,10 +894,10 @@ static unsigned int imm_ops(bits *force_bit, unsigned char opcode, bits immediat case IM_FORCE16: // currently only for 65ce02's PHW# return ((unsigned int) opcode) << 8; // opcode in bits8.15 forces two-byte argument - case IM_ACCUMULATOR: // for 65816 + case IM_ACCU_LENGTH: // for 65816 long_register = cpu_a_is_long; break; - case IM_INDEXREGS: // for 65816 + case IM_REGS_LENGTH: // for 65816 long_register = cpu_xy_are_long; break; default: diff --git a/src/output.c b/src/output.c index 32c9777..078f619 100644 --- a/src/output.c +++ b/src/output.c @@ -39,12 +39,19 @@ struct output { intval_t max; // highest address segment may use bits flags; // segment flags ("overlay" and "invisible", see header file) struct segment list_head; // head element of doubly-linked ring list - } segment; + } segment; // FIXME - rename either this component or "struct segment"! char xor; // output modifier }; // for offset assembly: -static struct pseudopc *pseudopc_current_context; // current struct (NULL when not in pseudopc block - FIXME, will change in future!) +// struct to describe a pseudopc context (each label gets a pointer to this) +struct pseudopc { + struct pseudopc *outer; // next layer (to be able to "unpseudopc" labels by more than one level) + intval_t offset; // inner minus outer pc + enum numtype ntype; // type of outer pc (INT/UNDEFINED) +}; +static struct pseudopc outermost_pseudopc_context; // dummy struct when "!pseudopc" not in use +static struct pseudopc *pseudopc_current_context = &outermost_pseudopc_context; // current struct // variables @@ -120,7 +127,7 @@ static void real_output(intval_t byte) out->highest_written = out->write_idx; // write byte and advance ptrs if (report->fd) - report_binary(byte & 0xff); // file for reporting, taking also CPU_2add + report_binary(byte & 0xff); // file for reporting out->buffer[out->write_idx++] = (byte & 0xff) ^ out->xor; ++statement_size; // count this byte } @@ -142,8 +149,10 @@ static void no_output(intval_t byte) void output_skip(int size) { if (size < 1) { - // FIXME - ok for zero, but why is there no error message + // ok for zero, but why is there no error message // output for negative values? + // ...because caller should have caught those! + // FIXME - add BUG() for those! return; } @@ -239,6 +248,7 @@ void output_createbuffer(void) out->initvalue_set = TRUE; // "!initmem" generates a warning fill_value = 0xff & config.mem_init_value; } +// FIXME - move both of these to passinit(), needed in future: // init output buffer (fill memory with initial value) fill_completely(fill_value); // init ring list of segments @@ -273,7 +283,8 @@ static void link_segment(intval_t start, intval_t length) // check whether given PC is inside segment. -// only call in first pass, otherwise too many warnings might be thrown (TODO - still?) +// only call in first pass, otherwise too many warnings might be thrown +// FIXME - do it the other way round and only complain if there were no other errors! static void check_segment(intval_t new_pc) { struct segment *test_segment = out->segment.list_head.next; @@ -327,7 +338,12 @@ void output_passinit(void) statement_size = 0; // increase PC by this at end of statement // pseudopc stuff: - pseudopc_current_context = NULL; // FIXME - let it point to dummy struct! + // init dummy pseudopc struct + outermost_pseudopc_context.outer = NULL; + outermost_pseudopc_context.offset = 0; + outermost_pseudopc_context.ntype = NUMTYPE_UNDEFINED; + // and use it: + pseudopc_current_context = &outermost_pseudopc_context; // this was moved over from caller - does it make sense to merge into some if/else? @@ -343,7 +359,7 @@ static void end_segment(void) { intval_t amount; - // in later passes, ignore completely + // in later passes, ignore completely (FIXME - change!) if (!FIRST_PASS) return; @@ -524,12 +540,6 @@ void output_get_result(const char **ptr, intval_t *size, intval_t *loadaddr) // pseudopc stuff: -// struct to describe a pseudopc context -struct pseudopc { - struct pseudopc *outer; // next layer (to be able to "unpseudopc" labels by more than one level) - intval_t offset; // inner minus outer pc - enum numtype ntype; // type of outer pc (INT/UNDEFINED) -}; // start offset assembly void pseudopc_start(struct number *new_pc) { @@ -552,16 +562,20 @@ void pseudopc_end(void) program_counter = (program_counter - pseudopc_current_context->offset) & (config.outbuf_size - 1); // pc might have wrapped around pc_ntype = pseudopc_current_context->ntype; pseudopc_current_context = pseudopc_current_context->outer; // go back to outer block + if (pseudopc_current_context == NULL) + BUG("PseudoPCContext", 0); } // un-pseudopc a label value by given number of levels // returns nonzero on error (if level too high) int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels) { while (levels--) { - //if (target->ntype == NUMTYPE_UNDEFINED) - // return 0; // ok (no sense in trying to unpseudo this, and it might be an unresolved forward ref anyway) + if (target->ntype == NUMTYPE_UNDEFINED) + return 0; // ok (no sense in trying to unpseudo this, and it might be an unresolved forward ref anyway) - if (context == NULL) { + if (context == NULL) + BUG("PseudoPCContext", 1); + if (context == &outermost_pseudopc_context) { Throw_error("Un-pseudopc operator '&' has no !pseudopc context."); return 1; // error } @@ -571,7 +585,7 @@ int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned } return 0; // ok } -// return pointer to current "pseudopc" struct (may be NULL!) FIXME - not anymore? +// return pointer to current "pseudopc" struct // this gets called when parsing label definitions struct pseudopc *pseudopc_get_context(void) { @@ -580,5 +594,5 @@ struct pseudopc *pseudopc_get_context(void) // returns nonzero if "!pseudopc" is in effect, zero otherwise int pseudopc_isactive(void) { - return pseudopc_current_context != NULL; // FIXME - compare to dummy struct instead! + return pseudopc_current_context != &outermost_pseudopc_context; } diff --git a/src/output.h b/src/output.h index 7ed8fae..80ae80c 100644 --- a/src/output.h +++ b/src/output.h @@ -79,7 +79,7 @@ extern void pseudopc_end(void); // returns nonzero on error (if level too high) extern int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned int levels); -// return pointer to current "pseudopc" struct (may be NULL!) +// return pointer to current "pseudopc" struct // this gets called when parsing label definitions extern struct pseudopc *pseudopc_get_context(void); diff --git a/src/version.h b/src/version.h index be967e7..a844970 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 "23 Feb" // update before release FIXME +#define CHANGE_DATE "24 Feb" // update before release FIXME #define CHANGE_YEAR "2024" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME diff --git a/testing/errors/nopseudopccontext1.a b/testing/errors/nopseudopccontext1.a index 170e44b..e88213f 100644 --- a/testing/errors/nopseudopccontext1.a +++ b/testing/errors/nopseudopccontext1.a @@ -1,2 +1,3 @@ -;ACME 0.96.5 - a = &c + *=$1000 +label nop + a = &label diff --git a/testing/errors/nopseudopccontext2.a b/testing/errors/nopseudopccontext2.a index a3b5dcc..e05cf65 100644 --- a/testing/errors/nopseudopccontext2.a +++ b/testing/errors/nopseudopccontext2.a @@ -1,2 +1,2 @@ -;ACME 0.96.5 + *=$1000 b = &*