mirror of
https://github.com/jamessanford/kegs.git
synced 2024-09-11 12:55:04 +00:00
2967 lines
45 KiB
C
2967 lines
45 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 */
|
|
/************************************************************************/
|
|
|
|
#ifdef ASM
|
|
# ifdef INCLUDE_RCSID_S
|
|
.stringz "@(#)$KmKId: instable.h,v 1.104 2004-10-05 20:12:08-04 kentd Exp $"
|
|
# endif
|
|
#endif
|
|
|
|
case 0x00: /* brk */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
ldil l%g_testing,arg3
|
|
ldil l%g_num_brk,arg1
|
|
ldw r%g_testing(arg3),arg3
|
|
INC_KPC_2;
|
|
ldw r%g_num_brk(arg1),arg2
|
|
comib,<> 0,arg3,brk_testing_16
|
|
extru kpc,31,16,arg0
|
|
addi 1,arg2,arg2
|
|
bb,>= psr,23,brk_native_16
|
|
stw arg2,r%g_num_brk(arg1)
|
|
|
|
bl push_16,link
|
|
nop
|
|
|
|
bl push_8,link
|
|
extru psr,31,8,arg0 ;B bit already on in PSR
|
|
|
|
ldil l%0xfffe,arg0
|
|
bl get_mem_long_16,link
|
|
ldo r%0xfffe(arg0),arg0
|
|
|
|
zdep ret0,31,16,kpc ;set kbank to 0
|
|
|
|
#if 0
|
|
bl set_halt_act,link
|
|
ldi 3,arg0
|
|
#endif
|
|
|
|
|
|
ldi 0,dbank ;clear dbank in emul mode
|
|
b dispatch
|
|
depi 1,29,2,psr ;ints masked, decimal off
|
|
|
|
|
|
brk_native_16
|
|
stw arg0,STACK_SAVE_COP_ARG0(sp)
|
|
bl push_8,link
|
|
extru kpc,15,8,arg0
|
|
|
|
bl push_16,link
|
|
ldw STACK_SAVE_COP_ARG0(sp),arg0
|
|
|
|
bl push_8,link
|
|
extru psr,31,8,arg0
|
|
|
|
ldil l%0xffe6,arg0
|
|
bl get_mem_long_16,link
|
|
ldo r%0xffe6(arg0),arg0
|
|
|
|
zdep ret0,31,16,kpc ;zero kbank in kpc
|
|
|
|
#if 0
|
|
#endif
|
|
bl set_halt_act,link
|
|
ldi 3,arg0
|
|
|
|
b dispatch
|
|
depi 1,29,2,psr ;ints masked, decimal off
|
|
|
|
brk_testing_16
|
|
DEC_KPC2;
|
|
CYCLES_PLUS_2
|
|
b dispatch_done
|
|
depi RET_BREAK,3,4,ret0
|
|
|
|
#else
|
|
GET_1BYTE_ARG;
|
|
if(g_testing) {
|
|
CYCLES_PLUS_2;
|
|
FINISH(RET_BREAK, arg);
|
|
}
|
|
g_num_brk++;
|
|
INC_KPC_2;
|
|
if(psr & 0x100) {
|
|
PUSH16(kpc & 0xffff);
|
|
PUSH8(psr & 0xff);
|
|
GET_MEMORY16(0xfffe, kpc, 0);
|
|
dbank = 0;
|
|
} else {
|
|
PUSH8(kpc >> 16);
|
|
PUSH16(kpc);
|
|
PUSH8(psr & 0xff);
|
|
GET_MEMORY16(0xffe6, kpc, 0);
|
|
halt_printf("Halting for native break!\n");
|
|
}
|
|
kpc = kpc & 0xffff;
|
|
psr |= 0x4;
|
|
psr &= ~(0x8);
|
|
#endif
|
|
|
|
break;
|
|
case 0x01: /* ORA (Dloc,X) */
|
|
/* called with arg = val to ORA in */
|
|
GET_DLOC_X_IND_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x02: /* COP */
|
|
#ifdef ASM
|
|
ldil l%g_num_cop,arg1
|
|
INC_KPC_2;
|
|
ldw r%g_num_cop(arg1),arg2
|
|
extru kpc,31,16,arg0
|
|
addi 1,arg2,arg2
|
|
bb,>= psr,23,cop_native_16
|
|
stw arg2,r%g_num_cop(arg1)
|
|
|
|
bl push_16,link
|
|
nop
|
|
|
|
bl push_8,link
|
|
extru psr,31,8,arg0
|
|
|
|
ldil l%0xfff4,arg0
|
|
bl get_mem_long_16,link
|
|
ldo r%0xfff4(arg0),arg0
|
|
|
|
ldi 0,dbank ;clear dbank in emul mode
|
|
zdep ret0,31,16,kpc ;clear kbank
|
|
|
|
bl set_halt_act,link
|
|
ldi 3,arg0
|
|
|
|
b dispatch
|
|
depi 1,29,2,psr ;ints masked, decimal off
|
|
|
|
cop_native_16
|
|
stw arg0,STACK_SAVE_COP_ARG0(sp)
|
|
bl push_8,link
|
|
extru kpc,15,8,arg0
|
|
|
|
bl push_16,link
|
|
ldw STACK_SAVE_COP_ARG0(sp),arg0
|
|
|
|
bl push_8,link
|
|
extru psr,31,8,arg0
|
|
|
|
ldil l%0xffe4,arg0
|
|
bl get_mem_long_16,link
|
|
ldo r%0xffe4(arg0),arg0
|
|
|
|
zdep ret0,31,16,kpc ;clear kbank
|
|
b dispatch
|
|
depi 1,29,2,psr ;ints masked, decimal off
|
|
|
|
|
|
#else
|
|
g_num_cop++;
|
|
INC_KPC_2;
|
|
if(psr & 0x100) {
|
|
halt_printf("Halting for emul COP at %04x\n", kpc);
|
|
PUSH16(kpc & 0xffff);
|
|
PUSH8(psr & 0xff);
|
|
GET_MEMORY16(0xfff4, kpc, 0);
|
|
dbank = 0;
|
|
} else {
|
|
PUSH8(kpc >> 16);
|
|
PUSH16(kpc & 0xffff);
|
|
PUSH8(psr & 0xff);
|
|
GET_MEMORY16(0xffe4, kpc, 0);
|
|
}
|
|
kpc = kpc & 0xffff;
|
|
psr |= 4;
|
|
psr &= ~(0x8);
|
|
#endif
|
|
|
|
break;
|
|
case 0x03: /* ORA Disp8,S */
|
|
GET_DISP8_S_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x04: /* TSB Dloc */
|
|
GET_DLOC_RD();
|
|
TSB_INST(1);
|
|
|
|
break;
|
|
case 0x05: /* ORA Dloc */
|
|
GET_DLOC_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x06: /* ASL Dloc */
|
|
GET_DLOC_RD();
|
|
ASL_INST(1);
|
|
|
|
break;
|
|
case 0x07: /* ORA [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x08: /* PHP */
|
|
#ifdef ASM
|
|
dep neg,24,1,psr
|
|
ldil l%dispatch,link
|
|
INC_KPC_1
|
|
depi 0,30,1,psr
|
|
comiclr,<> 0,zero,0
|
|
depi 1,30,1,psr
|
|
ldo r%dispatch(link),link
|
|
b push_8
|
|
extru psr,31,8,arg0
|
|
#else
|
|
INC_KPC_1;
|
|
psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1);
|
|
PUSH8(psr);
|
|
#endif
|
|
|
|
break;
|
|
case 0x09: /* ORA #imm */
|
|
GET_IMM_MEM();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x0a: /* ASL a */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
ldi 0xff,scratch1
|
|
sh1add acc,0,scratch3
|
|
INC_KPC_1
|
|
extru scratch3,24,1,neg
|
|
and scratch3,scratch1,zero
|
|
extru scratch3,23,1,scratch2
|
|
dep zero,31,8,acc
|
|
b dispatch
|
|
dep scratch2,31,1,psr /* set carry */
|
|
# else
|
|
zdepi -1,31,16,scratch1
|
|
sh1add acc,0,scratch3
|
|
INC_KPC_1
|
|
extru scratch3,16,1,neg
|
|
and scratch3,scratch1,zero
|
|
extru scratch3,15,1,scratch2
|
|
dep scratch2,31,1,psr /* set carry */
|
|
b dispatch
|
|
dep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
tmp1 = acc + acc;
|
|
# ifdef ACC8
|
|
SET_CARRY8(tmp1);
|
|
acc = (acc & 0xff00) + (tmp1 & 0xff);
|
|
SET_NEG_ZERO8(acc & 0xff);
|
|
# else
|
|
SET_CARRY16(tmp1);
|
|
acc = tmp1 & 0xffff;
|
|
SET_NEG_ZERO16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x0b: /* PHD */
|
|
#ifdef ASM
|
|
ldil l%dispatch,link
|
|
extru direct,31,16,arg0
|
|
INC_KPC_1
|
|
b push_16_unsafe
|
|
ldo r%dispatch(link),link
|
|
#else
|
|
INC_KPC_1;
|
|
PUSH16_UNSAFE(direct);
|
|
#endif
|
|
|
|
break;
|
|
case 0x0c: /* TSB abs */
|
|
GET_ABS_RD();
|
|
TSB_INST(0);
|
|
|
|
break;
|
|
case 0x0d: /* ORA abs */
|
|
GET_ABS_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x0e: /* ASL abs */
|
|
GET_ABS_RD();
|
|
ASL_INST(0);
|
|
|
|
break;
|
|
case 0x0f: /* ORA long */
|
|
GET_LONG_RD();
|
|
ORA_INST();
|
|
|
|
|
|
break;
|
|
case 0x10: /* BPL disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
comib,<> 0,neg,inst10_2_16
|
|
COND_BR2
|
|
|
|
inst10_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8(neg == 0);
|
|
#endif
|
|
|
|
break;
|
|
case 0x11: /* ORA (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x12: /* ORA (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x13: /* ORA (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x14: /* TRB Dloc */
|
|
GET_DLOC_RD();
|
|
TRB_INST(1);
|
|
|
|
break;
|
|
case 0x15: /* ORA Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x16: /* ASL Dloc,X */
|
|
GET_DLOC_X_RD();
|
|
ASL_INST(1);
|
|
|
|
break;
|
|
case 0x17: /* ORA [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x18: /* CLC */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
depi 0,31,1,psr /* clear carry */
|
|
#else
|
|
psr = psr & (~1);
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0x19: /* ORA abs,y */
|
|
GET_ABS_Y_RD();
|
|
ORA_INST();
|
|
|
|
|
|
break;
|
|
case 0x1a: /* INC a */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
ldi 0xff,scratch2
|
|
addi 1,acc,scratch1
|
|
extru scratch1,24,1,neg
|
|
INC_KPC_1
|
|
extru scratch1,31,8,zero
|
|
b dispatch
|
|
dep zero,31,8,acc
|
|
# else
|
|
zdepi -1,31,16,scratch2
|
|
addi 1,acc,scratch1
|
|
extru scratch1,16,1,neg
|
|
INC_KPC_1
|
|
extru scratch1,31,16,zero
|
|
b dispatch
|
|
dep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
# ifdef ACC8
|
|
acc = (acc & 0xff00) | ((acc + 1) & 0xff);
|
|
SET_NEG_ZERO8(acc & 0xff);
|
|
# else
|
|
acc = (acc + 1) & 0xffff;
|
|
SET_NEG_ZERO16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x1b: /* TCS */
|
|
#ifdef ASM
|
|
copy acc,stack
|
|
extru,= psr,23,1,0 /* in emulation mode, stack page 1 */
|
|
depi 1,23,24,stack
|
|
INC_KPC_1
|
|
b dispatch
|
|
nop
|
|
#else
|
|
stack = acc;
|
|
INC_KPC_1;
|
|
if(psr & 0x100) {
|
|
stack = (stack & 0xff) + 0x100;
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0x1c: /* TRB Abs */
|
|
GET_ABS_RD();
|
|
TRB_INST(0);
|
|
|
|
break;
|
|
case 0x1d: /* ORA Abs,X */
|
|
GET_ABS_X_RD();
|
|
ORA_INST();
|
|
|
|
break;
|
|
case 0x1e: /* ASL Abs,X */
|
|
GET_ABS_X_RD_WR();
|
|
ASL_INST(0);
|
|
|
|
break;
|
|
case 0x1f: /* ORA Long,X */
|
|
GET_LONG_X_RD();
|
|
ORA_INST();
|
|
|
|
|
|
break;
|
|
case 0x20: /* JSR abs */
|
|
#ifdef ASM
|
|
addi 2,kpc,arg0
|
|
ldb 1(scratch1),scratch2
|
|
CYCLES_PLUS_2
|
|
ldb 2(scratch1),scratch1
|
|
ldil l%dispatch,link
|
|
extru arg0,31,16,arg0
|
|
ldo r%dispatch(link),link
|
|
dep scratch2,31,8,kpc
|
|
b push_16
|
|
dep scratch1,23,8,kpc
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
INC_KPC_2;
|
|
PUSH16(kpc);
|
|
kpc = (kpc & 0xff0000) + arg;
|
|
CYCLES_PLUS_2;
|
|
#endif
|
|
|
|
break;
|
|
case 0x21: /* AND (Dloc,X) */
|
|
/* called with arg = val to AND in */
|
|
GET_DLOC_X_IND_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x22: /* JSL Long */
|
|
#ifdef ASM
|
|
INC_KPC_3
|
|
ldb 3(scratch1),scratch2
|
|
copy kpc,arg0
|
|
ldb 1(scratch1),kpc
|
|
ldb 2(scratch1),scratch1
|
|
CYCLES_PLUS_3
|
|
dep scratch2,15,8,kpc
|
|
stw scratch2,STACK_SAVE_INSTR_TMP1(sp)
|
|
bl push_24_unsafe,link
|
|
dep scratch1,23,8,kpc
|
|
|
|
b dispatch
|
|
nop
|
|
#else
|
|
GET_3BYTE_ARG;
|
|
tmp1 = arg;
|
|
CYCLES_PLUS_3;
|
|
INC_KPC_3;
|
|
PUSH24_UNSAFE(kpc);
|
|
kpc = tmp1 & 0xffffff;
|
|
#endif
|
|
|
|
break;
|
|
case 0x23: /* AND Disp8,S */
|
|
/* called with arg = val to AND in */
|
|
GET_DISP8_S_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x24: /* BIT Dloc */
|
|
GET_DLOC_RD();
|
|
BIT_INST();
|
|
|
|
break;
|
|
case 0x25: /* AND Dloc */
|
|
/* called with arg = val to AND in */
|
|
GET_DLOC_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x26: /* ROL Dloc */
|
|
GET_DLOC_RD();
|
|
/* save1 is now apple addr */
|
|
/* ret0 is data */
|
|
ROL_INST(1);
|
|
|
|
break;
|
|
case 0x27: /* AND [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x28: /* PLP */
|
|
#ifdef ASM
|
|
bl pull_8,link
|
|
ldi 0,zero
|
|
|
|
extru psr,27,2,scratch2 /* save old x & m */
|
|
dep ret0,31,8,psr
|
|
CYCLES_PLUS_1
|
|
INC_KPC_1
|
|
extru,<> ret0,30,1,0
|
|
ldi 1,zero
|
|
copy scratch2,arg0
|
|
b update_system_state
|
|
extru ret0,24,1,neg
|
|
#else
|
|
PULL8(tmp1);
|
|
tmp2 = psr;
|
|
CYCLES_PLUS_1;
|
|
INC_KPC_1;
|
|
psr = (psr & ~0xff) | (tmp1 & 0xff);
|
|
zero = !(psr & 2);
|
|
neg = (psr >> 7) & 1;
|
|
UPDATE_PSR(psr, tmp2);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x29: /* AND #imm */
|
|
GET_IMM_MEM();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x2a: /* ROL a */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
extru psr,31,1,scratch2
|
|
ldi 0xff,scratch1
|
|
sh1add acc,scratch2,scratch3
|
|
INC_KPC_1
|
|
extru scratch3,24,1,neg
|
|
and scratch3,scratch1,zero
|
|
extru scratch3,23,1,scratch2
|
|
dep zero,31,8,acc
|
|
b dispatch
|
|
dep scratch2,31,1,psr /* set carry */
|
|
# else
|
|
extru psr,31,1,scratch2
|
|
INC_KPC_1
|
|
sh1add acc,scratch2,scratch3
|
|
zdepi -1,31,16,scratch1
|
|
extru scratch3,16,1,neg
|
|
and scratch3,scratch1,zero
|
|
extru scratch3,15,1,scratch2
|
|
dep scratch2,31,1,psr /* set carry */
|
|
b dispatch
|
|
dep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
# ifdef ACC8
|
|
tmp1 = ((acc & 0xff) << 1) + (psr & 1);
|
|
SET_CARRY8(tmp1);
|
|
acc = (acc & 0xff00) + (tmp1 & 0xff);
|
|
SET_NEG_ZERO8(tmp1 & 0xff);
|
|
# else
|
|
tmp1 = (acc << 1) + (psr & 1);
|
|
SET_CARRY16(tmp1);
|
|
acc = (tmp1 & 0xffff);
|
|
SET_NEG_ZERO16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x2b: /* PLD */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bl pull_16_unsafe,link
|
|
CYCLES_PLUS_1
|
|
extru ret0,31,16,direct
|
|
extru ret0,16,1,neg
|
|
b dispatch
|
|
copy direct,zero
|
|
#else
|
|
INC_KPC_1;
|
|
PULL16_UNSAFE(direct);
|
|
CYCLES_PLUS_1;
|
|
SET_NEG_ZERO16(direct);
|
|
#endif
|
|
|
|
break;
|
|
case 0x2c: /* BIT abs */
|
|
GET_ABS_RD();
|
|
BIT_INST();
|
|
|
|
break;
|
|
case 0x2d: /* AND abs */
|
|
GET_ABS_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x2e: /* ROL abs */
|
|
GET_ABS_RD();
|
|
ROL_INST(0);
|
|
|
|
break;
|
|
case 0x2f: /* AND long */
|
|
GET_LONG_RD();
|
|
AND_INST();
|
|
|
|
|
|
break;
|
|
case 0x30: /* BMI disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
comib,= 0,neg,inst30_2_16
|
|
COND_BR2
|
|
|
|
inst30_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8(neg);
|
|
#endif
|
|
|
|
break;
|
|
case 0x31: /* AND (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x32: /* AND (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x33: /* AND (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x34: /* BIT Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
BIT_INST();
|
|
|
|
break;
|
|
case 0x35: /* AND Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x36: /* ROL Dloc,X */
|
|
GET_DLOC_X_RD();
|
|
ROL_INST(1);
|
|
|
|
break;
|
|
case 0x37: /* AND [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x38: /* SEC */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
depi 1,31,1,psr /* set carry */
|
|
#else
|
|
psr = psr | 1;
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0x39: /* AND abs,y */
|
|
GET_ABS_Y_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x3a: /* DEC a */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
addi -1,acc,scratch1
|
|
extru scratch1,24,1,neg
|
|
INC_KPC_1
|
|
extru scratch1,31,8,zero
|
|
b dispatch
|
|
dep zero,31,8,acc
|
|
# else
|
|
addi -1,acc,scratch1
|
|
extru scratch1,16,1,neg
|
|
INC_KPC_1
|
|
extru scratch1,31,16,zero
|
|
b dispatch
|
|
dep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
# ifdef ACC8
|
|
acc = (acc & 0xff00) | ((acc - 1) & 0xff);
|
|
SET_NEG_ZERO8(acc & 0xff);
|
|
# else
|
|
acc = (acc - 1) & 0xffff;
|
|
SET_NEG_ZERO16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x3b: /* TSC */
|
|
/* set N,Z according to 16 bit acc */
|
|
#ifdef ASM
|
|
copy stack,acc
|
|
extru stack,16,1,neg
|
|
INC_KPC_1
|
|
b dispatch
|
|
extru acc,31,16,zero
|
|
#else
|
|
INC_KPC_1;
|
|
acc = stack;
|
|
SET_NEG_ZERO16(acc);
|
|
#endif
|
|
|
|
break;
|
|
case 0x3c: /* BIT Abs,x */
|
|
GET_ABS_X_RD();
|
|
BIT_INST();
|
|
|
|
break;
|
|
case 0x3d: /* AND Abs,X */
|
|
GET_ABS_X_RD();
|
|
AND_INST();
|
|
|
|
break;
|
|
case 0x3e: /* ROL Abs,X */
|
|
GET_ABS_X_RD_WR();
|
|
ROL_INST(0);
|
|
|
|
break;
|
|
case 0x3f: /* AND Long,X */
|
|
GET_LONG_X_RD();
|
|
AND_INST();
|
|
|
|
|
|
break;
|
|
case 0x40: /* RTI */
|
|
#ifdef ASM
|
|
bb,>= psr,23,rti_native_16
|
|
CYCLES_PLUS_1
|
|
/* emulation */
|
|
bl pull_24,link
|
|
ldi 0,zero
|
|
|
|
extru psr,27,2,scratch2
|
|
extru ret0,23,16,scratch3
|
|
copy scratch2,arg0
|
|
extru,<> ret0,30,1,0
|
|
ldi 1,zero
|
|
dep ret0,31,8,psr
|
|
|
|
extru ret0,24,1,neg
|
|
b update_system_state
|
|
dep scratch3,31,16,kpc
|
|
|
|
rti_native_16
|
|
bl pull_8,link
|
|
ldi 0,zero
|
|
|
|
copy ret0,scratch1
|
|
extru ret0,24,1,neg
|
|
dep ret0,31,8,scratch1
|
|
bl pull_24,link
|
|
stw scratch1,STACK_SAVE_INSTR_TMP1(sp)
|
|
|
|
extru psr,27,2,scratch2
|
|
ldw STACK_SAVE_INSTR_TMP1(sp),psr
|
|
extru ret0,31,24,kpc
|
|
extru,<> psr,30,1,0
|
|
ldi 1,zero
|
|
|
|
b update_system_state_and_change_kbank
|
|
copy scratch2,arg0
|
|
#else
|
|
CYCLES_PLUS_1
|
|
if(psr & 0x100) {
|
|
PULL24(tmp1);
|
|
kpc = (kpc & 0xff0000) + ((tmp1 >> 8) & 0xffff);
|
|
tmp2 = psr;
|
|
psr = (psr & ~0xff) + (tmp1 & 0xff);
|
|
neg = (psr >> 7) & 1;
|
|
zero = !(psr & 2);
|
|
UPDATE_PSR(psr, tmp2);
|
|
} else {
|
|
PULL8(tmp1);
|
|
tmp2 = psr;
|
|
psr = (tmp1 & 0xff);
|
|
neg = (psr >> 7) & 1;
|
|
zero = !(psr & 2);
|
|
PULL24(kpc);
|
|
UPDATE_PSR(psr, tmp2);
|
|
}
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x41: /* EOR (Dloc,X) */
|
|
/* called with arg = val to EOR in */
|
|
GET_DLOC_X_IND_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x42: /* WDM */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
CYCLES_PLUS_5
|
|
CYCLES_PLUS_2
|
|
INC_KPC_2
|
|
b dispatch_done
|
|
depi RET_WDM,3,4,ret0
|
|
#else
|
|
GET_1BYTE_ARG;
|
|
INC_KPC_2;
|
|
CYCLES_PLUS_5;
|
|
CYCLES_PLUS_2;
|
|
FINISH(RET_WDM, arg & 0xff);
|
|
#endif
|
|
|
|
break;
|
|
case 0x43: /* EOR Disp8,S */
|
|
/* called with arg = val to EOR in */
|
|
GET_DISP8_S_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x44: /* MVP */
|
|
#ifdef ASM
|
|
ldb 2(scratch1),scratch2 /* src bank */
|
|
bb,< psr,23,inst44_notnat_16
|
|
ldb 1(scratch1),dbank /* dest bank */
|
|
bb,< psr,27,inst44_notnat_16
|
|
stw scratch2,STACK_SRC_BANK(sp)
|
|
|
|
inst44_loop_16
|
|
CYCLES_PLUS_1
|
|
ldw STACK_SRC_BANK(sp),scratch2
|
|
copy xreg,arg0
|
|
|
|
bl get_mem_long_8,link
|
|
dep scratch2,15,8,arg0
|
|
/* got byte */
|
|
copy ret0,arg1
|
|
copy yreg,arg0
|
|
bl set_mem_long_8,link
|
|
dep dbank,15,8,arg0
|
|
/* wrote byte, dec acc */
|
|
CYCLES_PLUS_2
|
|
fldds 0(fcycles_stop_ptr),fcycles_stop
|
|
addi -1,xreg,xreg
|
|
zdepi -1,31,16,scratch2
|
|
addi -1,yreg,yreg
|
|
addi -1,acc,acc
|
|
fcmp,<,dbl fcycles,fcycles_stop
|
|
and xreg,scratch2,xreg
|
|
extrs acc,31,16,scratch1
|
|
and yreg,scratch2,yreg
|
|
|
|
comib,= -1,scratch1,inst44_done_16
|
|
and acc,scratch2,acc
|
|
|
|
ftest
|
|
b inst44_out_of_time_16
|
|
|
|
CYCLES_PLUS_2
|
|
b inst44_loop_16
|
|
nop
|
|
|
|
/* get here if done */
|
|
inst44_done_16
|
|
INC_KPC_3
|
|
b dispatch
|
|
nop
|
|
|
|
inst44_notnat_16
|
|
copy dbank,ret0
|
|
dep scratch2,23,8,ret0
|
|
CYCLES_PLUS_3
|
|
depi RET_MVP,3,4,ret0
|
|
b dispatch_done
|
|
CYCLES_PLUS_2
|
|
|
|
inst44_out_of_time_16
|
|
/* cycle have gone positive, just get out, do not update kpc */
|
|
b,n dispatch
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
/* arg & 0xff = dest bank, arg & 0xff00 = src bank */
|
|
|
|
if(psr & 0x110) {
|
|
// OG MVP should work even with no native mode - keep the warning though
|
|
printf("MVP but not native m or x!\n");
|
|
/*
|
|
halt_printf("MVP but not native m or x!\n");
|
|
break;
|
|
*/
|
|
}
|
|
CYCLES_MINUS_2
|
|
dbank = arg & 0xff;
|
|
tmp1 = (arg >> 8) & 0xff;
|
|
while(1) {
|
|
CYCLES_PLUS_3;
|
|
GET_MEMORY8((tmp1 << 16) + xreg, arg);
|
|
SET_MEMORY8((dbank << 16) + yreg, arg);
|
|
CYCLES_PLUS_2;
|
|
xreg = (xreg - 1) & 0xffff;
|
|
yreg = (yreg - 1) & 0xffff;
|
|
acc = (acc - 1) & 0xffff;
|
|
if(acc == 0xffff) {
|
|
INC_KPC_3;
|
|
break;
|
|
}
|
|
if(fcycles >= g_fcycles_stop) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x45: /* EOR Dloc */
|
|
/* called with arg = val to EOR in */
|
|
GET_DLOC_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x46: /* LSR Dloc */
|
|
GET_DLOC_RD();
|
|
/* save1 is now apple addr */
|
|
/* ret0 is data */
|
|
LSR_INST(1);
|
|
|
|
break;
|
|
case 0x47: /* EOR [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x48: /* PHA */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
INC_KPC_1
|
|
ldil l%dispatch,link
|
|
extru acc,31,8,arg0
|
|
b push_8
|
|
ldo r%dispatch(link),link
|
|
# else
|
|
INC_KPC_1
|
|
ldil l%dispatch,link
|
|
extru acc,31,16,arg0
|
|
b push_16
|
|
ldo r%dispatch(link),link
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
# ifdef ACC8
|
|
PUSH8(acc);
|
|
# else
|
|
PUSH16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x49: /* EOR #imm */
|
|
GET_IMM_MEM();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x4a: /* LSR a */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
extru acc,31,1,scratch2
|
|
INC_KPC_1
|
|
extru acc,30,7,zero
|
|
ldi 0,neg
|
|
dep scratch2,31,1,psr /* set carry */
|
|
b dispatch
|
|
dep zero,31,8,acc
|
|
# else
|
|
extru acc,31,1,scratch2
|
|
INC_KPC_1
|
|
extru acc,30,15,zero
|
|
ldi 0,neg
|
|
dep scratch2,31,1,psr /* set carry */
|
|
b dispatch
|
|
dep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
# ifdef ACC8
|
|
tmp1 = ((acc & 0xff) >> 1);
|
|
SET_CARRY8(acc << 8);
|
|
acc = (acc & 0xff00) + (tmp1 & 0xff);
|
|
SET_NEG_ZERO8(tmp1 & 0xff);
|
|
# else
|
|
tmp1 = (acc >> 1);
|
|
SET_CARRY8((acc << 8));
|
|
acc = (tmp1 & 0xffff);
|
|
SET_NEG_ZERO16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x4b: /* PHK */
|
|
#ifdef ASM
|
|
ldil l%dispatch,link
|
|
extru kpc,15,8,arg0
|
|
INC_KPC_1
|
|
b push_8
|
|
ldo r%dispatch(link),link
|
|
#else
|
|
PUSH8(kpc >> 16);
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0x4c: /* JMP abs */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),scratch2
|
|
CYCLES_PLUS_1
|
|
ldb 2(scratch1),scratch1
|
|
dep scratch2,31,8,kpc
|
|
b dispatch
|
|
dep scratch1,23,8,kpc
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1;
|
|
kpc = (kpc & 0xff0000) + arg;
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x4d: /* EOR abs */
|
|
GET_ABS_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x4e: /* LSR abs */
|
|
GET_ABS_RD();
|
|
LSR_INST(0);
|
|
|
|
break;
|
|
case 0x4f: /* EOR long */
|
|
GET_LONG_RD();
|
|
EOR_INST();
|
|
|
|
|
|
break;
|
|
case 0x50: /* BVC disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
bb,< psr,25,inst50_2_16
|
|
COND_BR2
|
|
|
|
inst50_2_16
|
|
COND_BR_UNTAKEN
|
|
|
|
#else
|
|
BRANCH_DISP8((psr & 0x40) == 0);
|
|
#endif
|
|
|
|
break;
|
|
case 0x51: /* EOR (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x52: /* EOR (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x53: /* EOR (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x54: /* MVN */
|
|
#ifdef ASM
|
|
ldb 2(scratch1),scratch2 /* src bank */
|
|
bb,< psr,23,inst54_notnat_16
|
|
ldb 1(scratch1),dbank /* dest bank */
|
|
bb,< psr,27,inst54_notnat_16
|
|
stw scratch2,STACK_SRC_BANK(sp)
|
|
|
|
/* even in 8bit acc mode, use 16-bit accumulator! */
|
|
|
|
inst54_loop_16
|
|
CYCLES_PLUS_1
|
|
ldw STACK_SRC_BANK(sp),scratch2
|
|
copy xreg,arg0
|
|
|
|
bl get_mem_long_8,link
|
|
dep scratch2,15,8,arg0
|
|
/* got byte */
|
|
copy ret0,arg1
|
|
copy yreg,arg0
|
|
bl set_mem_long_8,link
|
|
dep dbank,15,8,arg0
|
|
/* wrote byte, dec acc */
|
|
CYCLES_PLUS_2
|
|
fldds 0(fcycles_stop_ptr),fcycles_stop
|
|
addi 1,xreg,xreg
|
|
zdepi -1,31,16,scratch2
|
|
addi 1,yreg,yreg
|
|
addi -1,acc,acc
|
|
fcmp,<,dbl fcycles,fcycles_stop
|
|
and xreg,scratch2,xreg
|
|
extrs acc,31,16,scratch1
|
|
and yreg,scratch2,yreg
|
|
|
|
comib,= -1,scratch1,inst54_done_16
|
|
and acc,scratch2,acc
|
|
ftest
|
|
b,n inst54_out_of_time_16
|
|
|
|
CYCLES_PLUS_2
|
|
b inst54_loop_16
|
|
nop
|
|
|
|
/* get here if done */
|
|
inst54_done_16
|
|
INC_KPC_3
|
|
b dispatch
|
|
nop
|
|
|
|
inst54_out_of_time_16
|
|
/* cycle have gone positive, just get out, don't update kpc */
|
|
b,n dispatch
|
|
|
|
inst54_notnat_16
|
|
copy dbank,ret0
|
|
dep scratch2,23,8,ret0
|
|
CYCLES_PLUS_3
|
|
depi RET_MVN,3,4,ret0
|
|
b dispatch_done
|
|
CYCLES_PLUS_3
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
/* arg & 0xff = dest bank, arg & 0xff00 = src bank */
|
|
if(psr & 0x110) {
|
|
// OG MVP should work even with no native mode - keep the warning though
|
|
printf("MVP but not native m or x!\n");
|
|
/*
|
|
halt_printf("MVN but not native m or x!\n");
|
|
break;
|
|
*/
|
|
}
|
|
CYCLES_MINUS_2;
|
|
dbank = arg & 0xff;
|
|
tmp1 = (arg >> 8) & 0xff;
|
|
while(1) {
|
|
CYCLES_PLUS_3;
|
|
GET_MEMORY8((tmp1 << 16) + xreg, arg);
|
|
SET_MEMORY8((dbank << 16) + yreg, arg);
|
|
CYCLES_PLUS_2;
|
|
xreg = (xreg + 1) & 0xffff;
|
|
yreg = (yreg + 1) & 0xffff;
|
|
acc = (acc - 1) & 0xffff;
|
|
if(acc == 0xffff) {
|
|
INC_KPC_3;
|
|
break;
|
|
}
|
|
if(fcycles >= g_fcycles_stop) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0x55: /* EOR Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x56: /* LSR Dloc,X */
|
|
GET_DLOC_X_RD();
|
|
LSR_INST(1);
|
|
|
|
break;
|
|
case 0x57: /* EOR [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x58: /* CLI */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b check_irqs_pending /* check for ints pending! */
|
|
depi 0,29,1,psr /* clear int disable */
|
|
#else
|
|
psr = psr & (~4);
|
|
INC_KPC_1;
|
|
if(((psr & 0x4) == 0) && g_irq_pending) {
|
|
FINISH(RET_IRQ, 0);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0x59: /* EOR abs,y */
|
|
GET_ABS_Y_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x5a: /* PHY */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
ldil l%dispatch,link
|
|
bb,>= psr,27,phy_16_16
|
|
ldo r%dispatch(link),link
|
|
|
|
b push_8
|
|
copy yreg,arg0
|
|
|
|
phy_16_16
|
|
b push_16
|
|
copy yreg,arg0
|
|
#else
|
|
INC_KPC_1;
|
|
if(psr & 0x10) {
|
|
PUSH8(yreg);
|
|
} else {
|
|
PUSH16(yreg);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0x5b: /* TCD */
|
|
#ifdef ASM
|
|
extru acc,31,16,direct
|
|
INC_KPC_1
|
|
copy acc,zero
|
|
b dispatch
|
|
extru acc,16,1,neg
|
|
#else
|
|
INC_KPC_1;
|
|
direct = acc;
|
|
SET_NEG_ZERO16(acc);
|
|
#endif
|
|
|
|
break;
|
|
case 0x5c: /* JMP Long */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),kpc
|
|
ldb 2(scratch1),scratch2
|
|
CYCLES_PLUS_1
|
|
ldb 3(scratch1),arg0 /* new bank */
|
|
dep scratch2,23,8,kpc
|
|
b dispatch
|
|
dep arg0,15,8,kpc
|
|
#else
|
|
GET_3BYTE_ARG;
|
|
CYCLES_PLUS_1;
|
|
kpc = arg;
|
|
#endif
|
|
|
|
break;
|
|
case 0x5d: /* EOR Abs,X */
|
|
GET_ABS_X_RD();
|
|
EOR_INST();
|
|
|
|
break;
|
|
case 0x5e: /* LSR Abs,X */
|
|
GET_ABS_X_RD_WR();
|
|
LSR_INST(0);
|
|
|
|
break;
|
|
case 0x5f: /* EOR Long,X */
|
|
GET_LONG_X_RD();
|
|
EOR_INST();
|
|
|
|
|
|
break;
|
|
case 0x60: /* RTS */
|
|
#ifdef ASM
|
|
bl pull_16,link
|
|
CYCLES_PLUS_2
|
|
/* ret0 is new kpc-1 */
|
|
addi 1,ret0,ret0
|
|
b dispatch
|
|
dep ret0,31,16,kpc
|
|
#else
|
|
CYCLES_PLUS_2
|
|
PULL16(tmp1);
|
|
kpc = (kpc & 0xff0000) + ((tmp1 + 1) & 0xffff);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x61: /* ADC (Dloc,X) */
|
|
/* called with arg = val to ADC in */
|
|
GET_DLOC_X_IND_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x62: /* PER */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
INC_KPC_3
|
|
ldb 2(scratch1),scratch1
|
|
CYCLES_PLUS_2
|
|
ldil l%dispatch,link
|
|
dep scratch1,23,8,ret0
|
|
ldo r%dispatch(link),link
|
|
add kpc,ret0,arg0
|
|
b push_16_unsafe
|
|
extru arg0,31,16,arg0
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_2;
|
|
INC_KPC_3;
|
|
PUSH16_UNSAFE(kpc + arg);
|
|
#endif
|
|
|
|
break;
|
|
case 0x63: /* ADC Disp8,S */
|
|
/* called with arg = val to ADC in */
|
|
GET_DISP8_S_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x64: /* STZ Dloc */
|
|
GET_DLOC_ADDR();
|
|
STZ_INST(1);
|
|
|
|
break;
|
|
case 0x65: /* ADC Dloc */
|
|
/* called with arg = val to ADC in */
|
|
GET_DLOC_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x66: /* ROR Dloc */
|
|
GET_DLOC_RD();
|
|
/* save1 is now apple addr */
|
|
/* ret0 is data */
|
|
ROR_INST(1);
|
|
|
|
break;
|
|
case 0x67: /* ADC [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x68: /* PLA */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
INC_KPC_1
|
|
bl pull_8,link
|
|
CYCLES_PLUS_1
|
|
extru ret0,31,8,zero
|
|
extru ret0,24,1,neg
|
|
b dispatch
|
|
dep ret0,31,8,acc
|
|
# else
|
|
INC_KPC_1
|
|
bl pull_16,link
|
|
CYCLES_PLUS_1
|
|
|
|
extru ret0,31,16,zero
|
|
extru ret0,16,1,neg
|
|
b dispatch
|
|
extru ret0,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
CYCLES_PLUS_1;
|
|
# ifdef ACC8
|
|
PULL8(tmp1);
|
|
acc = (acc & 0xff00) + tmp1;
|
|
SET_NEG_ZERO8(tmp1);
|
|
# else
|
|
PULL16(tmp1);
|
|
acc = tmp1;
|
|
SET_NEG_ZERO16(tmp1);
|
|
# endif
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x69: /* ADC #imm */
|
|
GET_IMM_MEM();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x6a: /* ROR a */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
extru psr,31,1,neg
|
|
INC_KPC_1
|
|
extru acc,30,7,zero
|
|
dep neg,24,1,zero
|
|
dep acc,31,1,psr /* set carry */
|
|
b dispatch
|
|
dep zero,31,8,acc
|
|
# else
|
|
extru psr,31,1,neg
|
|
INC_KPC_1
|
|
extru acc,30,15,zero
|
|
dep neg,16,1,zero
|
|
dep acc,31,1,psr /* set carry */
|
|
b dispatch
|
|
dep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
# ifdef ACC8
|
|
tmp1 = ((acc & 0xff) >> 1) + ((psr & 1) << 7);
|
|
SET_CARRY8((acc << 8));
|
|
acc = (acc & 0xff00) + (tmp1 & 0xff);
|
|
SET_NEG_ZERO8(tmp1 & 0xff);
|
|
# else
|
|
tmp1 = (acc >> 1) + ((psr & 1) << 15);
|
|
SET_CARRY16((acc << 16));
|
|
acc = (tmp1 & 0xffff);
|
|
SET_NEG_ZERO16(acc);
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x6b: /* RTL */
|
|
#ifdef ASM
|
|
bl pull_24,link
|
|
CYCLES_PLUS_1
|
|
/* ret0 is new kpc-1 */
|
|
copy ret0,kpc
|
|
addi 1,ret0,scratch1
|
|
b dispatch
|
|
dep scratch1,31,16,kpc
|
|
|
|
#else
|
|
CYCLES_PLUS_1;
|
|
PULL24(tmp1);
|
|
kpc = (tmp1 & 0xff0000) + ((tmp1 + 1) & 0xffff);
|
|
#endif
|
|
|
|
break;
|
|
case 0x6c: /* JMP (abs) */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
CYCLES_PLUS_1
|
|
ldb 2(scratch1),scratch1
|
|
bl get_mem_long_16,link
|
|
dep scratch1,23,8,arg0
|
|
/* ret0 is addr to jump to */
|
|
b dispatch
|
|
dep ret0,31,16,kpc
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1;
|
|
GET_MEMORY16(arg, tmp1, 1);
|
|
kpc = (kpc & 0xff0000) + tmp1;
|
|
#endif
|
|
|
|
break;
|
|
case 0x6d: /* ADC abs */
|
|
GET_ABS_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x6e: /* ROR abs */
|
|
GET_ABS_RD();
|
|
ROR_INST(0);
|
|
|
|
break;
|
|
case 0x6f: /* ADC long */
|
|
GET_LONG_RD();
|
|
ADC_INST();
|
|
|
|
|
|
break;
|
|
case 0x70: /* BVS disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
bb,>= psr,25,inst70_2_16
|
|
COND_BR2
|
|
|
|
inst70_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8((psr & 0x40));
|
|
#endif
|
|
|
|
break;
|
|
case 0x71: /* ADC (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x72: /* ADC (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x73: /* ADC (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x74: /* STZ Dloc,x */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
GET_DLOC_X_WR();
|
|
STZ_INST(1);
|
|
#else
|
|
GET_1BYTE_ARG;
|
|
GET_DLOC_X_WR();
|
|
STZ_INST(1);
|
|
#endif
|
|
|
|
break;
|
|
case 0x75: /* ADC Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x76: /* ROR Dloc,X */
|
|
GET_DLOC_X_RD();
|
|
ROR_INST(1);
|
|
|
|
break;
|
|
case 0x77: /* ADC [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x78: /* SEI */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
depi 1,29,1,psr /* set int disable */
|
|
#else
|
|
psr = psr | 4;
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0x79: /* ADC abs,y */
|
|
GET_ABS_Y_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x7a: /* PLY */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,>= psr,27,inst7a_16bit_16
|
|
nop
|
|
|
|
bl pull_8,link
|
|
CYCLES_PLUS_1
|
|
|
|
extru ret0,31,8,zero
|
|
extru ret0,24,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
|
|
inst7a_16bit_16
|
|
bl pull_16,link
|
|
CYCLES_PLUS_1
|
|
|
|
extru ret0,31,16,zero
|
|
extru ret0,16,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
|
|
#else
|
|
INC_KPC_1;
|
|
CYCLES_PLUS_1
|
|
if(psr & 0x10) {
|
|
PULL8(yreg);
|
|
SET_NEG_ZERO8(yreg);
|
|
} else {
|
|
PULL16(yreg);
|
|
SET_NEG_ZERO16(yreg);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0x7b: /* TDC */
|
|
#ifdef ASM
|
|
extru direct,31,16,zero
|
|
copy direct,acc
|
|
INC_KPC_1
|
|
b dispatch
|
|
extru direct,16,1,neg
|
|
#else
|
|
INC_KPC_1;
|
|
acc = direct;
|
|
SET_NEG_ZERO16(direct);
|
|
#endif
|
|
|
|
break;
|
|
case 0x7c: /* JMP (Abs,x) */
|
|
/* always access kbank, xreg cannot wrap into next bank */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
copy kpc,scratch2
|
|
ldb 2(scratch1),scratch1
|
|
dep xreg,31,16,scratch2
|
|
CYCLES_PLUS_2
|
|
dep scratch1,23,8,ret0
|
|
add ret0,scratch2,arg0
|
|
bl get_mem_long_16,link
|
|
extru arg0,31,24,arg0
|
|
b dispatch
|
|
dep ret0,31,16,kpc
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
arg = (kpc & 0xff0000) + ((xreg + arg) & 0xffff);
|
|
CYCLES_PLUS_2;
|
|
GET_MEMORY16(arg, tmp1, 1);
|
|
kpc = (kpc & 0xff0000) + tmp1;
|
|
#endif
|
|
|
|
break;
|
|
case 0x7d: /* ADC Abs,X */
|
|
GET_ABS_X_RD();
|
|
ADC_INST();
|
|
|
|
break;
|
|
case 0x7e: /* ROR Abs,X */
|
|
GET_ABS_X_RD_WR();
|
|
ROR_INST(0);
|
|
|
|
break;
|
|
case 0x7f: /* ADC Long,X */
|
|
GET_LONG_X_RD();
|
|
ADC_INST();
|
|
|
|
|
|
break;
|
|
case 0x80: /* BRA */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
COND_BR2
|
|
#else
|
|
BRANCH_DISP8(1);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x81: /* STA (Dloc,X) */
|
|
GET_DLOC_X_IND_ADDR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x82: /* BRL disp16 */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
CYCLES_PLUS_1
|
|
ldb 2(scratch1),scratch1
|
|
addi 3,kpc,scratch2
|
|
dep scratch1,23,8,ret0
|
|
add ret0,scratch2,scratch2
|
|
b dispatch
|
|
dep scratch2,31,16,kpc
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1;
|
|
kpc = (kpc & 0xff0000) + ((kpc + 3 + arg) & 0xffff);
|
|
#endif
|
|
|
|
break;
|
|
case 0x83: /* STA Disp8,S */
|
|
GET_DISP8_S_ADDR();
|
|
STA_INST(1);
|
|
|
|
break;
|
|
case 0x84: /* STY Dloc */
|
|
GET_DLOC_ADDR();
|
|
STY_INST(1);
|
|
|
|
|
|
break;
|
|
case 0x85: /* STA Dloc */
|
|
GET_DLOC_ADDR();
|
|
STA_INST(1);
|
|
|
|
break;
|
|
case 0x86: /* STX Dloc */
|
|
GET_DLOC_ADDR();
|
|
STX_INST(1);
|
|
|
|
|
|
break;
|
|
case 0x87: /* STA [Dloc] */
|
|
GET_DLOC_L_IND_ADDR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x88: /* DEY */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,< psr,27,inst88_8bit_16
|
|
addi -1,yreg,yreg
|
|
/* 16 bit */
|
|
extru yreg,31,16,zero
|
|
extru yreg,16,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
|
|
inst88_8bit_16
|
|
extru yreg,31,8,zero
|
|
extru yreg,24,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(yreg - 1, yreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0x89: /* BIT #imm */
|
|
#ifdef ASM
|
|
GET_IMM_MEM();
|
|
# ifdef ACC8
|
|
/* Immediate BIT does not set condition flags */
|
|
and acc,ret0,zero
|
|
b dispatch
|
|
extru zero,31,8,zero
|
|
# else
|
|
and acc,ret0,zero
|
|
b dispatch
|
|
extru zero,31,16,zero
|
|
# endif
|
|
#else
|
|
GET_IMM_MEM();
|
|
# ifdef ACC8
|
|
zero = (acc & arg) & 0xff;
|
|
# else
|
|
zero = (acc & arg) & 0xffff;
|
|
# endif
|
|
#endif
|
|
|
|
break;
|
|
case 0x8a: /* TXA */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
extru xreg,31,8,zero
|
|
INC_KPC_1
|
|
extru xreg,24,1,neg
|
|
b dispatch
|
|
dep zero,31,8,acc
|
|
# else
|
|
extru xreg,31,16,zero
|
|
INC_KPC_1
|
|
extru xreg,16,1,neg
|
|
b dispatch
|
|
zdep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
arg = xreg;
|
|
LDA_INST();
|
|
#endif
|
|
|
|
break;
|
|
case 0x8b: /* PHB */
|
|
#ifdef ASM
|
|
ldil l%dispatch,link
|
|
extru dbank,31,8,arg0
|
|
INC_KPC_1
|
|
b push_8
|
|
ldo r%dispatch(link),link
|
|
#else
|
|
INC_KPC_1;
|
|
PUSH8(dbank);
|
|
#endif
|
|
|
|
break;
|
|
case 0x8c: /* STY abs */
|
|
GET_ABS_ADDR();
|
|
STY_INST(0);
|
|
|
|
break;
|
|
case 0x8d: /* STA abs */
|
|
GET_ABS_ADDR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x8e: /* STX abs */
|
|
GET_ABS_ADDR();
|
|
STX_INST(0);
|
|
|
|
|
|
break;
|
|
case 0x8f: /* STA long */
|
|
GET_LONG_ADDR();
|
|
STA_INST(0);
|
|
|
|
|
|
break;
|
|
case 0x90: /* BCC disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
bb,< psr,31,inst90_2_16
|
|
COND_BR2
|
|
|
|
inst90_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8((psr & 0x01) == 0);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x91: /* STA (Dloc),y */
|
|
GET_DLOC_IND_Y_ADDR_FOR_WR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x92: /* STA (Dloc) */
|
|
GET_DLOC_IND_ADDR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x93: /* STA (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_ADDR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x94: /* STY Dloc,x */
|
|
GET_DLOC_X_ADDR();
|
|
STY_INST(1);
|
|
|
|
break;
|
|
case 0x95: /* STA Dloc,x */
|
|
GET_DLOC_X_ADDR();
|
|
STA_INST(1);
|
|
|
|
break;
|
|
case 0x96: /* STX Dloc,Y */
|
|
GET_DLOC_Y_ADDR();
|
|
STX_INST(1);
|
|
|
|
break;
|
|
case 0x97: /* STA [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_ADDR();
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x98: /* TYA */
|
|
#ifdef ASM
|
|
# ifdef ACC8
|
|
extru yreg,31,8,zero
|
|
INC_KPC_1
|
|
extru yreg,24,1,neg
|
|
b dispatch
|
|
dep zero,31,8,acc
|
|
# else
|
|
extru yreg,31,16,zero
|
|
INC_KPC_1
|
|
extru yreg,16,1,neg
|
|
b dispatch
|
|
zdep zero,31,16,acc
|
|
# endif
|
|
#else
|
|
INC_KPC_1;
|
|
arg = yreg;
|
|
LDA_INST();
|
|
#endif
|
|
|
|
break;
|
|
case 0x99: /* STA abs,y */
|
|
GET_ABS_INDEX_ADDR_FOR_WR(yreg)
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x9a: /* TXS */
|
|
#ifdef ASM
|
|
copy xreg,stack
|
|
extru,= psr,23,1,0
|
|
depi 1,23,24,stack
|
|
INC_KPC_1
|
|
b dispatch
|
|
nop
|
|
#else
|
|
stack = xreg;
|
|
if(psr & 0x100) {
|
|
stack = 0x100 | (stack & 0xff);
|
|
}
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x9b: /* TXY */
|
|
#ifdef ASM
|
|
extru xreg,24,1,neg
|
|
INC_KPC_1
|
|
extru,<> psr,27,1,0 ;skip next if 8bit
|
|
extru xreg,16,1,neg
|
|
copy xreg,yreg
|
|
b dispatch
|
|
copy xreg,zero
|
|
#else
|
|
SET_INDEX_REG(xreg, yreg);
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0x9c: /* STZ Abs */
|
|
GET_ABS_ADDR();
|
|
STZ_INST(0);
|
|
|
|
break;
|
|
case 0x9d: /* STA Abs,X */
|
|
GET_ABS_INDEX_ADDR_FOR_WR(xreg);
|
|
STA_INST(0);
|
|
|
|
break;
|
|
case 0x9e: /* STZ Abs,X */
|
|
GET_ABS_INDEX_ADDR_FOR_WR(xreg);
|
|
STZ_INST(0);
|
|
|
|
break;
|
|
case 0x9f: /* STA Long,X */
|
|
GET_LONG_X_ADDR_FOR_WR();
|
|
STA_INST(0);
|
|
|
|
|
|
break;
|
|
case 0xa0: /* LDY #imm */
|
|
#ifdef ASM
|
|
INC_KPC_2
|
|
bb,>= psr,27,insta0_16bit_16
|
|
ldb 1(scratch1),zero
|
|
|
|
extru zero,24,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
insta0_16bit_16
|
|
ldb 2(scratch1),scratch1
|
|
INC_KPC_1
|
|
CYCLES_PLUS_1
|
|
extru scratch1,24,1,neg
|
|
dep scratch1,23,8,zero
|
|
b dispatch
|
|
copy zero,yreg
|
|
#else
|
|
INC_KPC_2;
|
|
if((psr & 0x10) == 0) {
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1
|
|
INC_KPC_1;
|
|
} else {
|
|
GET_1BYTE_ARG;
|
|
}
|
|
SET_INDEX_REG(arg, yreg);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xa1: /* LDA (Dloc,X) */
|
|
/* called with arg = val to LDA in */
|
|
GET_DLOC_X_IND_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xa2: /* LDX #imm */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),zero
|
|
bb,>= psr,27,insta2_16bit_16
|
|
INC_KPC_2;
|
|
|
|
extru zero,24,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
insta2_16bit_16
|
|
ldb 2(scratch1),scratch1
|
|
INC_KPC_1
|
|
CYCLES_PLUS_1
|
|
extru scratch1,24,1,neg
|
|
dep scratch1,23,8,zero
|
|
b dispatch
|
|
copy zero,xreg
|
|
#else
|
|
INC_KPC_2;
|
|
if((psr & 0x10) == 0) {
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1
|
|
INC_KPC_1;
|
|
} else {
|
|
GET_1BYTE_ARG;
|
|
}
|
|
SET_INDEX_REG(arg, xreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xa3: /* LDA Disp8,S */
|
|
/* called with arg = val to LDA in */
|
|
GET_DISP8_S_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xa4: /* LDY Dloc */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
GET_DLOC_WR()
|
|
b get_yreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDY_DLOC();
|
|
#endif
|
|
|
|
break;
|
|
case 0xa5: /* LDA Dloc */
|
|
/* called with arg = val to LDA in */
|
|
GET_DLOC_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xa6: /* LDX Dloc */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
GET_DLOC_WR()
|
|
b get_xreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDX_DLOC();
|
|
#endif
|
|
|
|
break;
|
|
case 0xa7: /* LDA [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xa8: /* TAY */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,>= psr,27,insta8_16bit_16
|
|
extru acc,31,8,zero
|
|
|
|
extru acc,24,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
|
|
insta8_16bit_16
|
|
extru acc,31,16,zero
|
|
extru acc,16,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(acc, yreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xa9: /* LDA #imm */
|
|
GET_IMM_MEM();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xaa: /* TAX */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,>= psr,27,instaa_16bit_16
|
|
extru acc,31,8,zero
|
|
|
|
extru acc,24,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
|
|
instaa_16bit_16
|
|
extru acc,31,16,zero
|
|
extru acc,16,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(acc, xreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xab: /* PLB */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bl pull_8,link
|
|
CYCLES_PLUS_1
|
|
|
|
extru ret0,31,8,zero
|
|
extru ret0,24,1,neg
|
|
b dispatch
|
|
copy zero,dbank
|
|
#else
|
|
INC_KPC_1;
|
|
CYCLES_PLUS_1
|
|
PULL8(dbank);
|
|
SET_NEG_ZERO8(dbank);
|
|
#endif
|
|
|
|
break;
|
|
case 0xac: /* LDY abs */
|
|
#ifdef ASM
|
|
GET_ABS_ADDR()
|
|
b get_yreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDY_ABS();
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xad: /* LDA abs */
|
|
GET_ABS_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xae: /* LDX abs */
|
|
#ifdef ASM
|
|
GET_ABS_ADDR()
|
|
b get_xreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDX_ABS();
|
|
#endif
|
|
|
|
break;
|
|
case 0xaf: /* LDA long */
|
|
GET_LONG_RD();
|
|
LDA_INST();
|
|
|
|
|
|
break;
|
|
case 0xb0: /* BCS disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
bb,>= psr,31,instb0_2_16
|
|
COND_BR2
|
|
|
|
instb0_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8((psr & 0x01));
|
|
#endif
|
|
|
|
break;
|
|
case 0xb1: /* LDA (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xb2: /* LDA (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xb3: /* LDA (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xb4: /* LDY Dloc,x */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
GET_DLOC_X_WR();
|
|
b get_yreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDY_DLOC_X();
|
|
#endif
|
|
|
|
break;
|
|
case 0xb5: /* LDA Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xb6: /* LDX Dloc,y */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
GET_DLOC_Y_WR();
|
|
b get_xreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDX_DLOC_Y();
|
|
#endif
|
|
|
|
break;
|
|
case 0xb7: /* LDA [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xb8: /* CLV */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
depi 0,25,1,psr /* clear overflow */
|
|
#else
|
|
psr = psr & ~0x40;
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0xb9: /* LDA abs,y */
|
|
GET_ABS_Y_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xba: /* TSX */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,>= psr,27,instba_16bit_16
|
|
extru stack,31,8,zero
|
|
|
|
extru stack,24,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
instba_16bit_16
|
|
copy stack,zero
|
|
extru stack,16,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(stack, xreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xbb: /* TYX */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,>= psr,27,instbb_16bit_16
|
|
copy yreg,xreg
|
|
|
|
/* 8 bit */
|
|
extru yreg,24,1,neg
|
|
b dispatch
|
|
copy yreg,zero
|
|
instbb_16bit_16
|
|
extru yreg,16,1,neg
|
|
b dispatch
|
|
copy yreg,zero
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(yreg, xreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xbc: /* LDY Abs,X */
|
|
#ifdef ASM
|
|
GET_ABS_INDEX_ADDR_FOR_RD(xreg)
|
|
b get_yreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDY_ABS_X();
|
|
#endif
|
|
|
|
break;
|
|
case 0xbd: /* LDA Abs,X */
|
|
GET_ABS_X_RD();
|
|
LDA_INST();
|
|
|
|
break;
|
|
case 0xbe: /* LDX Abs,y */
|
|
#ifdef ASM
|
|
GET_ABS_INDEX_ADDR_FOR_RD(yreg)
|
|
b get_xreg_from_mem
|
|
nop
|
|
#else
|
|
C_LDX_ABS_Y();
|
|
#endif
|
|
|
|
break;
|
|
case 0xbf: /* LDA Long,X */
|
|
GET_LONG_X_RD();
|
|
LDA_INST();
|
|
|
|
|
|
break;
|
|
case 0xc0: /* CPY #imm */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
bb,>= psr,27,instc0_16bit_16
|
|
INC_KPC_2;
|
|
CMP_INDEX_REG_MEAT8(yreg)
|
|
instc0_16bit_16
|
|
ldb 2(scratch1),scratch1
|
|
CYCLES_PLUS_1
|
|
INC_KPC_1
|
|
dep scratch1,23,8,ret0
|
|
CMP_INDEX_REG_MEAT16(yreg)
|
|
#else
|
|
C_CPY_IMM();
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xc1: /* CMP (Dloc,X) */
|
|
/* called with arg = val to CMP in */
|
|
GET_DLOC_X_IND_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xc2: /* REP #imm */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
extru psr,27,2,arg0 /* save old x & m */
|
|
INC_KPC_2;
|
|
dep neg,24,1,psr
|
|
CYCLES_PLUS_1
|
|
depi 0,30,1,psr
|
|
comiclr,<> 0,zero,0
|
|
depi 1,30,1,psr
|
|
andcm psr,ret0,ret0
|
|
ldi 0,zero
|
|
extru,<> ret0,30,1,0
|
|
ldi 1,zero
|
|
dep ret0,31,8,psr
|
|
b update_system_state
|
|
extru ret0,24,1,neg
|
|
#else
|
|
GET_1BYTE_ARG;
|
|
tmp2 = psr;
|
|
CYCLES_PLUS_1;
|
|
INC_KPC_2;
|
|
psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1);
|
|
psr = psr & ~(arg & 0xff);
|
|
zero = !(psr & 2);
|
|
neg = (psr >> 7) & 1;
|
|
UPDATE_PSR(psr, tmp2);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xc3: /* CMP Disp8,S */
|
|
/* called with arg = val to CMP in */
|
|
GET_DISP8_S_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xc4: /* CPY Dloc */
|
|
#ifdef ASM
|
|
GET_DLOC_ADDR()
|
|
CMP_INDEX_REG_LOAD(instc4_16bit_16, yreg)
|
|
#else
|
|
C_CPY_DLOC();
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xc5: /* CMP Dloc */
|
|
GET_DLOC_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xc6: /* DEC Dloc */
|
|
GET_DLOC_RD();
|
|
DEC_INST(1);
|
|
|
|
break;
|
|
case 0xc7: /* CMP [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xc8: /* INY */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
addi 1,yreg,yreg
|
|
bb,>= psr,27,instc8_16bit_16
|
|
extru yreg,31,8,zero
|
|
|
|
extru yreg,24,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
|
|
instc8_16bit_16
|
|
extru yreg,31,16,zero
|
|
extru yreg,16,1,neg
|
|
b dispatch
|
|
copy zero,yreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(yreg + 1, yreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xc9: /* CMP #imm */
|
|
GET_IMM_MEM();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xca: /* DEX */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
addi -1,xreg,xreg
|
|
bb,>= psr,27,instca_16bit_16
|
|
extru xreg,31,8,zero
|
|
|
|
extru xreg,24,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
|
|
instca_16bit_16
|
|
extru xreg,31,16,zero
|
|
extru xreg,16,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(xreg - 1, xreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xcb: /* WAI */
|
|
#ifdef ASM
|
|
ldil l%g_wait_pending,scratch1
|
|
CYCLES_FINISH
|
|
ldi 1,scratch2
|
|
b dispatch
|
|
stw scratch2,r%g_wait_pending(scratch1)
|
|
#else
|
|
g_wait_pending = 1;
|
|
CYCLES_FINISH
|
|
#endif
|
|
|
|
break;
|
|
case 0xcc: /* CPY abs */
|
|
#ifdef ASM
|
|
GET_ABS_ADDR()
|
|
CMP_INDEX_REG_LOAD(instcc_16bit_16, yreg)
|
|
#else
|
|
C_CPY_ABS();
|
|
#endif
|
|
|
|
|
|
|
|
|
|
break;
|
|
case 0xcd: /* CMP abs */
|
|
GET_ABS_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xce: /* DEC abs */
|
|
GET_ABS_RD();
|
|
DEC_INST(0);
|
|
|
|
|
|
break;
|
|
case 0xcf: /* CMP long */
|
|
GET_LONG_RD();
|
|
CMP_INST();
|
|
|
|
|
|
break;
|
|
case 0xd0: /* BNE disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
comib,= 0,zero,instd0_2_16
|
|
COND_BR2
|
|
|
|
instd0_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8(zero != 0);
|
|
#endif
|
|
|
|
break;
|
|
case 0xd1: /* CMP (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xd2: /* CMP (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xd3: /* CMP (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xd4: /* PEI Dloc */
|
|
#ifdef ASM
|
|
GET_DLOC_ADDR()
|
|
bl get_mem_long_16,link
|
|
CYCLES_PLUS_1
|
|
|
|
/* push ret0 */
|
|
extru ret0,31,16,arg0
|
|
ldil l%dispatch,link
|
|
b push_16_unsafe
|
|
ldo r%dispatch(link),link
|
|
#else
|
|
GET_DLOC_ADDR()
|
|
GET_MEMORY16(arg, arg, 1);
|
|
CYCLES_PLUS_1;
|
|
PUSH16_UNSAFE(arg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xd5: /* CMP Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xd6: /* DEC Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
DEC_INST(1);
|
|
|
|
break;
|
|
case 0xd7: /* CMP [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xd8: /* CLD */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
depi 0,28,1,psr /* clear decimal */
|
|
#else
|
|
psr = psr & (~0x8);
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0xd9: /* CMP abs,y */
|
|
GET_ABS_Y_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xda: /* PHX */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
bb,>= psr,27,instda_16bit_16
|
|
ldil l%dispatch,link
|
|
|
|
extru xreg,31,8,arg0
|
|
b push_8
|
|
ldo r%dispatch(link),link
|
|
|
|
instda_16bit_16
|
|
extru xreg,31,16,arg0
|
|
b push_16
|
|
ldo r%dispatch(link),link
|
|
#else
|
|
INC_KPC_1;
|
|
if(psr & 0x10) {
|
|
PUSH8(xreg);
|
|
} else {
|
|
PUSH16(xreg);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0xdb: /* STP */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
CYCLES_PLUS_1
|
|
b dispatch_done
|
|
depi RET_STP,3,4,ret0
|
|
#else
|
|
CYCLES_FINISH
|
|
FINISH(RET_STP, 0);
|
|
#endif
|
|
|
|
break;
|
|
case 0xdc: /* JML (Abs) */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
ldb 2(scratch1),scratch1
|
|
CYCLES_PLUS_1
|
|
bl get_mem_long_24,link
|
|
dep scratch1,23,8,arg0
|
|
|
|
b dispatch
|
|
copy ret0,kpc
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1;
|
|
GET_MEMORY24(arg, kpc, 1);
|
|
#endif
|
|
|
|
break;
|
|
case 0xdd: /* CMP Abs,X */
|
|
GET_ABS_X_RD();
|
|
CMP_INST();
|
|
|
|
break;
|
|
case 0xde: /* DEC Abs,X */
|
|
GET_ABS_X_RD_WR();
|
|
DEC_INST(0);
|
|
|
|
break;
|
|
case 0xdf: /* CMP Long,X */
|
|
GET_LONG_X_RD();
|
|
CMP_INST();
|
|
|
|
|
|
break;
|
|
case 0xe0: /* CPX #imm */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
bb,>= psr,27,inste0_16bit_16
|
|
INC_KPC_2;
|
|
CMP_INDEX_REG_MEAT8(xreg)
|
|
inste0_16bit_16
|
|
ldb 2(scratch1),scratch1
|
|
CYCLES_PLUS_1
|
|
INC_KPC_1
|
|
dep scratch1,23,8,ret0
|
|
CMP_INDEX_REG_MEAT16(xreg)
|
|
#else
|
|
C_CPX_IMM();
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xe1: /* SBC (Dloc,X) */
|
|
/* called with arg = val to SBC in */
|
|
GET_DLOC_X_IND_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xe2: /* SEP #imm */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
extru psr,27,2,arg0 /* save old x & m */
|
|
INC_KPC_2;
|
|
dep neg,24,1,psr
|
|
CYCLES_PLUS_1
|
|
depi 0,30,1,psr
|
|
comiclr,<> 0,zero,0
|
|
depi 1,30,1,psr
|
|
or psr,ret0,ret0
|
|
ldi 0,zero
|
|
extru,<> ret0,30,1,0
|
|
ldi 1,zero
|
|
dep ret0,31,8,psr
|
|
b update_system_state
|
|
extru ret0,24,1,neg
|
|
#else
|
|
GET_1BYTE_ARG;
|
|
tmp2 = psr;
|
|
CYCLES_PLUS_1;
|
|
INC_KPC_2;
|
|
psr = (psr & ~0x82) | ((neg & 1) << 7) | ((!zero) << 1);
|
|
psr = psr | (arg & 0xff);
|
|
zero = !(psr & 2);
|
|
neg = (psr >> 7) & 1;
|
|
UPDATE_PSR(psr, tmp2);
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xe3: /* SBC Disp8,S */
|
|
/* called with arg = val to SBC in */
|
|
GET_DISP8_S_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xe4: /* CPX Dloc */
|
|
#ifdef ASM
|
|
GET_DLOC_ADDR()
|
|
CMP_INDEX_REG_LOAD(inste4_16bit_16, xreg)
|
|
#else
|
|
C_CPX_DLOC();
|
|
#endif
|
|
|
|
|
|
break;
|
|
case 0xe5: /* SBC Dloc */
|
|
/* called with arg = val to SBC in */
|
|
GET_DLOC_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xe6: /* INC Dloc */
|
|
GET_DLOC_RD();
|
|
INC_INST(1);
|
|
|
|
break;
|
|
case 0xe7: /* SBC [Dloc] */
|
|
GET_DLOC_L_IND_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xe8: /* INX */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
addi 1,xreg,xreg
|
|
bb,>= psr,27,inste8_16bit_16
|
|
extru xreg,31,8,zero
|
|
|
|
extru xreg,24,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
|
|
inste8_16bit_16
|
|
extru xreg,31,16,zero
|
|
extru xreg,16,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
#else
|
|
INC_KPC_1;
|
|
SET_INDEX_REG(xreg + 1, xreg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xe9: /* SBC #imm */
|
|
GET_IMM_MEM();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xea: /* NOP */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
nop
|
|
#else
|
|
INC_KPC_1;
|
|
#endif
|
|
|
|
break;
|
|
case 0xeb: /* XBA */
|
|
#ifdef ASM
|
|
extru acc,16,1,neg /* Z and N reflect status of low 8 */
|
|
CYCLES_PLUS_1 /* bits of final acc value! */
|
|
copy acc,scratch1 /* regardlessof ACC 8 or 16 bit */
|
|
extru acc,23,8,acc
|
|
INC_KPC_1
|
|
copy acc,zero
|
|
b dispatch
|
|
dep scratch1,23,8,acc
|
|
#else
|
|
tmp1 = acc & 0xff;
|
|
CYCLES_PLUS_1
|
|
acc = (tmp1 << 8) + (acc >> 8);
|
|
INC_KPC_1;
|
|
SET_NEG_ZERO8(acc & 0xff);
|
|
#endif
|
|
|
|
break;
|
|
case 0xec: /* CPX abs */
|
|
#ifdef ASM
|
|
GET_ABS_ADDR()
|
|
CMP_INDEX_REG_LOAD(instec_16bit_16, xreg)
|
|
#else
|
|
C_CPX_ABS();
|
|
#endif
|
|
|
|
|
|
|
|
|
|
break;
|
|
case 0xed: /* SBC abs */
|
|
GET_ABS_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xee: /* INC abs */
|
|
GET_ABS_RD();
|
|
INC_INST(0);
|
|
|
|
|
|
break;
|
|
case 0xef: /* SBC long */
|
|
GET_LONG_RD();
|
|
SBC_INST();
|
|
|
|
|
|
break;
|
|
case 0xf0: /* BEQ disp8 */
|
|
#ifdef ASM
|
|
COND_BR1
|
|
comib,<> 0,zero,instf0_2_16
|
|
COND_BR2
|
|
|
|
instf0_2_16
|
|
COND_BR_UNTAKEN
|
|
#else
|
|
BRANCH_DISP8(zero == 0);
|
|
#endif
|
|
|
|
break;
|
|
case 0xf1: /* SBC (Dloc),y */
|
|
GET_DLOC_IND_Y_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xf2: /* SBC (Dloc) */
|
|
GET_DLOC_IND_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xf3: /* SBC (Disp8,s),y */
|
|
GET_DISP8_S_IND_Y_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xf4: /* PEA Abs */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),arg0
|
|
ldil l%dispatch,link
|
|
ldb 2(scratch1),scratch1
|
|
INC_KPC_3
|
|
CYCLES_PLUS_1
|
|
ldo r%dispatch(link),link
|
|
b push_16_unsafe
|
|
dep scratch1,23,8,arg0
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
CYCLES_PLUS_1;
|
|
INC_KPC_3;
|
|
PUSH16_UNSAFE(arg);
|
|
#endif
|
|
|
|
break;
|
|
case 0xf5: /* SBC Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xf6: /* INC Dloc,x */
|
|
GET_DLOC_X_RD();
|
|
INC_INST(1);
|
|
|
|
break;
|
|
case 0xf7: /* SBC [Dloc],Y */
|
|
GET_DLOC_L_IND_Y_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xf8: /* SED */
|
|
#ifdef ASM
|
|
INC_KPC_1
|
|
b dispatch
|
|
depi 1,28,1,psr /* set decimal */
|
|
#else
|
|
INC_KPC_1;
|
|
psr |= 0x8;
|
|
#endif
|
|
|
|
break;
|
|
case 0xf9: /* SBC abs,y */
|
|
GET_ABS_Y_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xfa: /* PLX */
|
|
#ifdef ASM
|
|
bb,< psr,27,instfa_8bit_16
|
|
CYCLES_PLUS_1
|
|
|
|
INC_KPC_1
|
|
bl pull_16,link
|
|
nop
|
|
|
|
extru ret0,31,16,zero
|
|
extru ret0,16,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
|
|
instfa_8bit_16
|
|
INC_KPC_1
|
|
bl pull_8,link
|
|
nop
|
|
|
|
extru ret0,31,8,zero
|
|
extru ret0,24,1,neg
|
|
b dispatch
|
|
copy zero,xreg
|
|
#else
|
|
INC_KPC_1;
|
|
CYCLES_PLUS_1;
|
|
if(psr & 0x10) {
|
|
PULL8(xreg);
|
|
SET_NEG_ZERO8(xreg);
|
|
} else {
|
|
PULL16(xreg);
|
|
SET_NEG_ZERO16(xreg);
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case 0xfb: /* XCE */
|
|
#ifdef ASM
|
|
extru psr,27,2,arg0 /* save old x & m */
|
|
INC_KPC_1
|
|
extru psr,23,1,scratch1 /* e bit */
|
|
dep psr,23,1,psr /* copy carry to e bit */
|
|
b update_system_state
|
|
dep scratch1,31,1,psr /* copy e bit to carry */
|
|
#else
|
|
tmp2 = psr;
|
|
INC_KPC_1;
|
|
psr = (tmp2 & 0xfe) | ((tmp2 & 1) << 8) | ((tmp2 >> 8) & 1);
|
|
UPDATE_PSR(psr, tmp2);
|
|
#endif
|
|
|
|
break;
|
|
case 0xfc: /* JSR (Abs,X) */
|
|
#ifdef ASM
|
|
ldb 1(scratch1),ret0
|
|
extru kpc,15,8,scratch2
|
|
ldb 2(scratch1),scratch1
|
|
dep scratch2,15,16,ret0
|
|
INC_KPC_2;
|
|
dep scratch1,23,8,ret0
|
|
add xreg,ret0,arg0
|
|
bl get_mem_long_16,link
|
|
extru arg0,31,24,arg0
|
|
|
|
CYCLES_PLUS_2
|
|
extru kpc,31,16,arg0
|
|
ldil l%dispatch,link
|
|
dep ret0,31,16,kpc
|
|
b push_16_unsafe
|
|
ldo r%dispatch(link),link
|
|
#else
|
|
GET_2BYTE_ARG;
|
|
INC_KPC_2;
|
|
tmp1 = kpc;
|
|
arg = (kpc & 0xff0000) + ((arg + xreg) & 0xffff);
|
|
GET_MEMORY16(arg, tmp2, 1);
|
|
kpc = (kpc & 0xff0000) + tmp2;
|
|
CYCLES_PLUS_2
|
|
PUSH16_UNSAFE(tmp1);
|
|
#endif
|
|
|
|
break;
|
|
case 0xfd: /* SBC Abs,X */
|
|
GET_ABS_X_RD();
|
|
SBC_INST();
|
|
|
|
break;
|
|
case 0xfe: /* INC Abs,X */
|
|
GET_ABS_X_RD_WR();
|
|
INC_INST(0);
|
|
|
|
break;
|
|
case 0xff: /* SBC Long,X */
|
|
GET_LONG_X_RD();
|
|
SBC_INST();
|
|
|