kegs/src/engine_c.c

1027 lines
23 KiB
C

/************************************************************************/
/* KEGS: Apple //gs Emulator */
/* Copyright 2002 by Kent Dickey */
/* */
/* This code is covered by the GNU GPL */
/* */
/* The KEGS web page is kegs.sourceforge.net */
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_engine_c_c[] = "@(#)$KmKId: engine_c.c,v 1.57 2004-12-03 23:51:01-05 kentd Exp $";
#include "defc.h"
#include "protos_engine_c.h"
#if 0
# define LOG_PC
/* define FCYCS_PTR_FCYCLES_ROUND_SLOW to get accurate 1MHz write to slow mem*/
/* this might help joystick emulation in some Apple //gs games like */
/* Madness */
# define FCYCS_PTR_FCYCLES_ROUND_SLOW FCYCLES_ROUND; *fcycs_ptr = fcycles;
#endif
#ifndef FCYCS_PTR_FCYCLES_ROUND_SLOW
# define FCYCS_PTR_FCYCLES_ROUND_SLOW
#endif
extern int halt_sim;
extern int g_code_red;
extern int g_ignore_halts;
extern int g_user_halt_bad;
extern double g_fcycles_stop;
extern double g_last_vbl_dcycs;
extern double g_cur_dcycs;
extern int g_wait_pending;
extern int g_irq_pending;
extern int g_testing;
extern int g_num_brk;
extern int g_num_cop;
extern byte *g_slow_memory_ptr;
extern byte *g_memory_ptr;
extern byte *g_rom_fc_ff_ptr;
extern byte *g_rom_cards_ptr;
extern byte *g_dummy_memory1_ptr;
extern int g_num_breakpoints;
extern word32 g_breakpts[];
extern Pc_log *g_log_pc_ptr;
extern Pc_log *g_log_pc_start_ptr;
extern Pc_log *g_log_pc_end_ptr;
extern Data_log *g_log_data_ptr;
extern Data_log *g_log_data_start_ptr;
extern Data_log *g_log_data_end_ptr;
int size_tab[] = {
#include "size_c.h"
};
int bogus[] = {
0,
#include "op_routs.h"
};
#define FINISH(arg1, arg2) g_ret1 = arg1; g_ret2 = arg2; goto finish;
#define INC_KPC_1 kpc = (kpc & 0xff0000) + ((kpc + 1) & 0xffff);
#define INC_KPC_2 kpc = (kpc & 0xff0000) + ((kpc + 2) & 0xffff);
#define INC_KPC_3 kpc = (kpc & 0xff0000) + ((kpc + 3) & 0xffff);
#define INC_KPC_4 kpc = (kpc & 0xff0000) + ((kpc + 4) & 0xffff);
#define CYCLES_PLUS_1 fcycles += fplus_1;
#define CYCLES_PLUS_2 fcycles += fplus_2;
#define CYCLES_PLUS_3 fcycles += fplus_3;
#define CYCLES_PLUS_4 fcycles += (fplus_1 + fplus_3);
#define CYCLES_PLUS_5 fcycles += (fplus_2 + fplus_3);
#define CYCLES_MINUS_1 fcycles -= fplus_1;
#define CYCLES_MINUS_2 fcycles -= fplus_2;
#define CYCLES_FINISH fcycles = g_fcycles_stop + fplus_1;
#define FCYCLES_ROUND fcycles = (int)(fcycles + fplus_x_m1);
#ifdef LOG_PC
# define LOG_PC_MACRO() \
tmp_pc_ptr = g_log_pc_ptr++; \
tmp_pc_ptr->dbank_kpc = (dbank << 24) + kpc; \
tmp_pc_ptr->instr = (opcode << 24) + arg_ptr[1] + \
(arg_ptr[2] << 8) + (arg_ptr[3] << 16); \
tmp_pc_ptr->psr_acc = ((psr & ~(0x82)) << 16) + acc + \
(neg << 23) + ((!zero) << 17); \
tmp_pc_ptr->xreg_yreg = (xreg << 16) + yreg; \
tmp_pc_ptr->stack_direct = (stack << 16) + direct; \
tmp_pc_ptr->dcycs = fcycles + g_last_vbl_dcycs - fplus_2; \
if(g_log_pc_ptr >= g_log_pc_end_ptr) { \
/*halt2_printf("log_pc oflow %f\n", tmp_pc_ptr->dcycs);*/ \
g_log_pc_ptr = g_log_pc_start_ptr; \
}
# define LOG_DATA_MACRO(in_addr, in_val, in_size) \
g_log_data_ptr->dcycs = fcycles + g_last_vbl_dcycs; \
g_log_data_ptr->addr = in_addr; \
g_log_data_ptr->val = in_val; \
g_log_data_ptr->size = in_size; \
g_log_data_ptr++; \
if(g_log_data_ptr >= g_log_data_end_ptr) { \
g_log_data_ptr = g_log_data_start_ptr; \
}
#else
# define LOG_PC_MACRO()
# define LOG_DATA_MACRO(addr, val, size)
/* Just do nothing */
#endif
#define GET_1BYTE_ARG arg = arg_ptr[1];
#define GET_2BYTE_ARG arg = arg_ptr[1] + (arg_ptr[2] << 8);
#define GET_3BYTE_ARG arg = arg_ptr[1] + (arg_ptr[2] << 8) + (arg_ptr[3]<<16);
/* HACK HACK HACK */
#define UPDATE_PSR(dummy, old_psr) \
if(psr & 0x100) { \
psr |= 0x30; \
stack = 0x100 + (stack & 0xff); \
} \
if((old_psr ^ psr) & 0x10) { \
if(psr & 0x10) { \
xreg = xreg & 0xff; \
yreg = yreg & 0xff; \
} \
} \
if(((psr & 0x4) == 0) && g_irq_pending) { \
FINISH(RET_IRQ, 0); \
} \
if((old_psr ^ psr) & 0x20) { \
goto recalc_accsize; \
}
extern Page_info page_info_rd_wr[];
extern word32 slow_mem_changed[];
#define GET_MEMORY8(addr,dest) \
addr_latch = (addr); \
CYCLES_PLUS_1; \
stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if(wstat & (1 << (31 - BANK_IO_BIT))) { \
fcycles_tmp1 = fcycles; \
dest = get_memory8_io_stub((addr), stat, \
&fcycles_tmp1, fplus_x_m1); \
fcycles = fcycles_tmp1; \
} else { \
dest = *ptr; \
}
#define GET_MEMORY(addr,dest) GET_MEMORY8(addr, dest)
#define GET_MEMORY16(addr, dest, in_bank) \
save_addr = addr; \
stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if((wstat & (1 << (31 - BANK_IO_BIT))) || (((addr) & 0xff) == 0xff)) { \
fcycles_tmp1 = fcycles; \
dest = get_memory16_pieces_stub((addr), stat, \
&fcycles_tmp1, fplus_ptr, in_bank); \
fcycles = fcycles_tmp1; \
} else { \
CYCLES_PLUS_2; \
dest = ptr[0] + (ptr[1] << 8); \
} \
addr_latch = save_addr;
#define GET_MEMORY24(addr, dest, in_bank) \
save_addr = addr; \
stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if((wstat & (1 << (31 - BANK_IO_BIT))) || (((addr) & 0xfe) == 0xfe)) { \
fcycles_tmp1 = fcycles; \
dest = get_memory24_pieces_stub((addr), stat, \
&fcycles_tmp1, fplus_ptr, in_bank); \
fcycles = fcycles_tmp1; \
} else { \
CYCLES_PLUS_3; \
dest = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16); \
} \
addr_latch = save_addr;
#define GET_MEMORY_DIRECT_PAGE16(addr, dest) \
save_addr = addr; \
if(psr & 0x100) { \
if((direct & 0xff) == 0) { \
save_addr = (save_addr & 0xff) + direct; \
} \
} \
if((psr & 0x100) && (((addr) & 0xff) == 0xff)) { \
GET_MEMORY8(save_addr, getmem_tmp); \
save_addr = (save_addr + 1) & 0xffff; \
if((direct & 0xff) == 0) { \
save_addr = (save_addr & 0xff) + direct; \
} \
GET_MEMORY8(save_addr, dest); \
dest = (dest << 8) + getmem_tmp; \
} else { \
GET_MEMORY16(save_addr, dest, 1); \
}
#define PUSH8(arg) \
SET_MEMORY8(stack, arg); \
stack--; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
stack = stack & 0xffff;
#define PUSH16(arg) \
if((stack & 0xfe) == 0) { \
/* stack will cross page! */ \
PUSH8((arg) >> 8); \
PUSH8(arg); \
} else { \
stack -= 2; \
stack = stack & 0xffff; \
SET_MEMORY16(stack + 1, arg, 1); \
}
#define PUSH16_UNSAFE(arg) \
save_addr = (stack - 1) & 0xffff; \
stack -= 2; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
stack = stack & 0xffff; \
SET_MEMORY16(save_addr, arg, 1);
#define PUSH24_UNSAFE(arg) \
save_addr = (stack - 2) & 0xffff; \
stack -= 3; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
stack = stack & 0xffff; \
SET_MEMORY24(save_addr, arg, 1);
#define PULL8(dest) \
stack++; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
stack = stack & 0xffff; \
GET_MEMORY8(stack, dest);
#define PULL16(dest) \
if((stack & 0xfe) == 0xfe) { /* page cross */ \
PULL8(dest); \
PULL8(pull_tmp); \
dest = (pull_tmp << 8) + dest; \
} else { \
GET_MEMORY16(stack + 1, dest, 1); \
stack = (stack + 2) & 0xffff; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
}
#define PULL16_UNSAFE(dest) \
stack = (stack + 1) & 0xffff; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
GET_MEMORY16(stack, dest, 1); \
stack = (stack + 1) & 0xffff; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
}
#define PULL24(dest) \
if((stack & 0xfc) == 0xfc) { /* page cross */ \
PULL8(dest); \
PULL8(pull_tmp); \
pull_tmp = (pull_tmp << 8) + dest; \
PULL8(dest); \
dest = (dest << 16) + pull_tmp; \
} else { \
GET_MEMORY24(stack + 1, dest, 1); \
stack = (stack + 3) & 0xffff; \
if(psr & 0x100) { \
stack = 0x100 | (stack & 0xff); \
} \
}
#define SET_MEMORY8(addr, val) \
LOG_DATA_MACRO(addr, val, 8); \
CYCLES_PLUS_1; \
stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if(wstat) { \
fcycles_tmp1 = fcycles; \
set_memory8_io_stub((addr), val, stat, &fcycles_tmp1, \
fplus_x_m1); \
fcycles = fcycles_tmp1; \
} else { \
*ptr = val; \
}
#define SET_MEMORY16(addr, val, in_bank) \
LOG_DATA_MACRO(addr, val, 16); \
stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if((wstat) || (((addr) & 0xff) == 0xff)) { \
fcycles_tmp1 = fcycles; \
set_memory16_pieces_stub((addr), (val), \
&fcycles_tmp1, fplus_1, fplus_x_m1, in_bank); \
fcycles = fcycles_tmp1; \
} else { \
CYCLES_PLUS_2; \
ptr[0] = (val); \
ptr[1] = (val) >> 8; \
}
#define SET_MEMORY24(addr, val, in_bank) \
LOG_DATA_MACRO(addr, val, 24); \
stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if((wstat) || (((addr) & 0xfe) == 0xfe)) { \
fcycles_tmp1 = fcycles; \
set_memory24_pieces_stub((addr), (val), \
&fcycles_tmp1, fplus_ptr, in_bank); \
fcycles = fcycles_tmp1; \
} else { \
CYCLES_PLUS_3; \
ptr[0] = (val); \
ptr[1] = (val) >> 8; \
ptr[2] = (val) >> 16; \
}
void
check_breakpoints(word32 addr)
{
int count;
int i;
count = g_num_breakpoints;
for(i = 0; i < count; i++) {
if((g_breakpts[i] & 0xffffff) == addr) {
halt2_printf("Hit breakpoint at %06x\n", addr);
}
}
}
word32
get_memory8_io_stub(word32 addr, byte *stat, double *fcycs_ptr,
double fplus_x_m1)
{
double fcycles;
word32 wstat;
byte *ptr;
wstat = PTR2WORD(stat) & 0xff;
if(wstat & BANK_BREAK) {
check_breakpoints(addr);
}
fcycles = *fcycs_ptr;
if(wstat & BANK_IO2_TMP) {
FCYCLES_ROUND;
*fcycs_ptr = fcycles;
return get_memory_io((addr), fcycs_ptr);
} else {
ptr = stat - wstat + (addr & 0xff);
return *ptr;
}
}
word32
get_memory16_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr,
Fplus *fplus_ptr, int in_bank)
{
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1;
double fplus_x_m1;
word32 addrp1;
word32 wstat;
word32 addr_latch;
word32 ret;
word32 tmp1;
fcycles = *fcycs_ptr;
fplus_1 = fplus_ptr->plus_1;
fplus_x_m1 = fplus_ptr->plus_x_minus_1;
GET_MEMORY8(addr, tmp1);
addrp1 = addr + 1;
if(in_bank) {
addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff);
}
GET_MEMORY8(addrp1, ret);
*fcycs_ptr = fcycles;
return (ret << 8) + (tmp1);
}
word32
get_memory24_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr,
Fplus *fplus_ptr, int in_bank)
{
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1;
double fplus_x_m1;
word32 addrp1, addrp2;
word32 wstat;
word32 addr_latch;
word32 ret;
word32 tmp1;
word32 tmp2;
fcycles = *fcycs_ptr;
fplus_1 = fplus_ptr->plus_1;
fplus_x_m1 = fplus_ptr->plus_x_minus_1;
GET_MEMORY8(addr, tmp1);
addrp1 = addr + 1;
if(in_bank) {
addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff);
}
GET_MEMORY8(addrp1, tmp2);
addrp2 = addr + 2;
if(in_bank) {
addrp2 = (addr & 0xff0000) + (addrp2 & 0xffff);
}
GET_MEMORY8(addrp2, ret);
*fcycs_ptr = fcycles;
return (ret << 16) + (tmp2 << 8) + tmp1;
}
void
set_memory8_io_stub(word32 addr, word32 val, byte *stat, double *fcycs_ptr,
double fplus_x_m1)
{
double fcycles;
word32 setmem_tmp1;
word32 tmp1, tmp2;
byte *ptr;
word32 wstat;
wstat = PTR2WORD(stat) & 0xff;
if(wstat & (1 << (31 - BANK_BREAK_BIT))) {
check_breakpoints(addr);
}
ptr = stat - wstat + ((addr) & 0xff); \
fcycles = *fcycs_ptr;
if(wstat & (1 << (31 - BANK_IO2_BIT))) {
FCYCLES_ROUND;
*fcycs_ptr = fcycles;
set_memory_io((addr), val, fcycs_ptr);
} else if(wstat & (1 << (31 - BANK_SHADOW_BIT))) {
FCYCS_PTR_FCYCLES_ROUND_SLOW;
tmp1 = (addr & 0xffff);
setmem_tmp1 = g_slow_memory_ptr[tmp1];
*ptr = val;
if(setmem_tmp1 != ((val) & 0xff)) {
g_slow_memory_ptr[tmp1] = val;
slow_mem_changed[tmp1 >> CHANGE_SHIFT] |=
(1 << (31-((tmp1 >> SHIFT_PER_CHANGE) & 0x1f)));
}
} else if(wstat & (1 << (31 - BANK_SHADOW2_BIT))) {
FCYCS_PTR_FCYCLES_ROUND_SLOW;
tmp2 = (addr & 0xffff);
tmp1 = 0x10000 + tmp2;
setmem_tmp1 = g_slow_memory_ptr[tmp1];
*ptr = val;
if(setmem_tmp1 != ((val) & 0xff)) {
g_slow_memory_ptr[tmp1] = val;
slow_mem_changed[tmp2 >>CHANGE_SHIFT] |=
(1 <<(31-((tmp2 >> SHIFT_PER_CHANGE) & 0x1f)));
}
} else {
/* breakpoint only */
*ptr = val;
}
}
void
set_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr,
double fplus_1, double fplus_x_m1, int in_bank)
{
byte *ptr;
byte *stat;
double fcycles, fcycles_tmp1;
word32 addrp1;
word32 wstat;
fcycles = *fcycs_ptr;
SET_MEMORY8(addr, val);
addrp1 = addr + 1;
if(in_bank) {
addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff);
}
SET_MEMORY8(addrp1, val >> 8);
*fcycs_ptr = fcycles;
}
void
set_memory24_pieces_stub(word32 addr, word32 val, double *fcycs_ptr,
Fplus *fplus_ptr, int in_bank)
{
byte *ptr;
byte *stat;
double fcycles, fcycles_tmp1;
double fplus_1;
double fplus_x_m1;
word32 addrp1, addrp2;
word32 wstat;
fcycles = *fcycs_ptr;
fplus_1 = fplus_ptr->plus_1;
fplus_x_m1 = fplus_ptr->plus_x_minus_1;
SET_MEMORY8(addr, val);
addrp1 = addr + 1;
if(in_bank) {
addrp1 = (addr & 0xff0000) + (addrp1 & 0xffff);
}
SET_MEMORY8(addrp1, val >> 8);
addrp2 = addr + 2;
if(in_bank) {
addrp2 = (addr & 0xff0000) + (addrp2 & 0xffff);
}
SET_MEMORY8(addrp2, val >> 16);
*fcycs_ptr = fcycles;
}
word32
get_memory_c(word32 addr, int cycs)
{
byte *stat;
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1;
double fplus_x_m1;
word32 addr_latch;
word32 wstat;
word32 ret;
fcycles = 0;
fplus_1 = 0;
fplus_x_m1 = 0;
GET_MEMORY8(addr, ret);
return ret;
}
word32
get_memory16_c(word32 addr, int cycs)
{
double fcycs;
fcycs = 0;
return get_memory_c(addr, fcycs) +
(get_memory_c(addr+1, fcycs) << 8);
}
word32
get_memory24_c(word32 addr, int cycs)
{
double fcycs;
fcycs = 0;
return get_memory_c(addr, fcycs) +
(get_memory_c(addr+1, fcycs) << 8) +
(get_memory_c(addr+2, fcycs) << 16);
}
void
set_memory_c(word32 addr, word32 val, int cycs)
{
byte *stat;
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1;
double fplus_x_m1;
word32 wstat;
fcycles = g_cur_dcycs - g_last_vbl_dcycs;
fplus_1 = 0;
fplus_x_m1 = 0;
SET_MEMORY8(addr, val);
}
void
set_memory16_c(word32 addr, word32 val, int cycs)
{
byte *stat;
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1, fplus_2;
double fplus_x_m1;
word32 wstat;
fcycles = g_cur_dcycs - g_last_vbl_dcycs;
fplus_1 = 0;
fplus_2 = 0;
fplus_x_m1 = 0;
SET_MEMORY16(addr, val, 0);
}
void
set_memory24_c(word32 addr, word32 val, int cycs)
{
set_memory_c(addr, val, 0);
set_memory_c(addr + 1, val >> 8, 0);
set_memory_c(addr + 2, val >> 16, 0);
}
word32
do_adc_sbc8(word32 in1, word32 in2, word32 psr, int sub)
{
word32 sum, carry, overflow;
word32 zero;
int decimal;
overflow = 0;
decimal = psr & 8;
if(sub) {
in2 = (in2 ^ 0xff);
}
if(!decimal) {
sum = (in1 & 0xff) + in2 + (psr & 1);
overflow = ((sum ^ in2) >> 1) & 0x40;
} else {
/* decimal */
sum = (in1 & 0xf) + (in2 & 0xf) + (psr & 1);
if(sub) {
if(sum < 0x10) {
sum = (sum - 0x6) & 0xf;
}
} else {
if(sum >= 0xa) {
sum = (sum - 0xa) | 0x10;
}
}
sum = (in1 & 0xf0) + (in2 & 0xf0) + sum;
overflow = ((sum >> 2) ^ (sum >> 1)) & 0x40;
if(sub) {
if(sum < 0x100) {
sum = (sum + 0xa0) & 0xff;
}
} else {
if(sum >= 0xa0) {
sum += 0x60;
}
}
}
zero = ((sum & 0xff) == 0);
carry = (sum >= 0x100);
if((in1 ^ in2) & 0x80) {
overflow = 0;
}
psr = psr & (~0xc3);
psr = psr + (sum & 0x80) + overflow + (zero << 1) + carry;
return (psr << 16) + (sum & 0xff);
}
word32
do_adc_sbc16(word32 in1, word32 in2, word32 psr, int sub)
{
word32 sum, carry, overflow;
word32 tmp1, tmp2;
word32 zero;
int decimal;
overflow = 0;
decimal = psr & 8;
if(!decimal) {
if(sub) {
in2 = (in2 ^ 0xffff);
}
sum = in1 + in2 + (psr & 1);
overflow = ((sum ^ in2) >> 9) & 0x40;
} else {
/* decimal */
if(sub) {
tmp1 = do_adc_sbc8(in1 & 0xff, in2 & 0xff, psr, sub);
psr = (tmp1 >> 16);
tmp2 = do_adc_sbc8((in1 >> 8) & 0xff,
(in2 >> 8) & 0xff, psr, sub);
in2 = (in2 ^ 0xfffff);
} else {
tmp1 = do_adc_sbc8(in1 & 0xff, in2 & 0xff, psr, sub);
psr = (tmp1 >> 16);
tmp2 = do_adc_sbc8((in1 >> 8) & 0xff,
(in2 >> 8) &0xff, psr, sub);
}
sum = ((tmp2 & 0xff) << 8) + (tmp1 & 0xff) +
(((tmp2 >> 16) & 1) << 16);
overflow = (tmp2 >> 16) & 0x40;
}
zero = ((sum & 0xffff) == 0);
carry = (sum >= 0x10000);
if((in1 ^ in2) & 0x8000) {
overflow = 0;
}
psr = psr & (~0xc3);
psr = psr + ((sum & 0x8000) >> 8) + overflow + (zero << 1) + carry;
return (psr << 16) + (sum & 0xffff);
}
int g_ret1;
int g_ret2;
void
fixed_memory_ptrs_init()
{
/* set g_slow_memory_ptr, g_rom_fc_ff_ptr, g_dummy_memory1_ptr, */
/* and rom_cards_ptr */
g_slow_memory_ptr = memalloc_align(128*1024, 0, 0);
g_dummy_memory1_ptr = memalloc_align(256, 1024, 0);
g_rom_fc_ff_ptr = memalloc_align(256*1024, 512, 0);
g_rom_cards_ptr = memalloc_align(16*256, 256, 0);
#if 0
printf("g_memory_ptr: %08x, dummy_mem: %08x, slow_mem_ptr: %08x\n",
(word32)g_memory_ptr, (word32)g_dummy_memory1_ptr,
(word32)g_slow_memory_ptr);
printf("g_rom_fc_ff_ptr: %08x, g_rom_cards_ptr: %08x\n",
(word32)g_rom_fc_ff_ptr, (word32)g_rom_cards_ptr);
printf("page_info_rd = %08x, page_info_wr end = %08x\n",
(word32)&(page_info_rd_wr[0]),
(word32)&(page_info_rd_wr[PAGE_INFO_PAD_SIZE+0x1ffff].rd_wr));
#endif
}
word32
get_itimer()
{
#if defined(__i386) && defined(__GNUC__)
/* Here's my bad ia32 asm code to do rdtsc */
/* Linux source uses: */
/* asm volatile("rdtsc" : "=a"(ret) : : "edx"); */
/* asm volatile("rdtsc" : "=%eax"(ret) : : "%edx"); */
/* GCC bug report 2001-03/msg00786.html used: */
/*register word64 dtmp; */
/*asm volatile ("rdtsc" : "=A" (dtmp)); */
/*return (word32)dtmp; */
register word32 ret;
asm volatile ("rdtsc;movl %%eax,%0" : "=r"(ret) : : "%eax","%edx");
return ret;
#else
# if defined(__POWERPC__) && defined(__GNUC__)
register word32 ret;
asm volatile ("mftb %0" : "=r"(ret));
return ret;
# else
return 0;
# endif
#endif
}
void
set_halt_act(int val)
{
if(val == 1 && g_ignore_halts && !g_user_halt_bad) {
g_code_red++;
} else {
halt_sim |= val;
g_fcycles_stop = (double)0.0;
}
}
void
clr_halt_act()
{
halt_sim = 0;
}
word32
get_remaining_operands(word32 addr, word32 opcode, word32 psr, Fplus *fplus_ptr)
{
byte *stat;
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1, fplus_2, fplus_3;
double fplus_x_m1;
word32 addr_latch;
word32 wstat;
word32 save_addr;
word32 arg;
word32 addrp1;
int size;
fcycles = 0;
fplus_1 = 0;
fplus_2 = 0;
fplus_3 = 0;
fplus_x_m1 = 0;
size = size_tab[opcode];
addrp1 = (addr & 0xff0000) + ((addr + 1) & 0xffff);
switch(size) {
case 0:
arg = 0; /* no args */
break;
case 1:
GET_MEMORY8(addrp1, arg);
break; /* 1 arg, already done */
case 2:
GET_MEMORY16(addrp1, arg, 1);
break;
case 3:
GET_MEMORY24(addrp1, arg, 1);
break;
case 4:
if(psr & 0x20) {
GET_MEMORY8(addrp1, arg);
} else {
GET_MEMORY16(addrp1, arg, 1);
}
break;
case 5:
if(psr & 0x10) {
GET_MEMORY8(addrp1, arg);
} else {
GET_MEMORY16(addrp1, arg, 1);
}
break;
default:
printf("Unknown size: %d\n", size);
arg = 0;
exit(-2);
}
return arg;
}
#define FETCH_OPCODE \
addr = kpc; \
CYCLES_PLUS_2; \
stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
arg_ptr = ptr; \
opcode = *ptr; \
if((wstat & (1 << (31-BANK_IO_BIT))) || ((addr & 0xff) > 0xfc)) {\
if(wstat & BANK_BREAK) { \
check_breakpoints(addr); \
} \
if((addr & 0xfffff0) == 0x00c700) { \
if(addr == 0xc700) { \
FINISH(RET_C700, 0); \
} else if(addr == 0xc70a) { \
FINISH(RET_C70A, 0); \
} else if(addr == 0xc70d) { \
FINISH(RET_C70D, 0); \
} \
} \
if(wstat & (1 << (31 - BANK_IO2_BIT))) { \
FCYCLES_ROUND; \
fcycles_tmp1 = fcycles; \
opcode = get_memory_io((addr), &fcycles_tmp1); \
fcycles = fcycles_tmp1; \
} else { \
opcode = *ptr; \
} \
arg = get_remaining_operands(addr, opcode, psr, fplus_ptr);\
arg_ptr = (byte *)&tmp_bytes; \
arg_ptr[1] = arg; \
arg_ptr[2] = arg >> 8; \
arg_ptr[3] = arg >> 16; \
}
int
enter_engine(Engine_reg *engine_ptr)
{
register byte *ptr;
byte *arg_ptr;
Pc_log *tmp_pc_ptr;
byte *stat;
word32 wstat;
word32 arg;
register word32 kpc;
register word32 acc;
register word32 xreg;
register word32 yreg;
word32 stack;
word32 dbank;
register word32 direct;
register word32 psr;
register word32 zero;
register word32 neg;
word32 getmem_tmp;
word32 save_addr;
word32 pull_tmp;
word32 tmp_bytes;
double fcycles;
Fplus *fplus_ptr;
double fplus_1;
double fplus_2;
double fplus_3;
double fplus_x_m1;
double fcycles_tmp1;
word32 opcode;
register word32 addr;
word32 addr_latch;
word32 tmp1, tmp2;
tmp_pc_ptr = 0;
kpc = engine_ptr->kpc;
acc = engine_ptr->acc;
xreg = engine_ptr->xreg;
yreg = engine_ptr->yreg;
stack = engine_ptr->stack;
dbank = engine_ptr->dbank;
direct = engine_ptr->direct;
psr = engine_ptr->psr;
fcycles = engine_ptr->fcycles;
fplus_ptr = engine_ptr->fplus_ptr;
zero = !(psr & 2);
neg = (psr >> 7) & 1;
fplus_1 = fplus_ptr->plus_1;
fplus_2 = fplus_ptr->plus_2;
fplus_3 = fplus_ptr->plus_3;
fplus_x_m1 = fplus_ptr->plus_x_minus_1;
g_ret1 = 0;
g_ret2 = 0;
recalc_accsize:
if(psr & 0x20) {
while(fcycles <= g_fcycles_stop) {
#if 0
if((neg & ~1) || (psr & (~0x1ff))) {
halt_printf("psr = %04x\n", psr);
}
#endif
FETCH_OPCODE;
LOG_PC_MACRO();
switch(opcode) {
default:
halt_printf("acc8 unk op: %02x\n", opcode);
arg = 9
#define ACC8
#include "defs_instr.h"
* 2;
break;
#include "8inst_c.h"
break;
}
}
} else {
while(fcycles <= g_fcycles_stop) {
FETCH_OPCODE;
LOG_PC_MACRO();
switch(opcode) {
default:
halt_printf("acc16 unk op: %02x\n", opcode);
arg = 9
#undef ACC8
#include "defs_instr.h"
* 2;
break;
#include "16inst_c.h"
break;
}
}
}
finish:
engine_ptr->kpc = kpc;
engine_ptr->acc = acc;
engine_ptr->xreg = xreg;
engine_ptr->yreg = yreg;
engine_ptr->stack = stack;
engine_ptr->dbank = dbank;
engine_ptr->direct = direct;
engine_ptr->fcycles = fcycles;
psr = psr & (~0x82);
psr |= (neg << 7);
psr |= ((!zero) << 1);
engine_ptr->psr = psr;
return (g_ret1 << 28) + g_ret2;
}
int g_engine_c_mode = 1;
int defs_instr_start_8 = 0;
int defs_instr_end_8 = 0;
int defs_instr_start_16 = 0;
int defs_instr_end_16 = 0;
int op_routs_start = 0;
int op_routs_end = 0;