mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-02-19 09:31:42 +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();
|
||||
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_
|
||||
// UNDEFINED: complain _seriously_
|
||||
// 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?
|
||||
{
|
||||
struct expression expression;
|
||||
|
@ -122,4 +122,6 @@ void cputype_passinit(const struct cpu_type *cpu_type)
|
||||
{
|
||||
// handle cpu type (default is 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)
|
||||
static void near_branch(int preoffset)
|
||||
{
|
||||
struct number pc;
|
||||
struct number target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
vcpu_read_pc(&pc);
|
||||
get_int_arg(&target, TRUE);
|
||||
typesystem_want_addr(&target);
|
||||
// FIXME - read pc via function call instead!
|
||||
if (CPU_state.pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
||||
if (pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
||||
if ((target.val.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.val.intval);
|
||||
} 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
|
||||
if (offset & 0x8000)
|
||||
offset -= 0x10000;
|
||||
@ -817,17 +818,18 @@ static void near_branch(int preoffset)
|
||||
// helper function for relative addressing with 16-bit offset
|
||||
static void far_branch(int preoffset)
|
||||
{
|
||||
struct number pc;
|
||||
struct number target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
vcpu_read_pc(&pc);
|
||||
get_int_arg(&target, TRUE);
|
||||
typesystem_want_addr(&target);
|
||||
// FIXME - read pc via function call instead!
|
||||
if (CPU_state.pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
||||
if (pc.flags & target.flags & NUMBER_IS_DEFINED) {
|
||||
if ((target.val.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.val.intval);
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
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.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.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.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 xy_are_long;
|
||||
};
|
||||
// buffer to hold outer state while parsing "pseudopc" block
|
||||
struct pseudopc {
|
||||
intval_t offset;
|
||||
int flags;
|
||||
};
|
||||
|
||||
|
||||
// variables
|
||||
@ -98,6 +103,10 @@ extern void vcpu_read_pc(struct number *target);
|
||||
extern int vcpu_get_statement_size(void);
|
||||
// adjust program counter (called at end of each statement)
|
||||
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
|
||||
|
@ -540,18 +540,10 @@ static enum eos po_skip(void) // now GotByte = illegal char
|
||||
// insert byte until PC fits condition
|
||||
static enum eos po_align(void)
|
||||
{
|
||||
// FIXME - read cpu state via function call!
|
||||
struct number andresult,
|
||||
equalresult;
|
||||
intval_t fill,
|
||||
test = CPU_state.pc.val.intval;
|
||||
|
||||
// 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;
|
||||
}
|
||||
intval_t fill;
|
||||
struct number pc;
|
||||
|
||||
// TODO:
|
||||
// now: !align ANDVALUE, EQUALVALUE [,FILLVALUE]
|
||||
@ -565,35 +557,37 @@ static enum eos po_align(void)
|
||||
fill = ALU_any_int();
|
||||
else
|
||||
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);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
static const char Error_old_offset_assembly[] =
|
||||
"\"!pseudopc/!realpc\" is obsolete; use \"!pseudopc {}\" instead.";
|
||||
// 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)
|
||||
static enum eos po_pseudopc(void)
|
||||
{
|
||||
// FIXME - read pc using a function call!
|
||||
struct number new_pc_result;
|
||||
intval_t new_offset;
|
||||
int outer_flags = CPU_state.pc.flags;
|
||||
struct pseudopc buffer;
|
||||
struct number new_pc;
|
||||
|
||||
// set new
|
||||
ALU_defined_int(&new_pc_result); // 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!
|
||||
// get new value
|
||||
ALU_defined_int(&new_pc); // FIXME - allow for undefined! (complaining about non-addresses would be logical, but annoying)
|
||||
// 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 (Parse_optional_block()) {
|
||||
// restore old
|
||||
CPU_state.pc.val.intval = (CPU_state.pc.val.intval - new_offset) & 0xffff;
|
||||
CPU_state.pc.flags = outer_flags;
|
||||
// restore old state
|
||||
pseudopc_end(&buffer);
|
||||
} else {
|
||||
// not using a block is no longer allowed
|
||||
Throw_error(Error_old_offset_assembly);
|
||||
|
Loading…
x
Reference in New Issue
Block a user