mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-06-30 21:29:47 +00:00
cleanup, now only output.c accesses CPU_state.pc
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@186 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
dfca72688b
commit
0173eaf777
38
src/acme.c
38
src/acme.c
|
@ -587,3 +587,41 @@ int main(int argc, const char *argv[])
|
||||||
save_output_file();
|
save_output_file();
|
||||||
return ACME_finalize(EXIT_SUCCESS); // dump labels, if wanted
|
return ACME_finalize(EXIT_SUCCESS); // dump labels, if wanted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO - maybe add a "use version" switch to ease assembling old sources?
|
||||||
|
relevant changes are:
|
||||||
|
|
||||||
|
"0.05"
|
||||||
|
...would be the syntax before any changes
|
||||||
|
(how was offset assembly ended? '*' in a line on its own?)
|
||||||
|
BIT without any arg would output $2c, masking the next two bytes
|
||||||
|
"0.07"
|
||||||
|
"leading zeroes" info is now stored in symbols as well
|
||||||
|
changed argument order of mvp/mvn
|
||||||
|
!cbm outputs warning to use !ct pet instead
|
||||||
|
!end changed to !eof
|
||||||
|
*= is now segment change instead of offset assembly
|
||||||
|
added !pseudopc/!realpc
|
||||||
|
"0.86"
|
||||||
|
!pseudopc/!realpc gives a warning to use !pseudopc{} instead
|
||||||
|
"0.89"
|
||||||
|
>> now does ASR everywhere, added >>> as LSR
|
||||||
|
numbers before mnemonics are no longer interpreted as labels
|
||||||
|
"0.93"
|
||||||
|
*= no longer ends offset assembly
|
||||||
|
"0.94.6"
|
||||||
|
powerof is now right-associative
|
||||||
|
"0.94.8"
|
||||||
|
disabled !cbm
|
||||||
|
disabled !pseudopc/!realpc
|
||||||
|
disabled !subzone
|
||||||
|
"0.94.12"
|
||||||
|
new !for syntax
|
||||||
|
"0.95.2"
|
||||||
|
changed ANC#8 from 0x2b to 0x0b
|
||||||
|
"future"
|
||||||
|
backslash escaping (= strings)
|
||||||
|
TODO: paths should be relative to file, not start dir
|
||||||
|
TODO: ignore leading zeroes?
|
||||||
|
*/
|
||||||
|
|
|
@ -2049,6 +2049,8 @@ intval_t ALU_any_int(void) // ACCEPT_UNDEFINED
|
||||||
// EMPTY: complain _seriously_
|
// EMPTY: complain _seriously_
|
||||||
// UNDEFINED: complain _seriously_
|
// UNDEFINED: complain _seriously_
|
||||||
// FLOAT: convert to int
|
// FLOAT: convert to int
|
||||||
|
// FIXME - only very few callers actually _need_ a serious error to be thrown,
|
||||||
|
// so throw a normal one here and pass ok/fail as return value, so caller can react.
|
||||||
void ALU_defined_int(struct number *intresult) // no ACCEPT constants?
|
void ALU_defined_int(struct number *intresult) // no ACCEPT constants?
|
||||||
{
|
{
|
||||||
struct expression expression;
|
struct expression expression;
|
||||||
|
|
|
@ -122,4 +122,6 @@ void cputype_passinit(const struct cpu_type *cpu_type)
|
||||||
{
|
{
|
||||||
// handle cpu type (default is 6502)
|
// handle cpu type (default is 6502)
|
||||||
CPU_state.type = cpu_type ? cpu_type : &cpu_type_6502;
|
CPU_state.type = cpu_type ? cpu_type : &cpu_type_6502;
|
||||||
|
CPU_state.a_is_long = FALSE; // short accu
|
||||||
|
CPU_state.xy_are_long = FALSE; // short index regs
|
||||||
}
|
}
|
||||||
|
|
14
src/mnemo.c
14
src/mnemo.c
|
@ -783,17 +783,18 @@ static void not_in_bank(intval_t target)
|
||||||
// helper function for branches with 8-bit offset (including bbr0..7/bbs0..7)
|
// helper function for branches with 8-bit offset (including bbr0..7/bbs0..7)
|
||||||
static void near_branch(int preoffset)
|
static void near_branch(int preoffset)
|
||||||
{
|
{
|
||||||
|
struct number pc;
|
||||||
struct number target;
|
struct number target;
|
||||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||||
|
|
||||||
|
vcpu_read_pc(&pc);
|
||||||
get_int_arg(&target, TRUE);
|
get_int_arg(&target, TRUE);
|
||||||
typesystem_want_addr(&target);
|
typesystem_want_addr(&target);
|
||||||
// FIXME - read pc via function call instead!
|
if (pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
||||||
if (CPU_state.pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
|
||||||
if ((target.val.intval | 0xffff) != 0xffff) {
|
if ((target.val.intval | 0xffff) != 0xffff) {
|
||||||
not_in_bank(target.val.intval);
|
not_in_bank(target.val.intval);
|
||||||
} else {
|
} else {
|
||||||
offset = (target.val.intval - (CPU_state.pc.val.intval + preoffset)) & 0xffff; // clip to 16 bit offset
|
offset = (target.val.intval - (pc.val.intval + preoffset)) & 0xffff; // clip to 16 bit offset
|
||||||
// fix sign
|
// fix sign
|
||||||
if (offset & 0x8000)
|
if (offset & 0x8000)
|
||||||
offset -= 0x10000;
|
offset -= 0x10000;
|
||||||
|
@ -817,17 +818,18 @@ static void near_branch(int preoffset)
|
||||||
// helper function for relative addressing with 16-bit offset
|
// helper function for relative addressing with 16-bit offset
|
||||||
static void far_branch(int preoffset)
|
static void far_branch(int preoffset)
|
||||||
{
|
{
|
||||||
|
struct number pc;
|
||||||
struct number target;
|
struct number target;
|
||||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||||
|
|
||||||
|
vcpu_read_pc(&pc);
|
||||||
get_int_arg(&target, TRUE);
|
get_int_arg(&target, TRUE);
|
||||||
typesystem_want_addr(&target);
|
typesystem_want_addr(&target);
|
||||||
// FIXME - read pc via function call instead!
|
if (pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
||||||
if (CPU_state.pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
|
||||||
if ((target.val.intval | 0xffff) != 0xffff) {
|
if ((target.val.intval | 0xffff) != 0xffff) {
|
||||||
not_in_bank(target.val.intval);
|
not_in_bank(target.val.intval);
|
||||||
} else {
|
} else {
|
||||||
offset = (target.val.intval - (CPU_state.pc.val.intval + preoffset)) & 0xffff;
|
offset = (target.val.intval - (pc.val.intval + preoffset)) & 0xffff;
|
||||||
// no further checks necessary, 16-bit branches can access whole bank
|
// no further checks necessary, 16-bit branches can access whole bank
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
src/output.c
18
src/output.c
|
@ -496,8 +496,6 @@ void Output_passinit(void)
|
||||||
CPU_state.pc.flags = 0; // not defined yet
|
CPU_state.pc.flags = 0; // not defined yet
|
||||||
CPU_state.pc.val.intval = 0; // same as output's write_idx on pass init
|
CPU_state.pc.val.intval = 0; // same as output's write_idx on pass init
|
||||||
CPU_state.add_to_pc = 0; // increase PC by this at end of statement
|
CPU_state.add_to_pc = 0; // increase PC by this at end of statement
|
||||||
CPU_state.a_is_long = FALSE; // short accu
|
|
||||||
CPU_state.xy_are_long = FALSE; // short index regs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -630,3 +628,19 @@ 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) & 0xffff;
|
||||||
CPU_state.add_to_pc = 0;
|
CPU_state.add_to_pc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start offset assembly
|
||||||
|
void pseudopc_start(struct pseudopc *buffer, struct number *new_pc)
|
||||||
|
{
|
||||||
|
buffer->flags = CPU_state.pc.flags;
|
||||||
|
buffer->offset = (new_pc->val.intval - CPU_state.pc.val.intval) & 0xffff;
|
||||||
|
CPU_state.pc.val.intval = new_pc->val.intval;
|
||||||
|
CPU_state.pc.flags |= NUMBER_IS_DEFINED; // FIXME - remove when allowing undefined!
|
||||||
|
//new: CPU_state.pc.flags = new_pc->flags & (NUMBER_IS_DEFINED | NUMBER_EVER_UNDEFINED);
|
||||||
|
}
|
||||||
|
// end offset assembly
|
||||||
|
void pseudopc_end(struct pseudopc *buffer)
|
||||||
|
{
|
||||||
|
CPU_state.pc.val.intval = (CPU_state.pc.val.intval - buffer->offset) & 0xffff;
|
||||||
|
CPU_state.pc.flags = buffer->flags;
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,11 @@ struct vcpu {
|
||||||
boolean a_is_long;
|
boolean a_is_long;
|
||||||
boolean xy_are_long;
|
boolean xy_are_long;
|
||||||
};
|
};
|
||||||
|
// buffer to hold outer state while parsing "pseudopc" block
|
||||||
|
struct pseudopc {
|
||||||
|
intval_t offset;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
@ -98,6 +103,10 @@ extern void vcpu_read_pc(struct number *target);
|
||||||
extern int vcpu_get_statement_size(void);
|
extern int vcpu_get_statement_size(void);
|
||||||
// adjust program counter (called at end of each statement)
|
// adjust program counter (called at end of each statement)
|
||||||
extern void vcpu_end_statement(void);
|
extern void vcpu_end_statement(void);
|
||||||
|
// start offset assembly
|
||||||
|
extern void pseudopc_start(struct pseudopc *buffer, struct number *new_pc);
|
||||||
|
// end offset assembly
|
||||||
|
extern void pseudopc_end(struct pseudopc *buffer);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -540,18 +540,10 @@ static enum eos po_skip(void) // now GotByte = illegal char
|
||||||
// insert byte until PC fits condition
|
// insert byte until PC fits condition
|
||||||
static enum eos po_align(void)
|
static enum eos po_align(void)
|
||||||
{
|
{
|
||||||
// FIXME - read cpu state via function call!
|
|
||||||
struct number andresult,
|
struct number andresult,
|
||||||
equalresult;
|
equalresult;
|
||||||
intval_t fill,
|
intval_t fill;
|
||||||
test = CPU_state.pc.val.intval;
|
struct number pc;
|
||||||
|
|
||||||
// make sure PC is defined.
|
|
||||||
if ((CPU_state.pc.flags & NUMBER_IS_DEFINED) == 0) {
|
|
||||||
Throw_error(exception_pc_undefined);
|
|
||||||
CPU_state.pc.flags |= NUMBER_IS_DEFINED; // do not complain again
|
|
||||||
return SKIP_REMAINDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// now: !align ANDVALUE, EQUALVALUE [,FILLVALUE]
|
// now: !align ANDVALUE, EQUALVALUE [,FILLVALUE]
|
||||||
|
@ -565,35 +557,37 @@ static enum eos po_align(void)
|
||||||
fill = ALU_any_int();
|
fill = ALU_any_int();
|
||||||
else
|
else
|
||||||
fill = CPU_state.type->default_align_value;
|
fill = CPU_state.type->default_align_value;
|
||||||
while ((test++ & andresult.val.intval) != equalresult.val.intval)
|
|
||||||
|
// make sure PC is defined
|
||||||
|
vcpu_read_pc(&pc);
|
||||||
|
if (!(pc.flags & NUMBER_IS_DEFINED)) {
|
||||||
|
Throw_error(exception_pc_undefined);
|
||||||
|
return SKIP_REMAINDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((pc.val.intval++ & andresult.val.intval) != equalresult.val.intval)
|
||||||
output_8(fill);
|
output_8(fill);
|
||||||
return ENSURE_EOS;
|
return ENSURE_EOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char Error_old_offset_assembly[] =
|
static const char Error_old_offset_assembly[] =
|
||||||
"\"!pseudopc/!realpc\" is obsolete; use \"!pseudopc {}\" instead.";
|
"\"!pseudopc/!realpc\" is obsolete; use \"!pseudopc {}\" instead.";
|
||||||
// start offset assembly
|
// start offset assembly
|
||||||
// FIXME - split in two parts and move backend to output.c?
|
|
||||||
// TODO - maybe add a label argument to assign the block size afterwards (for assemble-to-end-address) (or add another pseudo opcode)
|
// TODO - maybe add a label argument to assign the block size afterwards (for assemble-to-end-address) (or add another pseudo opcode)
|
||||||
static enum eos po_pseudopc(void)
|
static enum eos po_pseudopc(void)
|
||||||
{
|
{
|
||||||
// FIXME - read pc using a function call!
|
struct pseudopc buffer;
|
||||||
struct number new_pc_result;
|
struct number new_pc;
|
||||||
intval_t new_offset;
|
|
||||||
int outer_flags = CPU_state.pc.flags;
|
|
||||||
|
|
||||||
// set new
|
// get new value
|
||||||
ALU_defined_int(&new_pc_result); // FIXME - allow for undefined! (complaining about non-addresses would be logical, but annoying)
|
ALU_defined_int(&new_pc); // FIXME - allow for undefined! (complaining about non-addresses would be logical, but annoying)
|
||||||
new_offset = (new_pc_result.val.intval - CPU_state.pc.val.intval) & 0xffff;
|
|
||||||
CPU_state.pc.val.intval = new_pc_result.val.intval;
|
|
||||||
CPU_state.pc.flags |= NUMBER_IS_DEFINED; // FIXME - remove when allowing undefined!
|
|
||||||
// TODO - accept ', name = "section name"'
|
// TODO - accept ', name = "section name"'
|
||||||
|
// remember old state in buffer, set new state
|
||||||
|
pseudopc_start(&buffer, &new_pc);
|
||||||
// if there's a block, parse that and then restore old value!
|
// if there's a block, parse that and then restore old value!
|
||||||
if (Parse_optional_block()) {
|
if (Parse_optional_block()) {
|
||||||
// restore old
|
// restore old state
|
||||||
CPU_state.pc.val.intval = (CPU_state.pc.val.intval - new_offset) & 0xffff;
|
pseudopc_end(&buffer);
|
||||||
CPU_state.pc.flags = outer_flags;
|
|
||||||
} else {
|
} else {
|
||||||
// not using a block is no longer allowed
|
// not using a block is no longer allowed
|
||||||
Throw_error(Error_old_offset_assembly);
|
Throw_error(Error_old_offset_assembly);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user