ghidra/Ghidra/Processors/PIC/data/languages/pic17c7xx_instructions.sinc

917 lines
20 KiB
Plaintext

#
# PIC-17C7xx Instruction Section
# includes token definitions, macros, sub-constructors and instruction definitions
#
# 16-bit instruction token uses big-endian bit numbering which agrees with
# instruction bit numbering with PIC documentation.
# 15-14-13-12-11-10-9-8-7-6-5-4-3-2-1-0
define token instr16(16)
op16 = (0,15)
op8 = (8,15)
op7 = (9,15)
op6 = (10,15)
op5 = (11,15)
op3 = (13,15)
t = (9,9)
d = (8,8)
s = (8,8)
i = (8,8)
b3 = (8,10)
p5_4 = (12,12)
p5_3 = (11,11)
p5 = (8,12)
p5reg = (8,12)
u4hi = (4,7)
u4lo = (0,3)
f8 = (0,7)
f8hi = (5,7)
f8_4 = (4,4)
f8_3 = (3,3)
f8reg = (0,4)
k8 = (0,7)
k8_h = (4,7)
k8_l = (0,3)
k13 = (0,12)
;
attach variables [ f8reg p5reg ] [
INDF0 FSR0 PCL PCLATH ALUSTA T0STA CPUSTA INTSTA
INDF1 FSR1 WREG TMR0L TMR0H TBLPTRL TBLPTRH BSR
_ _ _ _ _ _ _ _
PRODL PRODH _ _ _ _ _ _
];
attach variables [ t ] [ TBLATL TBLATH ];
#
# Special PIC-17 Operations
#
# Return a decimal adjusted value for the value provided (see DAW instruction)
define pcodeop decimalAdjust;
# Perform a Master Clear Reset
define pcodeop reset;
define pcodeop clearWatchDogTimer;
define pcodeop sleep;
#
# MACROS
#
macro setResultFlags(result) {
Z = (result == 0);
}
macro setAddCOverflowFlag(op1,op2) {
local tmpC = C & 1;
OV = scarry(op1,tmpC) || scarry(op2,op1 + tmpC);
}
macro setAddCCarryFlag(op1,op2) {
local tmpC = C & 1;
C = carry(op1,tmpC) || carry(op2,op1 + tmpC);
}
macro setAddCDigitCarryFlag(op1,op2) {
# op1 and op2 are assumed to be 8-bit values
local tmp1 = op1 << 4;
local tmp2 = op2 << 4;
local tmpDC = DC & 1;
DC = carry(tmp1,tmpDC) || carry(tmp2,tmp1 + tmpDC);
}
macro setAddCFlags(op1,op2) {
setAddCCarryFlag(op1,op2);
setAddCDigitCarryFlag(op1,op2);
setAddCOverflowFlag(op1,op2);
}
macro setAddFlags(op1,op2) {
C = carry(op1,op2);
DC = carry(op1<<4,op2<<4);
OV = scarry(op1,op2);
}
macro setSubtractCOverflowFlag(op1,op2) {
local notC = ~(C & 1);
OV = sborrow(op1,notC) || sborrow(op2,op1 - notC);
}
macro setSubtractCCarryFlag(op1,op2) {
local notC = ~(C & 1);
C = (op1 < notC) || (op2 < (op1 - notC));
}
macro setSubtractCDigitCarryFlag(op1,op2) {
# op1 and op2 are assumed to be 8-bit values
local notDC = ~(DC & 1);
local tmp1 = op1 << 4;
local tmp2 = op2 << 4;
local tmp3 = (tmp1 - notDC) << 4;
DC = (tmp1 < notDC) || (tmp2 < tmp3);
}
macro setSubtractCFlags(op1,op2) {
setSubtractCCarryFlag(op1,op2);
setSubtractCDigitCarryFlag(op1,op2);
setSubtractCOverflowFlag(op1,op2);
}
macro setSubtractFlags(op1,op2) {
# op1 and op2 are assumed to be 8-bit values
# NOTE: carry flag is SET if there is NO borrow
C = (op1 >= op2);
DC = ((op1<<4) < (op2<<4));
OV = sborrow(op1,op2);
}
macro push(val) { # TODO: Uncertain about this !!
# CheckStackFull();
*[HWSTACK]:2 STKPTR = val;
STKPTR = STKPTR + 2;
}
macro pop(rval) { # TODO: Uncertain about this !!
# CheckStackUnderflow();
STKPTR = STKPTR - 2;
rval = *[HWSTACK]:2 STKPTR;
}
#
# SUB-CONSTRUCTORS
#
# PC register write - instruction must set PCLATH/PCL and perform branch operation
fPC: "PC" is f8=0x02 { export PCL; }
pPC: "PC" is p5=0x02 { export PCL; }
# ALUSTA register
fALUSTA: f8reg is f8=0x04 & f8reg { export f8reg; }
#pALUSTA: p5reg is p5=0x04 & p5reg { export p5reg; }
#
# f Register subconstructors
#
# 0x00-0x0f Unbanked registers
fREGLoc: f8reg is f8hi=0 & f8_4=0 & f8reg { export f8reg; }
# 0x10-0x1f Banked registers
fREGLoc: f8 is f8hi=0 & f8_4=1 & f8_3=0 & f8 { ptr:2 = (zext(BSR & 0x0f) << 8) + f8; export *[DATA]:1 ptr; }
# 0x18-0x19 Unbanked registers (PRODL,PRODH)
fREGLoc: f8reg is f8=0x18 & f8reg { export f8reg; }
fREGLoc: f8reg is f8=0x19 & f8reg { export f8reg; }
# Unbanked general purpose RAM
fREGLoc: f8 is f8hi=0 & f8_4=1 & f8_3=1 & f8 { export *[DATA]:1 f8; }
# Banked general purpose RAM
fREGLoc: f8 is f8 { ptr:2 = (zext(BSR & 0xf0) << 4) + f8; export *[DATA]:1 ptr; }
# Indirect File Register access - INDF0
fREGLoc: f8reg is f8=0x00 & f8reg {
addr:1 = FSR0;
val:1 = ((FS10 == 0x1) * 1) + ((FS10 == 0x0) * -1);
FSR0 = addr + val;
export *[DATA]:1 addr;
}
# Indirect File Register access - INDF1
fREGLoc: f8reg is f8=0x08 & f8reg {
addr:1 = FSR1;
val:1 = ((FS32 == 0x1) * 1) + ((FS32 == 0x0) * -1);
FSR1 = addr + val;
export *[DATA]:1 addr;
}
#
# p Register subconstructors
#
# 0x00-0x0f Unbanked registers
pREGLoc: p5reg is p5_4=0 & p5reg { export p5reg; }
# 0x10-0x17 Banked registers
pREGLoc: p5 is p5_4=1 & p5_3=0 & p5 { ptr:2 = (zext(BSR & 0x0f) << 8) + p5; export *[DATA]:1 ptr; }
# 0x18-0x19 Unbanked registers (PRODL,PRODH)
pREGLoc: p5reg is p5=0x18 & p5reg { export p5reg; }
pREGLoc: p5reg is p5=0x19 & p5reg { export p5reg; }
# Unbanked general purpose RAM
pREGLoc: p5 is p5_4=1 & p5_3=1 & p5 { export *[DATA]:1 p5; }
# Indirect File Register access - INDF0
pREGLoc: p5reg is p5=0x00 & p5reg {
addr:1 = FSR0;
val:1 = ((FS10 == 0x1) * 1) + ((FS10 == 0x0) * -1);
FSR0 = addr + val;
export *[DATA]:1 addr;
}
# Indirect File Register access - INDF1
pREGLoc: p5reg is p5=0x08 & p5reg {
addr:1 = FSR1;
val:1 = ((FS32 == 0x1) * 1) + ((FS32 == 0x0) * -1);
FSR1 = addr + val;
export *[DATA]:1 addr;
}
# Direct File register data
srcFREG: fREGLoc is fREGLoc { export fREGLoc; }
# PCL read - latch PC into PCL and PCLATH
srcFREG: "PC" is f8=0x02 {
PCLAT = inst_start;
export PCL;
}
# Destination register (always fREGLoc)
destFREG: fREGLoc is fREGLoc { export fREGLoc; }
# Destination register (either fREGLoc or WREG)
destREG: "0" is d=0 { export WREG; }
destREG: "1" is d=1 & fREGLoc { export fREGLoc; }
# Direct File register data
srcPREG: pREGLoc is pREGLoc { export pREGLoc; }
# PCL read - latch PC into PCL and PCLATH
srcPREG: "PC" is p5=0x02 {
PCLAT = inst_start;
export PCL;
}
# Destination register (always pREGLoc)
destPREG: pREGLoc is pREGLoc { export pREGLoc; }
# Destination operand representation (w: W register is destination; f: specified fREG is destination)
D: "w" is d=0 { }
D: "f" is d=1 { }
# s-flag used by those instructions which can optionally store result in both srcFREG and WREG
S: "0" is s=0 { }
S: "1" is s=1 { }
# Table read/write i-flag
I: "0" is i=0 { }
I: "1" is i=1 { }
# Table read/write t-flag identifies table latch register (high or low byte)
T: t is t { export t; }
# Relative instruction location with an 8K page
shortAddr: nLoc is k13 [ nLoc = (inst_next & 0xe000) + k13; ] {
tmp:2 = nLoc:2 >> 8;
PCLATH = tmp:1;
export *[CODE]:2 nLoc;
}
# Absolute instruction location within 64K space (PCLATH contain upper 8-bits)
longAddr: k8 is k8 {
addr:2 = (zext(PCLATH) << 8) + k8;
export addr;
}
# Skip instruction address
skipInst: inst_skip is op16 [ inst_skip = inst_next + 1; ] {export *[CODE]:2 inst_skip; }
# Immediate Data (Literal operation)
imm8: "#"k8 is k8 { export *[const]:1 k8; }
imm8h: "#"k8_h is k8_h { export *[const]:1 k8_h; }
imm8l: "#"k8_l is k8_l { export *[const]:1 k8_l; }
# Bit identifier
bit: "#"b3 is b3 { export *[const]:1 b3; }
#
# Instructions
#
:ADDLW imm8 is op8=0xb1 & imm8 {
# 1011 0001 kkkk kkkk
tmp1:1 = WREG;
tmp2:1 = imm8;
setAddFlags(tmp1, tmp2);
local tmp = tmp1 + tmp2;
WREG = tmp;
setResultFlags(tmp);
}
:ADDWF srcFREG, D is op7=0x07 & D & srcFREG & destREG {
# 0000 111d ffff ffff
tmp1:1 = srcFREG; # read only once!
tmp2:1 = WREG;
setAddFlags(tmp1, tmp2);
local tmp = tmp1 + tmp2;
destREG = tmp;
setResultFlags(tmp);
}
:ADDWF fPC, D is op7=0x07 & D & d=1 & fPC {
# 0000 111d ffff ffff
# 0000 1110 ffff ffff -> ADDWF PCL, w
addr:2 = inst_start >> 1; # Compenstate for CODE wordsize
addrHi:1 = addr(1);
PCLATH = addrHi;
addrLo:1 = addr:1;
tmpW:1 = WREG;
setAddFlags(addrLo, tmpW);
addrLo = addrLo + tmpW;
addr = (zext(addrHi) << 8) + zext(addrLo);
setResultFlags(addrLo);
goto [addr];
}
:ADDWFC srcFREG, D is op7=0x08 & D & srcFREG & destREG {
# 0001 000d ffff ffff
local tmpC = C & 1;
tmp1:1 = srcFREG; # read only once!
tmp2:1 = WREG;
setAddCFlags(tmp1, tmp2);
local tmp = tmp1 + tmp2 + tmpC;
destREG = tmp;
setResultFlags(tmp);
}
:ANDLW imm8 is op8=0xb5 & imm8 {
# 1011 0101 kkkk kkkk
tmp:1 = WREG & imm8;
WREG = tmp;
setResultFlags(tmp);
}
:ANDWF srcFREG, D is op7=0x05 & D & srcFREG & destREG {
# 0000 101d ffff ffff
tmp:1 = srcFREG & WREG;
destREG = tmp;
setResultFlags(tmp);
}
:BCF srcFREG, bit is op5=0x11 & bit & srcFREG {
# 1000 1bbb ffff ffff
local bitmask = ~(1 << bit);
srcFREG = srcFREG & bitmask;
}
:BCF fALUSTA, bit is op5=0x11 & b3=0 & fALUSTA & bit {
# 1000 1000 0000 0100 -> BCF ALUSTA, #C
C = 0;
}
:BCF fALUSTA, bit is op5=0x11 & b3=1 & fALUSTA & bit {
# 1000 1001 0000 0100 -> BCF ALUSTA, #DC
DC = 0;
}
:BCF fALUSTA, bit is op5=0x11 & b3=2 & fALUSTA & bit {
# 1000 1010 0000 0100 -> BCF ALUSTA, #Z
Z = 0;
}
:BCF fALUSTA, bit is op5=0x11 & b3=3 & fALUSTA & bit {
# 1000 1011 0000 0100 -> BCF ALUSTA, #OV
OV = 0;
}
:BCF fALUSTA, bit is op5=0x11 & b3=4 & fALUSTA & bit {
# 1000 1100 0000 0100 -> BCF ALUSTA, #FS0
FS10 = FS10 & 0x2;
}
:BCF fALUSTA, bit is op5=0x11 & b3=5 & fALUSTA & bit {
# 1000 1101 0000 0100 -> BCF ALUSTA, #FS1
FS10 = FS10 & 0x1;
}
:BCF fALUSTA, bit is op5=0x11 & b3=6 & fALUSTA & bit {
# 1000 1110 0000 0100 -> BCF ALUSTA, #FS2
FS32 = FS32 & 0x2;
}
:BCF fALUSTA, bit is op5=0x11 & b3=7 & fALUSTA & bit {
# 1000 1111 0000 0100 -> BCF ALUSTA, #FS3
FS32 = FS32 & 0x1;
}
:BSF srcFREG, bit is op5=0x10 & bit & srcFREG {
# 1000 0bbb ffff ffff
local bitmask = 1 << bit;
srcFREG = srcFREG | bitmask;
}
:BSF fALUSTA, bit is op5=0x10 & b3=0 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #C
C = 1;
}
:BSF fALUSTA, bit is op5=0x10 & b3=1 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #DC
DC = 1;
}
:BSF fALUSTA, bit is op5=0x10 & b3=2 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #Z
Z = 1;
}
:BSF fALUSTA, bit is op5=0x10 & b3=3 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #OV
OV = 1;
}
:BSF fALUSTA, bit is op5=0x10 & b3=4 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #FS0
FS10 = FS10 | 0x1;
}
:BSF fALUSTA, bit is op5=0x10 & b3=5 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #FS1
FS10 = FS10 | 0x2;
}
:BSF fALUSTA, bit is op5=0x10 & b3=6 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #FS2
FS32 = FS32 | 0x1;
}
:BSF fALUSTA, bit is op5=0x10 & b3=7 & bit & fALUSTA {
# 1000 0000 0000 0100 -> BSF ALUSTA, #FS3
FS32 = FS32 | 0x2;
}
:BTFSC srcFREG, bit is op5=0x13 & bit & srcFREG & skipInst {
# 1001 1bbb ffff ffff
local bitmask = 1 << bit;
local tmp = srcFREG & bitmask;
if (tmp == 0) goto skipInst;
}
:BTFSC fALUSTA, bit is op5=0x13 & b3=0 & bit & fALUSTA & skipInst {
# 1001 1000 0000 0100 -> BTFSC STATUS, #C
if (C == 0) goto skipInst;
}
:BTFSC fALUSTA, bit is op5=0x13 & b3=1 & bit & fALUSTA & skipInst {
# 1001 1001 0000 0100 -> BTFSC STATUS, #DC
if (DC == 0) goto skipInst;
}
:BTFSC fALUSTA, bit is op5=0x13 & b3=2 & bit & fALUSTA & skipInst {
# 1001 1010 0000 0100 -> BTFSC STATUS, #Z
if (Z == 0) goto skipInst;
}
:BTFSC fALUSTA, bit is op5=0x13 & b3=3 & bit & fALUSTA & skipInst {
# 1001 1011 0000 0100 -> BTFSC STATUS, #OV
if (OV == 0) goto skipInst;
}
:BTFSS srcFREG, bit is op5=0x12 & bit & srcFREG & skipInst {
# 1001 0bbb ffff ffff
local bitmask = 1 << bit;
local tmp = srcFREG & bitmask;
if (tmp != 0) goto skipInst;
}
:BTFSS fALUSTA, bit is op5=0x12 & b3=0 & bit & fALUSTA & skipInst {
# 1001 1000 0000 0100 -> BTFSS STATUS, #C
if (C != 0) goto skipInst;
}
:BTFSS fALUSTA, bit is op5=0x12 & b3=1 & bit & fALUSTA & skipInst {
# 1001 1001 0000 0100 -> BTFSS STATUS, #DC
if (DC != 0) goto skipInst;
}
:BTFSS fALUSTA, bit is op5=0x12 & b3=2 & bit & fALUSTA & skipInst {
# 1001 1010 0000 0100 -> BTFSS STATUS, #Z
if (Z != 0) goto skipInst;
}
:BTFSS fALUSTA, bit is op5=0x12 & b3=3 & bit & fALUSTA & skipInst {
# 1001 1011 0000 0100 -> BTFSS STATUS, #OV
if (OV != 0) goto skipInst;
}
:BTG srcFREG, bit is op5=0x7 & bit & srcFREG & skipInst {
# 0011 1bbb ffff ffff
local bitmask = 1 << bit;
tmp:1 = srcFREG;
srcFREG = ~(tmp & bitmask) | (tmp & ~bitmask);
}
:CALL shortAddr is op3=0x7 & shortAddr {
# 111k kkkk kkkk kkkk
push(&:2 inst_next);
call shortAddr;
}
# Special case for Call which appears to correspond to uninitialized
:BADCALL shortAddr is op16=0xffff & shortAddr { addr:2 = shortAddr; return [addr]; }
:CLRF destFREG, S is op7=0x14 & s=0 & S & destFREG {
# 0010 1000 ffff ffff
destFREG = 0;
WREG = 0;
}
:CLRF destFREG, S is op7=0x14 & s=1 & S & destFREG {
# 0010 1001 ffff ffff
destFREG = 0;
}
:CLRF fALUSTA, S is op7=0x14 & s=0 & S & fALUSTA {
# 0010 1000 0000 0100
C = 0;
DC = 0;
Z = 0;
OV = 0;
FS10 = 0;
FS32 = 0;
WREG = 0;
}
:CLRF fALUSTA, S is op7=0x14 & s=1 & S & fALUSTA {
# 0010 1001 0000 0100
C = 0;
DC = 0;
Z = 0;
OV = 0;
FS10 = 0;
FS32 = 0;
}
:CLRWDT is op16=0x0004 {
# 0000 0000 0000 0100
clearWatchDogTimer();
}
:COMF srcFREG, D is op7=0x09 & D & srcFREG & destREG {
# 0001 001d ffff ffff
tmp:1 = ~srcFREG;
destREG = tmp;
setResultFlags(tmp);
}
:CPFSEQ srcFREG is op8=0x31 & srcFREG & skipInst {
# 0011 0001 ffff ffff
if (srcFREG == WREG) goto skipInst;
}
:CPFSGT srcFREG is op8=0x32 & srcFREG & skipInst {
# 0011 0010 ffff ffff
if (srcFREG > WREG) goto skipInst;
}
:CPFSLT srcFREG is op8=0x30 & srcFREG & skipInst {
# 0011 0000 ffff ffff
if (srcFREG < WREG) goto skipInst;
}
:DAW destFREG, S is op7=0x17 & s=0 & S & destFREG {
# 0010 1110 ffff ffff
tmp:1 = decimalAdjust(WREG);
destFREG = tmp;
WREG = tmp;
}
:DAW destFREG, S is op7=0x17 & s=1 & S & destFREG {
# 0010 1111 ffff ffff
tmp:1 = decimalAdjust(WREG);
destFREG = tmp;
setResultFlags(tmp);
}
:DECF srcFREG, D is op7=0x03 & D & srcFREG & destREG {
# 0000 011d ffff ffff
tmp:1 = srcFREG;
setSubtractFlags(tmp, 1);
tmp = tmp - 1;
destREG = tmp;
setResultFlags(tmp);
}
:DECFSZ srcFREG, D is op7=0x0b & D & srcFREG & destREG & skipInst {
# 0001 011d ffff ffff
val:1 = srcFREG - 1;
destREG = val;
if (val == 0) goto skipInst;
}
:DCFSNZ srcFREG, D is op7=0x13 & D & srcFREG & destREG & skipInst {
# 0010 011d ffff ffff
val:1 = srcFREG - 1;
destREG = val;
if (val != 0) goto skipInst;
}
:GOTO shortAddr is op3=0x6 & shortAddr {
# 110k kkkk kkkk kkkk
goto shortAddr;
}
:INCF srcFREG, D is op7=0x0a & D & srcFREG & destREG {
# 0001 010d ffff ffff
tmp:1 = srcFREG; # read once only!
setAddFlags(tmp, 1);
tmp = tmp + 1;
destREG = tmp;
setResultFlags(tmp);
}
:INCFSZ srcFREG, D is op7=0x0f & D & srcFREG & destREG & skipInst {
# 0001 111d ffff ffff
val:1 = srcFREG + 1;
destREG = val;
if (val == 0) goto skipInst;
}
:INFSNZ srcFREG, D is op7=0x12 & D & srcFREG & destREG & skipInst {
# 0010 010d ffff ffff
val:1 = srcFREG + 1;
destREG = val;
if (val != 0) goto skipInst;
}
:IORLW imm8 is op8=0xb3 & imm8 {
# 1011 0011 kkkk kkkk
tmp:1 = WREG | imm8;
WREG = tmp;
setResultFlags(tmp);
}
:IORWF srcFREG, D is op7=0x04 & D & srcFREG & destREG {
# 0000 100d ffff ffff
tmp:1 = WREG | srcFREG;
destREG = tmp;
setResultFlags(tmp);
}
:LCALL longAddr is op8=0xb7 & longAddr {
# 1011 0111 kkkk kkkk
push(&:2 inst_next);
call [longAddr];
}
:MOVFP srcFREG, destPREG is op3=0x3 & srcFREG & destPREG {
# 011p pppp ffff ffff
destPREG = srcFREG;
}
:MOVFP srcFREG, pPC is op3=0x3 & srcFREG & pPC {
# 0110 0010 ffff ffff
addr:2 = (zext(PCLATH) << 8) + zext(srcFREG);
goto [addr];
}
:MOVLB imm8l is op8=0xb8 & u4hi=0 & imm8l {
# 1011 1000 0000 kkkk
BSR = (BSR & 0xf0) | imm8l;
}
:MOVLR imm8h is op7=0x5d & u4lo=0 & imm8h {
# 1011 101x kkkk 0000
BSR = (BSR & 0x0f) | (imm8h << 4);
}
:MOVLW imm8 is op8=0xb0 & imm8 {
# 1011 0000 kkkk kkkk
WREG = imm8;
}
:MOVPF srcPREG, destFREG is op3=0x2 & srcPREG & destFREG {
# 010p pppp ffff ffff
tmp:1 = srcPREG;
destFREG = tmp;
setResultFlags(tmp);
}
:MOVPF srcPREG, fPC is op3=0x2 & srcPREG & fPC {
tmp:1 = srcPREG;
addr:2 = (zext(PCLATH) << 8) + zext(tmp);
setResultFlags(tmp);
goto [addr];
}
:MOVWF destFREG is op8=0x01 & destFREG {
# 0000 0001 ffff ffff
destFREG = WREG;
}
:MOVWF fPC is op8=0x01 & fPC {
addr:2 = (zext(PCLATH) << 8) + zext(WREG);
goto [addr];
}
:MULLW imm8 is op8=0xbc & imm8 {
# 1011 1100 kkkk kkkk
PROD = zext(WREG) * zext(imm8);
}
:MULLWF srcFREG is op8=0x34 & srcFREG {
# 0011 0100 ffff ffff
PROD = zext(WREG) * zext(srcFREG);
}
:NEGW destFREG, S is op7=0x16 & s=0 & S & destFREG {
# 0010 110s ffff ffff
tmp:1 = -WREG;
destFREG = tmp;
WREG = tmp;
C = (tmp s< 0);
OV = sborrow(0,tmp);
setResultFlags(tmp);
}
:NEGW destFREG, S is op7=0x16 & s=1 & S & destFREG {
# 0010 110s ffff ffff
tmp:1 = -WREG;
destFREG = tmp;
C = (tmp s< 0);
OV = sborrow(0,tmp);
setResultFlags(tmp);
}
:NOP is op16=0x0 { }
:RETFIE is op16=0x0005 {
# 0000 0000 0000 0101
retAddr:2 = 0;
pop(retAddr);
return [retAddr];
}
:RETLW imm8 is op8=0xb6 & imm8 {
# 1011 0110 kkkk kkkk
WREG = imm8;
retAddr:2 = 0;
pop(retAddr);
return [retAddr];
}
:RETURN is op16=0x0002 {
# 0000 0000 0000 0010
retAddr:2 = 0;
pop(retAddr);
return [retAddr];
}
:RLCF srcFREG, D is op7=0x0d & D & srcFREG & destREG {
# 0001 101d ffff ffff
local tmpC = C;
val:1 = srcFREG;
C = (val s< 0);
val = (val << 1) | tmpC;
destREG = val;
}
:RLNCF srcFREG, D is op7=0x11 & D & srcFREG & destREG {
# 0010 001d ffff ffff
tmp:1 = srcFREG << 1;
destREG = tmp;
}
:RRCF srcFREG, D is op7=0x0c & D & srcFREG & destREG {
# 0001 100d ffff ffff
local tmpC = C << 7;
tmp:1 = srcFREG;
C = (tmp & 1) != 0;
tmp = (tmp >> 1) | tmpC;
destREG = tmp;
}
:RRNCF srcFREG, D is op7=0x10 & D & srcFREG & destREG {
# 0010 000d ffff ffff
tmp:1 = srcFREG >> 1;
destREG = tmp;
}
:SETF destFREG, S is op7=0x15 & s=0 & S & destFREG {
# 0010 1010 ffff ffff
destFREG = 0xff;
WREG = 0xff;
}
:SETF destFREG, S is op7=0x15 & s=1 & S & destFREG {
# 0010 1011 ffff ffff
destFREG = 0xff;
}
:SETF fALUSTA, S is op7=0x15 & s=0 & S & fALUSTA {
# 0010 1010 0000 0100
C = 1;
DC = 1;
Z = 1;
OV = 1;
FS10 = 0x3;
FS32 = 0x3;
WREG = 0xff;
}
:SETF fALUSTA, S is op7=0x15 & s=1 & S & fALUSTA {
# 0010 1011 0000 0100
C = 1;
DC = 1;
Z = 1;
OV = 1;
FS10 = 0x3;
FS32 = 0x3;
}
:SLEEP is op16=0x0003 {
# 0000 0000 0000 0011
sleep();
}
:SUBLW imm8 is op8=0xb2 & imm8 {
# 1011 0010 kkkk kkkk
tmp:1 = imm8;
tmpW:1 = WREG;
setSubtractFlags(tmp, tmpW);
tmp = tmp - tmpW;
WREG = tmp;
setResultFlags(tmp);
}
:SUBWF srcFREG, D is op7=0x02 & D & srcFREG & destREG {
# 0000 010d ffff ffff
tmp:1 = srcFREG;
tmpW:1 = WREG;
setSubtractFlags(tmp, tmpW);
tmp = tmp - tmpW;
destREG = tmp;
setResultFlags(tmp);
}
:SUBWFB srcFREG, D is op7=0x01 & D & srcFREG & destREG {
# 0000 001d ffff ffff
local notC = ~(C & 1);
tmp:1 = srcFREG;
tmpW:1 = WREG;
setSubtractCFlags(tmp, tmpW);
tmp = tmp - tmpW - notC;
destREG = tmp;
setResultFlags(tmp);
}
:SWAPF srcFREG, D is op7=0x0e & D & srcFREG & destREG {
# 0001 110d ffff ffff
tmp:1 = srcFREG;
destREG = (tmp << 4) | (tmp >> 4);
}
:TABLRD T, I, destFREG is op6=0x2a & T & I & i & destFREG {
# 1010 10ti ffff ffff
destFREG = T;
ptr:2 = TBLPTR;
TBLAT = *[CODE]:2 ptr;
TBLPTR = ptr + i;
}
:TABLWT T, I, srcFREG is op6=0x2b & T & I & i & srcFREG {
# 1010 11ti ffff ffff
T = srcFREG;
ptr:2 = TBLPTR;
*[CODE]:2 ptr = TBLAT;
TBLPTR = ptr + i;
}
:TLRD T, destFREG is op6=0x28 & T & destFREG {
# 1010 00tx ffff ffff
destFREG = T;
}
:TLWT T, srcFREG is op6=0x29 & T & srcFREG {
# 1010 01tx ffff ffff
T = srcFREG;
}
:TSTFSZ srcFREG is op8=0x33 & srcFREG & skipInst {
# 0011 0011 ffff ffff
if (srcFREG == 0) goto skipInst;
}
:XORLW imm8 is op8=0xb4 & imm8 {
# 1011 0100 kkkk kkkk
tmp:1 = WREG ^ imm8;
WREG = tmp;
setResultFlags(tmp);
}
:XORWF srcFREG, D is op7=0x06 & D & srcFREG & destREG {
# 0000 110d ffff ffff
tmp:1 = WREG ^ srcFREG;
destREG = tmp;
setResultFlags(tmp);
}