mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-01-11 13:30:15 +00:00
Release 0.94.7: Fixed bug where setting the program counter to an address>$ffff
and writing a byte hung ACME. Thanks to groepaz/VICEteam for reporting this. Cleaned up output.c while at it. Verbose output now indicates hex values using "0x" instead of "$" more consistently. git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@25 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
d206b62eeb
commit
e9999a07a4
@ -12,6 +12,17 @@ platform used. There should be another help file in this archive
|
||||
outlining the platform specific changes.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.94.7
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Fixed bug: Setting the program counter to an address > $ffff and
|
||||
writing a byte hung ACME. Thanks to groepaz/VICEteam for reporting
|
||||
this.
|
||||
Verbose output now uses "0x" instead of "$" to indicate hexadecimal in
|
||||
more places.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.94.6
|
||||
----------------------------------------------------------------------
|
||||
@ -24,7 +35,7 @@ Section: New in release 0.94.5
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Fixed bug: wrap-around branches (from $ff80+ to zp and back) were
|
||||
reported as errors. Thanks to Bitbreaker for reporting this.
|
||||
reported as errors. Thanks to Bitbreaker/VOZ for reporting this.
|
||||
Fixed bug: left-shifting float values went wrong for large shifts.
|
||||
New error message: "Target not in bank (0xTARGET)" for branches.
|
||||
Fixed example program to get it to assemble with current library.
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
...the ACME Crossassembler for Multiple Environments
|
||||
|
||||
Release 0.94.5
|
||||
Release 0.94.7
|
||||
|
||||
- free software -
|
||||
|
||||
(C) 1998-2013 Marco Baye
|
||||
(C) 1998-2014 Marco Baye
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
@ -16,7 +16,7 @@ Section: Copyright
|
||||
----------------------------------------------------------------------
|
||||
|
||||
ACME - a crossassembler for producing 6502/6510/65c02/65816 code.
|
||||
Copyright (C) 1998-2006 Marco Baye
|
||||
Copyright (C) 1998-2014 Marco Baye
|
||||
The ACME icon was designed by Wanja "Brix" Gayk
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
14
src/acme.c
14
src/acme.c
@ -15,9 +15,9 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#define RELEASE "0.94.6" // update before release (FIXME)
|
||||
#define RELEASE "0.94.7" // update before release (FIXME)
|
||||
#define CODENAME "Zarquon" // update before release
|
||||
#define CHANGE_DATE "14 Jan" // update before release
|
||||
#define CHANGE_DATE "5 Mar" // update before release
|
||||
#define CHANGE_YEAR "2014" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
@ -182,7 +182,7 @@ static void save_output_file(void)
|
||||
static int perform_pass(void)
|
||||
{
|
||||
FILE *fd;
|
||||
int i;
|
||||
int ii;
|
||||
|
||||
// call modules' "pass init" functions
|
||||
CPU_passinit(default_cpu); // set default cpu values (PC undefined)
|
||||
@ -193,11 +193,11 @@ static int perform_pass(void)
|
||||
pass_undefined_count = 0; // no "NeedValue" errors yet
|
||||
pass_real_errors = 0; // no real errors yet
|
||||
// Process toplevel files
|
||||
for (i = 0; i < toplevel_src_count; i++) {
|
||||
if ((fd = fopen(toplevel_sources[i], FILE_READBINARY))) {
|
||||
Parse_and_close_file(fd, toplevel_sources[i]);
|
||||
for (ii = 0; ii < toplevel_src_count; ii++) {
|
||||
if ((fd = fopen(toplevel_sources[ii], FILE_READBINARY))) {
|
||||
Parse_and_close_file(fd, toplevel_sources[ii]);
|
||||
} else {
|
||||
fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[i]);
|
||||
fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[ii]);
|
||||
// FIXME - if "filename" starts with "-", tell user to give options FIRST, files SECOND!
|
||||
pass_real_errors++;
|
||||
}
|
||||
|
@ -268,11 +268,11 @@ void Label_dump_all(FILE *fd)
|
||||
void Label_clear_init(void)
|
||||
{
|
||||
struct node_ra_t **ptr;
|
||||
int i;
|
||||
int ii;
|
||||
|
||||
// cut down all the trees (clear pointer table)
|
||||
ptr = Label_forest;
|
||||
for (i = 255; i >= 0; i--)
|
||||
for (ii = 255; ii >= 0; ii--)
|
||||
*ptr++ = NULL;
|
||||
}
|
||||
|
||||
|
299
src/output.c
299
src/output.c
@ -5,6 +5,7 @@
|
||||
// Output stuff
|
||||
// 24 Nov 2007 Added possibility to suppress segment overlap warnings
|
||||
// 25 Sep 2011 Fixed bug in !to (colons in filename could be interpreted as EOS)
|
||||
// 5 Mar 2014 Fixed bug where setting *>0xffff resulted in hangups.
|
||||
#include <stdlib.h>
|
||||
//#include <stdio.h>
|
||||
#include <string.h> // for memset()
|
||||
@ -20,34 +21,39 @@
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
// Structure for linked list of segment data
|
||||
struct segment_t {
|
||||
struct segment_t *next,
|
||||
*prev;
|
||||
intval_t start,
|
||||
length;
|
||||
// constants
|
||||
#define OUTBUFFERSIZE 65536
|
||||
#define NO_SEGMENT_START (-1) // invalid value to signal "not in a segment"
|
||||
|
||||
|
||||
// structure for linked list of segment data
|
||||
struct segment {
|
||||
struct segment *next,
|
||||
*prev;
|
||||
intval_t start,
|
||||
length;
|
||||
};
|
||||
|
||||
|
||||
// constants
|
||||
#define OUTBUFFERSIZE 65536
|
||||
|
||||
// structure for all output stuff:
|
||||
struct output {
|
||||
// output buffer stuff
|
||||
char *buffer; // holds assembled code
|
||||
intval_t write_idx; // index of next write
|
||||
intval_t lowest_written; // smallest address used
|
||||
intval_t highest_written; // largest address used
|
||||
int initvalue_set; // actually bool
|
||||
struct {
|
||||
intval_t start; // start of current segment (or NO_SEGMENT_START)
|
||||
intval_t max; // highest address segment may use
|
||||
int flags; // "overlay" and "invisible" flags
|
||||
struct segment list_head; // head element of doubly-linked ring list
|
||||
} segment;
|
||||
};
|
||||
static struct output default_output;
|
||||
static struct output *out = &default_output;
|
||||
|
||||
// variables
|
||||
|
||||
// segment stuff
|
||||
static struct segment_t segments_head; // head element of segment list
|
||||
static intval_t segment_start; // start of current segment
|
||||
static intval_t segment_max; // highest address segment may use
|
||||
static int segment_flags; // "overlay" and "invisible" flags
|
||||
// misc
|
||||
static intval_t lowest_idx; // smallest address program uses
|
||||
static intval_t highest_idx; // end address of program plus one
|
||||
// output buffer stuff
|
||||
static char *output_buffer = NULL; // to hold assembled code
|
||||
static char *write_ptr = NULL; // points into output_buffer
|
||||
intval_t write_idx; // index in output buffer
|
||||
static int memory_initialised = FALSE;
|
||||
// predefined stuff
|
||||
static struct node_t *file_format_tree = NULL; // tree to hold output formats
|
||||
// possible file formats
|
||||
@ -78,27 +84,24 @@ static struct node_t segment_modifiers[] = {
|
||||
};
|
||||
|
||||
|
||||
// fill output buffer with given byte value
|
||||
static void fill_completely(char value)
|
||||
{
|
||||
memset(output_buffer, value, OUTBUFFERSIZE);
|
||||
}
|
||||
|
||||
|
||||
// set up new segment_max value according to the given address.
|
||||
// set up new out->segment.max value according to the given address.
|
||||
// just find the next segment start and subtract 1.
|
||||
static void find_segment_max(intval_t new_pc)
|
||||
{
|
||||
struct segment_t *test_segment = segments_head.next;
|
||||
struct segment *test_segment = out->segment.list_head.next;
|
||||
|
||||
// search for smallest segment start address that
|
||||
// is larger than given address
|
||||
// use list head as sentinel
|
||||
segments_head.start = OUTBUFFERSIZE;
|
||||
// FIXME - if +1 overflows intval_t, we have an infinite loop!
|
||||
out->segment.list_head.start = new_pc + 1;
|
||||
while (test_segment->start <= new_pc)
|
||||
test_segment = test_segment->next;
|
||||
segment_max = test_segment->start;
|
||||
segment_max--; // last free address available
|
||||
if (test_segment == &out->segment.list_head) {
|
||||
out->segment.max = OUTBUFFERSIZE - 1;
|
||||
} else {
|
||||
out->segment.max = test_segment->start - 1; // last free address available
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -109,66 +112,82 @@ static void border_crossed(int current_offset)
|
||||
Throw_serious_error("Produced too much code.");
|
||||
if (pass_count == 0) {
|
||||
Throw_warning("Segment reached another one, overwriting it.");
|
||||
find_segment_max(current_offset + 1);
|
||||
find_segment_max(current_offset + 1); // find new (next) limit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// send low byte to output buffer
|
||||
// function ptr to write byte into output buffer (might point to real fn or error trigger)
|
||||
void (*Output_byte)(intval_t byte);
|
||||
static void real_output(intval_t byte); // fn for actual output
|
||||
static void no_output(intval_t byte); // fn when output impossible
|
||||
|
||||
|
||||
// set output pointer (negative values deactivate output)
|
||||
static void set_mem_ptr(signed long index)
|
||||
{
|
||||
if (index < 0) {
|
||||
Output_byte = no_output;
|
||||
write_ptr = output_buffer;
|
||||
write_idx = 0;
|
||||
} else {
|
||||
Output_byte = real_output;
|
||||
write_ptr = output_buffer + index;
|
||||
write_idx = index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// send low byte to output buffer, automatically increasing program counter
|
||||
static void real_output(intval_t byte)
|
||||
{
|
||||
if (write_idx > segment_max)
|
||||
border_crossed(write_idx);
|
||||
*write_ptr++ = byte & 0xff;
|
||||
write_idx++;
|
||||
// did we reach segment limit?
|
||||
if (out->write_idx > out->segment.max)
|
||||
border_crossed(out->write_idx);
|
||||
// new minimum address?
|
||||
if (out->write_idx < out->lowest_written)
|
||||
out->lowest_written = out->write_idx;
|
||||
// new maximum address?
|
||||
if (out->write_idx > out->highest_written)
|
||||
out->highest_written = out->write_idx;
|
||||
// write byte and advance ptrs
|
||||
out->buffer[out->write_idx++] = byte & 0xff;
|
||||
CPU_2add++;
|
||||
}
|
||||
|
||||
|
||||
// fail to write to output buffer
|
||||
// activate output and set output pointer
|
||||
static void enable_output(intval_t index)
|
||||
{
|
||||
Output_byte = real_output;
|
||||
out->write_idx = index;
|
||||
}
|
||||
|
||||
|
||||
// throw error (pc undefined) and use fake pc from now on
|
||||
static void no_output(intval_t byte)
|
||||
{
|
||||
Throw_error(exception_pc_undefined);
|
||||
// set ptr to not complain again. as we have thrown an error, assembly
|
||||
// fails, so don't care about actual value.
|
||||
set_mem_ptr(512); // 512 to not garble zero page and stack. ;)
|
||||
CPU_2add++;
|
||||
enable_output(512); // 512 to not garble zero page and stack. ;)
|
||||
Output_byte(byte); // try again - the line above has changed the fn ptr!
|
||||
}
|
||||
|
||||
|
||||
// deactivate output - any byte written will trigger error!
|
||||
static void disable_output(void)
|
||||
{
|
||||
Output_byte = no_output;
|
||||
out->write_idx = 0;
|
||||
}
|
||||
|
||||
|
||||
// call this if really calling Output_byte would be a waste of time
|
||||
void Output_fake(int size)
|
||||
{
|
||||
if (size < 1)
|
||||
return;
|
||||
|
||||
// check whether ptr undefined
|
||||
if (Output_byte == no_output) {
|
||||
no_output(0);
|
||||
size--;
|
||||
Output_byte(0); // trigger error with a dummy byte
|
||||
size--; // fix amount to cater for dummy byte
|
||||
}
|
||||
if (write_idx + size - 1 > segment_max)
|
||||
border_crossed(write_idx + size - 1);
|
||||
write_ptr += size;
|
||||
write_idx += size;
|
||||
// did we reach segment limit?
|
||||
if (out->write_idx + size - 1 > out->segment.max)
|
||||
border_crossed(out->write_idx + size - 1);
|
||||
// new minimum address?
|
||||
if (out->write_idx < out->lowest_written)
|
||||
out->lowest_written = out->write_idx;
|
||||
// new maximum address?
|
||||
if (out->write_idx + size - 1 > out->highest_written)
|
||||
out->highest_written = out->write_idx + size - 1;
|
||||
// advance ptrs
|
||||
out->write_idx += size;
|
||||
CPU_2add += size;
|
||||
}
|
||||
|
||||
@ -222,6 +241,13 @@ void Output_32b(intval_t value)
|
||||
}
|
||||
|
||||
|
||||
// fill output buffer with given byte value
|
||||
static void fill_completely(char value)
|
||||
{
|
||||
memset(out->buffer, value, OUTBUFFERSIZE);
|
||||
}
|
||||
|
||||
|
||||
// define default value for empty memory ("!initmem" pseudo opcode)
|
||||
static enum eos_t PO_initmem(void)
|
||||
{
|
||||
@ -232,12 +258,12 @@ static enum eos_t PO_initmem(void)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// if MemInit flag is already set, complain
|
||||
if (memory_initialised) {
|
||||
if (out->initvalue_set) {
|
||||
Throw_warning("Memory already initialised.");
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
// set MemInit flag
|
||||
memory_initialised = TRUE;
|
||||
out->initvalue_set = TRUE;
|
||||
// get value and init memory
|
||||
content = ALU_defined_int();
|
||||
if ((content > 0xff) || (content < -0x80))
|
||||
@ -249,7 +275,7 @@ static enum eos_t PO_initmem(void)
|
||||
pass_undefined_count = 1;
|
||||
// FIXME - enforcing another pass is not needed if there hasn't been any
|
||||
// output yet. But that's tricky to detect without too much overhead.
|
||||
// The old solution was to add &&(lowest_idx < highest_idx) to "if" above
|
||||
// The old solution was to add &&(out->lowest_written < out->highest_written+1) to "if" above
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
@ -325,47 +351,58 @@ static struct node_t pseudo_opcodes[] = {
|
||||
};
|
||||
|
||||
|
||||
// init file format tree (is done early)
|
||||
// init file format tree (is done early, because it is needed for CLI argument parsing)
|
||||
void Outputfile_init(void)
|
||||
{
|
||||
Tree_add_table(&file_format_tree, file_formats);
|
||||
}
|
||||
|
||||
|
||||
// alloc and init mem buffer, register pseudo opcodes (done later)
|
||||
// init output struct, register pseudo opcodes (done later)
|
||||
void Output_init(signed long fill_value)
|
||||
{
|
||||
output_buffer = safe_malloc(OUTBUFFERSIZE);
|
||||
write_ptr = output_buffer;
|
||||
if (fill_value == MEMINIT_USE_DEFAULT)
|
||||
out->buffer = safe_malloc(OUTBUFFERSIZE);
|
||||
out->write_idx = 0;
|
||||
if (fill_value == MEMINIT_USE_DEFAULT) {
|
||||
fill_value = FILLVALUE_INITIAL;
|
||||
else
|
||||
memory_initialised = TRUE;
|
||||
out->initvalue_set = FALSE;
|
||||
} else {
|
||||
out->initvalue_set = TRUE;
|
||||
}
|
||||
// init output buffer (fill memory with initial value)
|
||||
fill_completely(fill_value & 0xff);
|
||||
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
|
||||
Tree_add_table(&segment_modifier_tree, segment_modifiers);
|
||||
// init ring list of segments
|
||||
segments_head.next = &segments_head;
|
||||
segments_head.prev = &segments_head;
|
||||
out->segment.list_head.next = &out->segment.list_head;
|
||||
out->segment.list_head.prev = &out->segment.list_head;
|
||||
}
|
||||
|
||||
|
||||
// dump memory buffer into output file
|
||||
// dump used portion of output buffer into output file
|
||||
void Output_save_file(FILE *fd)
|
||||
{
|
||||
intval_t amount = highest_idx - lowest_idx;
|
||||
intval_t start,
|
||||
amount;
|
||||
|
||||
if (out->highest_written < out->lowest_written) {
|
||||
// nothing written
|
||||
start = 0; // I could try to use some segment start, but what for?
|
||||
amount = 0;
|
||||
} else {
|
||||
start = out->lowest_written;
|
||||
amount = out->highest_written - start + 1;
|
||||
}
|
||||
if (Process_verbosity)
|
||||
printf("Saving %ld ($%lx) bytes ($%lx - $%lx exclusive).\n",
|
||||
amount, amount, lowest_idx, highest_idx);
|
||||
printf("Saving %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n",
|
||||
amount, amount, start, start + amount);
|
||||
// output file header according to file format
|
||||
switch (output_format) {
|
||||
case OUTPUT_FORMAT_APPLE:
|
||||
PLATFORM_SETFILETYPE_APPLE(output_filename);
|
||||
// output 16-bit load address in little-endian byte order
|
||||
putc(lowest_idx & 255, fd);
|
||||
putc(lowest_idx >> 8, fd);
|
||||
putc(start & 255, fd);
|
||||
putc(start >> 8, fd);
|
||||
// output 16-bit length in little-endian byte order
|
||||
putc(amount & 255, fd);
|
||||
putc(amount >> 8, fd);
|
||||
@ -377,31 +414,30 @@ void Output_save_file(FILE *fd)
|
||||
case OUTPUT_FORMAT_CBM:
|
||||
PLATFORM_SETFILETYPE_CBM(output_filename);
|
||||
// output 16-bit load address in little-endian byte order
|
||||
putc(lowest_idx & 255, fd);
|
||||
putc(lowest_idx >> 8, fd);
|
||||
putc(start & 255, fd);
|
||||
putc(start >> 8, fd);
|
||||
}
|
||||
// dump output buffer to file
|
||||
fwrite(output_buffer + lowest_idx, sizeof(char), amount, fd);
|
||||
fwrite(out->buffer + start, amount, 1, fd);
|
||||
}
|
||||
|
||||
|
||||
// link segment data into segment ring
|
||||
static void link_segment(intval_t start, intval_t length)
|
||||
{
|
||||
struct segment_t *new_segment,
|
||||
*test_segment = segments_head.next;
|
||||
struct segment *new_segment,
|
||||
*test_segment = out->segment.list_head.next;
|
||||
|
||||
// init new segment
|
||||
new_segment = safe_malloc(sizeof(*new_segment));
|
||||
new_segment->start = start;
|
||||
new_segment->length = length;
|
||||
// use ring head as sentinel
|
||||
segments_head.start = start;
|
||||
segments_head.length = length + 1;
|
||||
out->segment.list_head.start = start;
|
||||
out->segment.list_head.length = length + 1; // +1 to make sure sentinel exits loop
|
||||
// walk ring to find correct spot
|
||||
while ((test_segment->start < new_segment->start) ||
|
||||
((test_segment->start == new_segment->start) &&
|
||||
(test_segment->length < new_segment->length)))
|
||||
while ((test_segment->start < new_segment->start)
|
||||
|| ((test_segment->start == new_segment->start) && (test_segment->length < new_segment->length)))
|
||||
test_segment = test_segment->next;
|
||||
// link into ring
|
||||
new_segment->next = test_segment;
|
||||
@ -417,21 +453,19 @@ void Output_end_segment(void)
|
||||
{
|
||||
intval_t amount;
|
||||
|
||||
// if no segments were started, ignore the call at end-of-pass:
|
||||
if (out->segment.start == NO_SEGMENT_START)
|
||||
return;
|
||||
|
||||
if (CPU_uses_pseudo_pc())
|
||||
Throw_first_pass_warning("Offset assembly still active at end of segment."); // FIXME - should be error!
|
||||
if ((pass_count == 0) && !(segment_flags & SEGMENT_FLAG_INVISIBLE)) {
|
||||
amount = write_idx - segment_start;
|
||||
link_segment(segment_start, amount);
|
||||
if ((pass_count == 0) && !(out->segment.flags & SEGMENT_FLAG_INVISIBLE)) {
|
||||
amount = out->write_idx - out->segment.start;
|
||||
link_segment(out->segment.start, amount);
|
||||
if (Process_verbosity > 1)
|
||||
printf(
|
||||
"Segment size is %ld ($%lx) bytes ($%lx - $%lx exclusive).\n",
|
||||
amount, amount, segment_start, write_idx);
|
||||
printf("Segment size is %ld (0x%lx) bytes (0x%lx - 0x%lx exclusive).\n",
|
||||
amount, amount, out->segment.start, out->write_idx);
|
||||
}
|
||||
|
||||
// FIXME - this was in real_output():
|
||||
// check for new max address (FIXME - move to close_segment?)
|
||||
if (write_idx > highest_idx)
|
||||
highest_idx = write_idx;
|
||||
}
|
||||
|
||||
|
||||
@ -439,11 +473,11 @@ amount, amount, segment_start, write_idx);
|
||||
// only call in first pass, otherwise too many warnings might be thrown
|
||||
static void check_segment(intval_t new_pc)
|
||||
{
|
||||
struct segment_t *test_segment = segments_head.next;
|
||||
struct segment *test_segment = out->segment.list_head.next;
|
||||
|
||||
// use list head as sentinel
|
||||
segments_head.start = new_pc + 1;
|
||||
segments_head.length = 1;
|
||||
out->segment.list_head.start = new_pc + 1; // +1 to make sure sentinel exits loop
|
||||
out->segment.list_head.length = 1;
|
||||
// search ring for matching entry
|
||||
while (test_segment->start <= new_pc) {
|
||||
if ((test_segment->start + test_segment->length) > new_pc) {
|
||||
@ -456,38 +490,34 @@ static void check_segment(intval_t new_pc)
|
||||
}
|
||||
|
||||
|
||||
// init lowest and highest address
|
||||
static void init_borders(intval_t address)
|
||||
{
|
||||
lowest_idx = address;
|
||||
highest_idx = address;
|
||||
}
|
||||
|
||||
|
||||
// clear segment list
|
||||
void Output_passinit(signed long start_addr)
|
||||
{
|
||||
// struct segment_t *temp;
|
||||
// struct segment *temp;
|
||||
|
||||
//FIXME - why clear ring list in every pass?
|
||||
// delete segment list (and free blocks)
|
||||
// while ((temp = segment_list)) {
|
||||
// segment_list = segment_list->next;
|
||||
// free(temp);
|
||||
// }
|
||||
set_mem_ptr(start_addr); // negative values deactivate output
|
||||
|
||||
// invalidate start and end (first byte actually output will fix them)
|
||||
out->lowest_written = OUTBUFFERSIZE - 1;
|
||||
out->highest_written = 0;
|
||||
|
||||
// if start address given, set program counter
|
||||
if (start_addr >= 0) {
|
||||
enable_output(start_addr);
|
||||
CPU_set_pc(start_addr);
|
||||
// FIXME - integrate next two?
|
||||
init_borders(start_addr);
|
||||
segment_start = start_addr;
|
||||
out->segment.start = start_addr;
|
||||
} else {
|
||||
init_borders(0); // set to _something_ (for !initmem)
|
||||
segment_start = 0;
|
||||
disable_output();
|
||||
out->segment.start = NO_SEGMENT_START;
|
||||
}
|
||||
// other stuff
|
||||
segment_max = OUTBUFFERSIZE - 1;
|
||||
segment_flags = 0;
|
||||
out->segment.max = OUTBUFFERSIZE - 1;
|
||||
out->segment.flags = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -513,12 +543,9 @@ void Output_start_segment(void)
|
||||
new_flags |= (int) node_body;
|
||||
}
|
||||
|
||||
// to allow for undefined pseudopc, this must be changed to use memaddress instead!
|
||||
if (CPU_pc.flags & MVALUE_DEFINED) {
|
||||
// it's a redefinition. Check some things:
|
||||
// check whether new low
|
||||
if (new_addr < lowest_idx)
|
||||
lowest_idx = new_addr;
|
||||
// if there was a segment before, end it
|
||||
if (out->segment.start != NO_SEGMENT_START) {
|
||||
// it's a redefinition, so:
|
||||
// show status of previous segment
|
||||
Output_end_segment();
|
||||
// in first pass, maybe issue warning
|
||||
@ -527,11 +554,9 @@ void Output_start_segment(void)
|
||||
check_segment(new_addr);
|
||||
find_segment_max(new_addr);
|
||||
}
|
||||
} else {
|
||||
init_borders(new_addr); // it's the first pc definition
|
||||
}
|
||||
out->segment.start = new_addr;
|
||||
out->segment.flags = new_flags;
|
||||
enable_output(new_addr);
|
||||
CPU_set_pc(new_addr);
|
||||
segment_start = new_addr;
|
||||
segment_flags = new_flags;
|
||||
set_mem_ptr(new_addr);
|
||||
}
|
||||
|
@ -192,9 +192,9 @@ void dump_tree(struct node_ra_t *node, int id_number, void (*fn)(struct node_ra_
|
||||
// Calls Tree_dump_tree for each non-zero entry of the given tree table.
|
||||
void Tree_dump_forest(struct node_ra_t **forest, int id_number, void (*fn)(struct node_ra_t *, FILE *), FILE *env)
|
||||
{
|
||||
int i;
|
||||
int ii;
|
||||
|
||||
for (i = 255; i >= 0; i--) {
|
||||
for (ii = 255; ii >= 0; ii--) {
|
||||
if (*forest)
|
||||
dump_tree(*forest, id_number, fn, env);
|
||||
forest++;
|
||||
|
Loading…
x
Reference in New Issue
Block a user