added experimental support for 16MiB outbuf using "--test"

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@274 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-07-04 13:43:20 +00:00
parent 70b9ee222d
commit eb138ae785
4 changed files with 33 additions and 22 deletions

View File

@ -422,6 +422,7 @@ static void set_starting_pc(const char expression[])
start_address = string_to_number(expression); start_address = string_to_number(expression);
if ((start_address > -1) && (start_address < 65536)) if ((start_address > -1) && (start_address < 65536))
return; return;
fprintf(stderr, "%sProgram counter out of range (0-0xffff).\n", cliargs_error); fprintf(stderr, "%sProgram counter out of range (0-0xffff).\n", cliargs_error);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -433,6 +434,7 @@ static void set_mem_contents(const char expression[])
fill_value = string_to_number(expression); fill_value = string_to_number(expression);
if ((fill_value >= -128) && (fill_value <= 255)) if ((fill_value >= -128) && (fill_value <= 255))
return; return;
fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error); fprintf(stderr, "%sInitmem value out of range (0-0xff).\n", cliargs_error);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -653,7 +655,7 @@ int main(int argc, const char *argv[])
ALU_init(); ALU_init();
Macro_init(); Macro_init();
Mnemo_init(); Mnemo_init();
Output_init(fill_value); Output_init(fill_value, config.test_new_features);
pseudoopcodes_init(); // setup keyword tree for pseudo opcodes pseudoopcodes_init(); // setup keyword tree for pseudo opcodes
if (do_actual_work()) if (do_actual_work())
save_output_file(); save_output_file();

View File

@ -24,7 +24,6 @@
// constants // constants
#define OUTBUFFERSIZE 65536
#define NO_SEGMENT_START (-1) // invalid value to signal "not in a segment" #define NO_SEGMENT_START (-1) // invalid value to signal "not in a segment"
@ -39,6 +38,7 @@ struct segment {
// structure for all output stuff: // structure for all output stuff:
struct output { struct output {
// output buffer stuff // output buffer stuff
intval_t bufsize; // either 64 KiB or 16 MiB
char *buffer; // holds assembled code char *buffer; // holds assembled code
intval_t write_idx; // index of next write intval_t write_idx; // index of next write
intval_t lowest_written; // smallest address used intval_t lowest_written; // smallest address used
@ -110,7 +110,7 @@ static void find_segment_max(intval_t new_pc)
while (test_segment->start <= new_pc) while (test_segment->start <= new_pc)
test_segment = test_segment->next; test_segment = test_segment->next;
if (test_segment == &out->segment.list_head) if (test_segment == &out->segment.list_head)
out->segment.max = OUTBUFFERSIZE - 1; out->segment.max = out->bufsize - 1;
else else
out->segment.max = test_segment->start - 1; // last free address available out->segment.max = test_segment->start - 1; // last free address available
} }
@ -119,8 +119,9 @@ static void find_segment_max(intval_t new_pc)
// //
static void border_crossed(int current_offset) static void border_crossed(int current_offset)
{ {
if (current_offset >= OUTBUFFERSIZE) if (current_offset >= out->bufsize)
Throw_serious_error("Produced too much code."); Throw_serious_error("Produced too much code.");
// TODO - get rid of FIRST_PASS condition, because user can suppress these warnings if they want
if (FIRST_PASS) { if (FIRST_PASS) {
// TODO: make warn/err an arg for a general "Throw" function // TODO: make warn/err an arg for a general "Throw" function
if (config.segment_warning_is_error) if (config.segment_warning_is_error)
@ -139,7 +140,9 @@ void (*Output_byte)(intval_t byte);
// send low byte to output buffer, automatically increasing program counter // send low byte to output buffer, automatically increasing program counter
static void real_output(intval_t byte) static void real_output(intval_t byte)
{ {
// did we reach segment limit? // CAUTION - there are two copies of these checks!
// TODO - add additional check for current segment's "limit" value
// did we reach next segment?
if (out->write_idx > out->segment.max) if (out->write_idx > out->segment.max)
border_crossed(out->write_idx); border_crossed(out->write_idx);
// new minimum address? // new minimum address?
@ -182,7 +185,9 @@ void output_skip(int size)
Output_byte(0); // trigger error with a dummy byte Output_byte(0); // trigger error with a dummy byte
--size; // fix amount to cater for dummy byte --size; // fix amount to cater for dummy byte
} }
// did we reach segment limit? // CAUTION - there are two copies of these checks!
// TODO - add additional check for current segment's "limit" value
// did we reach next segment?
if (out->write_idx + size - 1 > out->segment.max) if (out->write_idx + size - 1 > out->segment.max)
border_crossed(out->write_idx + size - 1); border_crossed(out->write_idx + size - 1);
// new minimum address? // new minimum address?
@ -200,7 +205,7 @@ void output_skip(int size)
// fill output buffer with given byte value // fill output buffer with given byte value
static void fill_completely(char value) static void fill_completely(char value)
{ {
memset(out->buffer, value, OUTBUFFERSIZE); memset(out->buffer, value, out->bufsize);
} }
@ -251,6 +256,7 @@ int outputfile_prefer_cbm_format(void)
{ {
if (output_format != OUTPUT_FORMAT_UNSPECIFIED) if (output_format != OUTPUT_FORMAT_UNSPECIFIED)
return 0; return 0;
output_format = OUTPUT_FORMAT_CBM; output_format = OUTPUT_FORMAT_CBM;
return 1; return 1;
} }
@ -272,9 +278,10 @@ int outputfile_set_filename(void)
// init output struct (done later) // init output struct (done later)
void Output_init(signed long fill_value) void Output_init(signed long fill_value, boolean use_large_buf)
{ {
out->buffer = safe_malloc(OUTBUFFERSIZE); out->bufsize = use_large_buf ? 0x1000000 : 0x10000;
out->buffer = safe_malloc(out->bufsize);
if (fill_value == MEMINIT_USE_DEFAULT) { if (fill_value == MEMINIT_USE_DEFAULT) {
fill_value = FILLVALUE_INITIAL; fill_value = FILLVALUE_INITIAL;
out->initvalue_set = FALSE; out->initvalue_set = FALSE;
@ -358,7 +365,7 @@ static void link_segment(intval_t start, intval_t length)
// check whether given PC is inside segment. // check whether given PC is inside segment.
// only call in first pass, otherwise too many warnings might be thrown // only call in first pass, otherwise too many warnings might be thrown (TODO - still?)
static void check_segment(intval_t new_pc) static void check_segment(intval_t new_pc)
{ {
struct segment *test_segment = out->segment.list_head.next; struct segment *test_segment = out->segment.list_head.next;
@ -389,7 +396,7 @@ void Output_passinit(void)
//FIXME - why clear ring list in every pass? //FIXME - why clear ring list in every pass?
// Because later pass shouldn't complain about overwriting the same segment from earlier pass! // Because later pass shouldn't complain about overwriting the same segment from earlier pass!
// Currently this does not happen because segment checks are only done in first pass. FIXME! // Currently this does not happen because segment warnings are only generated in first pass. FIXME!
// delete segment list (and free blocks) // delete segment list (and free blocks)
// while ((temp = segment_list)) { // while ((temp = segment_list)) {
// segment_list = segment_list->next; // segment_list = segment_list->next;
@ -397,13 +404,13 @@ void Output_passinit(void)
// } // }
// invalidate start and end (first byte actually written will fix them) // invalidate start and end (first byte actually written will fix them)
out->lowest_written = OUTBUFFERSIZE - 1; out->lowest_written = out->bufsize - 1;
out->highest_written = 0; out->highest_written = 0;
// deactivate output - any byte written will trigger error: // deactivate output - any byte written will trigger error:
Output_byte = no_output; Output_byte = no_output;
out->write_idx = 0; // same as pc on pass init! out->write_idx = 0; // same as pc on pass init!
out->segment.start = NO_SEGMENT_START; // TODO - "no active segment" could be made a segment flag! out->segment.start = NO_SEGMENT_START; // TODO - "no active segment" could be made a segment flag!
out->segment.max = OUTBUFFERSIZE - 1; out->segment.max = out->bufsize - 1; // TODO - use end of bank?
out->segment.flags = 0; out->segment.flags = 0;
out->xor = 0; out->xor = 0;
@ -455,18 +462,20 @@ void Output_end_segment(void)
// change output pointer and enable output // change output pointer and enable output
// TODO - this only gets called from vcpu_set_pc so could be made static!
void Output_start_segment(intval_t address_change, bits segment_flags) void Output_start_segment(intval_t address_change, bits segment_flags)
{ {
// properly finalize previous segment (link to list, announce) // properly finalize previous segment (link to list, announce)
Output_end_segment(); Output_end_segment();
// calculate start of new segment // calculate start of new segment
out->write_idx = (out->write_idx + address_change) & 0xffff; out->write_idx = (out->write_idx + address_change) & (out->bufsize - 1);
out->segment.start = out->write_idx; out->segment.start = out->write_idx;
out->segment.flags = segment_flags; out->segment.flags = segment_flags;
// allow writing to output buffer // allow writing to output buffer
Output_byte = real_output; Output_byte = real_output;
// in first pass, check for other segments and maybe issue warning // in first pass, check for other segments and maybe issue warning
// TODO - remove FIRST_PASS condition
if (FIRST_PASS) { if (FIRST_PASS) {
if (!(segment_flags & SEGMENT_FLAG_OVERLAY)) if (!(segment_flags & SEGMENT_FLAG_OVERLAY))
check_segment(out->segment.start); check_segment(out->segment.start);
@ -490,7 +499,7 @@ void output_set_xor(char xor)
// in addition to that, it will be called on each "*= VALUE". // in addition to that, it will be called on each "*= VALUE".
void vcpu_set_pc(intval_t new_pc, bits segment_flags) void vcpu_set_pc(intval_t new_pc, bits segment_flags)
{ {
intval_t new_offset; intval_t pc_change;
// support stupidly bad, old, ancient, deprecated, obsolete behaviour: // support stupidly bad, old, ancient, deprecated, obsolete behaviour:
if (pseudopc_current_context != NULL) { if (pseudopc_current_context != NULL) {
@ -506,12 +515,12 @@ void vcpu_set_pc(intval_t new_pc, bits segment_flags)
// stuff happens! i see no reason to try to mimic that. // stuff happens! i see no reason to try to mimic that.
} }
} }
new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff; pc_change = new_pc - CPU_state.pc.val.intval;
CPU_state.pc.val.intval = new_pc; CPU_state.pc.val.intval = new_pc;
CPU_state.pc.ntype = NUMTYPE_INT; // FIXME - remove when allowing undefined! CPU_state.pc.ntype = NUMTYPE_INT; // FIXME - remove when allowing undefined!
CPU_state.pc.addr_refs = 1; // yes, PC counts as address CPU_state.pc.addr_refs = 1; // yes, PC counts as address
// now tell output buffer to start a new segment // now tell output buffer to start a new segment
Output_start_segment(new_offset, segment_flags); Output_start_segment(pc_change, segment_flags);
} }
/* /*
TODO - overhaul program counter and memory pointer stuff: TODO - overhaul program counter and memory pointer stuff:
@ -560,7 +569,7 @@ int vcpu_get_statement_size(void)
// adjust program counter (called at end of each statement) // adjust program counter (called at end of each statement)
void vcpu_end_statement(void) void vcpu_end_statement(void)
{ {
CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & 0xffff; CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & (out->bufsize - 1);
CPU_state.add_to_pc = 0; CPU_state.add_to_pc = 0;
} }
@ -599,7 +608,7 @@ void pseudopc_end(void)
if (config.wanted_version >= VER_DISABLED_OBSOLETE_STUFF) if (config.wanted_version >= VER_DISABLED_OBSOLETE_STUFF)
Bug_found("ClosingUnopenedPseudopcBlock", 0); Bug_found("ClosingUnopenedPseudopcBlock", 0);
} else { } else {
CPU_state.pc.val.intval = (CPU_state.pc.val.intval - pseudopc_current_context->offset) & 0xffff; // pc might have wrapped around CPU_state.pc.val.intval = (CPU_state.pc.val.intval - pseudopc_current_context->offset) & (out->bufsize - 1); // pc might have wrapped around
CPU_state.pc.ntype = pseudopc_current_context->ntype; CPU_state.pc.ntype = pseudopc_current_context->ntype;
pseudopc_current_context = pseudopc_current_context->outer; // go back to outer block pseudopc_current_context = pseudopc_current_context->outer; // go back to outer block
} }
@ -623,7 +632,7 @@ int pseudopc_unpseudo(struct number *target, struct pseudopc *context, unsigned
return 1; // error return 1; // error
} }
// FIXME - in future, check both target and context for NUMTYPE_UNDEFINED! // FIXME - in future, check both target and context for NUMTYPE_UNDEFINED!
target->val.intval = (target->val.intval - context->offset) & 0xffff; // FIXME - is masking really needed? target->val.intval = (target->val.intval - context->offset) & (out->bufsize - 1); // FIXME - is masking really needed? TODO
context = context->outer; context = context->outer;
} }
return 0; // ok return 0; // ok

View File

@ -42,7 +42,7 @@ extern void Output_passinit(void);
// outbuf stuff: // outbuf stuff:
// alloc and init mem buffer (done later) // alloc and init mem buffer (done later)
extern void Output_init(signed long fill_value); extern void Output_init(signed long fill_value, boolean use_large_buf);
// skip over some bytes in output buffer without starting a new segment // skip over some bytes in output buffer without starting a new segment
// (used by "!skip", and also called by "!binary" if really calling // (used by "!skip", and also called by "!binary" if really calling
// Output_byte would be a waste of time) // Output_byte would be a waste of time)

View File

@ -9,7 +9,7 @@
#define RELEASE "0.97" // update before release FIXME #define RELEASE "0.97" // update before release FIXME
#define CODENAME "Zem" // update before release #define CODENAME "Zem" // update before release
#define CHANGE_DATE "29 June" // update before release FIXME #define CHANGE_DATE "4 Jul" // update before release FIXME
#define CHANGE_YEAR "2020" // update before release #define CHANGE_YEAR "2020" // update before release
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/"
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME