2016-12-28 20:32:00 +00:00
|
|
|
// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code.
|
2020-05-06 11:40:06 +00:00
|
|
|
// Copyright (C) 1998-2020 Marco Baye
|
2012-02-27 21:14:46 +00:00
|
|
|
// Have a look at "acme.c" for further info
|
|
|
|
//
|
2014-03-11 14:22:32 +00:00
|
|
|
// CPU type stuff
|
2014-12-22 00:47:52 +00:00
|
|
|
#include "cpu.h"
|
2012-02-27 21:14:46 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "alu.h"
|
|
|
|
#include "dynabuf.h"
|
2020-05-19 16:28:36 +00:00
|
|
|
#include "global.h"
|
2012-02-27 21:14:46 +00:00
|
|
|
#include "input.h"
|
|
|
|
#include "mnemo.h"
|
|
|
|
#include "output.h"
|
|
|
|
#include "tree.h"
|
|
|
|
|
|
|
|
|
|
|
|
// constants
|
2014-03-10 00:17:10 +00:00
|
|
|
static struct cpu_type cpu_type_6502 = {
|
2016-12-28 20:32:00 +00:00
|
|
|
keyword_is_6502_mnemo,
|
2012-02-27 21:14:46 +00:00
|
|
|
CPUFLAG_INDIRECTJMPBUGGY, // JMP ($xxFF) is buggy
|
2015-06-14 23:16:23 +00:00
|
|
|
234 // !align fills with "NOP"
|
2012-02-27 21:14:46 +00:00
|
|
|
};
|
2014-03-10 00:17:10 +00:00
|
|
|
static struct cpu_type cpu_type_6510 = {
|
2016-12-28 20:32:00 +00:00
|
|
|
keyword_is_6510_mnemo,
|
2015-06-14 23:16:23 +00:00
|
|
|
CPUFLAG_INDIRECTJMPBUGGY | CPUFLAG_8B_AND_AB_NEED_0_ARG, // JMP ($xxFF) is buggy, ANE/LXA #$xx are unstable unless arg is $00
|
|
|
|
234 // !align fills with "NOP"
|
2012-02-27 21:14:46 +00:00
|
|
|
};
|
2014-11-23 23:40:01 +00:00
|
|
|
static struct cpu_type cpu_type_c64dtv2 = {
|
2016-12-28 20:32:00 +00:00
|
|
|
keyword_is_c64dtv2_mnemo,
|
2015-06-14 23:16:23 +00:00
|
|
|
CPUFLAG_INDIRECTJMPBUGGY | CPUFLAG_8B_AND_AB_NEED_0_ARG, // JMP ($xxFF) is buggy, ANE/LXA #$xx are unstable unless arg is $00
|
|
|
|
234 // !align fills with "NOP"
|
2014-11-23 23:40:01 +00:00
|
|
|
};
|
2014-03-10 00:17:10 +00:00
|
|
|
static struct cpu_type cpu_type_65c02 = {
|
2016-12-28 20:32:00 +00:00
|
|
|
keyword_is_65c02_mnemo,
|
2015-06-14 23:16:23 +00:00
|
|
|
0, // no flags
|
|
|
|
234 // !align fills with "NOP"
|
2012-02-27 21:14:46 +00:00
|
|
|
};
|
2016-12-28 20:32:00 +00:00
|
|
|
static struct cpu_type cpu_type_r65c02 = {
|
|
|
|
keyword_is_r65c02_mnemo,
|
2015-06-14 23:16:23 +00:00
|
|
|
0, // no flags
|
|
|
|
234 // !align fills with "NOP"
|
2012-02-27 21:14:46 +00:00
|
|
|
};
|
2016-12-28 20:32:00 +00:00
|
|
|
static struct cpu_type cpu_type_w65c02 = {
|
|
|
|
keyword_is_w65c02_mnemo,
|
2015-06-14 23:16:23 +00:00
|
|
|
0, // no flags
|
|
|
|
234 // !align fills with "NOP"
|
2012-02-27 21:14:46 +00:00
|
|
|
};
|
2014-03-10 00:17:10 +00:00
|
|
|
static struct cpu_type cpu_type_65816 = {
|
2016-12-28 20:32:00 +00:00
|
|
|
keyword_is_65816_mnemo,
|
2012-02-27 21:14:46 +00:00
|
|
|
CPUFLAG_SUPPORTSLONGREGS, // allows A and XY to be 16bits wide
|
2015-06-14 23:16:23 +00:00
|
|
|
234 // !align fills with "NOP"
|
2012-02-27 21:14:46 +00:00
|
|
|
};
|
2016-12-28 20:32:00 +00:00
|
|
|
static struct cpu_type cpu_type_65ce02 = {
|
|
|
|
keyword_is_65ce02_mnemo,
|
|
|
|
CPUFLAG_DECIMALSUBTRACTBUGGY, // SBC does not work reliably in decimal mode
|
|
|
|
234 // !align fills with "NOP"
|
|
|
|
};
|
|
|
|
static struct cpu_type cpu_type_4502 = {
|
|
|
|
keyword_is_4502_mnemo,
|
|
|
|
CPUFLAG_DECIMALSUBTRACTBUGGY, // SBC does not work reliably in decimal mode
|
|
|
|
234 // !align fills with "NOP"
|
|
|
|
};
|
2012-02-27 21:14:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
// variables
|
2014-03-10 00:17:10 +00:00
|
|
|
|
2012-02-27 21:14:46 +00:00
|
|
|
// predefined stuff
|
2014-12-04 15:31:54 +00:00
|
|
|
static struct ronode *cputype_tree = NULL;
|
|
|
|
static struct ronode cputype_list[] = {
|
2016-12-28 20:32:00 +00:00
|
|
|
#define KNOWN_TYPES "'6502', '6510', '65c02', 'r65c02', 'w65c02', '65816', '65ce02', '4502', 'c64dtv2'" // shown in CLI error message for unknown types
|
2014-03-10 00:17:10 +00:00
|
|
|
// PREDEFNODE("z80", &cpu_type_Z80),
|
|
|
|
PREDEFNODE("6502", &cpu_type_6502),
|
|
|
|
PREDEFNODE("6510", &cpu_type_6510),
|
|
|
|
PREDEFNODE("65c02", &cpu_type_65c02),
|
2016-12-28 20:32:00 +00:00
|
|
|
PREDEFNODE("r65c02", &cpu_type_r65c02),
|
|
|
|
PREDEFNODE("w65c02", &cpu_type_w65c02),
|
|
|
|
PREDEFNODE("65816", &cpu_type_65816),
|
|
|
|
PREDEFNODE("65ce02", &cpu_type_65ce02),
|
|
|
|
PREDEFNODE("4502", &cpu_type_4502),
|
|
|
|
PREDEFLAST("c64dtv2", &cpu_type_c64dtv2),
|
2012-02-27 21:14:46 +00:00
|
|
|
// ^^^^ this marks the last element
|
|
|
|
};
|
2016-02-21 12:58:22 +00:00
|
|
|
const char cputype_names[] = KNOWN_TYPES; // string to show if cputype_find() returns NULL
|
2012-02-27 21:14:46 +00:00
|
|
|
|
2014-12-04 15:31:54 +00:00
|
|
|
// lookup cpu type held in DynaBuf and return its struct pointer (or NULL on failure)
|
|
|
|
const struct cpu_type *cputype_find(void)
|
|
|
|
{
|
|
|
|
void *node_body;
|
|
|
|
|
|
|
|
// make sure tree is initialised
|
|
|
|
if (cputype_tree == NULL)
|
|
|
|
Tree_add_table(&cputype_tree, cputype_list);
|
|
|
|
// perform lookup
|
|
|
|
if (!Tree_easy_scan(cputype_tree, &node_body, GlobalDynaBuf))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return node_body;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if cpu type and value match, set register length variable to value.
|
|
|
|
// if cpu type and value don't match, complain instead.
|
2014-12-16 08:21:44 +00:00
|
|
|
// FIXME - error message might be confusing if it is thrown not because of
|
|
|
|
// initial change, but because of reverting back to old cpu type after "{}" block!
|
2020-05-06 11:40:06 +00:00
|
|
|
void vcpu_check_and_set_reg_length(boolean *var, boolean make_long)
|
2014-12-04 15:31:54 +00:00
|
|
|
{
|
|
|
|
if (((CPU_state.type->flags & CPUFLAG_SUPPORTSLONGREGS) == 0) && make_long)
|
|
|
|
Throw_error("Chosen CPU does not support long registers.");
|
|
|
|
else
|
|
|
|
*var = make_long;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// set default values for pass
|
2014-12-16 08:21:44 +00:00
|
|
|
void cputype_passinit(const struct cpu_type *cpu_type)
|
2014-12-04 15:31:54 +00:00
|
|
|
{
|
|
|
|
// handle cpu type (default is 6502)
|
|
|
|
CPU_state.type = cpu_type ? cpu_type : &cpu_type_6502;
|
|
|
|
}
|