mirror of
https://github.com/uffejakobsen/acme.git
synced 2025-04-08 20:37:20 +00:00
more cleanup - moved some stuff between files
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@28 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
538dd38861
commit
e1516161ce
@ -186,11 +186,11 @@ static int perform_pass(void)
|
||||
int ii;
|
||||
|
||||
// call modules' "pass init" functions
|
||||
Output_passinit(); // disable output (until PC gets set)
|
||||
CPU_passinit(default_cpu); // set default cpu values (PC undefined)
|
||||
Output_passinit(); // disable output, PC undefined
|
||||
CPU_passinit(default_cpu); // set default cpu type
|
||||
// if start address was given on command line, use it:
|
||||
if (start_address != ILLEGAL_START_ADDRESS)
|
||||
CPU_set_pc(start_address, 0);
|
||||
vcpu_set_pc(start_address, 0);
|
||||
Encoding_passinit(); // set default encoding
|
||||
Section_passinit(); // set initial zone (untitled)
|
||||
// init variables
|
||||
|
@ -12,12 +12,12 @@
|
||||
#include <math.h> // only for fp support
|
||||
#include "platform.h"
|
||||
#include "alu.h"
|
||||
#include "cpu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "encoding.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "output.h"
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
|
||||
@ -485,9 +485,11 @@ static void parse_octal_value(void) // Now GotByte = "&"
|
||||
// Parse program counter ('*')
|
||||
static void parse_program_counter(void) // Now GotByte = "*"
|
||||
{
|
||||
struct result_int_t pc;
|
||||
|
||||
GetByte();
|
||||
// FIXME - read pc via function call, then move cpu struct from .h to .c file
|
||||
PUSH_INTOPERAND(CPU_state.pc.intval, CPU_state.pc.flags | MVALUE_EXISTS);
|
||||
vcpu_read_pc(&pc);
|
||||
PUSH_INTOPERAND(pc.intval, pc.flags | MVALUE_EXISTS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,9 +116,10 @@ static enum eos PO_binary(void)
|
||||
fclose(fd);
|
||||
// if verbose, produce some output
|
||||
if ((pass_count == 0) && (Process_verbosity > 1)) {
|
||||
// FIXME - read "add_to_pc" via function call so struct can be moved from .h to .c file
|
||||
int amount = vcpu_get_statement_size();
|
||||
|
||||
printf("Loaded %d (0x%04x) bytes from file offset %ld (0x%04lx).\n",
|
||||
CPU_state.add_to_pc, CPU_state.add_to_pc, skip, skip);
|
||||
amount, amount, skip, skip);
|
||||
}
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
60
src/cpu.c
60
src/cpu.c
@ -2,7 +2,7 @@
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// CPU stuff
|
||||
// CPU type stuff
|
||||
#include "config.h"
|
||||
#include "alu.h"
|
||||
#include "cpu.h"
|
||||
@ -15,7 +15,6 @@
|
||||
|
||||
|
||||
// constants
|
||||
// FIXME - move to new cpu_type.c file
|
||||
static struct cpu_type cpu_type_6502 = {
|
||||
keyword_is_6502mnemo,
|
||||
CPUFLAG_INDIRECTJMPBUGGY, // JMP ($xxFF) is buggy
|
||||
@ -55,7 +54,6 @@ static struct cpu_type cpu_type_65816 = {
|
||||
// variables
|
||||
|
||||
// predefined stuff
|
||||
// FIXME - move to cpu_type.c file
|
||||
static struct node_t *CPU_tree = NULL; // tree to hold CPU types
|
||||
static struct node_t CPUs[] = {
|
||||
// PREDEFNODE("z80", &cpu_type_Z80),
|
||||
@ -68,13 +66,12 @@ static struct node_t CPUs[] = {
|
||||
// ^^^^ this marks the last element
|
||||
};
|
||||
|
||||
// FIXME - make static
|
||||
struct cpu CPU_state; // current CPU state
|
||||
|
||||
// insert byte until PC fits condition
|
||||
// FIXME - move to basics.c
|
||||
static enum eos PO_align(void)
|
||||
{
|
||||
// FIXME - read cpu state via function call!
|
||||
intval_t and,
|
||||
equal,
|
||||
fill,
|
||||
@ -101,7 +98,6 @@ static enum eos PO_align(void)
|
||||
}
|
||||
|
||||
|
||||
// FIXME - move to cpu_type.c file
|
||||
// try to find CPU type held in DynaBuf. Returns whether succeeded.
|
||||
// FIXME - why not return ptr (or NULL to indicate failure)?
|
||||
int CPU_find_cpu_struct(const struct cpu_type **target)
|
||||
@ -145,10 +141,11 @@ static enum eos PO_realpc(void)
|
||||
|
||||
|
||||
// start offset assembly
|
||||
// FIXME - split into PO (move to basics.c) and backend
|
||||
// FIXME - split into PO (move to basics.c) and backend (move to output.c)
|
||||
// TODO - add a label argument to assign the block size afterwards (for assemble-to-end-address)
|
||||
static enum eos PO_pseudopc(void)
|
||||
{
|
||||
// FIXME - read pc using a function call!
|
||||
intval_t new_pc,
|
||||
new_offset;
|
||||
int outer_flags = CPU_state.pc.flags;
|
||||
@ -171,45 +168,6 @@ static enum eos PO_pseudopc(void)
|
||||
}
|
||||
|
||||
|
||||
// set program counter to defined value (FIXME - allow for undefined!)
|
||||
// if start address was given on command line, main loop will call this before each pass.
|
||||
// in addition to that, it will be called on each "* = VALUE".
|
||||
void CPU_set_pc(intval_t new_pc, int segment_flags)
|
||||
{
|
||||
intval_t new_offset;
|
||||
|
||||
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff;
|
||||
CPU_state.pc.intval = new_pc;
|
||||
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
|
||||
// now tell output buffer to start a new segment
|
||||
Output_start_segment(new_offset, segment_flags);
|
||||
}
|
||||
/*
|
||||
FIXME - TODO:
|
||||
general stuff: PC and mem ptr might be marked as "undefined" via flags field.
|
||||
However, their "value" fields are still updated, so we can calculate differences.
|
||||
|
||||
on pass init:
|
||||
if value given on command line, set PC and out ptr to that value
|
||||
otherwise, set both to zero and mark as "undefined"
|
||||
when ALU asks for "*":
|
||||
return current PC (value and flags)
|
||||
when encountering "!pseudopc VALUE { BLOCK }":
|
||||
parse new value (NEW: might be undefined!)
|
||||
remember difference between current and new value
|
||||
set PC to new value
|
||||
after BLOCK, use remembered difference to change PC back
|
||||
when encountering "* = VALUE":
|
||||
parse new value (NEW: might be undefined!)
|
||||
calculate difference between current PC and new value
|
||||
set PC to new value
|
||||
tell outbuf to add difference to mem ptr (starting a new segment) - if new value is undefined, tell outbuf to disable output
|
||||
|
||||
Problem: always check for "undefined"; there are some problematic combinations.
|
||||
I need a way to return the size of a generated code block even if PC undefined.
|
||||
*/
|
||||
|
||||
|
||||
// if cpu type and value match, set register length variable to value.
|
||||
// if cpu type and value don't match, complain instead.
|
||||
static void check_and_set_reg_length(int *var, int make_long)
|
||||
@ -235,14 +193,14 @@ static enum eos set_register_length(int *var, int make_long)
|
||||
}
|
||||
|
||||
|
||||
// switch to long accu ("!al" pseudo opcode)
|
||||
// switch to long accumulator ("!al" pseudo opcode)
|
||||
static enum eos PO_al(void)
|
||||
{
|
||||
return set_register_length(&CPU_state.a_is_long, TRUE);
|
||||
}
|
||||
|
||||
|
||||
// switch to short accu ("!as" pseudo opcode)
|
||||
// switch to short accumulator ("!as" pseudo opcode)
|
||||
static enum eos PO_as(void)
|
||||
{
|
||||
return set_register_length(&CPU_state.a_is_long, FALSE);
|
||||
@ -283,16 +241,10 @@ void CPU_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.pc.flags = 0; // not defined yet
|
||||
CPU_state.pc.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
|
||||
}
|
||||
|
||||
|
||||
// create cpu type tree (is done early)
|
||||
// FIXME - move to cpu_type.c
|
||||
void CPUtype_init(void)
|
||||
{
|
||||
Tree_add_table(&CPU_tree, CPUs);
|
||||
|
32
src/cpu.h
32
src/cpu.h
@ -2,55 +2,33 @@
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// CPU stuff
|
||||
#ifndef cpu_H
|
||||
#define cpu_H
|
||||
// CPU type stuff
|
||||
#ifndef cpu_type_H
|
||||
#define cpu_type_H
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// FIXME - create cpu_type.c file and move cpu type stuff to it
|
||||
// CPU type structure definition
|
||||
struct cpu_type {
|
||||
// This function is not allowed to change GlobalDynaBuf
|
||||
// because that's where the mnemonic is stored!
|
||||
int (*keyword_is_mnemonic)(int);
|
||||
int flags;
|
||||
int flags; // see below for bit meanings
|
||||
char default_align_value;
|
||||
};
|
||||
#define CPUFLAG_INDIRECTJMPBUGGY (1u << 0) // warn if "jmp ($xxff)" is assembled
|
||||
#define CPUFLAG_SUPPORTSLONGREGS (1u << 1) // allow "!al" and "!rl" pseudo opcodes
|
||||
#define CPUFLAG_AB_NEEDS_0_ARG (1u << 2) // warn if "lxa #$xx" uses non-zero arg
|
||||
|
||||
// current CPU state
|
||||
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
|
||||
struct cpu {
|
||||
const struct cpu_type *type; // current CPU type (default 6502)
|
||||
struct result_int_t pc; // current program counter (pseudo value)
|
||||
int add_to_pc; // add to PC after statement
|
||||
int a_is_long;
|
||||
int xy_are_long;
|
||||
};
|
||||
|
||||
|
||||
// variables
|
||||
// FIXME - restrict visibility to cpu.c file
|
||||
extern struct cpu CPU_state; // current CPU state
|
||||
|
||||
|
||||
// FIXME - move to new cpu_type.h file
|
||||
// create cpu type tree (is done early)
|
||||
extern void CPUtype_init(void);
|
||||
|
||||
// register pseudo opcodes (done later)
|
||||
extern void CPU_init(void);
|
||||
// set default values for pass
|
||||
// set default value for pass
|
||||
extern void CPU_passinit(const struct cpu_type *cpu_type);
|
||||
// set program counter to defined value (FIXME - allow undefined!)
|
||||
extern void CPU_set_pc(intval_t new_pc, int flags);
|
||||
|
||||
// FIXME - move to new cpu_type.h file
|
||||
// try to find CPU type held in DynaBuf. Returns whether succeeded.
|
||||
// FIXME - why not simply return struct ptr, or NULL in case of failure?
|
||||
extern int CPU_find_cpu_struct(const struct cpu_type **target);
|
||||
|
@ -299,10 +299,7 @@ void Parse_until_eob_or_eof(void)
|
||||
}
|
||||
}
|
||||
} while (GotByte != CHAR_EOS); // until end-of-statement
|
||||
// adjust program counter
|
||||
// FIXME - next two lines should be a function call!
|
||||
CPU_state.pc.intval = (CPU_state.pc.intval + CPU_state.add_to_pc) & 0xffff;
|
||||
CPU_state.add_to_pc = 0;
|
||||
vcpu_end_statement(); // adjust program counter
|
||||
// go on with next byte
|
||||
GetByte(); //NEXTANDSKIPSPACE();
|
||||
}
|
||||
|
13
src/label.c
13
src/label.c
@ -9,11 +9,11 @@
|
||||
#include <stdio.h>
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
#include "cpu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "output.h"
|
||||
#include "platform.h"
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
@ -206,16 +206,17 @@ static struct node_t pseudo_opcodes[] = {
|
||||
// GlobalDynaBuf holds the label name.
|
||||
void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change)
|
||||
{
|
||||
struct result_t result;
|
||||
struct label *label;
|
||||
struct result_int_t pc;
|
||||
struct result_t result;
|
||||
struct label *label;
|
||||
|
||||
label = Label_find(zone, force_bit);
|
||||
// implicit label definition (label)
|
||||
if ((stat_flags & SF_FOUND_BLANK) && warn_on_indented_labels)
|
||||
Throw_first_pass_warning("Implicit label definition not in leftmost column.");
|
||||
// FIXME - read pc via function call!
|
||||
result.flags = CPU_state.pc.flags & MVALUE_DEFINED;
|
||||
result.val.intval = CPU_state.pc.intval;
|
||||
vcpu_read_pc(&pc);
|
||||
result.flags = pc.flags & MVALUE_DEFINED;
|
||||
result.val.intval = pc.intval;
|
||||
Label_set_value(label, &result, change);
|
||||
}
|
||||
|
||||
|
75
src/output.c
75
src/output.c
@ -49,10 +49,12 @@ struct output {
|
||||
struct segment list_head; // head element of doubly-linked ring list
|
||||
} segment;
|
||||
};
|
||||
static struct output default_output;
|
||||
static struct output *out = &default_output;
|
||||
|
||||
// variables
|
||||
static struct output default_output;
|
||||
static struct output *out = &default_output;
|
||||
// FIXME - make static
|
||||
struct vcpu CPU_state; // current CPU state
|
||||
|
||||
// FIXME - move file format stuff to some other .c file!
|
||||
// predefined stuff
|
||||
@ -480,6 +482,13 @@ void Output_passinit(void)
|
||||
out->segment.start = NO_SEGMENT_START; // TODO - "no active segment" could be made a segment flag!
|
||||
out->segment.max = OUTBUFFERSIZE - 1;
|
||||
out->segment.flags = 0;
|
||||
|
||||
//vcpu stuff:
|
||||
CPU_state.pc.flags = 0; // not defined yet
|
||||
CPU_state.pc.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
|
||||
}
|
||||
|
||||
|
||||
@ -537,6 +546,46 @@ void Output_start_segment(intval_t address_change, int segment_flags)
|
||||
|
||||
|
||||
// TODO - add "!skip AMOUNT" pseudo opcode as alternative to "* = * + AMOUNT" (needed for assemble-to-end-address)
|
||||
|
||||
// set program counter to defined value (FIXME - allow for undefined!)
|
||||
// if start address was given on command line, main loop will call this before each pass.
|
||||
// in addition to that, it will be called on each "* = VALUE".
|
||||
void vcpu_set_pc(intval_t new_pc, int segment_flags)
|
||||
{
|
||||
intval_t new_offset;
|
||||
|
||||
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff;
|
||||
CPU_state.pc.intval = new_pc;
|
||||
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
|
||||
// now tell output buffer to start a new segment
|
||||
Output_start_segment(new_offset, segment_flags);
|
||||
}
|
||||
/*
|
||||
FIXME - TODO:
|
||||
general stuff: PC and mem ptr might be marked as "undefined" via flags field.
|
||||
However, their "value" fields are still updated, so we can calculate differences.
|
||||
|
||||
on pass init:
|
||||
if value given on command line, set PC and out ptr to that value
|
||||
otherwise, set both to zero and mark as "undefined"
|
||||
when ALU asks for "*":
|
||||
return current PC (value and flags)
|
||||
when encountering "!pseudopc VALUE { BLOCK }":
|
||||
parse new value (NEW: might be undefined!)
|
||||
remember difference between current and new value
|
||||
set PC to new value
|
||||
after BLOCK, use remembered difference to change PC back
|
||||
when encountering "* = VALUE":
|
||||
parse new value (NEW: might be undefined!)
|
||||
calculate difference between current PC and new value
|
||||
set PC to new value
|
||||
tell outbuf to add difference to mem ptr (starting a new segment) - if new value is undefined, tell outbuf to disable output
|
||||
|
||||
Problem: always check for "undefined"; there are some problematic combinations.
|
||||
I need a way to return the size of a generated code block even if PC undefined.
|
||||
*/
|
||||
|
||||
|
||||
// called when "* = EXPRESSION" is parsed
|
||||
// setting program counter via "* = VALUE"
|
||||
// FIXME - move to basics.c
|
||||
@ -560,7 +609,27 @@ void PO_setpc(void)
|
||||
|
||||
segment_flags |= (int) node_body;
|
||||
}
|
||||
CPU_set_pc(new_addr, segment_flags);
|
||||
vcpu_set_pc(new_addr, segment_flags);
|
||||
}
|
||||
|
||||
|
||||
// get program counter
|
||||
void vcpu_read_pc(struct result_int_t *target)
|
||||
{
|
||||
*target = CPU_state.pc;
|
||||
}
|
||||
|
||||
|
||||
// get size of current statement (until now) - needed for "!bin" verbose output
|
||||
int vcpu_get_statement_size(void)
|
||||
{
|
||||
return CPU_state.add_to_pc;
|
||||
}
|
||||
|
||||
|
||||
// adjust program counter (called at end of each statement)
|
||||
void vcpu_end_statement(void)
|
||||
{
|
||||
CPU_state.pc.intval = (CPU_state.pc.intval + CPU_state.add_to_pc) & 0xffff;
|
||||
CPU_state.add_to_pc = 0;
|
||||
}
|
||||
|
27
src/output.h
27
src/output.h
@ -11,10 +11,26 @@
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// Constants
|
||||
// constants
|
||||
#define MEMINIT_USE_DEFAULT 256
|
||||
|
||||
|
||||
// current CPU state
|
||||
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
|
||||
struct vcpu {
|
||||
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
|
||||
struct result_int_t pc; // current program counter (pseudo value)
|
||||
int add_to_pc; // add to PC after statement
|
||||
int a_is_long;
|
||||
int xy_are_long;
|
||||
};
|
||||
|
||||
|
||||
// variables
|
||||
// FIXME - restrict visibility to .c file
|
||||
extern struct vcpu CPU_state; // current CPU state
|
||||
|
||||
|
||||
// Prototypes
|
||||
|
||||
// Init file format tree (is done early)
|
||||
@ -46,5 +62,14 @@ extern void Output_start_segment(intval_t address_change, int segment_flags);
|
||||
// Show start and end of current segment
|
||||
extern void Output_end_segment(void);
|
||||
|
||||
// set program counter to defined value (FIXME - allow undefined!)
|
||||
extern void vcpu_set_pc(intval_t new_pc, int flags);
|
||||
// get program counter
|
||||
extern void vcpu_read_pc(struct result_int_t *target);
|
||||
// get size of current statement (until now) - needed for "!bin" verbose output
|
||||
extern int vcpu_get_statement_size(void);
|
||||
// adjust program counter (called at end of each statement)
|
||||
extern void vcpu_end_statement(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user