#
# TI MSP430 
#
# Texas Instruments microcontroller 16-bit CPU


#
# 	Memory Architecture
# 

define endian=$(ENDIAN);
define alignment=2;
define space RAM type=ram_space size=$(REG_SIZE) default;
define space register type=register_space size=2;

#
#	General Registers
#
define register offset=0x0000 size=$(REG_SIZE) [
	PC # R0 # Program Counter
	SP # R1 # Stack Pointer
	SR # R2 # Status Register 
	R3 # R3 # Constant Generator
		
	#Available for general use:
	R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
	
	#None:
	None
];

@if REG_SIZE == "4"

define register offset=0x0000 size=2 [
	PC_16 _ SP_16 _ SR_16  _ R3_16  _ R4_16  _ R5_16  _ R6_16  _ R7_16 _
	R8_16 _ R9_16 _ R10_16 _ R11_16 _ R12_16 _ R13_16 _ R14_16 _ R15_16 _
	
];

define register offset=0x0000 size=1 [
	PC_lo PC_hi _ _ # R0 # Program Counter
	SP_lo SP_hi _ _ # R1 # Stack Pointer
	SR_lo SR_hi _ _ # R2 # Status Register 
	R3_lo R3_hi _ _ # R3 # Constant Generator
		
	#Available for general use:
	R4_lo  R4_hi _ _
    R5_lo  R5_hi _ _
    R6_lo  R6_hi _ _
    R7_lo  R7_hi _ _
    R8_lo  R8_hi _ _
    R9_lo  R9_hi _ _
    R10_lo R10_hi _ _
    R11_lo R11_hi _ _
    R12_lo R12_hi _ _
    R13_lo R13_hi _ _
    R14_lo R14_hi _ _
    R15_lo R15_hi _ _
	
	#None:
	None_lo None_hi _ _
];
@else

define register offset=0x0000 size=1 [
	PC_lo PC_hi # R0 # Program Counter
	SP_lo SP_hi # R1 # Stack Pointer
	SR_lo SR_hi # R2 # Status Register 
	R3_lo R3_hi # R3 # Constant Generator
		
	#Available for general use:
	R4_lo  R4_hi
    R5_lo  R5_hi
    R6_lo  R6_hi
    R7_lo  R7_hi
    R8_lo  R8_hi
    R9_lo  R9_hi
    R10_lo R10_hi
    R11_lo R11_hi
    R12_lo R12_hi
    R13_lo R13_hi
    R14_lo R14_hi
    R15_lo R15_hi
	
	#None:
	None_lo None_hi
];

@endif

define register offset=0x1000 size=4   contextreg;
define context contextreg
# NOTE: Only instructions that don't use immediates (except ones from constant generator) can
# use the repeat feature.
# NOTE: The POPM/PUSM have a starting register & # of register to pop/push. We need to track
# that info in context for the subtables that do the work.
  ctx_isHi=(0,0) noflow					# Used in pspec to flag msp430 instruction > 64k
  ctx_al=(1,1) noflow					# extension word al field
  ctx_ctregdest=(2,5) noflow			# extension word dest register/immediate field
  ctx_ctregdests=(2,5) signed noflow	# signed version of above
  ctx_repreg=(2,5) noflow				# register repeat count comes from. 
  ctx_regsrc=(6,9) noflow				# extension word src register/immediate field
  ctx_regsrcs=(6,9) signed noflow		# signed version of above
  ctx_zc=(10,10) noflow					# extension word zero carry field
  ctx_num=(11,11) noflow				# is repetition field a # or register
  ctx_haveext=(12,14) noflow			# used to track type of extension word used
  ctx_popreg_set=(15,18) noflow			# used to set register for POPM/PUSHM instructions
  ctx_popreg=(15,18) noflow				# display register, linked for POPM/PUSHM instructions
  ctx_count=(19,22) noflow				# tracks count of registers for POPM/PUSHM
  ctx_mreg=(23,26) noflow				# register being accessed in POPM/PUSHM
;

define register offset=0x2000 size=1 [ CNT ];

#
# 	Tokens
#
define token instr16(16)
	op16_0_8	= (0, 7)
	op16_4_4	= (4, 7)
	op16_0_4  	= (0, 3)
	op16_7_9	= (7, 15)
	op16_8_4	= (8, 11)
	op16_8_8	= (8, 15)
	op16_12_4	= (12, 15)
	opext_11_5	= (11, 15)
	op16_7_1  	= (7, 7)
	op16_13_3  	= (13, 15)
	
	src		= (0, 3)
	dest	= (0, 3)
	
	as	= (4, 5)
	bow	= (6, 6)
	insid = (4, 7)
	insidbig 			= (4, 9)
	reg16_0_4			= (0, 3)
	dest_0_4			= (0, 3)
	imm_0_4				= (0, 4)
	reg_Direct16_0_4	= (0, 3)
	reg_Direct16_0_4W	= (0, 3)
	reg_Indexed16_0_4	= (0, 3)
	reg_InDirect16_0_4	= (0, 3)
	dest_Direct16_0_4	= (0, 3)
	dest_Indexed16_0_4 	= (0, 3)
	dest_Direct_lo		= (0, 3)
	dest_Direct_hi		= (0, 3)
	
	condition	= (10, 12)
	
	off16  = (0, 9) signed
	off16_8_2	= (8, 9)
	off16_4_4	= (4, 7)
	off16_0_4 	= (0, 3)

	zc	= (8, 8)	
	ad	= (7, 7)
	al	= (6, 6)
	imm_4_4		= (4, 7)
	imm_8_4		= (8, 11)
	src_8_4		= (8, 11)
	src16_8_4	= (8, 11)
	src_Direct16_8_4	= (8, 11)
	reg_Direct16_8_4W	= (8, 11)
	src_InDirect16_8_4	= (8, 11)
	src_Indexed16_8_4	= (8, 11)
	src_Direct_lo		= (8, 11)
	src_Direct_hi		= (8, 11)
	src_ext				= (7, 10)
	rrn					= (10, 11)
	
	imm_0_16			= (0, 15)
	imms_0_16			= (0, 15) signed
	indexExtWord16_0_16 = (0, 15)
	indexExtWord16_0_16s = (0, 15) signed
	indexExt2Word16_0_16 = (0, 15)
	indexExt2Word16_0_16s = (0, 15) signed
;


#
#	Attach(s)
#
attach variables [ 	src_8_4
					dest_0_4
					reg_Direct16_0_4 
					src_Direct16_8_4 
					dest_Direct16_0_4
					ctx_popreg
					ctx_repreg ] [ PC SP SR R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 ];
					
attach variables [ dest_Direct_lo src_Direct_lo] [ PC_lo SP_lo SR_lo   _      R4_lo  R5_lo  R6_lo  R7_lo
                                      			R8_lo R9_lo R10_lo  R11_lo R12_lo R13_lo R14_lo R15_lo ];
attach variables [ dest_Direct_hi src_Direct_hi] [ PC_hi SP_hi SR_hi   _      R4_hi  R5_hi  R6_hi  R7_hi
                                      			R8_hi R9_hi R10_hi  R11_hi R12_hi R13_hi R14_hi R15_hi ];
                                      					 
attach variables [ 	reg_Indexed16_0_4 
					src_Indexed16_8_4 
					dest_Indexed16_0_4 ] [ None SP _ _ R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 ];

attach variables [ 	reg_InDirect16_0_4 
					src_InDirect16_8_4 ] [ PC SP _ _ R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 ];

@if REG_SIZE == "4"
attach variables [reg_Direct16_0_4W reg_Direct16_8_4W] [PC_16 SP_16 SR_16 _ R4_16 R5_16 R6_16 R7_16 R8_16 R9_16 R10_16 R11_16 R12_16 R13_16 R14_16 R15_16];
@else
attach variables [reg_Direct16_0_4W reg_Direct16_8_4W] [PC SP SR _ R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15];
@endif

SRC16_8_4: src_Direct16_8_4		is src_Direct16_8_4 & reg_Direct16_8_4W {export reg_Direct16_8_4W;}
DST16_0_4: dest_Direct16_0_4		is dest_Direct16_0_4 & reg_Direct16_0_4W {export reg_Direct16_0_4W;}
SRC8_8_4: src_Direct16_8_4		is src_Direct16_8_4 & src_Direct_lo {export src_Direct_lo;}
DST8_0_4: reg_Direct16_0_4		is reg_Direct16_0_4 & dest_Direct_lo {export dest_Direct_lo;}

####################################
# Status Register (SR) Map
####################################
# b15-b9:	Reserved
# b8:		V (overflow bit)
# b7:		SCG1 (System Clock generator 1)
# b6:		SCG0 (System Clock generator 0)
# b5: 		OSCOFF (Oscillator Off)
# b4:		CPUOFF (CPU off)
# b3:		GIE	(General Interrupt Enable)
# b2:		N	(Negative Bit) (Word = bit 15, Byte = bit 7)(sign bit)
# b1:		Z	(Zero Bit)
# b0:		C	(Carry Bit)
####################################

@define CARRY	"SR[0,1]"
@define ZERO	"SR[1,1]"
@define SIGN	"SR[2,1]"
@define OVERFLOW "SR[8,1]"
@define GIE		"SR[3,1]"

#
#	Sub Constructors
#
#-----------------------------------------------
# B/W: 	Byte or Word operation
#		0: Word Operation
#		1: Byte Operation
#-----------------------------------------------

@if REG_SIZE == "4"
AMASK: val	is ctx_isHi=1 [ val = 0xFFFF; ]  { export *[const]:4 val; }
AMASK: val	is ctx_isHi=0 [ val = 0xFFFFF; ] { export *[const]:4 val; }
@else
AMASK: val	is bow=0 [ val = 0xFFFE; ]  { export *[const]:2 val; } # Memory accesses for unaligned (odd) word addresses round down for alignment.
AMASK: val	is bow=1 [ val = 0xFFFF; ]  { export *[const]:2 val; }
@endif

#-----------------------------------------------
#
#	REGISTER (REG)
#
# The REG modes are used for the 1 operand form instructions
#
#-----------------------------------------------
REG_W_AS: DST16_0_4 			 		 is DST16_0_4 & as=0x0 & bow=0x0  {export DST16_0_4;} # Word/Register Direct (Rn):
REG_W_AS: DST16_0_4 			 		 is DST16_0_4 & reg16_0_4=0 & as=0x0 & bow=0x0  {DST16_0_4 = inst_next & 0xFFFE; export DST16_0_4;} # PC register accesses point to next instruction
REG_W_AS: indexExtWord16_0_16s^"("^reg_Indexed16_0_4^")" is reg_Indexed16_0_4 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (reg_Indexed16_0_4 + indexExtWord16_0_16s) & AMASK; export *:2 tmp;}
REG_W_AS: indexExtWord16_0_16s^"("^reg_Indexed16_0_4^")" is reg_Indexed16_0_4 & as=0x1 & bow=0x0 & AMASK & reg_Indexed16_0_4=1 ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (reg_Indexed16_0_4 + indexExtWord16_0_16s - 0x2) & AMASK; export *:2 tmp;} # PUSH, CALL X(SP) - addressing includes SP decrement
REG_W_AS: "@"^reg_InDirect16_0_4 	 is reg_InDirect16_0_4 & as=0x2 & bow=0x0 & AMASK {tmp:$(REG_SIZE) = reg_InDirect16_0_4 & AMASK; export *:2 tmp;} # Word/Register Indirect (@Rn):
REG_W_AS: "@"^reg_InDirect16_0_4^"+" is reg_InDirect16_0_4 & as=0x3 & bow=0x0 & AMASK {tmp:$(REG_SIZE) = reg_InDirect16_0_4 & AMASK; export *:2 tmp;} # Word/Register Indirect Autoincrement (@Rn+):
REG_W_AS: labelCalc 				 is reg16_0_4=0x0 & as=0x1 & bow=0x0 & AMASK; indexExtWord16_0_16 [labelCalc = inst_start + 2 + indexExtWord16_0_16; ] {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:2 tmp; } # Symbolic
REG_W_AS: "#"^indexExtWord16_0_16 	 is reg16_0_4=0x0 & as=0x3 & bow=0x0 ; indexExtWord16_0_16 {export *[const]:2 indexExtWord16_0_16; } # Immediate
REG_W_AS: "&"^indexExtWord16_0_16 	 is reg16_0_4=0x2 & as=0x1 & bow=0x0 & AMASK; indexExtWord16_0_16 {tmp:$(REG_SIZE) = indexExtWord16_0_16 & AMASK; export *:2 tmp; } # Absolute
REG_W_AS: "#4" 						 is reg16_0_4=0x2 & as=0x2 & bow=0x0  { export 4:2;}		# Constant
REG_W_AS: "#8" 						 is reg16_0_4=0x2 & as=0x3 & bow=0x0  { export 8:2;}		# Constant
REG_W_AS: "#0" 						 is reg16_0_4=0x3 & as=0x0 & bow=0x0  { export 0:2;}		# Constant
REG_W_AS: "#1" 						 is reg16_0_4=0x3 & as=0x1 & bow=0x0  { export 1:2;}		# Constant
REG_W_AS: "#2" 						 is reg16_0_4=0x3 & as=0x2 & bow=0x0  { export 2:2;}		# Constant
REG_W_AS: "#-1" 					 is	reg16_0_4=0x3 & as=0x3 & bow=0x0  { export 0xffff:2;} 	    # Constant

REG_W_AS_DEST: DST16_0_4 			 is DST16_0_4 & as=0x0 & bow=0x0  {export DST16_0_4;} # Word/Register Direct (Rn):
REG_W_AS_DEST: DST16_0_4 			 is DST16_0_4 & reg16_0_4=0 & as=0x0 & bow=0x0  {DST16_0_4 = inst_next & 0xFFFE; export DST16_0_4;} # PC register accesses point to next instruction
REG_W_AS_DEST: indexExtWord16_0_16s^"("^reg_Indexed16_0_4^")" is reg_Indexed16_0_4 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (reg_Indexed16_0_4 + indexExtWord16_0_16s) & AMASK; export *:2 tmp;}
REG_W_AS_DEST: "@"^reg_InDirect16_0_4 	 is reg_InDirect16_0_4 & as=0x2 & bow=0x0 & AMASK {tmp:$(REG_SIZE) = reg_InDirect16_0_4 & AMASK; export *:2 tmp;} # Word/Register Indirect (@Rn):
REG_W_AS_DEST: "@"^reg_InDirect16_0_4^"+" is reg_InDirect16_0_4 & as=0x3 & bow=0x0 & AMASK {tmp:$(REG_SIZE) = reg_InDirect16_0_4 & AMASK; export *:2 tmp;} # Word/Register Indirect Autoincrement (@Rn+):
REG_W_AS_DEST: labelCalc 				 is reg16_0_4=0x0 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16 [labelCalc = inst_start + 2 + indexExtWord16_0_16; ] {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:2 tmp; } # Symbolic
REG_W_AS_DEST: "#"^indexExtWord16_0_16 	 is reg16_0_4=0x0 & as=0x3 & bow=0x0 & AMASK ; indexExtWord16_0_16 {export *:2 inst_next; } # Immediate - Undocumented behaviour
REG_W_AS_DEST: "&"^indexExtWord16_0_16 	 is reg16_0_4=0x2 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16 {tmp:$(REG_SIZE) = indexExtWord16_0_16 & AMASK; export *:2 tmp; } # Absolute

#-----------------------------------------------
REG_B_AS: DST8_0_4 			 		 is DST8_0_4 & as=0x0 & bow=0x1  { export DST8_0_4;} # Word/Register Direct (Rn):
REG_B_AS: DST8_0_4 			 		 is DST8_0_4 & reg16_0_4=0 & as=0x0 & bow=0x1  {tmp:$(REG_SIZE) = inst_next; DST8_0_4 = tmp:1 & 0xFF; export DST8_0_4;} # PC register accesses point to next instruction - must return register for resulting stores
REG_B_AS: indexExtWord16_0_16s^"("^reg_Indexed16_0_4^")" is reg_Indexed16_0_4 & as=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (reg_Indexed16_0_4 + indexExtWord16_0_16s) & AMASK; export *:1 tmp;}
REG_B_AS: indexExtWord16_0_16s^"("^reg_Indexed16_0_4^")" is reg_Indexed16_0_4 & as=0x1 & bow=0x1 & AMASK & reg_Indexed16_0_4=1 ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (reg_Indexed16_0_4 + indexExtWord16_0_16s - 0x2) & AMASK; export *:1 tmp;} # PUSH.B X(SP) - includes SP decrement
REG_B_AS: "@"^reg_InDirect16_0_4 	 is reg_InDirect16_0_4 & as=0x2 & bow=0x1  {export *:1 reg_InDirect16_0_4;} # Word/Register Indirect (@Rn):
REG_B_AS: "@"^reg_InDirect16_0_4^"+" is reg_InDirect16_0_4 & as=0x3 & bow=0x1  {export *:1 reg_InDirect16_0_4;} # Word/Register Indirect Autoincrement (@Rn+):	
REG_B_AS: labelCalc 				 is reg16_0_4=0x0 & as=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16 [labelCalc = inst_start + 2 + indexExtWord16_0_16; ] {tmp:$(REG_SIZE) = labelCalc & AMASK;export *:1 tmp; } # Symbolic
REG_B_AS: "#"^indexExtWord16_0_16 	 is reg16_0_4=0x0 & as=0x3 & bow=0x1 ; indexExtWord16_0_16 { export *[const]:1 indexExtWord16_0_16; } # Immediate
REG_B_AS: "&"^indexExtWord16_0_16 	 is reg16_0_4=0x2 & as=0x1 & bow=0x1 ; indexExtWord16_0_16 {export *:1 indexExtWord16_0_16; } # Absolute
REG_B_AS: "#4" 						 is reg16_0_4=0x2 & as=0x2 & bow=0x1  { export 4:1;}		# Constant
REG_B_AS: "#8" 						 is reg16_0_4=0x2 & as=0x3 & bow=0x1  { export 8:1;}		# Constant
REG_B_AS: "#0" 						 is reg16_0_4=0x3 & as=0x0 & bow=0x1  { export 0:1;}		# Constant
REG_B_AS: "#1" 						 is reg16_0_4=0x3 & as=0x1 & bow=0x1  { export 1:1;}		# Constant
REG_B_AS: "#2" 						 is reg16_0_4=0x3 & as=0x2 & bow=0x1  { export 2:1;}		# Constant
REG_B_AS: "#-1" 					 is	reg16_0_4=0x3 & as=0x3 & bow=0x1  { export 0xff:1;} 	# Constant	

REG_B_AS_DEST: DST8_0_4 			 	 is DST8_0_4 & as=0x0 & bow=0x1  { export DST8_0_4;} # Word/Register Direct (Rn):
REG_B_AS_DEST: DST8_0_4 			 	 is DST8_0_4 & reg16_0_4=0 & as=0x0 & bow=0x1  {tmp:$(REG_SIZE) = inst_next; DST8_0_4 = tmp:1 & 0xFF; export DST8_0_4;} # PC register accesses point to next instruction
REG_B_AS_DEST: indexExtWord16_0_16s^"("^reg_Indexed16_0_4^")" is reg_Indexed16_0_4 & as=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (reg_Indexed16_0_4 + indexExtWord16_0_16s) & AMASK; export *:1 tmp;}
REG_B_AS_DEST: "@"^reg_InDirect16_0_4 	 is reg_InDirect16_0_4 & as=0x2 & bow=0x1  {export *:1 reg_InDirect16_0_4;} # Word/Register Indirect (@Rn):
REG_B_AS_DEST: "@"^reg_InDirect16_0_4^"+" is reg_InDirect16_0_4 & as=0x3 & bow=0x1  {export *:1 reg_InDirect16_0_4;} # Word/Register Indirect Autoincrement (@Rn+):	
REG_B_AS_DEST: labelCalc 				 is reg16_0_4=0x0 & as=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16 [labelCalc = inst_start + 2 + indexExtWord16_0_16; ] {tmp:$(REG_SIZE) = labelCalc & AMASK;export *:1 tmp; } # Symbolic
REG_B_AS_DEST: "#"^indexExtWord16_0_16 	 is reg16_0_4=0x0 & as=0x3 & bow=0x1 & AMASK ; indexExtWord16_0_16 {export *:1 inst_next; } # Undocumented behaviour
REG_B_AS_DEST: "&"^indexExtWord16_0_16 	 is reg16_0_4=0x2 & as=0x1 & bow=0x1 ; indexExtWord16_0_16 {export *:1 indexExtWord16_0_16; } # Absolute

#-----------------------------------------------
#
# SOURCE (SRC)
#
#-----------------------------------------------
SRC_W_AS: SRC16_8_4 			 		 is SRC16_8_4 & as=0x0 & bow=0x0  {export SRC16_8_4;} # Word/Register Direct (Rn):
SRC_W_AS: SRC16_8_4 			 		 is SRC16_8_4 & src16_8_4=0 & as=0x0 & bow=0x0 {tmp:2 = inst_next; export tmp;} # PC register accesses point to next instruction (PC-relative addresses already covered by Immediate/Symbolic modes)
SRC_W_AS: indexExtWord16_0_16s^"("^src_Indexed16_8_4^")" is src_Indexed16_8_4 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (src_Indexed16_8_4 + indexExtWord16_0_16s) & AMASK; export *:2 tmp;}
SRC_W_AS: "@"^src_InDirect16_8_4 	 is src_InDirect16_8_4 & as=0x2 & bow=0x0 & AMASK {tmp:$(REG_SIZE) = src_InDirect16_8_4 & AMASK; export *:2 tmp;} # Word/Register Indirect (@Rn):
SRC_W_AS: "@"^src_InDirect16_8_4^"+" is src_InDirect16_8_4 & as=0x3 & bow=0x0 & AMASK {tmp:$(REG_SIZE) = src_InDirect16_8_4 & AMASK; export *:2 tmp;} # Word/Register Indirect Autoincrement (@Rn+):
SRC_W_AS: labelCalc 				 is src16_8_4=0x0 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16 [labelCalc = inst_start + 2 + indexExtWord16_0_16; ] {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:2 tmp; } # Symbolic
SRC_W_AS: "#"^indexExtWord16_0_16 	 is src16_8_4=0x0 & as=0x3 & bow=0x0 ; indexExtWord16_0_16 {export *[const]:2 indexExtWord16_0_16; } # Immediate
SRC_W_AS: "&"^indexExtWord16_0_16 	 is src16_8_4=0x2 & as=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16 {tmp:$(REG_SIZE) = indexExtWord16_0_16 & AMASK; export *:2 tmp; } # Absolute
SRC_W_AS: "#4" 						 is src16_8_4=0x2 & as=0x2 & bow=0x0  { export 4:2; }		# Constant
SRC_W_AS: "#8" 						 is src16_8_4=0x2 & as=0x3 & bow=0x0  { export 8:2; }		# Constant
SRC_W_AS: "#0" 						 is src16_8_4=0x3 & as=0x0 & bow=0x0  { export 0:2; }		# Constant
SRC_W_AS: "#1" 						 is src16_8_4=0x3 & as=0x1 & bow=0x0  { export 1:2; }		# Constant
SRC_W_AS: "#2" 						 is src16_8_4=0x3 & as=0x2 & bow=0x0  { export 2:2; }		# Constant
SRC_W_AS: "#-1" 					 is	src16_8_4=0x3 & as=0x3 & bow=0x0  { export 0xffff:2; } 	# Constant	
#-----------------------------------------------
SRC_B_AS: SRC8_8_4 			 		 is SRC8_8_4 & as=0x0 & bow=0x1  { export SRC8_8_4;} # Word/Register Direct (Rn):
SRC_B_AS: SRC8_8_4 			 		 is SRC8_8_4 & src16_8_4=0 & as=0x0 & bow=0x1  {tmp:$(REG_SIZE) = inst_next; tmp2:1 = tmp:1; export tmp2;} # PC register accesses point to next instruction.
SRC_B_AS: indexExtWord16_0_16s^"("^src_Indexed16_8_4^")" is src_Indexed16_8_4 & as=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16s {tmp:$(REG_SIZE) = (src_Indexed16_8_4 + indexExtWord16_0_16s) & AMASK; export *:1 tmp;}
SRC_B_AS: "@"^src_InDirect16_8_4 	 is src_InDirect16_8_4 & as=0x2 & bow=0x1  {export *:1 src_InDirect16_8_4;} # Word/Register Indirect (@Rn):
SRC_B_AS: "@"^src_InDirect16_8_4^"+" is src_InDirect16_8_4 & as=0x3 & bow=0x1  {export *:1 src_InDirect16_8_4;} # Word/Register Indirect Autoincrement (@Rn+):	
SRC_B_AS: labelCalc 				 is src16_8_4=0x0 & as=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16 [labelCalc = inst_start + 2 + indexExtWord16_0_16; ] {tmp:$(REG_SIZE) = labelCalc & AMASK;export *:1 tmp; } # Symbolic
SRC_B_AS: "#"^indexExtWord16_0_16 	 is src16_8_4=0x0 & as=0x3 & bow=0x1 ; indexExtWord16_0_16 {export *[const]:1 indexExtWord16_0_16;} # Immediate
SRC_B_AS: "&"^indexExtWord16_0_16 	 is src16_8_4=0x2 & as=0x1 & bow=0x1 ; indexExtWord16_0_16 {export *:1 indexExtWord16_0_16; } # Absolute
SRC_B_AS: "#4" 						 is src16_8_4=0x2 & as=0x2 & bow=0x1  { export 4:1; }		# Constant
SRC_B_AS: "#8" 						 is src16_8_4=0x2 & as=0x3 & bow=0x1  { export 8:1; }		# Constant
SRC_B_AS: "#0" 						 is src16_8_4=0x3 & as=0x0 & bow=0x1  { export 0:1; }		# Constant
SRC_B_AS: "#1" 						 is src16_8_4=0x3 & as=0x1 & bow=0x1  { export 1:1; }		# Constant
SRC_B_AS: "#2" 						 is src16_8_4=0x3 & as=0x2 & bow=0x1  { export 2:1; }		# Constant
SRC_B_AS: "#-1" 					 is	src16_8_4=0x3 & as=0x3 & bow=0x1  { export 0xff:1; } 	# Constant

#-----------------------------------------------
#
#	DESTINATION (DEST)
#
#-----------------------------------------------
DEST_W_AD: DST16_0_4 		  		 is DST16_0_4 & ad=0x0 & bow=0x0
     {export DST16_0_4;} # Word/Register Direct (Rn):
DEST_W_AD: DST16_0_4 			 		 is DST16_0_4 & dest_0_4=0 & ad=0x0 & bow=0x0  {DST16_0_4 = inst_next; export DST16_0_4;} # PC register accesses point to next instruction.

# Register relative destinations for R1, R4-R15
DEST_W_AD: indexExtWord16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16s
     {tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + indexExtWord16_0_16s) & AMASK; export *:2 tmp;}
#---Depends on SRC ---#
# Source is register-relative and involves 'embedded' immediate
DEST_W_AD: indexExt2Word16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x0 & AMASK & as=0x1 & ((src16_8_4>=0x0 & src16_8_4<=0x2) | (src16_8_4>=0x4 & src16_8_4<=0xF)) ; indexExtWord16_0_16 ; indexExt2Word16_0_16s
     {tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + indexExt2Word16_0_16s) & AMASK; export *:2 tmp;}
# Source is an 'embedded' immediate implemented by @PC+
DEST_W_AD: indexExt2Word16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x0 & AMASK & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16s
     {tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + indexExt2Word16_0_16s) & AMASK; export *:2 tmp;}
# Source is involves a register increment (@reg+) that applies to the destination (of same register, but not PC, SR, R3)
DEST_W_AD: indexExt2Word16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x0 & AMASK & as=0x3 & src16_8_4=dest_0_4 & (src16_8_4 = 1 | src16_8_4 >= 4) ; indexExt2Word16_0_16s
     {tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + 2 + indexExt2Word16_0_16s) & AMASK; export *:2 tmp;}
#---End of Depend ----#

# PC-relative destinations
DEST_W_AD: labelCalc 				  is dest=0x0 & ad=0x1 & bow=0x0 & AMASK ; indexExtWord16_0_16s [labelCalc = inst_start + 2 + indexExtWord16_0_16s; ]
     {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:2 tmp; } # Symbolic
#---Depends on SRC ---#
DEST_W_AD: labelCalc 				  is dest=0x0 & ad=0x1 & bow=0x0 & AMASK & as=0x1 & ((src16_8_4>=0x0 & src16_8_4<=0x2) | (src16_8_4>=0x4 & src16_8_4<=0xF)) ; indexExtWord16_0_16 ; indexExt2Word16_0_16s [labelCalc = inst_start + 4 + indexExt2Word16_0_16s; ]
     {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:2 tmp; } # Symbolic
DEST_W_AD: labelCalc 				  is dest=0x0 & ad=0x1 & bow=0x0 & AMASK & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16s [labelCalc = inst_start + 4 + indexExt2Word16_0_16s; ]
     {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:2 tmp; } # Symbolic
#---End of Depend ----#

# SR-relative (absolute value) destinations
DEST_W_AD: "&"^indexExtWord16_0_16 	  is dest=0x2 & ad=0x1 & bow=0x0 & AMASK; indexExtWord16_0_16
     {tmp:$(REG_SIZE) = indexExtWord16_0_16 & AMASK; export *:2 tmp;} # Absolute
#---Depends on SRC ---#
DEST_W_AD: "&"^indexExt2Word16_0_16   is dest=0x2 & ad=0x1 & bow=0x0 & AMASK & as=0x1 & ((src16_8_4>=0x0 & src16_8_4<=0x2) | (src16_8_4>=0x4 & src16_8_4<=0xF)) ; indexExtWord16_0_16 ; indexExt2Word16_0_16
     {tmp:$(REG_SIZE) = indexExt2Word16_0_16 & AMASK; export *:2 tmp;} # Absolute
DEST_W_AD: "&"^indexExt2Word16_0_16   is dest=0x2 & ad=0x1 & bow=0x0 & AMASK & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16
     {tmp:$(REG_SIZE) = indexExt2Word16_0_16 & AMASK; export *:2 tmp; } # Absolute
#---End of Depend ----#

#-----------------------------------------------
DEST_B_AD: DST8_0_4 		  			 is DST8_0_4 & dest_Direct_lo & ad=0x0 & bow=0x1
     { export DST8_0_4; }        # Word/Register Direct (Rn):
DEST_B_AD: DST8_0_4 			 		 is DST8_0_4 & dest_Direct_lo & dest_0_4=0 & ad=0x0 & bow=0x1  {tmp:$(REG_SIZE) = inst_next; DST8_0_4 = tmp:1 & 0xFF; export DST8_0_4;} # PC register accesses point to next instruction

DEST_B_AD: indexExtWord16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16s
     { tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + indexExtWord16_0_16s) & AMASK; export *:1 tmp;}
#---Depends on SRC ---#
DEST_B_AD: indexExt2Word16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x1 & AMASK & as=0x1 & ((src16_8_4>=0x0 & src16_8_4<=0x2) | (src16_8_4>=0x4 & src16_8_4<=0xF)) ; indexExtWord16_0_16 ; indexExt2Word16_0_16s
     { tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + indexExt2Word16_0_16s) & AMASK; export *:1 tmp;}
DEST_B_AD: indexExt2Word16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x1 & AMASK & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16s
     { tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + indexExt2Word16_0_16s) & AMASK; export *:1 tmp;}
# Source includes a register increment (@reg+) that applies to the destination (use of same register in source and dest, but not PC, SR, R3)
DEST_B_AD: indexExt2Word16_0_16s^"("^dest_Indexed16_0_4^")" is dest_Indexed16_0_4 & ad=0x1 & bow=0x1 & AMASK & as=0x3 & src16_8_4=dest_0_4 & (src16_8_4 = 1 | src16_8_4 >= 4) ; indexExt2Word16_0_16s
     {tmp:$(REG_SIZE) = (dest_Indexed16_0_4 + 2 + indexExt2Word16_0_16s) & AMASK; export *:1 tmp;}
#---End of Depend ----#

DEST_B_AD: labelCalc 				  is dest=0x0 & ad=0x1 & bow=0x1 & AMASK ; indexExtWord16_0_16s [labelCalc = inst_start + 2 + indexExtWord16_0_16s; ]
     {tmp:$(REG_SIZE) = labelCalc & AMASK; export *:1 tmp; } # Symbolic
#---Depends on SRC ---#
DEST_B_AD: labelCalc 				  is dest=0x0 & ad=0x1 & bow=0x1 & AMASK & as=0x1 & ((src16_8_4>=0x0 & src16_8_4<=0x2) | (src16_8_4>=0x4 & src16_8_4<=0xF)) ; indexExtWord16_0_16 ; indexExt2Word16_0_16s [labelCalc = inst_start + 4 + indexExt2Word16_0_16s; ]
     {tmp:$(REG_SIZE) = labelCalc & AMASK;export *:1 tmp; } # Symbolic
DEST_B_AD: labelCalc 				  is dest=0x0 & ad=0x1 & bow=0x1 & AMASK & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16s [labelCalc = inst_start + 4 + indexExt2Word16_0_16s; ]
     {tmp:$(REG_SIZE) = labelCalc & AMASK;export *:1 tmp; } # Symbolic
#---End of Depend ----#

DEST_B_AD: "&"^indexExtWord16_0_16 	  is dest=0x2 & ad=0x1 & bow=0x1 ; indexExtWord16_0_16
     {export *:1 indexExtWord16_0_16; } # Absolute
#---Depends on SRC ---#
DEST_B_AD: "&"^indexExt2Word16_0_16   is dest=0x2 & ad=0x1 & bow=0x1 & as=0x1 & ((src16_8_4>=0x0 & src16_8_4<=0x2) | (src16_8_4>=0x4 & src16_8_4<=0xF)) ; indexExtWord16_0_16 ; indexExt2Word16_0_16
     {export *:1 indexExt2Word16_0_16; } # Absolute
DEST_B_AD: "&"^indexExt2Word16_0_16   is dest=0x2 & ad=0x1 & bow=0x1 & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16
     {export *:1 indexExt2Word16_0_16; } # Absolute
#---End of Depend ----#


# For handling constant operands in CALL and BR instructions.
DirectAddr: "#"^label is indexExtWord16_0_16 [label = indexExtWord16_0_16 & 0xFFFE;] {export *:$(REG_SIZE) label; } # Align value to show and jump to actual target

# Following is only valid for double operand instructions, whose dest uses ad
tbl_bzero:			is ad=0 & reg_Direct16_0_4 & dest_Direct_lo {ztmp:1 = dest_Direct_lo; reg_Direct16_0_4 = 0; dest_Direct_lo = ztmp; }
tbl_bzero:			is epsilon {}

# Following is valid for single operand instructions whose dest uses as
tbl_bzero_singleop:			is as=0 & reg_Direct16_0_4 & dest_Direct_lo {ztmp:1 = dest_Direct_lo; reg_Direct16_0_4 = 0; dest_Direct_lo = ztmp; }
tbl_bzero_singleop:			is epsilon {}


@if REG_SIZE == "4"
tbl_wzero:			is ad=0 & reg_Direct16_0_4 & reg_Direct16_0_4W {ztmp:2 = reg_Direct16_0_4W; reg_Direct16_0_4 = 0; reg_Direct16_0_4W = ztmp; }
@endif
tbl_wzero:			is epsilon {}

#
# Post Processing
#    does correct increment of source register
#    Also catches when PC is being stored to and does the correct branching
#
postRegIncrement:   is as=0x3 & dest_0_4   & bow=0x0 & reg_InDirect16_0_4                { reg_InDirect16_0_4 = reg_InDirect16_0_4 + 2; }
postRegIncrement:   is as=0x3 & dest_0_4=1 & bow=0x0 & reg_InDirect16_0_4 & (op16_12_4=0x1 & op16_8_4=0x2 & op16_7_1=0x0)               { } # PUSH.W SP, SP modification covered by PUSH
postRegIncrement:   is as=0x3 & dest_0_4   & bow=0x1 & reg_InDirect16_0_4                 { reg_InDirect16_0_4 = reg_InDirect16_0_4 + 1; }
postRegIncrement:  	is as=0x3 & dest_0_4=1 & bow=0x1 & reg_InDirect16_0_4 { reg_InDirect16_0_4 = reg_InDirect16_0_4 + 2; }
postRegIncrement:  	is as=0x3 & dest_0_4=1 & bow=0x1 & reg_InDirect16_0_4 & (op16_12_4=0x1 & op16_8_4=0x2 & op16_7_1=0x0) { } # PUSH.B @SP+, SP modification covered by PUSH
postRegIncrement:   is as=0x3 & dest_0_4=0 & bow=0x0 & reg_InDirect16_0_4   { }     # PC is incremented by 2, but that is just to skip over the value
postRegIncrement:   is as=0x3 & dest_0_4=0 & bow=0x1 & reg_InDirect16_0_4   { }     # PC is incremented by 2, but that is just to skip over the value
postRegIncrement:   is as=0x3 & dest_0_4=2 & bow=0x1     { }
postRegIncrement:   is as=0x3 & dest_0_4=3 & bow=0x1     { }
postRegIncrement:   is as=0x3 & dest_0_4=2 & bow=0x0     { }
postRegIncrement:   is as=0x3 & dest_0_4=3 & bow=0x0     { }
postRegIncrement:   is as=0x0 & dest_0_4=0 & bow=0x0 & (op16_12_4!=0x1 | op16_8_4!=0x2 | op16_7_1!=0x0) { PC = PC & 0xFFFE; goto [PC]; } # If PC is modified, alter flow (except for PUSH instructions)
postRegIncrement:   is as=0x0 & dest_0_4=0 & bow=0x1 & (op16_12_4!=0x1 | op16_8_4!=0x2 | op16_7_1!=0x0) { PC = PC & 0xFE; goto [PC]; } # If PC is modified, alter flow (except for PUSH instructions)
postRegIncrement:   is as     & bow                       { }

# R2 and R3 are constant generators - post-increment not supported
postIncrement:               is as=0x3 & ctx_haveext=0 & src16_8_4=2 & bow=0x0 & ctx_al=0
{  }
postIncrement:               is as=0x3 & ctx_haveext=0 & src16_8_4=2 & bow=0x1 & ctx_al=0
{  }
postIncrement:               is as=0x3 & ctx_haveext=0 & src16_8_4=3 & bow=0x0 & ctx_al=0
{  }
postIncrement:               is as=0x3 & ctx_haveext=0 & src16_8_4=3 & bow=0x1 & ctx_al=0
{  }
postIncrement:               is as=0x3 & src16_8_4=2 & bow=0x0
{  }
postIncrement:               is as=0x3 & src16_8_4=2 & bow=0x1
{  }
postIncrement:               is as=0x3 & src16_8_4=3 & bow=0x0
{  }
postIncrement:               is as=0x3 & src16_8_4=3 & bow=0x1
{  }

postIncrement:  			 is as=0x3 & src16_8_4=0 & bow=0x1 & src_InDirect16_8_4
{  }     # PC is incremented by 2, but that is just to skip over the value
postIncrement:  			 is as=0x3 & src16_8_4=0 & bow=0x0 & src_InDirect16_8_4
{  }     # PC is incremented by 2, but that is just to skip over the value

postIncrement:  			 is as=0x3 & src16_8_4 & bow=0x0 & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 2;  }

postIncrement:  			 is as=0x3 & src16_8_4 & bow=0x1 & ctx_al=0  & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 4;  }
postIncrement:  			 is as=0x3 & src16_8_4=1 & bow=0x1 & ctx_al=0 & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 4;  }

postIncrement:  			 is as=0x3 & src16_8_4 & bow=0x1 & ctx_al=1  & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 1;  }
postIncrement:  			 is as=0x3 & src16_8_4=1 & bow=0x1 & ctx_al=1 & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 2;  }

postIncrement:  			 is as=0x3 & ctx_haveext=0 & src16_8_4 & bow=0x1 & ctx_al=0 & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 1;  }
postIncrement:  			 is as=0x3 & ctx_haveext=0 & src16_8_4=1 & bow=0x1 & ctx_al=0 & src_InDirect16_8_4
{ src_InDirect16_8_4 = src_InDirect16_8_4 + 2;  }

postIncrement:               is as & src16_8_4 & bow
{  }


#
# Zero Extends if the store is byte oriented, and a register is being stored to
zeroExtend: is dest_Direct_lo & dest_Direct16_0_4
{ dest_Direct16_0_4 = zext(dest_Direct_lo); }

#
# Post processing when destination is the PC - for byte operations
#
postIncrementStore:  			 is postIncrement & ad=0x0 & src_InDirect16_8_4 & as=0x3 & src16_8_4=1 & dest_Direct16_0_4=0x0 & bow=0x1 & ctx_al=1 & zeroExtend
{ build zeroExtend; build postIncrement; return [PC]; }
postIncrementStore:  			 is postIncrement & ad=0x0 & dest_Direct16_0_4=0x0 & bow=0x1 & ctx_al=1 & zeroExtend
{ build zeroExtend; build postIncrement; PC = PC & 0xFFFFFE; goto [PC];} # Writes to PC are rounded to alignment
postIncrementStore:              is postIncrement & ad=0x0 & bow=0x1 & ctx_al=1 & zeroExtend
{ build zeroExtend; build postIncrement; }

postIncrementStore:  			 is postIncrement & ctx_haveext=0 & ad=0x0 & src_InDirect16_8_4 & as=0x3 & src16_8_4=1 & dest_Direct16_0_4=0x0 & bow=0x1 & zeroExtend 
{ build zeroExtend; build postIncrement; return [PC]; }
postIncrementStore:  			 is postIncrement & ctx_haveext=0 & ad=0x0 & dest_Direct16_0_4=0x0 & bow=0x1 & zeroExtend # MOV.B any,PC
{ build zeroExtend; build postIncrement; PC = PC & 0xFE; goto [PC];} # Writes to PC are rounded to alignment
postIncrementStore:              is postIncrement & ctx_haveext=0 & ad=0x0 & bow=0x1 & zeroExtend
{ build zeroExtend; build postIncrement; }

postIncrementStore:  			 is postIncrement & ad=0x0 & src_InDirect16_8_4 & as=0x3 & src16_8_4=1 & dest_Direct16_0_4=0x0
{ build postIncrement; return [PC]; }
postIncrementStore:  			 is postIncrement & ad=0x0 & dest_Direct16_0_4=0x0
{ build postIncrement; PC = PC & 0xFFFE; goto [PC];} # Writes to PC are rounded to alignment
postIncrementStore:              is postIncrement & ad & bow
{ build postIncrement; }

#-----------------------------------------------
#
#	JUMP CONDITION (JCND)
#
#-----------------------------------------------

JCND: "NE"	is condition=0x0 {cndTst:1 = !$(ZERO); export cndTst;}                    # Not Equal/Zero (cleared)
JCND: "EQ"	is condition=0x1 {cndTst:1 = $(ZERO); export cndTst;}                    # Equal/Zero	 (set)
JCND: "NC"	is condition=0x2 {cndTst:1 = !$(CARRY); export cndTst;}                   # No Carry/Lower (cleared)
JCND: "C"	is condition=0x3 {cndTst:1 = $(CARRY); export cndTst;}                   # Carry/Higher or same (set)
JCND: "N"	is condition=0x4 {cndTst:1 = $(SIGN); export cndTst;}                    # Negative (set)
JCND: "GE"	is condition=0x5 {cndTst:1 = ($(SIGN) == $(OVERFLOW)); export cndTst;}    # Greater or equal (>=)
JCND: "L"	is condition=0x6 {cndTst:1 = ($(SIGN) != $(OVERFLOW)); export cndTst;}    # Less (<)
JCND: "MP"	is condition=0x7 {cndTst:1 = 0x1; export cndTst;}                               # Unconditional

#-----------------------------------------------
#
#	10 BIT OFFSET
#
#-----------------------------------------------

OFFSET_10BIT: offset10 is off16   [offset10 = inst_start + 2 + off16 * 2; ]
	{ export *:2 offset10;}
	
	
###################################################################################
#
#	Single-operand arithmetic
#	
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |   opcode   | B/W |   As    |     register    |
#   ------------------------------------------------------------------------------
###################################################################################

###################################################################################
#
#	RRC: Rotate right through carry
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     000    | B/W |   As    |     register    | 
:RRC^".W" REG_W_AS_DEST is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x0 & op16_7_1=0x0 & bow=0x0 & tbl_wzero & postRegIncrement) ... & REG_W_AS_DEST {
	# Operation Flags...
	$(OVERFLOW) = 0;	# V Flag is reset
	# Operation...
	tmp:1 = $(CARRY);
	$(CARRY) = REG_W_AS_DEST[0,1];
	REG_W_AS_DEST = ((zext(tmp) << 0xF) | (REG_W_AS_DEST >> 0x1));
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (REG_W_AS_DEST s< 0x0);			# S Flag
	$(ZERO) = (REG_W_AS_DEST == 0x0);			# Z Flag
	build postRegIncrement;
}


:RRC^".B" REG_B_AS_DEST is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x0 & op16_7_1=0x0 & bow=0x1 & tbl_bzero_singleop & postRegIncrement) ... & REG_B_AS_DEST {
	# Operation Flags...
	$(OVERFLOW) = 0;	# V Flag is reset
	# Operation...
	tmp:1 = $(CARRY);
	$(CARRY) = (REG_B_AS_DEST & 0x1);
	REG_B_AS_DEST = ((tmp << 0x7) | (REG_B_AS_DEST >> 0x1));
	build tbl_bzero_singleop;
	# Result Flags...
	$(SIGN) = (REG_B_AS_DEST s< 0x0);			# S Flag
	$(ZERO) = (REG_B_AS_DEST == 0x0);			# Z Flag
	build postRegIncrement;
}


###################################################################################
#
#	SWPB: Swap bytes
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     001    |  0  |   As    |     register    | 
:SWPB REG_W_AS_DEST is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x0 & op16_7_1=0x1 & bow=0x0 & tbl_wzero & postRegIncrement) ... & REG_W_AS_DEST {
	lowByte:1 = REG_W_AS_DEST[0,8];
	highByte:1 = REG_W_AS_DEST[8,8];
	REG_W_AS_DEST = (((zext(lowByte)) << 0x8) | zext(highByte));
	build tbl_wzero;
	#Status bits are not affected
	build postRegIncrement;
}



###################################################################################
#
#	RRA: Rotate right arithmetic
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     010    | B/W |   As    |     register    | 
:RRA^".W" REG_W_AS_DEST is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x1 & op16_7_1=0x0 & bow=0x0 & tbl_wzero & postRegIncrement) ... & REG_W_AS_DEST {
	# Operation Flags...
	$(OVERFLOW) = 0x0;					# V Flag (reset)
	# Operation...
	$(CARRY) = REG_W_AS_DEST[0,1];
	MSB:2 = REG_W_AS_DEST >> 0xF;
	REG_W_AS_DEST = ((MSB << 0xF) | (REG_W_AS_DEST >> 0x1));
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (REG_W_AS_DEST s< 0x0);			# S Flag
	$(ZERO) = (REG_W_AS_DEST == 0x0);			# Z Flag
	build postRegIncrement;
}


:RRA^".B" REG_B_AS_DEST is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x1 & op16_7_1=0x0 & bow=0x1 & tbl_bzero_singleop & postRegIncrement) ... & REG_B_AS_DEST {
	# Operation Flags...
	$(OVERFLOW) = 0x0;					# V Flag (reset)
	# Operation...
	$(CARRY) = (REG_B_AS_DEST & 0x1);
	MSB:1 = REG_B_AS_DEST >> 0x7;
	REG_B_AS_DEST = ((MSB << 0x7) | (REG_B_AS_DEST >> 0x1));
	build tbl_bzero_singleop;
	# Result Flags...
	$(SIGN) = (REG_B_AS_DEST s< 0x0);			# S Flag
	$(ZERO) = (REG_B_AS_DEST == 0x0);			# Z Flag
	build postRegIncrement;
}


###################################################################################
#
#	SXT: Sign extend byte to word
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     011    |  0  |   As    |     register    | 
:SXT REG_W_AS_DEST is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x1 & op16_7_1=0x1 & bow=0x0 & tbl_wzero & postRegIncrement) ... & REG_W_AS_DEST {
	# Operation Flags...
	$(OVERFLOW) = 0x0;						# V Flag
	# Operation...	
	byteVal:1 = REG_W_AS_DEST[0,8];
	REG_W_AS_DEST = sext(byteVal);
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (REG_W_AS_DEST s< 0x0);			# S Flag
	$(ZERO) = (REG_W_AS_DEST == 0x0);			# Z Flag
	$(CARRY) = (REG_W_AS_DEST != 0x0);			# C Flag
	build postRegIncrement;
}


###################################################################################
#
#	PUSH: Push value onto stack
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     100    | B/W |   As    |     register    | 
:PUSH^".W" REG_W_AS is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x2 & op16_7_1=0x0 & bow=0x0 & postRegIncrement & AMASK) ... & REG_W_AS {
	*:2 ((SP - 0x2) & AMASK) = REG_W_AS; # Mask for possible unaligned SP
	SP = SP - 0x2; # Actual behaviour, in conflict with documentation
	#Status bits are not affected
	build postRegIncrement;
}

:PUSH^".B" REG_B_AS is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x2 & op16_7_1=0x0 & bow=0x1 & postRegIncrement) ... & REG_B_AS {
	*:1 (SP - 0x2) = REG_B_AS;
	SP = SP - 0x2; # Actual behaviour, in conflict with documentation
	#Status bits are not affected
	build postRegIncrement;
}	


###################################################################################
#
#	CALL: Subroutine call; push PC and move source to PC
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     101    |  0  |   As    |     register    | 
:CALL REG_W_AS is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x2 & op16_7_1=0x1 & bow=0x0 & postRegIncrement & AMASK) ... & REG_W_AS {
    PC = zext(REG_W_AS) & 0xFFFFFFFE:$(REG_SIZE); # PC assignment before SP modification (relevant for CALL SP). Behaviour differs from documentation
    SP = SP - 0x2;
    *:2 (SP & AMASK) = inst_next;
    build postRegIncrement;
    call [PC];
    #Status bits are not affected
}

:CALL DirectAddr       is ctx_haveext=0 & (op16_12_4=0x1 & op16_8_4=0x2 & op16_7_1=0x1 & reg16_0_4=0x0 & as=0x3 & bow=0x0 & postRegIncrement & AMASK); DirectAddr {
    PC = &DirectAddr; # PC assignment before SP modification (relevant for CALL SP). Behaviour differs from documentation
    SP = SP - 0x2;
    *:2 (SP & AMASK) = inst_next;
    build postRegIncrement;
    call DirectAddr;
    #Status bits are not affected
}



###################################################################################
#
#	RETI: Return from interrupt; pop SR then pop PC
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 0  | 1  | 0  | 0  |     110    |  0  |   00    |       0000      | 
:RETI is ctx_haveext=0 & op16_12_4=0x1 & op16_8_4=0x3 & op16_7_1=0x0 & as=0x0 & bow=0x0 & op16_0_4=0x0 & op16_4_4=0x0 & AMASK {
@if REG_SIZE == "2"
	SR = *:2 (SP & AMASK);
	SP = SP + 0x2;
	PC = (*:2 (SP & AMASK)) & AMASK;
@else
	tmp:$(REG_SIZE) = zext(*:2 SP);
	SR = zext(tmp[0,12]);
	SP = SP + 0x2;
	PC = zext(*:2 SP) | ((tmp & 0xF000) << 4);
@endif	
	SP = SP + 0x2;
	return [PC];
	#Status bits are restored from system stack
}

###################################################################################
#
#	Conditional jump; PC = PC + 2*offset
#	
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 1  |  condition   |   			10-bit signed offset		     |
#   ------------------------------------------------------------------------------
###################################################################################

###################################################################################
#
#	J^JumpCondition 10-bit_signed_offset
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0  | 0  | 1  |  condition   |   			10-bit signed offset		     | 
:J^JCND OFFSET_10BIT is ctx_haveext=0 & op16_13_3=0x1 & JCND & OFFSET_10BIT {
	if (JCND) goto OFFSET_10BIT;
	#Status bits are not affected
}

:JMP OFFSET_10BIT is ctx_haveext=0 & op16_13_3=0x1 & condition=0x7 & OFFSET_10BIT {
	goto OFFSET_10BIT;
	#Status bits are not affected
}

###################################################################################
#
#	Two-operand arithmetic
#	
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	|       opcode      |     source      | Ad | B/W |   As    |   destination   |
#   ------------------------------------------------------------------------------
###################################################################################

###################################################################################
#
#	MOV: Move source to destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0    1    0    0  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Branch
:BR SRC_W_AS   is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x0 & ad=0x0 & dest_Direct16_0_4=0x0 & postIncrement) ... & SRC_W_AS ... {
	PC = zext(SRC_W_AS) & 0xFFFFFFFE:$(REG_SIZE);
	build postIncrement; # needed before branch
	goto [PC];
	#Status bits are not affected
}

# Branch to an immediate value
:BR DirectAddr       is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x0 & ad=0x0 & dest_Direct16_0_4=0x0 & src_Direct16_8_4=0x0 & as=0x3); DirectAddr {
	PC = &DirectAddr;
    goto DirectAddr;
    #Status bits are not affected
}

# No operation
:NOP           is ctx_haveext=0 & op16_12_4=0x4 & bow=0x0 & ad=0x0 & as=0x0 & dest_Direct16_0_4=0x3 & src_Direct16_8_4=0x3 & postIncrement {
	#Status bits are not affected
	build postIncrement;
}

# Pop word from stack
:POP^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x0 & (ad=0x1 | dest_Direct16_0_4) & as=0x3 & src_Direct16_8_4=0x1 & tbl_wzero & AMASK) ... & DEST_W_AD ... {
	DEST_W_AD = *:2 (SP & AMASK);
	build tbl_wzero;
	SP = SP + 0x2;
	#Status bits are not affected
}

# Pop byte from stack
:POP^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x1 & (ad=0x1 | dest_Direct16_0_4) & as=0x3 & src_Direct16_8_4=0x1 & tbl_bzero) ... & DEST_B_AD ... {
	DEST_B_AD = *:1 SP;
	build tbl_bzero;
	SP = SP + 0x2;
	#Status bits are not affected
}

# POP.W SP - increment occurs after read but before write, and is therefore lost
:POP^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x0 & ad=0x0 & dest_Direct16_0_4 & as=0x3 & src_Direct16_8_4=0x1 & dest_Direct16_0_4=0x1 & tbl_wzero & AMASK) ... & DEST_W_AD ... {
	DEST_W_AD = *:2 (SP & AMASK); # Unaligned word memory accesses round down
	build tbl_wzero;
	#Status bits are not affected
}

# POP.B SP - increment occurs after read but before write, and is therefore lost
:POP^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x1 & ad=0x0 & dest_Direct16_0_4 & as=0x3 & src_Direct16_8_4=0x1 & dest_Direct16_0_4=0x1 & tbl_bzero) ... & DEST_B_AD ... {
	DEST_B_AD = *:1 SP;
	build tbl_bzero;
	#Status bits are not affected
}

# POP.B PC - writes to PC are rounded down, but base instruction does not use postIncrementStore to handle this case
:POP^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x1 & ad=0x0 & dest_Direct16_0_4 & as=0x3 & src_Direct16_8_4=0x1 & dest_Direct16_0_4=0x0 & tbl_bzero) ... & DEST_B_AD ... {
	DEST_B_AD = *:1 SP;
	build tbl_bzero;
	SP = SP + 0x2;
	PC = PC & 0xFFFFFFFE:$(REG_SIZE);
	goto [PC];
	#Status bits are not affected
}

# Return from subroutine
:RET           is ctx_haveext=0 & op16_12_4=0x4 & bow=0x0 & ad=0x0 & as=0x3 & dest_Direct16_0_4=0x0 & src_Direct16_8_4=0x1 & AMASK {
	PC = zext(*:2 (SP & AMASK)) & AMASK; # Stack pointer can be misaligned, and subsequent write to PC rounds to alignment
	SP = SP + 0x2;
	return [PC];
	#Status bits are not affected
}

#------------------
#	SRC Word
#------------------
:MOV^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	DEST_W_AD = SRC_W_AS;
	build tbl_wzero;
	#Status bits are not affected
	build postIncrementStore;
}


#------------------
#   SRC Byte
#------------------
:MOV^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x4 & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	DEST_B_AD = SRC_B_AS;
	build tbl_bzero;
	#Status bits are not affected
	build postIncrementStore;
}


###################################################################################
#
#	ADD: Add source to destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0    1    0    1  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Increment word
:INC^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x5 & as=0x1 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	$(CARRY) = carry(DEST_W_AD,1); 	 	# C Flag
	$(OVERFLOW) = scarry(DEST_W_AD,1); 	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD + 0x1;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Increment byte
:INC^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x5 & as=0x1 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	$(CARRY) = carry(DEST_B_AD,1); 	 	# C Flag
	$(OVERFLOW) = scarry(DEST_B_AD,1); 	# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD + 0x1;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Double increment word
:INCD^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x5 & as=0x2 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	$(CARRY) = carry(DEST_W_AD,2); 	 	# C Flag
	$(OVERFLOW) = scarry(DEST_W_AD,2); 	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD + 0x2;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Double increment byte
:INCD^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x5 & as=0x2 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	$(CARRY) = carry(DEST_B_AD,2); 	 	# C Flag
	$(OVERFLOW) = scarry(DEST_B_AD,2); 	# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD + 0x2;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Rotate left arithmetic (left shift once) word
:RLA^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x5 & as=0x0 & ad=0x0 & src_Direct16_8_4=dest_Direct16_0_4 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	$(CARRY) = carry(DEST_W_AD, DEST_W_AD); 	 	# C Flag
	$(OVERFLOW) = scarry(DEST_W_AD, DEST_W_AD); 	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD + DEST_W_AD;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Rotate left arithmetic (left shift once) byte
:RLA^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x5 & as=0x0 & ad=0x0 & src_Direct16_8_4=dest_Direct16_0_4 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	$(CARRY) = carry(DEST_B_AD, DEST_B_AD); 	 	# C Flag
	$(OVERFLOW) = scarry(DEST_B_AD, DEST_B_AD); 	# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD + DEST_B_AD;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Word
#------------------
:ADD^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x5 & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation Flags...
	tmp_carry:1 = carry(SRC_W_AS, DEST_W_AD); 	 	# C Flag
	tmp_overflow:1 = scarry(SRC_W_AS, DEST_W_AD); 	# V Flag
	# Operation...
	DEST_W_AD = SRC_W_AS + DEST_W_AD;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	build postIncrementStore;
}


#------------------
#	16 bit SRC Byte
#------------------
:ADD^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x5 & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation Flags...
	tmp_carry:1 = carry(SRC_B_AS, DEST_B_AD); 	 	# C Flag
	tmp_overflow:1 = scarry(SRC_B_AS, DEST_B_AD); 	# V Flag
	# Operation...
	DEST_B_AD = SRC_B_AS + DEST_B_AD;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	build postIncrementStore;
}


###################################################################################
#
#	ADDC: Add source and carry to destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0    1    1    0  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Add carry to word
:ADC^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x6 & as=0x0 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	tmp_carry:1 = carry(DEST_W_AD,zext($(CARRY)));		 #C Flag
 	tmp_overflow:1 = scarry(DEST_W_AD, zext($(CARRY))); #V Flag
 	# Operation...
	DEST_W_AD = DEST_W_AD + zext($(CARRY));
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	build postIncrementStore;
}

# Add carry to byte
:ADC^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x6 & as=0x0 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	tmp_carry:1 = carry(DEST_B_AD,$(CARRY));		 #C Flag
 	tmp_overflow:1 = scarry(DEST_B_AD,$(CARRY)); #V Flag
 	# Operation...
	DEST_B_AD = DEST_B_AD + $(CARRY);
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	build postIncrementStore;
}

# Rotate word left through carry
:RLC^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x6 & as=0x0 & ad=0x0 & src_Direct16_8_4=dest_Direct16_0_4 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	tmp_carry:1 = (carry(DEST_W_AD,zext($(CARRY))) || carry(DEST_W_AD,DEST_W_AD + zext($(CARRY))));		 #C Flag
 	tmp_overflow:1 = (scarry(DEST_W_AD,zext($(CARRY))) || scarry(DEST_W_AD,DEST_W_AD + zext($(CARRY)))); #V Flag
 	# Operation...
	DEST_W_AD = DEST_W_AD + DEST_W_AD + zext($(CARRY));
	build tbl_wzero;
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Rotate byte left through carry
:RLC^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x6 & as=0x0 & ad=0x0 & src_Direct16_8_4=dest_Direct16_0_4 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	tmp_carry:1 = (carry(DEST_B_AD, $(CARRY)) || carry(DEST_B_AD,DEST_B_AD + $(CARRY)));		 #C Flag
 	$(OVERFLOW) = (scarry(DEST_B_AD, $(CARRY)) || scarry(DEST_B_AD,DEST_B_AD + $(CARRY))); #V Flag
 	# Operation...
	DEST_B_AD = DEST_B_AD + DEST_B_AD + $(CARRY);
	build tbl_bzero;
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

macro addWithCarry(src, dest){
    local incoming_carry = zext($(CARRY));
    local sum_without_carry = src + dest;
    
    local tmp_carry:1 = carry(src, dest);
    tmp_carry = tmp_carry || carry(sum_without_carry, incoming_carry);
    
    local tmp_overflow:1 = scarry(src, dest);
    tmp_overflow = tmp_overflow ^^ scarry(sum_without_carry, incoming_carry);
    
    dest = sum_without_carry + incoming_carry;
    $(CARRY) = tmp_carry;
    $(OVERFLOW) = tmp_overflow;
 }


#------------------
#	16 bit SRC Word
#------------------
:ADDC^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x6 & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	addWithCarry(SRC_W_AS,DEST_W_AD);
	build tbl_wzero;
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Byte
#------------------
:ADDC^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x6 & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	addWithCarry(SRC_B_AS, DEST_B_AD);
	build tbl_bzero;
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}


###################################################################################
#
#	SUBC: Subtract source from destination (with carry)
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 0    1    1    1  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Subtract borrow from word
:SBC^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x7 & as=0x0 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	brw:2 = 1 - zext( $(CARRY) );
	$(CARRY) = (brw <= DEST_W_AD);		# Carry flag is NOT set if there is a borrow
	$(OVERFLOW) = sborrow(DEST_W_AD, brw);	
	# Operation...
	DEST_W_AD = DEST_W_AD - brw;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Subtract borrow from byte
:SBC^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x7 & as=0x0 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	brw:1 = 1 - $(CARRY);
    $(CARRY) = (brw <= DEST_B_AD);             # Carry flag is NOT set if there is a borrow
	$(OVERFLOW) = sborrow(DEST_B_AD, brw);	
	# Operation...
	DEST_B_AD = DEST_B_AD - brw;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

macro subtractWithCarry(dest, src){
    local incoming_carry = zext($(CARRY));
    local not_incoming_carry = zext(!($(CARRY)));
    local diff_without_carry = dest - src;
    
    local tmp_carry:1 = dest > src;
    tmp_carry = tmp_carry || (diff_without_carry < incoming_carry);
    
    local tmp_overflow:1 = sborrow(dest, src);
    tmp_overflow = tmp_overflow ^^ sborrow(diff_without_carry, not_incoming_carry);
    
    dest = diff_without_carry - not_incoming_carry;
    $(CARRY) = tmp_carry;
    $(OVERFLOW) = tmp_overflow;
}

#------------------
#	16 bit SRC Word
#------------------
:SUBC^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x7 & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	subtractWithCarry(DEST_W_AD,SRC_W_AS);
	build tbl_wzero;
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}


#------------------
#	16 bit SRC Byte
#------------------
:SUBC^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x7 & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	subtractWithCarry(DEST_B_AD,SRC_B_AS);
	build tbl_bzero;
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}


###################################################################################
#
#	SUB: Subtract source from destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    0    0    0  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Decrement word
:DEC^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x8 & as=0x1 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	$(CARRY) = (0x0 != DEST_W_AD);			# C Flag
	$(OVERFLOW) = (0x8000 == DEST_W_AD);	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD - 0x1;		
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Decrement byte
:DEC^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x8 & as=0x1 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	$(CARRY) = (0x0 != DEST_B_AD);			# C Flag
	$(OVERFLOW) = (0x80 == DEST_B_AD);		# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD - 0x1;		
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Double decrement word
:DECD^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x8 & as=0x2 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	$(CARRY) = ((0x0 != DEST_W_AD) && (0x1 != DEST_W_AD));			# C Flag
	$(OVERFLOW) = ((0x8000 == DEST_W_AD) || (0x8001 == DEST_W_AD));	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD - 0x2;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Double decrement byte
:DECD^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x8 & as=0x2 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	$(CARRY) = ((0x0 != DEST_B_AD) && (0x1 != DEST_B_AD));			# C Flag
	$(OVERFLOW) = ((0x80 == DEST_B_AD) || (0x81 == DEST_B_AD));		# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD - 0x2;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Word
#------------------
:SUB^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x8 & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation Flags...
	tmp_carry:1 = (SRC_W_AS <= DEST_W_AD);		# Carry is NOT set if there is a borrow
	tmp_overflow:1 = sborrow(DEST_W_AD, SRC_W_AS);								# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD - SRC_W_AS;		
	build tbl_wzero;
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}


#------------------
#	16 bit SRC Byte
#------------------
:SUB^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x8 & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation Flags...
	tmp_carry:1 = (SRC_B_AS <= DEST_B_AD);		# Carry is NOT set if there is a borrow
	tmp_overflow:1 = sborrow(DEST_B_AD, SRC_B_AS);									# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD - SRC_B_AS;		
	build tbl_bzero;
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	build postIncrementStore;
}


###################################################################################
#
#	CMP: Compare (pretend to subtract) source from destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    0    0    1  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Test word
:TST^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x9 & as=0x0 & src_Direct16_8_4=0x3 & bow=0x0 & postIncrement) ... & DEST_W_AD ... {
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	# Operation Flags...
	$(CARRY) = 1;		# Carry is NOT set if there is a borrow
	$(OVERFLOW) = 0;	# V Flag
	build postIncrement;
}

# Test byte
:TST^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x9 & as=0x0 & src_Direct16_8_4=0x3 & bow=0x1 & postIncrement) ... & DEST_B_AD ... {
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	# Operation Flags...
	$(CARRY) = 1;		
	$(OVERFLOW) = 0;	
	build postIncrement;
}

#------------------
#	16 bit SRC Word
#------------------
:CMP^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0x9 & bow=0x0 & postIncrement) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation Flags...
	tmp_carry:1 = (SRC_W_AS <= DEST_W_AD);		# Carry is NOT set if there is a borrow
	tmp_overflow:1 = sborrow(DEST_W_AD, SRC_W_AS);	# V Flag
	# Operation...
	result:2 = (DEST_W_AD - SRC_W_AS);
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (result s< 0x0);			# S Flag
	$(ZERO) = (result == 0x0);			# Z Flag
	build postIncrement;
}


#------------------
#	16 bit SRC Byte
#------------------
:CMP^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0x9 & bow=0x1 & postIncrement) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation Flags...
	tmp_carry:1 = (SRC_B_AS <= DEST_B_AD);		# Carry is NOT set if there is a borrow
	tmp_overflow:1 = sborrow(DEST_B_AD, SRC_B_AS);	# V Flag
	# Operation...
	result:1 = (DEST_B_AD - SRC_B_AS);
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (result s< 0x0);			# S Flag
	$(ZERO) = (result == 0x0);			# Z Flag
	build postIncrement;
}


###################################################################################
#
#	DADD: Decimal add source to destination (with carry)
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    0    1    0  |     source      | Ad | B/W |   As    |   destination   | 
#----------------------------------------------------------------------------------------------------------------
# These decimal add instructions appear to lack supporting BCD p-code operations to easily handle the operation and flags.
#----------------------------------------------------------------------------------------------------------------
#-----------------------
# Emulated instructions
#-----------------------
# Decimal add carry to word
:DADC^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xA & as=0x0 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation...
	dst_nibble0:2 = DEST_W_AD & 0xf;
	dst_nibble1:2 = (DEST_W_AD >> 4) & 0xf;
	dst_nibble2:2 = (DEST_W_AD >> 8) & 0xf;
	dst_nibble3:2 = (DEST_W_AD >> 12) & 0xf;

	res_nibble0:2 = dst_nibble0 + zext($(CARRY));
	carry_nibble0:2 = zext(res_nibble0 > 9);
	res_nibble0 = (res_nibble0 - carry_nibble0 * 10) & 0xf;

	res_nibble1:2 = dst_nibble1 + carry_nibble0;
	carry_nibble1:2 = zext(res_nibble1 > 9);
	res_nibble1 = (res_nibble1 - carry_nibble1 * 10) & 0xf;

	res_nibble2:2 = dst_nibble2 + carry_nibble1;
	carry_nibble2:2 = zext(res_nibble2 > 9);
	res_nibble2 = (res_nibble2 - carry_nibble2 * 10) & 0xf;

	res_nibble3:2 = dst_nibble3 + carry_nibble2;
	tmp_carry:1 = res_nibble3 > 9;
	carry_nibble3:2 = zext(res_nibble3 > 9);
	res_nibble3 = (res_nibble3 - carry_nibble3 * 10) & 0xf;

	tmp_res:2 = (res_nibble3 << 12) + (res_nibble2 << 8) + (res_nibble1 << 4) + res_nibble0;
	DEST_W_AD = tmp_res;

	build tbl_wzero;
	# Operation Flags...
	$(CARRY) = tmp_carry;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

# Decimal add carry to byte
:DADC^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xA & as=0x0 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation...
	dst_nibble0:1 = DEST_B_AD & 0xf;
	dst_nibble1:1 = (DEST_B_AD >> 4) & 0xf;

	res_nibble0:1 = dst_nibble0 + zext($(CARRY));
	carry_nibble0:1 = zext(res_nibble0 > 9);
	res_nibble0 = (res_nibble0 - carry_nibble0 * 10) & 0xf;

	res_nibble1:1 = dst_nibble1 + carry_nibble0;
	tmp_carry:1 = res_nibble1 > 9;
	carry_nibble1:1 = zext(res_nibble1 > 9);
	res_nibble1 = (res_nibble1 - carry_nibble1 * 10) & 0xf;

	tmp_res:1 = (res_nibble1 << 4) + res_nibble0;
	DEST_B_AD = tmp_res;

	build tbl_bzero;
	# Operation Flags...
	$(CARRY) = tmp_carry;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);		# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);		# Z Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Word
#------------------
:DADD^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xA & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation...
	src_nibble0:2 = SRC_W_AS & 0xf;
	src_nibble1:2 = (SRC_W_AS >> 4) & 0xf;
	src_nibble2:2 = (SRC_W_AS >> 8) & 0xf;
	src_nibble3:2 = (SRC_W_AS >> 12) & 0xf;
	dst_nibble0:2 = DEST_W_AD & 0xf;
	dst_nibble1:2 = (DEST_W_AD >> 4) & 0xf;
	dst_nibble2:2 = (DEST_W_AD >> 8) & 0xf;
	dst_nibble3:2 = (DEST_W_AD >> 12) & 0xf;

	res_nibble0:2 = src_nibble0 + dst_nibble0 + zext($(CARRY));
	carry_nibble0:2 = zext(res_nibble0 > 9);
	res_nibble0 = (res_nibble0 - carry_nibble0 * 10) & 0xf;

	res_nibble1:2 = src_nibble1 + dst_nibble1 + carry_nibble0;
	carry_nibble1:2 = zext(res_nibble1 > 9);
	res_nibble1 = (res_nibble1 - carry_nibble1 * 10) & 0xf;

	res_nibble2:2 = src_nibble2 + dst_nibble2 + carry_nibble1;
	carry_nibble2:2 = zext(res_nibble2 > 9);
	res_nibble2 = (res_nibble2 - carry_nibble2 * 10) & 0xf;

	res_nibble3:2 = src_nibble3 + dst_nibble3 + carry_nibble2;
	tmp_carry:1 = res_nibble3 > 9;
	carry_nibble3:2 = zext(res_nibble3 > 9);
	res_nibble3 = (res_nibble3 - carry_nibble3 * 10) & 0xf;

	tmp_res:2 = (res_nibble3 << 12) + (res_nibble2 << 8) + (res_nibble1 << 4) + res_nibble0;
	DEST_W_AD = tmp_res;

	build tbl_wzero;
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Byte
#------------------
:DADD^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xA & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation...
	src_nibble0:1 = SRC_B_AS & 0xf;
	src_nibble1:1 = (SRC_B_AS >> 4) & 0xf;
	dst_nibble0:1 = DEST_B_AD & 0xf;
	dst_nibble1:1 = (DEST_B_AD >> 4) & 0xf;

	res_nibble0:1 = src_nibble0 + dst_nibble0 + zext($(CARRY));
	carry_nibble0:1 = zext(res_nibble0 > 9);
	res_nibble0 = (res_nibble0 - carry_nibble0 * 10) & 0xf;

	res_nibble1:1 = src_nibble1 + dst_nibble1 + carry_nibble0;
	tmp_carry:1 = res_nibble1 > 9;
	carry_nibble1:1 = zext(res_nibble1 > 9);
	res_nibble1 = (res_nibble1 - carry_nibble1 * 10) & 0xf;

	tmp_res:1 = (res_nibble1 << 4) + res_nibble0;
	DEST_B_AD = tmp_res;

	build tbl_bzero;
	# Result Flags...
	$(CARRY) = tmp_carry;
	$(SIGN) = (tmp_res s< 0x0);		# S Flag
	$(ZERO) = (tmp_res == 0x0);		# Z Flag
	build postIncrementStore;
}


###################################################################################
#
#	BIT: Test bits of source AND destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    0    1    1  |     source      | Ad | B/W |   As    |   destination   | 
#------------------
#	16 bit SRC Word
#------------------
:BIT^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xB & bow=0x0 & postIncrement) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation...
	result:2 = DEST_W_AD & SRC_W_AS;
	# Operation Flags...
	$(OVERFLOW) = 0x0;					# V Flag (reset)
	# Result Flags...
	$(CARRY) = (result != 0x0);			# C Flag
	$(SIGN) = (result s< 0x0);			# S Flag
	$(ZERO) = (result == 0x0);			# Z Flag
	build postIncrement;
}


#------------------
#	16 bit SRC Byte
#------------------
:BIT^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xB & bow=0x1 & postIncrement) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation...
	result:1 = DEST_B_AD & SRC_B_AS;
	# Operation Flags...
	$(OVERFLOW) = 0x0;					# V Flag (reset)
	# Result Flags...
	$(CARRY) = (result != 0x0);			# C Flag
	$(SIGN) = (result s< 0x0);			# S Flag
	$(ZERO) = (result == 0x0);			# Z Flag
	build postIncrement;
}


###################################################################################
#
#	BIC: Bit clear (dest &= ~src)
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    1    0    0  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Clear carry bit
:CLRC	is ctx_haveext=0 & op16_12_4=0xC & as=0x1 & src_Direct16_8_4=0x3 & ad=0x0 & dest_Direct16_0_4=0x2 & bow=0x0 & postIncrementStore {
	$(CARRY) = 0;
	build postIncrementStore;
}

# Clear sign bit
:CLRN	is ctx_haveext=0 & op16_12_4=0xC & as=0x2 & src_Direct16_8_4=0x2 & ad=0x0 & dest_Direct16_0_4=0x2 & bow=0x0 & postIncrementStore {
	$(SIGN) = 0;
	build postIncrementStore;
}

# Clear zero bit
:CLRZ	is ctx_haveext=0 & op16_12_4=0xC & as=0x2 & src_Direct16_8_4=0x3 & ad=0x0 & dest_Direct16_0_4=0x2 & bow=0x0 & postIncrementStore {
	$(ZERO) = 0;
	build postIncrementStore;
}

# Disable interrupts
:DINT	is ctx_haveext=0 & op16_12_4=0xC & as=0x3 & src_Direct16_8_4=0x2 & ad=0x0 & dest_Direct16_0_4=0x2 & postIncrementStore {
	$(GIE) = 0;
	build postIncrementStore;
}

#------------------
#	16 bit SRC Word
#------------------
:BIC^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xC & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	DEST_W_AD = (~SRC_W_AS) & DEST_W_AD;
	build tbl_wzero;
	#Status bits are not affected
	build postIncrementStore;
}


#------------------
#	16 bit SRC Byte
#------------------
:BIC^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xC & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	DEST_B_AD = (~SRC_B_AS) & DEST_B_AD;
	build tbl_bzero;
	#Status bits are not affected
	build postIncrementStore;
}


###################################################################################
#
#	BIS: Bit set (logical OR)
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    1    0    1  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Enable interrupts
:EINT	is ctx_haveext=0 & op16_12_4=0xD & as=0x3 & src_Direct16_8_4=0x2 & ad=0x0 & dest_Direct16_0_4=0x2 & postIncrementStore {
	$(GIE) = 1;
	build postIncrementStore;
}

# Set carry bit
:SETC 	is ctx_haveext=0 & (op16_12_4=0xD & as=0x1 & src_Direct16_8_4=0x3 & ad=0x0 & dest_Direct16_0_4=0x2 & bow=0x0 & postIncrementStore) {
	$(CARRY) = 1;
	build postIncrementStore;
}

# Set sign bit
:SETN 	is ctx_haveext=0 & (op16_12_4=0xD & as=0x2 & src_Direct16_8_4=0x2 & ad=0x0 & dest_Direct16_0_4=0x2 & bow=0x0 & postIncrementStore) {
	$(SIGN) = 1;
	build postIncrementStore;
}

# Set zero bit
:SETZ 	is ctx_haveext=0 & (op16_12_4=0xD & as=0x2 & src_Direct16_8_4=0x3 & ad=0x0 & dest_Direct16_0_4=0x2 & bow=0x0 & postIncrementStore) {
	$(ZERO) = 1;
	build postIncrementStore;
}

#------------------
#	16 bit SRC Word
#------------------
:BIS^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xD & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	DEST_W_AD = SRC_W_AS | DEST_W_AD;
	build tbl_wzero;
	#Status bits are not affected
	build postIncrementStore;
}


#------------------
#	16 bit SRC Byte
#------------------
:BIS^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xD & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	DEST_B_AD = SRC_B_AS | DEST_B_AD;
	build tbl_bzero;
	#Status bits are not affected
	build postIncrementStore;
}



###################################################################################
#
#	XOR: Exclusive or source with destination
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3 | 2 | 1 |  0  |
#	------------------------------------------------------------------------------
#	| 1    1    1    0  |     source      | Ad | B/W |   As    |   destination   | 
#-----------------------
# Emulated instructions
#-----------------------
# Invert word
:INV^".W" DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xE & as=0x3 & src_Direct16_8_4=0x3 & bow=0x0 & tbl_wzero & postIncrementStore) ... & DEST_W_AD ... {
	# Operation Flags...
	$(OVERFLOW) = (DEST_W_AD s< 0x0);	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD ^ 0xFFFF;
	build tbl_wzero;
	# Result Flags...
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	$(CARRY) = (DEST_W_AD != 0x0);			# C Flag
	build postIncrementStore;
}

# Invert byte
:INV^".B" DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xE & as=0x3 & src_Direct16_8_4=0x3 & bow=0x1 & tbl_bzero & postIncrementStore) ... & DEST_B_AD ... {
	# Operation Flags...
	$(OVERFLOW) = (DEST_B_AD s< 0x0);	# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD ^ 0xFF;
	build tbl_bzero;
	# Result Flags...
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	$(CARRY) = (DEST_B_AD != 0x0);			# C Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Word
#------------------
:XOR^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xE & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation Flags...
	tmp_overflow:1 = ((DEST_W_AD s< 0x0) && (SRC_W_AS s< 0x0)) ;	# V Flag
	# Operation...
	DEST_W_AD = DEST_W_AD ^ SRC_W_AS;
	build tbl_wzero;
	# Result Flags...
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (DEST_W_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_W_AD == 0x0);			# Z Flag
	$(CARRY) = (DEST_W_AD != 0x0);			# C Flag
	build postIncrementStore;
}

#------------------
#	16 bit SRC Byte
#------------------
:XOR^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xE & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation Flags...
	tmp_overflow:1 = ((DEST_B_AD s< 0x0) && (SRC_B_AS s< 0x0)) ;	# V Flag
	# Operation...
	DEST_B_AD = DEST_B_AD ^ SRC_B_AS;
	build tbl_bzero;
	# Result Flags...
	$(OVERFLOW) = tmp_overflow;
	$(SIGN) = (DEST_B_AD s< 0x0);			# S Flag
	$(ZERO) = (DEST_B_AD == 0x0);			# Z Flag
	$(CARRY) = (DEST_B_AD != 0x0);			# C Flag
	build postIncrementStore;
}


###################################################################################
#
#	AND: Logical AND source with destination (dest &= src)
#   ------------------------------------------------------------------------------
#	| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7  |  6  | 5  | 4  | 3  | 2  | 1 | 0 |
#	------------------------------------------------------------------------------
#	| 1    1    1    1  |     source      | Ad | B/W |   As    |   destination   | 
#------------------
#	16 bit SRC Word
#------------------
:AND^".W" SRC_W_AS, DEST_W_AD is ctx_haveext=0 & (op16_12_4=0xF & bow=0x0 & tbl_wzero & postIncrementStore) ... & SRC_W_AS ... & DEST_W_AD ... {
	# Operation...
	result:2 = DEST_W_AD & SRC_W_AS;
	DEST_W_AD = result;
	build tbl_wzero;
	# Operation Flags...
	$(OVERFLOW) = 0x0;					# V Flag
	# Result Flags...
	$(SIGN) = (result s< 0x0);			# S Flag
	$(ZERO) = (result == 0x0);			# Z Flag
	$(CARRY) = (result != 0x0);			# C Flag
	build postIncrementStore;
}


#------------------
#	16 bit SRC Byte
#------------------
:AND^".B" SRC_B_AS, DEST_B_AD is ctx_haveext=0 & (op16_12_4=0xF & bow=0x1 & tbl_bzero & postIncrementStore) ... & SRC_B_AS ... & DEST_B_AD ... {
	# Operation...
	result:1 = DEST_B_AD & SRC_B_AS;
	DEST_B_AD = result;
	build tbl_bzero;
	# Operation Flags...
	$(OVERFLOW) = 0x0;					# V Flag
	# Result Flags...
	$(SIGN) = (result s< 0x0);			# S Flag
	$(ZERO) = (result == 0x0);			# Z Flag
	$(CARRY) = (result != 0x0);			# C Flag
	build postIncrementStore;
}
