diff --git a/docs/AllPOs.txt b/docs/AllPOs.txt index 7fa6631..4d53310 100644 --- a/docs/AllPOs.txt +++ b/docs/AllPOs.txt @@ -761,12 +761,13 @@ Purpose: Select the processor to produce code for. If this PO the previously chosen CPU value is restored afterwards. Parameters: KEYWORD: Currently valid keywords are: - 6502 allows official mnemonics and addressing modes - 6510 adds mnemonics for some undocumented opcodes - (but includes all the official 6502 stuff) - c64dtv2 allows DTV2 extensions (includes 6510) - 65c02 allows official 65c02 stuff (includes 6502) - 65816 allows official 65816 stuff (includes 65c02) + 6502 mnemonics and addressing modes of 6502 cpu + 65c02 superset of 6502, adds 65c02 extensions + 65816 superset of 65c02, adds 65816 extensions + 6510 superset of 6502, adds mnemonics for + undocumented opcodes + c64dtv2 superset of 6510, adds mnemonics for DTV2 + extensions (BRA/SAC/SIR) BLOCK: A block of assembler statements. Examples: !if cputype = $65c02 { !cpu 65c02 { ; temporarily allow 65c02 stuff diff --git a/src/Makefile b/src/Makefile index f74e571..6864200 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ RM = rm PROGS = acme BINDIR = /usr/local/bin USERBIN = $(HOME)/bin -OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o +OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o pseudoopcodes.o section.o symbol.o tree.o typesystem.o all: $(PROGS) @@ -17,7 +17,7 @@ acme: $(OBJS) strip acme -acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c +acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h pseudoopcodes.h section.h symbol.h acme.h acme.c alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c @@ -29,11 +29,11 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c -flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h tree.h symbol.h flow.h flow.c +flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c -global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c +global.o: config.h platform.h acme.h cpu.h input.h macro.h pseudoopcodes.h section.h symbol.h global.h global.c -input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c +input.o: config.h alu.h dynabuf.h global.h section.h tree.h input.h input.c macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c @@ -43,9 +43,11 @@ output.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h tree.h output.h platform.o: config.h platform.h platform.c +pseudoopcodes.o: acme.h alu.h input.h output.h pseudoopcodes.h pseudoopcodes.c + section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c -symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c +symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h symbol.h symbol.c tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c diff --git a/src/Makefile.dos b/src/Makefile.dos index f22dee5..c2c9ddb 100644 --- a/src/Makefile.dos +++ b/src/Makefile.dos @@ -8,7 +8,7 @@ RM = rm PROGS = acme #BINDIR = /usr/local/bin #USERBIN = $(HOME)/bin -OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o +OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o pseudoopcodes.o section.o symbol.o tree.o typesystem.o all: $(PROGS) @@ -18,7 +18,7 @@ acme: $(OBJS) djp acme.exe djp acmepmod.exe -acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c +acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h pseudoopcodes.h section.h symbol.h acme.h acme.c alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c @@ -32,9 +32,9 @@ encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h enc flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c -global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c +global.o: config.h platform.h acme.h cpu.h input.h macro.h pseudoopcodes.h section.h symbol.h global.h global.c -input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c +input.o: config.h alu.h dynabuf.h global.h section.h tree.h input.h input.c macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c @@ -44,9 +44,11 @@ output.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h tree.h output.h platform.o: config.h platform.h platform.c +pseudoopcodes.o: acme.h alu.h input.h output.h pseudoopcodes.h pseudoopcodes.c + section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c -symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c +symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h symbol.h symbol.c tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c diff --git a/src/Makefile.mingw b/src/Makefile.mingw index f584b05..31f2378 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -15,13 +15,13 @@ USERBIN = $(HOME)/bin all: $(PROGS) -acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o _dos.o resource.res - $(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o resource.res +acme.exe: acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o pseudoopcodes.o section.o symbol.o tree.o typesystem.o _dos.o resource.res + $(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o pseudoopcodes.o section.o symbol.o tree.o typesystem.o resource.res strip acme.exe -acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h _dos.h acme.c +acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h pseudoopcodes.h section.h symbol.h acme.h _dos.h acme.c alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c @@ -35,9 +35,9 @@ encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h enc flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c -global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c +global.o: config.h platform.h acme.h cpu.h input.h macro.h pseudoopcodes.h section.h symbol.h global.h global.c -input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c +input.o: config.h alu.h dynabuf.h global.h section.h tree.h input.h input.c macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c @@ -47,9 +47,11 @@ output.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h tree.h output.h platform.o: config.h platform.h platform.c +pseudoopcodes.o: acme.h alu.h input.h output.h pseudoopcodes.h pseudoopcodes.c + section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c -symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c +symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h symbol.h symbol.c tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c diff --git a/src/Makefile.riscos b/src/Makefile.riscos index 030c540..1a1c4e8 100644 --- a/src/Makefile.riscos +++ b/src/Makefile.riscos @@ -8,7 +8,7 @@ RM = rm PROGS = acme #BINDIR = /usr/local/bin #USERBIN = $(HOME)/bin -OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o +OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o pseudoopcodes.o section.o symbol.o tree.o typesystem.o all: $(PROGS) @@ -16,12 +16,10 @@ acme: $(OBJS) $(CC) $(CFLAGS) -o !Unsqueezed $(OBJS) $(LIBS) Squeeze -f -v !Unsqueezed !ACME.!RunImage -acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c +acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h pseudoopcodes.h section.h symbol.h acme.h acme.c alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c -basics.o: config.h alu.h cpu.h dynabuf.h input.h global.h output.h tree.h basics.h basics.c - cliargs.o: cliargs.h cliargs.c cpu.o: config.h alu.h dynabuf.h global.h input.h mnemo.h output.h tree.h cpu.h cpu.c @@ -32,7 +30,7 @@ encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h enc flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c -global.o: config.h platform.h acme.h cpu.h input.h macro.h output.h section.h symbol.h tree.h global.h global.c +global.o: config.h platform.h acme.h cpu.h input.h macro.h pseudoopcodes.h section.h symbol.h global.h global.c input.o: config.h alu.h dynabuf.h global.h section.h tree.h input.h input.c @@ -44,6 +42,8 @@ output.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h tree.h output.h platform.o: config.h platform.h platform.c +pseudoopcodes.o: acme.h alu.h input.h output.h pseudoopcodes.h pseudoopcodes.c + section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h symbol.h symbol.c diff --git a/src/acme.c b/src/acme.c index fe5e972..876336d 100644 --- a/src/acme.c +++ b/src/acme.c @@ -17,7 +17,7 @@ #define RELEASE "0.95.4" // update before release (FIXME) #define CODENAME "Fenchurch" // update before release -#define CHANGE_DATE "30 Nov" // update before release +#define CHANGE_DATE "3 Dec" // 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 @@ -27,7 +27,6 @@ #include #include "acme.h" #include "alu.h" -#include "basics.h" #include "cliargs.h" #include "config.h" #include "cpu.h" @@ -40,6 +39,7 @@ #include "mnemo.h" #include "output.h" #include "platform.h" +#include "pseudoopcodes.h" #include "section.h" #include "symbol.h" @@ -333,7 +333,7 @@ static void keyword_to_dynabuf(const char keyword[]) static void set_output_format(void) { keyword_to_dynabuf(cliargs_safe_get_next("output format")); - if (!Output_set_output_format()) { + if (output_set_output_format()) { // FIXME - list actual formats instead of outputting a fixed list! // FIXME - or AT LEAST define error message near the actual format list, so they match! fprintf(stderr, "%sUnknown output format (use 'cbm', 'plain' or 'apple').\n", cliargs_error); @@ -545,10 +545,6 @@ int main(int argc, const char *argv[]) // For example, this could read the library path from an // environment variable, which in turn may need DynaBuf already. PLATFORM_INIT; - // init some keyword trees needed for argument handling - CPUtype_init(); - symbols_clear_init(); // needed so - Outputfile_init(); // prepare a buffer large enough to hold pointers to "-D" switch values // cli_defines = safe_malloc(argc * sizeof(*cli_defines)); // handle command line arguments @@ -557,7 +553,6 @@ int main(int argc, const char *argv[]) cliargs_get_rest(&toplevel_src_count, &toplevel_sources, "No top level sources given"); // Init modules (most of them will just build keyword trees) ALU_init(); - Basics_init(); CPU_init(); Encoding_init(); Flow_init(); @@ -566,6 +561,7 @@ int main(int argc, const char *argv[]) Macro_init(); Mnemo_init(); Output_init(fill_value); + pseudoopcodes_init(); // setup keyword tree for pseudo opcodes Section_init(); if (do_actual_work()) save_output_file(); diff --git a/src/basics.h b/src/basics.h deleted file mode 100644 index e658da6..0000000 --- a/src/basics.h +++ /dev/null @@ -1,17 +0,0 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye -// Have a look at "acme.c" for further info -// -// basic assembly stuff -#ifndef basics_H -#define basics_H - - -#include "config.h" - - -// register pseudo opcodes and create dynamic buffer -extern void Basics_init(void); - - -#endif diff --git a/src/cpu.c b/src/cpu.c index d854e63..4bc9994 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -7,10 +7,11 @@ #include "alu.h" #include "cpu.h" #include "dynabuf.h" -#include "global.h" +#include "global.h" // FIXME - remove when no longer needed #include "input.h" #include "mnemo.h" #include "output.h" +#include "pseudoopcodes.h" // FIXME - remove when no longer needed #include "tree.h" @@ -100,7 +101,7 @@ static enum eos PO_align(void) else fill = CPU_state.type->default_align_value; while ((test++ & and) != equal) - Output_8b(fill); + output_8(fill); return ENSURE_EOS; } @@ -111,6 +112,10 @@ int CPU_find_cpu_struct(const struct cpu_type **target) { void *node_body; + // make sure tree is initialised + if (CPU_tree == NULL) + Tree_add_table(&CPU_tree, CPUs); + // perform lookup if (!Tree_easy_scan(CPU_tree, &node_body, GlobalDynaBuf)) return 0; *target = node_body; @@ -119,7 +124,7 @@ int CPU_find_cpu_struct(const struct cpu_type **target) // select CPU ("!cpu" pseudo opcode) -// FIXME - move to basics.c +// FIXME - move to pseudoopcodes.c static enum eos PO_cpu(void) { const struct cpu_type *cpu_buffer = CPU_state.type; // remember current cpu @@ -149,7 +154,7 @@ static enum eos PO_realpc(void) // start offset assembly // 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) +// 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! @@ -251,13 +256,6 @@ void CPU_passinit(const struct cpu_type *cpu_type) } -// create cpu type tree (is done early) -void CPUtype_init(void) -{ - Tree_add_table(&CPU_tree, CPUs); -} - - // register pseudo opcodes (done later) // FIXME - move to basics.c void CPU_init(void) diff --git a/src/cpu.h b/src/cpu.h index 028600a..a381218 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -22,8 +22,6 @@ struct cpu_type { #define CPUFLAG_SUPPORTSLONGREGS (1u << 1) // allow "!al" and "!rl" pseudo opcodes #define CPUFLAG_8B_AND_AB_NEED_0_ARG (1u << 2) // warn if "ane/lxa #$xx" uses non-zero arg -// create cpu type tree (is done early) -extern void CPUtype_init(void); // register pseudo opcodes (done later) extern void CPU_init(void); diff --git a/src/encoding.c b/src/encoding.c index 7fe418a..b004a79 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -9,8 +9,9 @@ #include "acme.h" #include "dynabuf.h" #include "encoding.h" -#include "global.h" +#include "global.h" // FIXME - remove when no longer needed #include "output.h" +#include "pseudoopcodes.h" // FIXME - remove when no longer needed #include "input.h" #include "tree.h" @@ -51,7 +52,7 @@ static enum eos encode_string(encoder_t inner_encoder, char xor) GetQuotedByte(); // send characters until closing quote is reached while (GotByte && (GotByte != '"')) { - Output_8b(xor ^ Encoding_encode_char(GotByte)); + output_8(xor ^ Encoding_encode_char(GotByte)); GetQuotedByte(); } if (GotByte == CHAR_EOS) @@ -63,7 +64,7 @@ static enum eos encode_string(encoder_t inner_encoder, char xor) // Parse value. No problems with single characters // because the current encoding is // temporarily set to the given one. - Output_8b(ALU_any_int()); + output_8(ALU_any_int()); } } while (Input_accept_comma()); Encoding_encode_char = outer_encoder; // reactivate buffered encoder diff --git a/src/flow.c b/src/flow.c index ffc4071..403e5bc 100644 --- a/src/flow.c +++ b/src/flow.c @@ -16,10 +16,11 @@ #include "alu.h" #include "config.h" #include "dynabuf.h" -#include "global.h" +#include "global.h" // FIXME - remove when no longer needed #include "input.h" #include "macro.h" #include "mnemo.h" +#include "pseudoopcodes.h" // FIXME - remove when no longer needed #include "symbol.h" #include "tree.h" diff --git a/src/global.c b/src/global.c index 65ff293..8424b0f 100644 --- a/src/global.c +++ b/src/global.c @@ -17,6 +17,7 @@ #include "input.h" #include "macro.h" #include "output.h" +#include "pseudoopcodes.h" #include "section.h" #include "symbol.h" #include "tree.h" @@ -98,7 +99,6 @@ const char Byte_flags[256] = { // variables -struct ronode *pseudo_opcode_tree = NULL; // tree to hold pseudo opcodes (FIXME - move when grouping all POs) int pass_count; // number of current pass (starts 0) char GotByte; // Last byte read (processed) int Process_verbosity = 0; // Level of additional output @@ -136,7 +136,7 @@ static void parse_pc_def(void) // Now GotByte = "*" // re-definitions of program counter change segment if (GotByte == '=') { GetByte(); // proceed with next char - PO_setpc(); + notreallypo_setpc(); Input_ensure_EOS(); } else { Throw_error(exception_syntax); @@ -155,6 +155,8 @@ static void parse_pseudo_opcode(void) // Now GotByte = "!" GetByte(); // read next byte // on missing keyword, return (complaining will have been done) if (Input_read_and_lower_keyword()) { + +// move this to pseudoopcodes.c: // search for tree item if ((Tree_easy_scan(pseudo_opcode_tree, &node_body, GlobalDynaBuf)) && node_body) { diff --git a/src/global.h b/src/global.h index 1050be9..6309d90 100644 --- a/src/global.h +++ b/src/global.h @@ -54,9 +54,6 @@ extern const char Byte_flags[]; // bits 2, 1 and 0 are currently unused -// Variables - -extern struct ronode *pseudo_opcode_tree; // tree to hold pseudo opcodes (FIXME - move when grouping all POs) // structures // different ways to handle end-of-statement: enum eos { diff --git a/src/input.c b/src/input.c index c4562c8..f3fbcbd 100644 --- a/src/input.c +++ b/src/input.c @@ -7,9 +7,10 @@ #include "config.h" #include "alu.h" #include "dynabuf.h" -#include "global.h" +#include "global.h" // FIXME - remove when no longer needed #include "input.h" #include "platform.h" +#include "pseudoopcodes.h" // FIXME - remove when no longer needed #include "section.h" #include "tree.h" diff --git a/src/mnemo.c b/src/mnemo.c index 78db8b4..16949b1 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -629,8 +629,8 @@ static void group_only_relative8_addressing(int opcode) Output_byte(opcode); // this fn has its own range check (see above). // No reason to irritate the user with another error message, - // so use Output_byte() instead of Output_8b() - //Output_8b(offset); + // so use Output_byte() instead of output_8() + //output_8(offset); Output_byte(offset); Input_ensure_EOS(); } @@ -653,7 +653,7 @@ static void group_only_relative16_addressing(int opcode) } } Output_byte(opcode); - Output_16b(offset); + output_le16(offset); Input_ensure_EOS(); } @@ -672,15 +672,15 @@ static void make_command(int force_bit, struct result *result, unsigned long opc switch (calc_arg_size(force_bit, result, addressing_modes)) { case MVALUE_FORCE08: Output_byte(opcodes & 255); - Output_8b(result->val.intval); + output_8(result->val.intval); break; case MVALUE_FORCE16: Output_byte((opcodes >> 8) & 255); - Output_16b(result->val.intval); + output_le16(result->val.intval); break; case MVALUE_FORCE24: Output_byte((opcodes >> 16) & 255); - Output_24b(result->val.intval); + output_le24(result->val.intval); } } @@ -809,8 +809,8 @@ static void group_move(int opcode) if (Input_accept_comma()) { target = ALU_any_int(); // machine language: Output_byte(opcode); // opcode - Output_8b(target); // target - Output_8b(source); // source + output_8(target); // target + output_8(source); // source Input_ensure_EOS(); } else { Throw_error(exception_syntax); diff --git a/src/output.c b/src/output.c index d808c4a..3ca503f 100644 --- a/src/output.c +++ b/src/output.c @@ -46,13 +46,10 @@ struct output { struct { intval_t start; // start of current segment (or NO_SEGMENT_START) intval_t max; // highest address segment may use - int flags; // segment flags ("overlay" and "invisible", see below) + int flags; // segment flags ("overlay" and "invisible", see header file) struct segment list_head; // head element of doubly-linked ring list } segment; }; -// segment flags (FIXME - move to header file when setpc() is moved to pseudo_opcodes.c): -#define SEGMENT_FLAG_OVERLAY (1u << 0) // do not warn about this segment overwriting another one -#define SEGMENT_FLAG_INVISIBLE (1u << 1) // do not warn about other segments overwriting this one // variables @@ -187,7 +184,7 @@ void Output_fake(int size) // output 8-bit value with range check -void Output_8b(intval_t value) +void output_8(intval_t value) { if ((value <= 0xff) && (value >= -0x80)) Output_byte(value); @@ -197,7 +194,7 @@ void Output_8b(intval_t value) // output 16-bit value with range check -void Output_16b(intval_t value) +void output_le16(intval_t value) { if ((value <= 0xffff) && (value >= -0x8000)) { Output_byte(value); @@ -209,7 +206,7 @@ void Output_16b(intval_t value) // output 24-bit value with range check -void Output_24b(intval_t value) +void output_le24(intval_t value) { if ((value <= 0xffffff) && (value >= -0x800000)) { Output_byte(value); @@ -222,7 +219,7 @@ void Output_24b(intval_t value) // output 32-bit value (without range check) -void Output_32b(intval_t value) +void output_le32(intval_t value) { // if ((Value <= 0x7fffffff) && (Value >= -0x80000000)) { Output_byte(value); @@ -243,26 +240,16 @@ static void fill_completely(char value) // define default value for empty memory ("!initmem" pseudo opcode) -// FIXME - move to basics.c -static enum eos PO_initmem(void) +// returns zero if ok, nonzero if already set +int output_initmem(char content) { - intval_t content; - - // ignore in all passes but in first - if (pass_count) - return SKIP_REMAINDER; - // if MemInit flag is already set, complain if (out->initvalue_set) { Throw_warning("Memory already initialised."); - return SKIP_REMAINDER; + return 1; // failed } // set MemInit flag out->initvalue_set = TRUE; - // get value and init memory - content = ALU_defined_int(); - if ((content > 0xff) || (content < -0x80)) - Throw_error(exception_number_out_of_range); // init memory fill_completely(content); // enforce another pass @@ -271,93 +258,53 @@ static enum eos PO_initmem(void) // 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 &&(out->lowest_written < out->highest_written+1) to "if" above - return ENSURE_EOS; + return 0; // ok } -// try to set output format held in DynaBuf. Returns whether succeeded. -// FIXME - move to basics.c? -int Output_set_output_format(void) +// try to set output format held in DynaBuf. Returns zero on success. +int output_set_output_format(void) { void *node_body; + // make sure tree is initialised + if (file_format_tree == NULL) + Tree_add_table(&file_format_tree, file_formats); + // perform lookup if (!Tree_easy_scan(file_format_tree, &node_body, GlobalDynaBuf)) - return FALSE; + return 1; output_format = (enum output_format) node_body; - return TRUE; + return 0; } - -// select output file and format ("!to" pseudo opcode) -// FIXME - move to basics.c -static enum eos PO_to(void) +// if file format was already chosen, returns zero. +// if file format isn't set, chooses CBM and returns 1. +int output_prefer_cbm_file_format(void) { - // bugfix: first read filename, *then* check for first pass. - // if skipping right away, quoted colons might be misinterpreted as EOS - // FIXME - why not just fix the skipping code to handle quotes? :) - // "!sl" has been fixed as well - - // read filename to global dynamic buffer - // if no file name given, exit (complaining will have been done) - if (Input_read_filename(FALSE)) - return SKIP_REMAINDER; - - // only act upon this pseudo opcode in first pass - if (pass_count) - return SKIP_REMAINDER; + if (output_format != OUTPUT_FORMAT_UNSPECIFIED) + return 0; + output_format = OUTPUT_FORMAT_CBM; + return 1; +} +// select output file ("!to" pseudo opcode) +// returns zero on success, nonzero if already set +int output_set_output_filename(void) +{ // if output file already chosen, complain and exit if (output_filename) { Throw_warning("Output file already chosen."); - return SKIP_REMAINDER; + return 1; // failed } // get malloc'd copy of filename output_filename = DynaBuf_get_copy(GlobalDynaBuf); - // select output format - // if no comma found, use default file format - if (Input_accept_comma() == FALSE) { - if (output_format == OUTPUT_FORMAT_UNSPECIFIED) { - output_format = OUTPUT_FORMAT_CBM; - // output deprecation warning - Throw_warning("Used \"!to\" without file format indicator. Defaulting to \"cbm\"."); - } - return ENSURE_EOS; - } - - // parse output format name - // if no keyword given, give up - if (Input_read_and_lower_keyword() == 0) - return SKIP_REMAINDER; - - if (Output_set_output_format()) - return ENSURE_EOS; // success - - // error occurred - Throw_error("Unknown output format."); - return SKIP_REMAINDER; + return 0; // ok } -// pseudo ocpode table -// FIXME - move to basics.c -static struct ronode pseudo_opcodes[] = { - PREDEFNODE("initmem", PO_initmem), - PREDEFLAST("to", PO_to), - // ^^^^ this marks the last element -}; - - -// init file format tree (is done early, because it is needed for CLI argument parsing) -// FIXME - move to some other file -void Outputfile_init(void) -{ - Tree_add_table(&file_format_tree, file_formats); -} - - -// init output struct, register pseudo opcodes (done later) +// init output struct (done later) void Output_init(signed long fill_value) { out->buffer = safe_malloc(OUTBUFFERSIZE); @@ -369,7 +316,6 @@ void Output_init(signed long fill_value) } // init output buffer (fill memory with initial value) fill_completely(fill_value & 0xff); - Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); // init ring list of segments out->segment.list_head.next = &out->segment.list_head; out->segment.list_head.prev = &out->segment.list_head; @@ -551,9 +497,6 @@ 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) -// the new pseudo opcode would skip the given amount of bytes without starting a new segment - // 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". @@ -598,34 +541,6 @@ Maybe like this: */ -// called when "* = EXPRESSION" is parsed -// setting program counter via "* = VALUE" -// FIXME - move to basics.c -void PO_setpc(void) -{ - int segment_flags = 0; - intval_t new_addr = ALU_defined_int(); - - // check for modifiers - while (Input_accept_comma()) { - // parse modifier - // if no keyword given, give up - if (Input_read_and_lower_keyword() == 0) - return; - - if (strcmp(GlobalDynaBuf->buffer, "overlay") == 0) { - segment_flags |= SEGMENT_FLAG_OVERLAY; - } else if (strcmp(GlobalDynaBuf->buffer, "invisible") == 0) { - segment_flags |= SEGMENT_FLAG_INVISIBLE; - } else { - Throw_error("Unknown \"* =\" segment modifier."); - return; - } - } - vcpu_set_pc(new_addr, segment_flags); -} - - // get program counter void vcpu_read_pc(struct result *target) { diff --git a/src/output.h b/src/output.h index 9591dfd..0607190 100644 --- a/src/output.h +++ b/src/output.h @@ -13,6 +13,9 @@ // constants #define MEMINIT_USE_DEFAULT 256 +// segment flags +#define SEGMENT_FLAG_OVERLAY (1u << 0) // do not warn about this segment overwriting another one +#define SEGMENT_FLAG_INVISIBLE (1u << 1) // do not warn about other segments overwriting this one // current CPU state @@ -33,9 +36,7 @@ extern struct vcpu CPU_state; // current CPU state // Prototypes -// Init file format tree (is done early) -extern void Outputfile_init(void); -// alloc and init mem buffer, register pseudo opcodes (done later) +// alloc and init mem buffer (done later) extern void Output_init(signed long fill_value); // clear segment list and disable output extern void Output_passinit(void); @@ -44,19 +45,25 @@ extern void Output_fake(int size); // Send low byte of arg to output buffer and advance pointer extern void (*Output_byte)(intval_t); // Output 8-bit value with range check -extern void Output_8b(intval_t); +extern void output_8(intval_t); // Output 16-bit value with range check -extern void Output_16b(intval_t); +extern void output_le16(intval_t); // Output 24-bit value with range check -extern void Output_24b(intval_t); +extern void output_le24(intval_t); // Output 32-bit value (without range check) -extern void Output_32b(intval_t); -// Try to set output format held in DynaBuf. Returns whether succeeded. -extern int Output_set_output_format(void); +extern void output_le32(intval_t); +// define default value for empty memory ("!initmem" pseudo opcode) +// returns zero if ok, nonzero if already set +extern int output_initmem(char content); +// try to set output format held in DynaBuf. Returns zero on success. +extern int output_set_output_format(void); +// if file format was already chosen, returns zero. +// if file format isn't set, chooses CBM and returns 1. +extern int output_prefer_cbm_file_format(void); +// try to set output file name held in DynaBuf. Returns zero on success. +extern int output_set_output_filename(void); // write smallest-possible part of memory buffer to file extern void Output_save_file(FILE *fd); -// Call when "* = EXPRESSION" is parsed -extern void PO_setpc(void); // change output pointer and enable output extern void Output_start_segment(intval_t address_change, int segment_flags); // Show start and end of current segment diff --git a/src/basics.c b/src/pseudoopcodes.c similarity index 54% rename from src/basics.c rename to src/pseudoopcodes.c index 2b9f69f..8a2a896 100644 --- a/src/basics.c +++ b/src/pseudoopcodes.c @@ -2,12 +2,12 @@ // Copyright (C) 1998-2014 Marco Baye // Have a look at "acme.c" for further info // -// basic assembly stuff +// pseudo opcode stuff #include #include +//#include "acme.h" #include "config.h" #include "cpu.h" -#include "basics.h" #include "alu.h" #include "dynabuf.h" #include "input.h" @@ -15,21 +15,111 @@ #include "output.h" #include "tree.h" #include "typesystem.h" +#include "pseudoopcodes.h" // constants -#define USERMSG_DYNABUF_INITIALSIZE 80 static const char s_08[] = "08"; #define s_8 (s_08 + 1) // Yes, I know I'm sick #define s_16 (s_65816 + 3) // Yes, I know I'm sick // variables -static struct dynabuf *user_message; // dynamic buffer (!warn/error/serious) +struct ronode *pseudo_opcode_tree = NULL; // tree to hold pseudo opcodes + + +// not really a pseudo opcode, but close enough to be put here: +// called when "* = EXPRESSION" is parsed +// setting program counter via "* = VALUE" +void notreallypo_setpc(void) +{ + int segment_flags = 0; + intval_t new_addr = ALU_defined_int(); + + // check for modifiers + while (Input_accept_comma()) { + // parse modifier. if no keyword given, give up + if (Input_read_and_lower_keyword() == 0) + return; + + if (strcmp(GlobalDynaBuf->buffer, "overlay") == 0) { + segment_flags |= SEGMENT_FLAG_OVERLAY; + } else if (strcmp(GlobalDynaBuf->buffer, "invisible") == 0) { + segment_flags |= SEGMENT_FLAG_INVISIBLE; + } else { + Throw_error("Unknown \"* =\" segment modifier."); + return; + } + } + vcpu_set_pc(new_addr, segment_flags); +} + + +// define default value for empty memory ("!initmem" pseudo opcode) +static enum eos po_initmem(void) +{ + intval_t content; + + // ignore in all passes but in first + if (pass_count) + return SKIP_REMAINDER; + + // get value + content = ALU_defined_int(); + if ((content > 0xff) || (content < -0x80)) + Throw_error(exception_number_out_of_range); + if (output_initmem(content & 0xff)) + return SKIP_REMAINDER; + return ENSURE_EOS; +} + + +// select output file and format ("!to" pseudo opcode) +static enum eos po_to(void) +{ + // bugfix: first read filename, *then* check for first pass. + // if skipping right away, quoted colons might be misinterpreted as EOS + // FIXME - fix the skipping code to handle quotes! :) + // "!sl" has been fixed as well + + // read filename to global dynamic buffer + // if no file name given, exit (complaining will have been done) + if (Input_read_filename(FALSE)) + return SKIP_REMAINDER; + + // only act upon this pseudo opcode in first pass + if (pass_count) + return SKIP_REMAINDER; + + if (output_set_output_filename()) + return SKIP_REMAINDER; + + // select output format + // if no comma found, use default file format + if (Input_accept_comma() == FALSE) { + if (output_prefer_cbm_file_format()) { + // output deprecation warning + Throw_warning("Used \"!to\" without file format indicator. Defaulting to \"cbm\"."); + } + return ENSURE_EOS; + } + + // parse output format name + // if no keyword given, give up + if (Input_read_and_lower_keyword() == 0) + return SKIP_REMAINDER; + + if (output_set_output_format()) { + // error occurred + Throw_error("Unknown output format."); + return SKIP_REMAINDER; + } + return ENSURE_EOS; // success +} // helper function for !8, !16, !24 and !32 pseudo opcodes -static enum eos output_objects(void (*fn)(intval_t)) +static enum eos iterate(void (*fn)(intval_t)) { do fn(ALU_any_int()); @@ -39,35 +129,36 @@ static enum eos output_objects(void (*fn)(intval_t)) // Insert 8-bit values ("!08" / "!8" / "!by" / "!byte" pseudo opcode) -static enum eos PO_8(void) +static enum eos po_8(void) { - return output_objects(Output_8b); + return iterate(output_8); } // Insert 16-bit values ("!16" / "!wo" / "!word" pseudo opcode) -static enum eos PO_16(void) +static enum eos po_16(void) { - return output_objects(Output_16b); + return iterate(output_le16); } // Insert 24-bit values ("!24" pseudo opcode) -static enum eos PO_24(void) +static enum eos po_24(void) { - return output_objects(Output_24b); + return iterate(output_le24); } // Insert 32-bit values ("!32" pseudo opcode) -static enum eos PO_32(void) +static enum eos po_32(void) { - return output_objects(Output_32b); + return iterate(output_le32); } -// Include binary file -static enum eos PO_binary(void) +// Include binary file ("!binary" pseudo opcode) +// FIXME - split this into "parser" and "worker" fn and move worker fn somewhere else. +static enum eos po_binary(void) { FILE *fd; int byte; @@ -127,7 +218,7 @@ static enum eos PO_binary(void) // Reserve space by sending bytes of given value ("!fi" / "!fill" pseudo opcode) -static enum eos PO_fill(void) +static enum eos po_fill(void) { intval_t fill = FILLVALUE_FILL, size = ALU_defined_int(); @@ -135,13 +226,13 @@ static enum eos PO_fill(void) if (Input_accept_comma()) fill = ALU_any_int(); while (size--) - Output_8b(fill); + output_8(fill); return ENSURE_EOS; } // force explicit label definitions to set "address" flag ("!addr"). Has to be re-entrant. -static enum eos PO_addr(void) // Now GotByte = illegal char +static enum eos po_addr(void) // now GotByte = illegal char { SKIPSPACE(); if (GotByte == CHAR_SOB) { @@ -152,8 +243,23 @@ static enum eos PO_addr(void) // Now GotByte = illegal char return PARSE_REMAINDER; } +/* +// TODO - add "!skip AMOUNT" pseudo opcode as alternative to "* = * + AMOUNT" (needed for assemble-to-end-address) +// the new pseudo opcode would skip the given amount of bytes without starting a new segment +static enum eos po_skip(void) // now GotByte = illegal char +{ +} +*/ -// show user-defined message +// constants +#define USERMSG_DYNABUF_INITIALSIZE 80 + + +// variables +static struct dynabuf *user_message; // dynamic buffer (!warn/error/serious) + + +// helper function to show user-defined messages static enum eos throw_string(const char prefix[], void (*fn)(const char *)) { struct result result; @@ -209,15 +315,15 @@ static enum eos throw_string(const char prefix[], void (*fn)(const char *)) //// -//static enum eos PO_debug(void) -//static enum eos PO_info(void) +//static enum eos po_debug(void) +//static enum eos po_info(void) //{ // return throw_string(); //} // throw warning as given in source code -static enum eos PO_warn(void) +static enum eos po_warn(void) { return throw_string("!warn: ", Throw_warning); @@ -225,47 +331,50 @@ static enum eos PO_warn(void) // throw error as given in source code -static enum eos PO_error(void) +static enum eos po_error(void) { return throw_string("!error: ", Throw_error); } // throw serious error as given in source code -static enum eos PO_serious(void) +static enum eos po_serious(void) { return throw_string("!serious: ", Throw_serious_error); } -// pseudo ocpode table +// pseudo opcode table static struct ronode pseudo_opcodes[] = { - PREDEFNODE(s_08, PO_8), - PREDEFNODE(s_8, PO_8), - PREDEFNODE("by", PO_8), - PREDEFNODE("byte", PO_8), - PREDEFNODE(s_16, PO_16), - PREDEFNODE("wo", PO_16), - PREDEFNODE("word", PO_16), - PREDEFNODE("24", PO_24), - PREDEFNODE("32", PO_32), - PREDEFNODE("bin", PO_binary), - PREDEFNODE("binary", PO_binary), - PREDEFNODE("fi", PO_fill), - PREDEFNODE("fill", PO_fill), - PREDEFNODE("addr", PO_addr), - PREDEFNODE("address", PO_addr), -// PREDEFNODE("debug", PO_debug), -// PREDEFNODE("info", PO_info), - PREDEFNODE("warn", PO_warn), - PREDEFNODE(s_error, PO_error), - PREDEFLAST("serious", PO_serious), + PREDEFNODE("initmem", po_initmem), + PREDEFNODE("to", po_to), + PREDEFNODE(s_08, po_8), + PREDEFNODE(s_8, po_8), + PREDEFNODE("by", po_8), + PREDEFNODE("byte", po_8), + PREDEFNODE(s_16, po_16), + PREDEFNODE("wo", po_16), + PREDEFNODE("word", po_16), + PREDEFNODE("24", po_24), + PREDEFNODE("32", po_32), + PREDEFNODE("bin", po_binary), + PREDEFNODE("binary", po_binary), + PREDEFNODE("fi", po_fill), + PREDEFNODE("fill", po_fill), + PREDEFNODE("addr", po_addr), + PREDEFNODE("address", po_addr), +// PREDEFNODE("skip", po_skip), +// PREDEFNODE("debug", po_debug), +// PREDEFNODE("info", po_info), + PREDEFNODE("warn", po_warn), + PREDEFNODE(s_error, po_error), + PREDEFLAST("serious", po_serious), // ^^^^ this marks the last element }; // register pseudo opcodes and create dynamic buffer -void Basics_init(void) +void pseudoopcodes_init(void) { user_message = DynaBuf_create(USERMSG_DYNABUF_INITIALSIZE); Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes); diff --git a/src/pseudoopcodes.h b/src/pseudoopcodes.h new file mode 100644 index 0000000..cadda56 --- /dev/null +++ b/src/pseudoopcodes.h @@ -0,0 +1,20 @@ +// ACME - a crossassembler for producing 6502/65c02/65816 code. +// Copyright (C) 1998-2014 Marco Baye +// Have a look at "acme.c" for further info +// +// pseudo opcode stuff +#ifndef pseudoopcodes_H +#define pseudoopcodes_H + + +// FIXME - after grouping all pseudo opcodes in .c file, make this static: +extern struct ronode *pseudo_opcode_tree; // tree to hold pseudo opcodes + + +// call when "* = EXPRESSION" is parsed +extern void notreallypo_setpc(void); +// register pseudo opcodes +extern void pseudoopcodes_init(void); + + +#endif diff --git a/src/section.c b/src/section.c index 51888ed..c3074fc 100644 --- a/src/section.c +++ b/src/section.c @@ -5,8 +5,9 @@ // Section stuff #include "config.h" #include "dynabuf.h" -#include "global.h" +#include "global.h" // FIXME - remove when no longer needed #include "input.h" +#include "pseudoopcodes.h" // FIXME - remove when no longer needed #include "tree.h" #include "section.h" diff --git a/src/symbol.c b/src/symbol.c index 44fbc86..9e63cbf 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -11,10 +11,11 @@ #include "acme.h" #include "alu.h" #include "dynabuf.h" -#include "global.h" +#include "global.h" // FIXME - remove when no longer needed #include "input.h" #include "output.h" #include "platform.h" +#include "pseudoopcodes.h" // FIXME - remove when no longer needed #include "section.h" #include "symbol.h" #include "tree.h" @@ -26,7 +27,7 @@ // variables -struct rwnode *symbols_forest[256]; // ... (because of 8-bit hash) +struct rwnode *symbols_forest[256] = { NULL }; // because of 8-bit hash - must be (at least partially) pre-defined so array will be zeroed! // Dump symbol value and flags to dump file @@ -322,18 +323,6 @@ void symbols_vicelabels(FILE *fd) Tree_dump_forest(symbols_forest, ZONE_GLOBAL, dump_vice_address, fd); } -// clear symbols forest (is done early) -void symbols_clear_init(void) -{ - struct rwnode **ptr; - int ii; - - // cut down all the trees (clear pointer table) - ptr = symbols_forest; - for (ii = 255; ii >= 0; --ii) - *ptr++ = NULL; -} - // register pseudo opcodes (done later) void symbols_register_init(void) diff --git a/src/symbol.h b/src/symbol.h index 4ab1052..7424858 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -22,8 +22,6 @@ struct symbol { extern struct rwnode *symbols_forest[]; // trees (because of 8-bit hash) -// clear symbol forest (is done early) -extern void symbols_clear_init(void); // register pseudo opcodes (done later) extern void symbols_register_init(void); // function acts upon the symbol's flag bits and produces an error if needed.