/*
 *   opcodes.c
 *
 *   This file is part of Emu48
 *
 *   Copyright (C) 1995 Sebastien Carlier
 *   Copyright (C) 1999 Christoph Gießelink
 *
 */
#include "pch.h"
#include "Emu48.h"
#include "Opcodes.h"
#include "apple.h"
#include "io.h"								// I/O register definitions

#define w Chipset
#define GOYES3    {if(w.carry) o_goyes3(I);else{w.pc+=2;return;}}
#define GOYES5    {if(w.carry) o_goyes5(I);else{w.pc+=2;return;}}

#if !defined _BIGENDIAN
#define REG(t,r) (*((t*)&(r)))								// little endian machine
#else
#define REG(t,r) (*((t*)((BYTE*)&(r)+sizeof(r)-sizeof(t))))	// big endian machine
#endif

#pragma intrinsic(memset,memcpy)

#include "Ops.h"

// Fields start and length
UINT F_s[16] = {0/*P*/,0,2,0,15,3,0,0,0,0,0,0,0,0,0,0};
UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5};

VOID o00(LPBYTE I) // RTNSXM
{
	w.cycles+=9;
	w.pc = rstkpop();
	w.HST |= XM;
	return;
}

VOID o01(LPBYTE I) // RTN
{
	w.cycles+=9;
	w.pc = rstkpop();
	return;
}

VOID o02(LPBYTE I) // RTNSC
{
	w.cycles+=9;
	w.pc = rstkpop();
	w.carry = TRUE;
	return;
}

VOID o03(LPBYTE I) // RTNCC
{
	w.cycles+=9;
	w.pc = rstkpop();
	w.carry = FALSE;
	return;
}

VOID o04(LPBYTE I) // SETHEX
{
	w.cycles+=3;
	w.pc+=2;
	w.mode_dec = FALSE;
	return;
}

VOID o05(LPBYTE I) // SETDEC
{
	w.cycles+=3;
	w.pc+=2;
	w.mode_dec = TRUE;
	return;
}

VOID o06(LPBYTE I) // RSTK=C
{
	w.cycles+=8;
	w.pc+=2;
	rstkpush(Npack(w.C,5));
	return;
}

VOID o07(LPBYTE I) // C=RSTK
{
	w.cycles+=8;
	w.pc+=2;
	Nunpack(w.C,rstkpop(),5);
	return;
}

VOID o08(LPBYTE I) // CLRST
{
	w.cycles+=5;
	w.pc+=2;
	memset(w.ST, 0, 3);
	return;
}

VOID o09(LPBYTE I) // C=ST
{
	w.cycles+=5;
	w.pc+=2;
	memcpy(w.C, w.ST, 3);
	return;
}

VOID o0A(LPBYTE I) // ST=C
{
	w.cycles+=5;
	w.pc+=2;
	memcpy(w.ST, w.C, 3);
	return;
}

VOID o0B(LPBYTE I) // CSTEX
{
	w.cycles+=5;
	w.pc+=2;
	Nxchg(w.C, w.ST, 3);
	return;
}

VOID o0C(LPBYTE I) // P=P+1
{
	w.cycles+=3;
	w.pc+=2;
	if (w.P<15)
	{
		w.P++;
		w.carry=FALSE;
	}
	else
	{
		w.P=0;
		w.carry=TRUE;
	}
	PCHANGED;
	return;
}

VOID o0D(LPBYTE I) // P=P-1
{
	w.cycles+=3;
	w.pc+=2;
	if (w.P)
	{
		w.P--;
		w.carry=FALSE;
	}
	else
	{
		w.P=0xF;
		w.carry=TRUE;
	}
	PCHANGED;
	return;
}

VOID o0Ef0(LPBYTE I) // A=A&B f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.A,w.B,I[2]);
	return;
}
VOID o0Ef1(LPBYTE I) // B=B&C f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.B,w.C,I[2]);
	return;
}
VOID o0Ef2(LPBYTE I) // C=C&A f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.C,w.A,I[2]);
	return;
}
VOID o0Ef3(LPBYTE I) // D=D&C f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.D,w.C,I[2]);
	return;
}
VOID o0Ef4(LPBYTE I) // B=B&A f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.B,w.A,I[2]);
	return;
}
VOID o0Ef5(LPBYTE I) // C=C&B f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.C,w.B,I[2]);
	return;
}
VOID o0Ef6(LPBYTE I) // A=A&C f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.A,w.C,I[2]);
	return;
}
VOID o0Ef7(LPBYTE I) // C=C&D f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFand(w.C,w.D,I[2]);
	return;
}

VOID o0Ef8(LPBYTE I) // A=A!B f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.A,w.B,I[2]);
	return;
}
VOID o0Ef9(LPBYTE I) // B=B!C f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.B,w.C,I[2]);
	return;
}
VOID o0EfA(LPBYTE I) // C=C!A f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.C,w.A,I[2]);
	return;
}
VOID o0EfB(LPBYTE I) // D=D!C f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.D,w.C,I[2]);
	return;
}
VOID o0EfC(LPBYTE I) // B=B!A f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.B,w.A,I[2]);
	return;
}
VOID o0EfD(LPBYTE I) // C=C!B f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.C,w.B,I[2]);
	return;
}
VOID o0EfE(LPBYTE I) // A=A!C f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.A,w.C,I[2]);
	return;
}
VOID o0EfF(LPBYTE I) // C=C!D f
{
	w.cycles+=4+F_l[I[2]];
	w.pc+=4;
	NFor(w.C,w.D,I[2]);
	return;
}

VOID o0F(LPBYTE I) // RTI
{
	w.cycles+=9;
	w.pc = rstkpop();
	w.inte = TRUE;							// enable interrupt

	if ((w.intd && w.intk) || w.IR15X)		// keyboard interrupt pending
	{
		w.intd = FALSE;						// no keyboard interrupt pending any more
		INTERRUPT;							// restart interrupt handler
	}

	// low interrupt lines
	{
		BOOL bNINT2 = Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0;
		BOOL bNINT  = (Chipset.IORam[SRQ2] & NINT) != 0;

		// card detection off and timer running
		if ((Chipset.IORam[CARDCTL] & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
		{
			// state of CDT2
			bNINT2 = bNINT2 && (Chipset.cards_status & (P2W|P2C)) != P2C;
			// state of CDT1
			bNINT  = bNINT  && (Chipset.cards_status & (P1W|P1C)) != P1C;
		}

		if (!bNINT2 || !bNINT)				// NINT2 or NINT interrupt line low
			INTERRUPT;						// restart interrupt handler
	}

	// restart interrupt handler when timer interrupt
	if (w.IORam[TIMER1_CTRL]&INTR)			// INT bit of timer1 is set
		ReadT1();							// check for int

	if (w.IORam[TIMER2_CTRL]&INTR)			// INT bit of timer2 is set
		ReadT2();							// check for int
	return;
}

VOID o100(LPBYTE I) // R0=A W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R0, w.A, 16);
	return;
}

VOID o101(LPBYTE I) // R1=A W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R1, w.A, 16);
	return;
}

VOID o102(LPBYTE I) // R2=A W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R2, w.A, 16);
	return;
}

VOID o103(LPBYTE I) // R3=A W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R3, w.A, 16);
	return;
}

VOID o104(LPBYTE I) // R4=A W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R4, w.A, 16);
	return;
}

VOID o108(LPBYTE I) // R0=C W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R0, w.C, 16);
	return;
}

VOID o109(LPBYTE I) // R1=C W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R1, w.C, 16);
	return;
}

VOID o10A(LPBYTE I) // R2=C W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R2, w.C, 16);
	return;
}

VOID o10B(LPBYTE I) // R3=C W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R3, w.C, 16);
	return;
}

VOID o10C(LPBYTE I) // R4=C W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.R4, w.C, 16);
	return;
}

VOID o110(LPBYTE I) // A=R0 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.A, w.R0, 16);
	return;
}

VOID o111(LPBYTE I) // A=R1 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.A, w.R1, 16);
	return;
}

VOID o112(LPBYTE I) // A=R2 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.A, w.R2, 16);
	return;
}

VOID o113(LPBYTE I) // A=R3 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.A, w.R3, 16);
	return;
}

VOID o114(LPBYTE I) // A=R4 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.A, w.R4, 16);
	return;
}

VOID o118(LPBYTE I) // C=R0 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.C, w.R0, 16);
	return;
}

VOID o119(LPBYTE I) // C=R1 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.C, w.R1, 16);
	return;
}

VOID o11A(LPBYTE I) // C=R2 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.C, w.R2, 16);
	return;
}

VOID o11B(LPBYTE I) // C=R3 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.C, w.R3, 16);
	return;
}

VOID o11C(LPBYTE I) // C=R4 W
{
	w.cycles+=19;
	w.pc+=3;
	memcpy(w.C, w.R4, 16);
	return;
}

VOID o120(LPBYTE I) // AR0EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.A, w.R0, 16);
	return;
}

VOID o121(LPBYTE I) // AR1EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.A, w.R1, 16);
	return;
}

VOID o122(LPBYTE I) // AR2EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.A, w.R2, 16);
	return;
}

VOID o123(LPBYTE I) // AR3EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.A, w.R3, 16);
	return;
}

VOID o124(LPBYTE I) // AR4EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.A, w.R4, 16);
	return;
}

VOID o128(LPBYTE I) // CR0EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.C, w.R0, 16);
	return;
}

VOID o129(LPBYTE I) // CR1EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.C, w.R1, 16);
	return;
}

VOID o12A(LPBYTE I) // CR2EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.C, w.R2, 16);
	return;
}

VOID o12B(LPBYTE I) // CR3EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.C, w.R3, 16);
	return;
}

VOID o12C(LPBYTE I) // CR4EX W
{
	w.cycles+=19;
	w.pc+=3;
	Nxchg(w.C, w.R4, 16);
	return;
}

VOID o130(LPBYTE I) // D0=A
{
	w.cycles+=8;
	w.pc+=3;
	w.d0=Npack(w.A,5);
	return;
}

VOID o131(LPBYTE I) // D1=A
{
	w.cycles+=8;
	w.pc+=3;
	w.d1=Npack(w.A,5);
	return;
}

VOID o132(LPBYTE I) // AD0EX
{
	DWORD d = w.d0;
	w.d0=Npack(w.A,5);
	Nunpack(w.A,d,5);
	w.cycles+=8;
	w.pc+=3;
	return;
}

VOID o133(LPBYTE I) // AD1EX
{
	DWORD d=w.d1;
	w.d1=Npack(w.A,5);
	Nunpack(w.A,d,5);
	w.cycles+=8;
	w.pc+=3;
	return;
}

VOID o134(LPBYTE I) // D0=C
{
	w.cycles+=8;
	w.pc+=3;
	w.d0=Npack(w.C,5);
	return;
}

VOID o135(LPBYTE I) // D1=C
{
	w.cycles+=8;
	w.pc+=3;
	w.d1=Npack(w.C,5);
	return;
}

VOID o136(LPBYTE I) // CD0EX
{
	DWORD d=w.d0;
	w.d0=Npack(w.C,5);
	Nunpack(w.C,d,5);
	w.cycles+=8;
	w.pc+=3;
	return;
}

VOID o137(LPBYTE I) // CD1EX
{
	DWORD d=w.d1;
	w.d1=Npack(w.C,5);
	Nunpack(w.C,d,5);
	w.cycles+=8;
	w.pc+=3;
	return;
}

VOID o138(LPBYTE I) // D0=AS
{
	w.cycles+=7;
	w.pc+=3;
	REG(WORD,w.d0)=(WORD)Npack(w.A,4);
	return;
}

VOID o139(LPBYTE I) // D1=AS
{
	w.cycles+=7;
	w.pc+=3;
	REG(WORD,w.d1)=(WORD)Npack(w.A,4);
	return;
}

VOID o13A(LPBYTE I) // AD0XS
{
	DWORD d=w.d0;
	REG(WORD,w.d0)=(WORD)Npack(w.A,4);
	Nunpack(w.A,d,4);
	w.cycles+=7;
	w.pc+=3;
	return;
}

VOID o13B(LPBYTE I) // AD1XS
{
	DWORD d=w.d1;
	REG(WORD,w.d1)=(WORD)Npack(w.A,4);
	Nunpack(w.A,d,4);
	w.cycles+=7;
	w.pc+=3;
	return;
}

VOID o13C(LPBYTE I) // D0=CS
{
	w.cycles+=7;
	w.pc+=3;
	REG(WORD,w.d0)=(WORD)Npack(w.C,4);
	return;
}

VOID o13D(LPBYTE I) // D1=CS
{
	w.cycles+=7;
	w.pc+=3;
	REG(WORD,w.d1)=(WORD)Npack(w.C,4);
	return;
}

VOID o13E(LPBYTE I) // CD0XS
{
	DWORD d=w.d0;
	REG(WORD,w.d0)=(WORD)Npack(w.C,4);
	Nunpack(w.C,d,4);
	w.cycles+=7;
	w.pc+=3;
	return;
}

VOID o13F(LPBYTE I) // CD1XS
{
	DWORD d=w.d1;
	REG(WORD,w.d1)=(WORD)Npack(w.C,4);
	Nunpack(w.C,d,4);
	w.cycles+=7;
	w.pc+=3;
	return;
}

VOID o140(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.A, w.d0, 5); return; } // DAT0=A A
VOID o141(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.A, w.d1, 5); return; } // DAT1=A A
VOID o144(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.C, w.d0, 5); return; } // DAT0=C A
VOID o145(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.C, w.d1, 5); return; } // DAT1=C A
VOID o148(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.A, w.d0, 2); return; } // DAT0=A B
VOID o149(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.A, w.d1, 2); return; } // DAT1=A B
VOID o14C(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.C, w.d0, 2); return; } // DAT0=C B
VOID o14D(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.C, w.d1, 2); return; } // DAT1=C B

VOID o142(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.A, w.d0, 5); return; } // A=DAT0 A
VOID o143(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.A, w.d1, 5); return; } // A=DAT1 A
VOID o146(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.C, w.d0, 5); return; } // C=DAT0 A
VOID o147(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.C, w.d1, 5); return; } // C=DAT1 A
VOID o14A(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.A, w.d0, 2); return; } // A=DAT0 B
VOID o14B(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.A, w.d1, 2); return; } // A=DAT1 B
VOID o14E(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.C, w.d0, 2); return; } // C=DAT0 B
VOID o14F(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.C, w.d1, 2); return; } // C=DAT0 B

VOID o150a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.A, w.d0, I[3]); return; } // DAT0=A a
VOID o151a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.A, w.d1, I[3]); return; } // DAT1=A a
VOID o154a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.C, w.d0, I[3]); return; } // DAT0=C a
VOID o155a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.C, w.d1, I[3]); return; } // DAT1=C a
VOID o152a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.A, w.d0, I[3]); return; } // A=DAT0 a
VOID o153a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.A, w.d1, I[3]); return; } // A=DAT1 a
VOID o156a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.C, w.d0, I[3]); return; } // C=DAT0 a
VOID o157a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.C, w.d1, I[3]); return; } // C=DAT1 a

VOID o158x(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nwrite(w.A, w.d0, I[3]+1); return; } // DAT0=A x
VOID o159x(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nwrite(w.A, w.d1, I[3]+1); return; } // DAT1=A x
VOID o15Cx(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nwrite(w.C, w.d0, I[3]+1); return; } // DAT0=C x
VOID o15Dx(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nwrite(w.C, w.d1, I[3]+1); return; } // DAT1=C x
VOID o15Ax(LPBYTE I) { w.cycles+=17+I[3]+1; w.pc+=4; Nread(w.A, w.d0, I[3]+1); return; } // A=DAT0 x
VOID o15Bx(LPBYTE I) { w.cycles+=17+I[3]+1; w.pc+=4; Nread(w.A, w.d1, I[3]+1); return; } // A=DAT1 x
VOID o15Ex(LPBYTE I) { w.cycles+=17+I[3]+1; w.pc+=4; Nread(w.C, w.d0, I[3]+1); return; } // C=DAT0 x
VOID o15Fx(LPBYTE I) { w.cycles+=17+I[3]+1; w.pc+=4; Nread(w.C, w.d1, I[3]+1); return; } // C=DAT1 x

VOID o16x(LPBYTE I) // D0=D0+ (n+1)
{
	w.cycles+=7;
	w.pc+=3;
	w.d0+=I[2]+1;
	if (w.d0>0xfffff)
	{
		w.d0&=0xfffff;
		w.carry=TRUE;
	}
	else
	{
		w.carry=FALSE;
	}
	return;
}

VOID o17x(LPBYTE I) // D1=D1+ (n+1)
{
	w.cycles+=7;
	w.pc+=3;
	w.d1+=I[2]+1;
	if (w.d1>0xfffff)
	{
		w.d1&=0xfffff;
		w.carry=TRUE;
	}
	else
	{
		w.carry=FALSE;
	}
	return;
}

VOID o18x(LPBYTE I) // D0=D0- (n+1)
{
	w.cycles+=7;
	w.pc+=3;
	w.d0-=I[2]+1;
	if (w.d0>0xfffff)
	{
		w.d0&=0xfffff;
		w.carry=TRUE;
	}
	else
	{
		w.carry=FALSE;
	}
	return;
}

VOID o19d2(LPBYTE I) // D0=(2) #dd
{
	w.cycles+=4;
	w.pc+=4;
	REG(BYTE,w.d0)=(BYTE)Npack(I+2,2);
	return;
}

VOID o1Ad4(LPBYTE I) // D0=(4) #dddd
{
	w.cycles+=6;
	w.pc+=6;
	REG(WORD,w.d0)=(WORD)Npack(I+2,4);
	return;
}

VOID o1Bd5(LPBYTE I) // D0=(5) #ddddd
{
	w.cycles+=7;
	w.pc+=7;
	w.d0=Npack(I+2,5);
	return;
}

VOID o1Cx(LPBYTE I) // D1=D1- (n+1)
{
	w.cycles+=7;
	w.pc+=3;
	w.d1-=I[2]+1;
	if (w.d1>0xfffff)
	{
		w.d1&=0xfffff;
		w.carry=TRUE;
	}
	else
	{
		w.carry=FALSE;
	}
	return;
}

VOID o1Dd2(LPBYTE I) // D1=(2) #dd
{
	w.cycles+=4;
	w.pc+=4;
	REG(BYTE,w.d1)=(BYTE)Npack(I+2,2);
	return;
}

VOID o1Ed4(LPBYTE I) // D1=(4) #dddd
{
	w.cycles+=6;
	w.pc+=6;
	REG(WORD,w.d1)=(WORD)Npack(I+2,4);
	return;
}

VOID o1Fd5(LPBYTE I) // D1=(5) #ddddd
{
	w.cycles+=7;
	w.pc+=7;
	w.d1=Npack(I+2,5);
	return;
}

VOID o2n(LPBYTE I) // P= n
{
	w.cycles+=2;
	w.pc+=2;
	w.P=I[1];
	PCHANGED;
	return;
}

VOID o3X(LPBYTE I) // LCHEX
{
	UINT n=I[1]+1;
	UINT d=16-w.P;
	w.cycles+=3+I[1];
	w.pc+=2;
	I+=2; // UNSAFE
	if (n<=d)
	{
		memcpy(w.C+w.P,I,n);
	}
	else
	{
		memcpy(w.C+w.P,I,d);
		memcpy(w.C,I+d,n-d);
	}
	w.pc+=n;
	return;
}

VOID o4d2(LPBYTE I) // GOC #dd
{
	if (!w.carry)
	{
		w.cycles+=3;
		w.pc+=3;
	}
	else
	{
		signed char jmp=I[1]+(I[2]<<4);
		if (jmp)
			w.pc+=jmp+1;
		else
			w.pc=rstkpop();
		w.cycles+=10;
		w.pc&=0xFFFFF;
	}
	return;
}

VOID o5d2(LPBYTE I) // GONC
{
	if (w.carry)
	{
		w.cycles+=3;
		w.pc+=3;
	}
	else
	{
		signed char jmp=I[1]+(I[2]<<4);
		if (jmp)
			w.pc+=jmp+1;
		else
			w.pc=rstkpop();
		w.cycles+=10;
		w.pc&=0xFFFFF;
	}
	return;
}

VOID o6d3(LPBYTE I) // GOTO
{
	DWORD d=Npack(I+1,3);
	if (d&0x800)
		w.pc-=0xFFF-d;
	else
		w.pc+=d+1;
	w.cycles+=11;
	w.pc&=0xFFFFF;
	return;
}

VOID o7d3(LPBYTE I) // GOSUB
{
	DWORD d=Npack(I+1,3);
	rstkpush(w.pc+4);
	if (d&0x800) w.pc-=0xFFC-d; else w.pc+=d+4;
	w.cycles+=12;
	w.pc&=0xFFFFF;
	return;
}

VOID o800(LPBYTE I) // OUT=CS
{
	w.cycles+=4;
	w.pc+=3;
	w.out = (w.out&0xff0) | w.C[0];
	ScanKeyboard(FALSE,FALSE);				// 1ms keyboard poll
	return;
}

VOID o801(LPBYTE I) // OUT=C
{
	WORD wOut;
	w.cycles+=6;
	w.pc+=3;
	wOut = (WORD) Npack(w.C, 3);
	if (((wOut ^ w.out) & 0x800) != 0)		// beeper bit OR[11] changed
		SoundOut(&w,wOut);
	w.out = wOut;
	ScanKeyboard(FALSE,FALSE);				// 1ms keyboard poll
	return;
}

VOID o802(LPBYTE I) // A=IN
{
	w.cycles+=7;
	// emulate Clarke/Yorke bug
	if ((w.pc & 1) == 0 || MapData(w.pc) == M_IO)
		w.pc+=3;
	ScanKeyboard(TRUE,FALSE);				// update Chipset.in register (direct)
	IOBit(0x19,8,w.in != 0);				// update KDN bit in the SRQ register
	Nunpack(w.A, w.in, 4);
	return;
}

VOID o803(LPBYTE I) // C=IN
{
	w.cycles+=7;
	// emulate Clarke/Yorke bug
	if ((w.pc & 1) == 0 || MapData(w.pc) == M_IO)
		w.pc+=3;
	ScanKeyboard(TRUE,FALSE);				// update Chipset.in register (direct)
	IOBit(0x19,8,w.in != 0);				// update KDN bit in the SRQ register
	Nunpack(w.C, w.in, 4);
	return;
}

VOID o804(LPBYTE I) // UNCNFG
{
	w.cycles+=12;
	w.pc+=3;
	Uncnfg();
	return;
}

VOID o805(LPBYTE I) // CONFIG
{
	w.cycles+=11;
	w.pc+=3;
	Config();
	return;
}

VOID o806(LPBYTE I) // C=ID
{
	w.cycles+=11;
	w.pc+=3;
	C_Eq_Id();
	return;
}

VOID o807(LPBYTE I) // SHUTDN
{
	BOOL bShutdn = TRUE;					// shut down

	// only shut down when no timer wake up
	if (w.IORam[TIMER1_CTRL]&WKE)			// WKE bit of timer1 is set
	{
		if (ReadT1()&0x08)					// and MSB of timer1 is set
		{
			w.IORam[TIMER1_CTRL] &= ~WKE;	// clear WKE
			bShutdn = FALSE;				// don't shut down
		}
	}
	if (w.IORam[TIMER2_CTRL]&WKE)			// WKE bit of timer2 is set
	{
		if (ReadT2()&0x80000000)			// and MSB of timer2 is set
		{
			w.IORam[TIMER2_CTRL] &= ~WKE;	// clear WKE
			bShutdn = FALSE;				// don't shut down
		}
	}
	ScanKeyboard(TRUE,FALSE);				// update Chipset.in register (direct)
	// out register going low during shutdown, so normal keys produce a rising
	// edge trigger when out register going high again. Because the ON key is not
	// connected to the out register, the rising edge trigger must be done manually.
	if ((w.in & 0x7FFF) == 0 && bShutdn)	// shut down only when enabled
	{
		w.Shutdn = TRUE;					// set mode before exit emulation loop
		bInterrupt = TRUE;

		// emulation of BS reset circuit in deep sleep
		// HP39/40G, HP48GX, HP49G, display off, card control off or in slow mode
		if (   (cCurrentRomType=='E' || cCurrentRomType=='G' || cCurrentRomType=='X' || cCurrentRomType=='2' || cCurrentRomType=='P' || cCurrentRomType=='Q')  // CdB for HP: add apples
			&& (w.IORam[BITOFFSET]&DON) == 0
			&& ((w.IORam[CARDCTL]&(ECDT|RCDT)) != (ECDT|RCDT)))
		{
			// on HP48GX ROM must be selected (DA19=1) and
			// the NOT MA18 address line must be low (test for high)
			// else we get power on VCO from the ROM chip
			// (MA18 input pin security diode to VCC pin)
			if (   cCurrentRomType!='G'
				|| ((w.IORam[LINECOUNT+1]&DA19) && (w.pc & 0x80000)))
			{
				w.Bank_FF = 0;				// reset bank switcher FF
				RomSwitch(w.Bank_FF);		// force new mapping
			}
		}
	}
	w.cycles+=6;
	w.pc+=3;
	return;
}

VOID o8080(LPBYTE I) // INTON
{
	w.cycles+=5;
	w.pc+=4;
	w.intk = TRUE;
	ScanKeyboard(FALSE,FALSE);				// 1ms keyboard poll
	if (w.intd || w.IR15X)					// keyboard interrupt pending
	{
		w.intd = FALSE;						// no keyboard interrupt pending any more
		INTERRUPT;							// restart interrupt handler
	}
	return;
}

VOID o80810(LPBYTE I) // RSI
{
	w.cycles+=6;
	w.pc+=5;
	ScanKeyboard(TRUE,TRUE);				// one input bit high (direct)?

	// enable KDN update
	w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF) - dwT2Cycles * 16;

	if (w.in && w.inte == FALSE)			// key interrupt pending
		w.intd = TRUE;						// keyboard interrupt pending
	return;
}

VOID o8082X(LPBYTE I) // LA
{
	UINT n=I[4]+1;
	UINT d=16-w.P;
	w.cycles+=6+I[4];
	w.pc+=5+n;
	I+=5; // UNSAFE
	if (n<=d)
	{
		memcpy(w.A+w.P,I,n);
	}
	else
	{
		memcpy(w.A+w.P,I,d);
		memcpy(w.A,I+d,n-d);
	}
	return;
}

VOID o8083(LPBYTE I) // BUSCB
{
	w.cycles+=7;
	w.pc+=4;
	// emulated as NOP
	// InfoMessage(_T("BUSCB instruction executed."));
	return;
}

VOID o8084n(LPBYTE I) // ABIT=0 n
{
	w.cycles+=6;
	w.pc+=5;
	Nbit0(w.A, I[4]);
	return;
}

VOID o8085n(LPBYTE I) // ABIT=1 n
{
	w.cycles+=6;
	w.pc+=5;
	Nbit1(w.A, I[4]);
	return;
}

VOID o8086n(LPBYTE I) // ?ABIT=0 n
{
	w.cycles+=9;
	w.pc+=5;
	Tbit0(w.A, I[4]);
	GOYES5;
}

VOID o8087n(LPBYTE I) // ?ABIT=1 n
{
	w.cycles+=9;
	w.pc+=5;
	Tbit1(w.A, I[4]);
	GOYES5;
}

VOID o8088n(LPBYTE I) // CBIT=0 n
{
	w.cycles+=6;
	w.pc+=5;
	Nbit0(w.C, I[4]);
	return;
}

VOID o8089n(LPBYTE I) // CBIT=1 n
{
	w.cycles+=6;
	w.pc+=5;
	Nbit1(w.C, I[4]);
	return;
}

VOID o808An(LPBYTE I) // ?CBIT=0 n
{
	w.cycles+=9;
	w.pc+=5;
	Tbit0(w.C, I[4]);
	GOYES5;
}

VOID o808Bn(LPBYTE I) // ?CBIT=1 n
{
	w.cycles+=9;
	w.pc+=5;
	Tbit1(w.C, I[4]);
	GOYES5;
}

VOID o808C(LPBYTE I) // PC=(A)
{
	BYTE p[5];
	w.cycles+=23;
	Nread(p,Npack(w.A,5),5);				// read (A) and update CRC
	w.pc=Npack(p,5);
	return;
}

VOID o808D(LPBYTE I) // BUSCD
{
	w.cycles+=7;
	w.pc+=4;
	// emulated as NOP
	// InfoMessage(_T("BUSCD instruction executed."));
	return;
}

VOID o808E(LPBYTE I) // PC=(C)
{
	BYTE p[5];
	w.cycles+=23;
	Nread(p,Npack(w.C,5),5);				// read (C) and update CRC
	w.pc=Npack(p,5);
	return;
}

VOID o808F(LPBYTE I) // INTOFF
{
	w.cycles+=5;
	w.pc+=4;
	UpdateKdnBit();							// update KDN bit
	w.intk = FALSE;
	return;
}

VOID o809(LPBYTE I) // C+P+1 - HEX MODE
{
	w.cycles+=8;
	w.pc+=3;
	w.C[0]+=w.P; Nincx(w.C,5);
	return;
}

VOID o80A(LPBYTE I) // RESET
{
	w.cycles+=6;
	w.pc+=3;
	Reset();
	return;
}

VOID o80B(LPBYTE I) // BUSCC
{
	w.cycles+=6;
	w.pc+=3;
	// emulated as NOP
	// InfoMessage(_T("BUSCC instruction executed."));
	if (cCurrentRomType=='Q' || cCurrentRomType=='2' || cCurrentRomType=='P')
	{
		o80BExt(I);							// Saturnator extentions
	}
	return;
}

VOID o80Cn(LPBYTE I) // C=P n
{
	w.cycles+=6;
	w.pc+=4;
	w.C[I[3]] = w.P;
	return;
}

VOID o80Dn(LPBYTE I) // P=C n
{
	w.cycles+=6;
	w.pc+=4;
	w.P = w.C[I[3]];
	PCHANGED;
	return;
}

VOID o80E(LPBYTE I) // SREQ?
{
	w.cycles+=7;
	w.pc+=3;
	w.C[0]=0;								// no device
	return;
}

VOID o80Fn(LPBYTE I) // CPEX n
{
	BYTE n = w.P;
	w.P = w.C[I[3]];
	w.C[I[3]] = n;
	PCHANGED;
	w.cycles+=6;
	w.pc+=4;
	return;
}

VOID o810(LPBYTE I) // ASLC
{
	w.cycles+=21;
	w.pc+=3;
	Nslc(w.A, 16);
	return;
}

VOID o811(LPBYTE I) // BSLC
{
	w.cycles+=21;
	w.pc+=3;
	Nslc(w.B, 16);
	return;
}

VOID o812(LPBYTE I) // CSLC
{
	w.cycles+=21;
	w.pc+=3;
	Nslc(w.C, 16);
	return;
}

VOID o813(LPBYTE I) // DSLC
{
	w.cycles+=21;
	w.pc+=3;
	Nslc(w.D, 16);
	return;
}

VOID o814(LPBYTE I) // ASRC
{
	w.cycles+=21;
	w.pc+=3;
	Nsrc(w.A, 16);
	return;
}

VOID o815(LPBYTE I) // BSRC
{
	w.cycles+=21;
	w.pc+=3;
	Nsrc(w.B, 16);
	return;
}

VOID o816(LPBYTE I) // CSRC
{
	w.cycles+=21;
	w.pc+=3;
	Nsrc(w.C, 16);
	return;
}

VOID o817(LPBYTE I) // DSRC
{
	w.cycles+=21;
	w.pc+=3;
	Nsrc(w.D, 16);
	return;
}

VOID o818f0x(LPBYTE I) // A=A+x+1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.A[F_s[I[3]]]+=I[5];					// add constant value-1
	Ninc16(w.A,nF_l,F_s[I[3]]);				// add one and adjust in HEX mode
	return;
}

VOID o818f1x(LPBYTE I) // B=B+x+1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.B[F_s[I[3]]]+=I[5];					// add constant value-1
	Ninc16(w.B,nF_l,F_s[I[3]]);				// add one and adjust in HEX mode
	return;
}

VOID o818f2x(LPBYTE I) // C=C+x+1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.C[F_s[I[3]]]+=I[5];					// add constant value-1
	Ninc16(w.C,nF_l,F_s[I[3]]);				// add one and adjust in HEX mode
	return;
}

VOID o818f3x(LPBYTE I) // D=D+x+1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.D[F_s[I[3]]]+=I[5];					// add constant value-1
	Ninc16(w.D,nF_l,F_s[I[3]]);				// add one and adjust in HEX mode
	return;
}

VOID o818f8x(LPBYTE I) // A=A-x-1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.A[F_s[I[3]]]-=I[5];					// sub constant value+1
	Ndec16(w.A,nF_l,F_s[I[3]]);				// dec one and adjust in HEX mode
	return;
}

VOID o818f9x(LPBYTE I) // B=B-x-1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.B[F_s[I[3]]]-=I[5];					// sub constant value+1
	Ndec16(w.B,nF_l,F_s[I[3]]);				// dec one and adjust in HEX mode
	return;
}

VOID o818fAx(LPBYTE I) // C=C-x-1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.C[F_s[I[3]]]-=I[5];					// sub constant value+1
	Ndec16(w.C,nF_l,F_s[I[3]]);				// dec one and adjust in HEX mode
	return;
}

VOID o818fBx(LPBYTE I) // D=D-x-1 f
{
	// register length with saturn bug emulation
	UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]];

	w.cycles+=5+F_l[I[3]];
	w.pc+=6;
	w.D[F_s[I[3]]]-=I[5];					// sub constant value+1
	Ndec16(w.D,nF_l,F_s[I[3]]);				// dec one and adjust in HEX mode
	return;
}

VOID o819f0(LPBYTE I) // ASRB.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=5;
	NFsrb(w.A, I[3]);
	return;
}

VOID o819f1(LPBYTE I) // BSRB.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=5;
	NFsrb(w.B, I[3]);
	return;
}

VOID o819f2(LPBYTE I) // CSRB.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=5;
	NFsrb(w.C, I[3]);
	return;
}

VOID o819f3(LPBYTE I) // DSRB.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=5;
	NFsrb(w.D, I[3]);
	return;
}

VOID o81Af00(LPBYTE I) // R0=A.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R0, w.A, I[3]);
	return;
}

VOID o81Af01(LPBYTE I) // R1=A.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R1, w.A, I[3]);
	return;
}

VOID o81Af02(LPBYTE I) // R2=A.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R2, w.A, I[3]);
	return;
}

VOID o81Af03(LPBYTE I) // R3=A.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R3, w.A, I[3]);
	return;
}

VOID o81Af04(LPBYTE I) // R4=A.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R4, w.A, I[3]);
	return;
}

VOID o81Af08(LPBYTE I) // R0=C.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R0, w.C, I[3]);
	return;
}

VOID o81Af09(LPBYTE I) // R1=C.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R1, w.C, I[3]);
	return;
}

VOID o81Af0A(LPBYTE I) // R2=C.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R2, w.C, I[3]);
	return;
}

VOID o81Af0B(LPBYTE I) // R3=C.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R3, w.C, I[3]);
	return;
}

VOID o81Af0C(LPBYTE I) // R4=C.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.R4, w.C, I[3]);
	return;
}

VOID o81Af10(LPBYTE I) // A=R0.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.A, w.R0, I[3]);
	return;
}

VOID o81Af11(LPBYTE I) // A=R1.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.A, w.R1, I[3]);
	return;
}

VOID o81Af12(LPBYTE I) // A=R2.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.A, w.R2, I[3]);
	return;
}

VOID o81Af13(LPBYTE I) // A=R3.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.A, w.R3, I[3]);
	return;
}

VOID o81Af14(LPBYTE I) // A=R4.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.A, w.R4, I[3]);
	return;
}

VOID o81Af18(LPBYTE I) // C=R0.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.C, w.R0, I[3]);
	return;
}

VOID o81Af19(LPBYTE I) // C=R1.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.C, w.R1, I[3]);
	return;
}

VOID o81Af1A(LPBYTE I) // C=R2.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.C, w.R2, I[3]);
	return;
}

VOID o81Af1B(LPBYTE I) // C=R3.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.C, w.R3, I[3]);
	return;
}

VOID o81Af1C(LPBYTE I) // C=R4.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFcopy(w.C, w.R4, I[3]);
	return;
}

VOID o81Af20(LPBYTE I) // AR0EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.A, w.R0, I[3]);
	return;
}

VOID o81Af21(LPBYTE I) // AR1EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.A, w.R1, I[3]);
	return;
}

VOID o81Af22(LPBYTE I) // AR2EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.A, w.R2, I[3]);
	return;
}

VOID o81Af23(LPBYTE I) // AR3EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.A, w.R3, I[3]);
	return;
}

VOID o81Af24(LPBYTE I) // AR4EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.A, w.R4, I[3]);
	return;
}

VOID o81Af28(LPBYTE I) // CR0EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.C, w.R0, I[3]);
	return;
}

VOID o81Af29(LPBYTE I) // CR1EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.C, w.R1, I[3]);
	return;
}

VOID o81Af2A(LPBYTE I) // CR2EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.C, w.R2, I[3]);
	return;
}

VOID o81Af2B(LPBYTE I) // CR3EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.C, w.R3, I[3]);
	return;
}

VOID o81Af2C(LPBYTE I) // CR4EX.F f
{
	w.cycles+=6+F_l[I[3]];
	w.pc+=6;
	NFxchg(w.C, w.R4, I[3]);
	return;
}

VOID o81B2(LPBYTE I) // PC=A
{
	w.cycles+=16;
	w.pc = Npack(w.A,5);
	return;
}

VOID o81B3(LPBYTE I) // PC=C
{
	w.cycles+=16;
	w.pc = Npack(w.C,5);
	return;
}

VOID o81B4(LPBYTE I) // A=PC
{
	w.cycles+=9;
	w.pc+=4;
	Nunpack(w.A,w.pc,5);
	return;
}

VOID o81B5(LPBYTE I) // C=PC
{
	w.cycles+=9;
	w.pc+=4;
	Nunpack(w.C,w.pc,5);
	return;
}

VOID o81B6(LPBYTE I) // APCEX
{
	DWORD d=w.pc+4;
	w.cycles+=16;
	w.pc=Npack(w.A,5);
	Nunpack(w.A,d,5);
	return;
}

VOID o81B7(LPBYTE I) // CPCEX
{
	DWORD d=w.pc+4;
	w.cycles+=16;
	w.pc=Npack(w.C,5);
	Nunpack(w.C,d,5);
	return;
}

VOID o81C(LPBYTE I) // ASRB
{
	w.cycles+=20;
	w.pc+=3;
	Nsrb(w.A, 16);
	return;
}

VOID o81D(LPBYTE I) // BSRB
{
	w.cycles+=20;
	w.pc+=3;
	Nsrb(w.B, 16);
	return;
}

VOID o81E(LPBYTE I) // CSRB
{
	w.cycles+=20;
	w.pc+=3;
	Nsrb(w.C, 16);
	return;
}

VOID o81F(LPBYTE I) // DSRB
{
	w.cycles+=20;
	w.pc+=3;
	Nsrb(w.D, 16);
	return;
}

VOID o82n(LPBYTE I) // HST=0 m
{
	w.cycles+=3;
	w.pc+=3;
	w.HST&=~I[2];
	return;
}

VOID o83n(LPBYTE I) // ?HST=0 m
{
	w.cycles+=6;
	w.pc+=3;
	w.carry=((w.HST&I[2])==0);
	GOYES3;
}

VOID o84n(LPBYTE I) // ST=0 n
{
	w.cycles+=4;
	w.pc+=3;
	Nbit0(w.ST, I[2]);
	return;
}

VOID o85n(LPBYTE I) // ST=1 n
{
	w.cycles+=4;
	w.pc+=3;
	Nbit1(w.ST, I[2]);
	return;
}

VOID o86n(LPBYTE I) // ?ST=0 n
{
	w.cycles+=7;
	w.pc+=3;
	Tbit0(w.ST, I[2]);
	GOYES3;
}

VOID o87n(LPBYTE I) // ?ST=1 n
{
	w.cycles+=7;
	w.pc+=3;
	Tbit1(w.ST, I[2]);
	GOYES3;
}

VOID o88n(LPBYTE I) // ?P# n
{
	w.cycles+=6;
	w.pc+=3;
	w.carry=(w.P!=I[2]);
	GOYES3;
}

VOID o89n(LPBYTE I) // ?P= n
{
	w.cycles+=6;
	w.pc+=3;
	w.carry=(w.P==I[2]);
	GOYES3;
}

VOID o8A0(LPBYTE I) // ?A=B A
{
	w.cycles+=11;
	w.pc+=3;
	Te(w.A, w.B, 5);
	GOYES3;
}

VOID o8A1(LPBYTE I) // ?B=C A
{
	w.cycles+=11;
	w.pc+=3;
	Te(w.B, w.C, 5);
	GOYES3;
}

VOID o8A2(LPBYTE I) // ?C=A A
{
	w.cycles+=11;
	w.pc+=3;
	Te(w.C, w.A, 5);
	GOYES3;
}

VOID o8A3(LPBYTE I) // ?D=C A
{
	w.cycles+=11;
	w.pc+=3;
	Te(w.D, w.C, 5);
	GOYES3;
}

VOID o8A4(LPBYTE I) // ?A#B A
{
	w.cycles+=11;
	w.pc+=3;
	Tne(w.A, w.B, 5);
	GOYES3;
}

VOID o8A5(LPBYTE I) // ?B#C A
{
	w.cycles+=11;
	w.pc+=3;
	Tne(w.B, w.C, 5);
	GOYES3;
}

VOID o8A6(LPBYTE I) // ?C#A A
{
	w.cycles+=11;
	w.pc+=3;
	Tne(w.C, w.A, 5);
	GOYES3;
}

VOID o8A7(LPBYTE I) // ?D#C A
{
	w.cycles+=11;
	w.pc+=3;
	Tne(w.D, w.C, 5);
	GOYES3;
}

VOID o8A8(LPBYTE I) // ?A=0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tz(w.A, 5);
	GOYES3;
}

VOID o8A9(LPBYTE I) // ?B=0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tz(w.B, 5);
	GOYES3;
}

VOID o8AA(LPBYTE I) // ?C=0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tz(w.C, 5);
	GOYES3;
}

VOID o8AB(LPBYTE I) // ?D=0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tz(w.D, 5);
	GOYES3;
}

VOID o8AC(LPBYTE I) // ?A#0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tnz(w.A, 5);
	GOYES3;
}

VOID o8AD(LPBYTE I) // ?B#0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tnz(w.B, 5);
	GOYES3;
}

VOID o8AE(LPBYTE I) // ?C#0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tnz(w.C, 5);
	GOYES3;
}

VOID o8AF(LPBYTE I) // ?D#0 A
{
	w.cycles+=11;
	w.pc+=3;
	Tnz(w.D, 5);
	GOYES3;
}

VOID o8B0(LPBYTE I) // ?A>B A
{
	w.cycles+=11;
	w.pc+=3;
	Ta(w.A, w.B, 5);
	GOYES3;
}

VOID o8B1(LPBYTE I) // ?B>C A
{
	w.cycles+=11;
	w.pc+=3;
	Ta(w.B, w.C, 5);
	GOYES3;
}

VOID o8B2(LPBYTE I) // ?C>A A
{
	w.cycles+=11;
	w.pc+=3;
	Ta(w.C, w.A, 5);
	GOYES3;
}

VOID o8B3(LPBYTE I) // ?D>C A
{
	w.cycles+=11;
	w.pc+=3;
	Ta(w.D, w.C, 5);
	GOYES3;
}

VOID o8B4(LPBYTE I) // ?A<B A
{
	w.cycles+=11;
	w.pc+=3;
	Tb(w.A, w.B, 5);
	GOYES3;
}

VOID o8B5(LPBYTE I) // ?B<C A
{
	w.cycles+=11;
	w.pc+=3;
	Tb(w.B, w.C, 5);
	GOYES3;
}

VOID o8B6(LPBYTE I) // ?C<A A
{
	w.cycles+=11;
	w.pc+=3;
	Tb(w.C, w.A, 5);
	GOYES3;
}

VOID o8B7(LPBYTE I) // ?D<C A
{
	w.cycles+=11;
	w.pc+=3;
	Tb(w.D, w.C, 5);
	GOYES3;
}

VOID o8B8(LPBYTE I) // ?A>=B A
{
	w.cycles+=11;
	w.pc+=3;
	Tae(w.A, w.B, 5);
	GOYES3;
}

VOID o8B9(LPBYTE I) // ?B>=C A
{
	w.cycles+=11;
	w.pc+=3;
	Tae(w.B, w.C, 5);
	GOYES3;
}

VOID o8BA(LPBYTE I) // ?C>=A A
{
	w.cycles+=11;
	w.pc+=3;
	Tae(w.C, w.A, 5);
	GOYES3;
}

VOID o8BB(LPBYTE I) // ?D>=C A
{
	w.cycles+=11;
	w.pc+=3;
	Tae(w.D, w.C, 5);
	GOYES3;
}

VOID o8BC(LPBYTE I) // ?A<=B A
{
	w.cycles+=11;
	w.pc+=3;
	Tbe(w.A, w.B, 5);
	GOYES3;
}

VOID o8BD(LPBYTE I) // ?B<=C A
{
	w.cycles+=11;
	w.pc+=3;
	Tbe(w.B, w.C, 5);
	GOYES3;
}

VOID o8BE(LPBYTE I) // ?C<=A A
{
	w.cycles+=11;
	w.pc+=3;
	Tbe(w.C, w.A, 5);
	GOYES3;
}

VOID o8BF(LPBYTE I) // ?D<=C A
{
	w.cycles+=11;
	w.pc+=3;
	Tbe(w.D, w.C, 5);
	GOYES3;
}

VOID o8Cd4(LPBYTE I) // GOLONG #dddd
{
	DWORD d=Npack(I+2, 4);
	if (d&0x8000) w.pc -= 0xfffe - d; else w.pc+= d + 2;
	w.cycles+=14;
	w.pc&=0xFFFFF;
	return;
}

VOID o8Dd5(LPBYTE I) // GOVLNG #ddddd
{
	w.cycles+=14;
	w.pc = Npack(I+2, 5);
	return;
}

VOID o8Ed4(LPBYTE I) // GOSUBL #dddd
{
	DWORD d=Npack(I+2,4);
	rstkpush(w.pc+6);
	if (d&0x8000) w.pc -= 0xfffa - d; else w.pc += d + 6;
	w.cycles+=14;
	w.pc&=0xFFFFF;
	return;
}

VOID o8Fd5(LPBYTE I) // GOSBVL #ddddd
{
	w.cycles+=15;
	rstkpush(w.pc+7);
	w.pc=Npack(I+2, 5);
	return;
}

	  // ?r=s f
VOID o9a0(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.A, w.B, I[1]); GOYES3; }
VOID o9a1(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.B, w.C, I[1]); GOYES3; }
VOID o9a2(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.C, w.A, I[1]); GOYES3; }
VOID o9a3(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.D, w.C, I[1]); GOYES3; }

	  // ?r#s f
VOID o9a4(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.A, w.B, I[1]); GOYES3; }
VOID o9a5(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.B, w.C, I[1]); GOYES3; }
VOID o9a6(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.C, w.A, I[1]); GOYES3; }
VOID o9a7(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.D, w.C, I[1]); GOYES3; }

	  // ?r=0 f
VOID o9a8(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.A, I[1]); GOYES3; }
VOID o9a9(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.B, I[1]); GOYES3; }
VOID o9aA(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.C, I[1]); GOYES3; }
VOID o9aB(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.D, I[1]); GOYES3; }

	  // ?r#0 f
VOID o9aC(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.A, I[1]); GOYES3; }
VOID o9aD(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.B, I[1]); GOYES3; }
VOID o9aE(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.C, I[1]); GOYES3; }
VOID o9aF(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.D, I[1]); GOYES3; }

	  // ?s>r f
VOID o9b0(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.A, w.B, I[1]&7); GOYES3; }
VOID o9b1(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.B, w.C, I[1]&7); GOYES3; }
VOID o9b2(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.C, w.A, I[1]&7); GOYES3; }
VOID o9b3(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.D, w.C, I[1]&7); GOYES3; }

	  // ?r<s f
VOID o9b4(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFb(w.A, w.B, I[1]&7); GOYES3; }
VOID o9b5(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFb(w.B, w.C, I[1]&7); GOYES3; }
VOID o9b6(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFb(w.C, w.A, I[1]&7); GOYES3; }
VOID o9b7(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFb(w.D, w.C, I[1]&7); GOYES3; }

	  // ?r>=s f
VOID o9b8(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.A, w.B, I[1]&7); GOYES3; }
VOID o9b9(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.B, w.C, I[1]&7); GOYES3; }
VOID o9bA(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.C, w.A, I[1]&7); GOYES3; }
VOID o9bB(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.D, w.C, I[1]&7); GOYES3; }

	  // ?r<=s f
VOID o9bC(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.A, w.B, I[1]&7); GOYES3; }
VOID o9bD(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.B, w.C, I[1]&7); GOYES3; }
VOID o9bE(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.C, w.A, I[1]&7); GOYES3; }
VOID o9bF(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.D, w.C, I[1]&7); GOYES3; }

	  // r=r+s f
VOID oAa0(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.B, I[1]); return; }
VOID oAa1(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.C, I[1]); return; }
VOID oAa2(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.A, I[1]); return; }
VOID oAa3(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.D, w.C, I[1]); return; }

	  // r=r+r f
VOID oAa4(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.A, I[1]); return; }
VOID oAa5(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.B, I[1]); return; }
VOID oAa6(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.C, I[1]); return; }
VOID oAa7(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.D, w.D, I[1]); return; }

	  // s=s+r f
VOID oAa8(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.A, I[1]); return; }
VOID oAa9(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.B, I[1]); return; }
VOID oAaA(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.C, I[1]); return; }
VOID oAaB(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.D, I[1]); return; }

	  // r=r-1 f
VOID oAaC(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.A, I[1]); return; }
VOID oAaD(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.B, I[1]); return; }
VOID oAaE(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.C, I[1]); return; }
VOID oAaF(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.D, I[1]); return; }

	  // r=0 f
VOID oAb0(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.A, I[1]&7); return; }
VOID oAb1(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.B, I[1]&7); return; }
VOID oAb2(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.C, I[1]&7); return; }
VOID oAb3(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.D, I[1]&7); return; }

	  // r=s f
VOID oAb4(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.A, w.B, I[1]&7); return; }
VOID oAb5(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.B, w.C, I[1]&7); return; }
VOID oAb6(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.A, I[1]&7); return; }
VOID oAb7(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.D, w.C, I[1]&7); return; }

	  // s=r f
VOID oAb8(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.B, w.A, I[1]&7); return; }
VOID oAb9(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.B, I[1]&7); return; }
VOID oAbA(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.A, w.C, I[1]&7); return; }
VOID oAbB(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.D, I[1]&7); return; }

	  // rsEX f
VOID oAbC(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.A, w.B, I[1]&7); return; }
VOID oAbD(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.B, w.C, I[1]&7); return; }
VOID oAbE(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.C, w.A, I[1]&7); return; }
VOID oAbF(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.D, w.C, I[1]&7); return; }

	  // r=r-s f
VOID oBa0(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.A, w.B, I[1]); return; }
VOID oBa1(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.B, w.C, I[1]); return; }
VOID oBa2(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.A, I[1]); return; }
VOID oBa3(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.D, w.C, I[1]); return; }

	  // r=r+1 f
VOID oBa4(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.A, I[1]); return; }
VOID oBa5(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.B, I[1]); return; }
VOID oBa6(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.C, I[1]); return; }
VOID oBa7(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.D, I[1]); return; }

	  // s=s-r f
VOID oBa8(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.B, w.A, I[1]); return; }
VOID oBa9(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.B, I[1]); return; }
VOID oBaA(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.A, w.C, I[1]); return; }
VOID oBaB(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.D, I[1]); return; }

	  // r=s-r f
VOID oBaC(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.A, w.B, I[1]); return; }
VOID oBaD(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.B, w.C, I[1]); return; }
VOID oBaE(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.C, w.A, I[1]); return; }
VOID oBaF(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.D, w.C, I[1]); return; }

	  // rSL f
VOID oBb0(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsl(w.A, I[1]&7); return; }
VOID oBb1(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsl(w.B, I[1]&7); return; }
VOID oBb2(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsl(w.C, I[1]&7); return; }
VOID oBb3(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsl(w.D, I[1]&7); return; }

	  // rSR f
VOID oBb4(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsr(w.A, I[1]&7); return; }
VOID oBb5(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsr(w.B, I[1]&7); return; }
VOID oBb6(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsr(w.C, I[1]&7); return; }
VOID oBb7(LPBYTE I) { w.cycles+=4+F_l[I[1]&7]; w.pc+=3; NFsr(w.D, I[1]&7); return; }

	  // r=-r f
VOID oBb8(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.A, I[1]&7); return; }
VOID oBb9(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.B, I[1]&7); return; }
VOID oBbA(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.C, I[1]&7); return; }
VOID oBbB(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.D, I[1]&7); return; }

	  // r=-r-1 f
VOID oBbC(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.A, I[1]&7); return; }
VOID oBbD(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.B, I[1]&7); return; }
VOID oBbE(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.C, I[1]&7); return; }
VOID oBbF(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.D, I[1]&7); return; }

	 // r=r+s A
VOID oC0(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.A, w.B, 5); return; }
VOID oC1(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.B, w.C, 5); return; }
VOID oC2(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.A, 5); return; }
VOID oC3(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.D, w.C, 5); return; }

	 // r=r+r A
VOID oC4(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.A, w.A, 5); return; }
VOID oC5(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.B, w.B, 5); return; }
VOID oC6(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.C, 5); return; }
VOID oC7(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.D, w.D, 5); return; }

	 // s=s+r A
VOID oC8(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.B, w.A, 5); return; }
VOID oC9(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.B, 5); return; }
VOID oCA(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.A, w.C, 5); return; }
VOID oCB(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.D, 5); return; }

	 // r=r-1 A
VOID oCC(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.A, 5, 0); return; }
VOID oCD(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.B, 5, 0); return; }
VOID oCE(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.C, 5, 0); return; }
VOID oCF(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.D, 5, 0); return; }

	 // r=0 A
VOID oD0(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.A, 0, 5); return; }
VOID oD1(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.B, 0, 5); return; }
VOID oD2(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.C, 0, 5); return; }
VOID oD3(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.D, 0, 5); return; }

	 // r=s A
VOID oD4(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.A, w.B, 5); return; }
VOID oD5(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.B, w.C, 5); return; }
VOID oD6(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.C, w.A, 5); return; }
VOID oD7(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.D, w.C, 5); return; }

	 // s=r A
VOID oD8(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.B, w.A, 5); return; }
VOID oD9(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.C, w.B, 5); return; }
VOID oDA(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.A, w.C, 5); return; }
VOID oDB(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.C, w.D, 5); return; }

	 // rsEX
VOID oDC(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.A, w.B, 5); return; }
VOID oDD(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.B, w.C, 5); return; }
VOID oDE(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.C, w.A, 5); return; }
VOID oDF(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.D, w.C, 5); return; }

	 // r=r-s A
VOID oE0(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.A, w.B, 5); return; }
VOID oE1(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.B, w.C, 5); return; }
VOID oE2(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.C, w.A, 5); return; }
VOID oE3(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.D, w.C, 5); return; }

	 // r=r+1 A
VOID oE4(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.A, 5, 0); return; }
VOID oE5(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.B, 5, 0); return; }
VOID oE6(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.C, 5, 0); return; }
VOID oE7(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.D, 5, 0); return; }

	 // s=s-r A
VOID oE8(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.B, w.A, 5); return; }
VOID oE9(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.C, w.B, 5); return; }
VOID oEA(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.A, w.C, 5); return; }
VOID oEB(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.C, w.D, 5); return; }

	 // r=s-r A
VOID oEC(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.A, w.B, 5); return; }
VOID oED(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.B, w.C, 5); return; }
VOID oEE(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.C, w.A, 5); return; }
VOID oEF(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.D, w.C, 5); return; }

	 // rSL A
VOID oF0(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsl(w.A, 5); return; }
VOID oF1(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsl(w.B, 5); return; }
VOID oF2(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsl(w.C, 5); return; }
VOID oF3(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsl(w.D, 5); return; }

	 // rSR A
VOID oF4(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsr(w.A, 5); return; }
VOID oF5(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsr(w.B, 5); return; }
VOID oF6(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsr(w.C, 5); return; }
VOID oF7(LPBYTE I) { w.cycles+=8; w.pc+=2; Nsr(w.D, 5); return; }

	 // r=-r A
VOID oF8(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.A, 5); return; }
VOID oF9(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.B, 5); return; }
VOID oFA(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.C, 5); return; }
VOID oFB(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.D, 5); return; }

	 // r=-r-1 A
VOID oFC(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.A, 5); return; }
VOID oFD(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.B, 5); return; }
VOID oFE(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.C, 5); return; }
VOID oFF(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.D, 5); return; }

// length is guessed, just skip
VOID o_invalid3(LPBYTE I)
{
	_ASSERT(FALSE);								// invalid, length guessed, skip 3 nibbles
	w.pc+=3;
	return;
}

VOID o_invalid4(LPBYTE I)
{
	_ASSERT(FALSE);								// invalid, length guessed, skip 4 nibbles
	w.pc+=4;
	return;
}

VOID o_invalid5(LPBYTE I)
{
	_ASSERT(FALSE);								// invalid, length guessed, skip 5 nibbles
	w.pc+=5;
	return;
}

VOID o_invalid6(LPBYTE I)
{
	_ASSERT(FALSE);								// invalid, length guessed, skip 6 nibbles
	w.pc+=6;
	return;
}

VOID o_goyes3(LPBYTE I)
{
	signed char jmp = I[3]+(I[4]<<4);
	w.cycles+=7;
	if (jmp)
		w.pc=(w.pc+jmp)&0xFFFFF;
	else
		w.pc=rstkpop();
	return;
}

VOID o_goyes5(LPBYTE I)
{
	signed char jmp = I[5]+(I[6]<<4);
	w.cycles+=7;
	if (jmp)
		w.pc=(w.pc+jmp)&0xFFFFF;
	else
		w.pc=rstkpop();
	return;
}

//////// EXTENSIONS ////////
VOID o81B1(LPBYTE I)
{
	if (cCurrentRomType=='Q' || cCurrentRomType=='2' || cCurrentRomType=='P')
	{
		// The ARM-based calculators use this previously-unused opcode to return to RPL
		w.cycles+=48;
		o80B00();							// LOOP2
	}
	else
	{
		// this opcode was used for the beep patch on the non-ARM-based calculators, not used any more
		o_invalid4(I);
	}
	return;
}
////////////////////////////
