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

940 lines
23 KiB
Plaintext

#
# PIC-16 Instruction Section
# includes token definitions, macros, sub-constructors and instruction definitions
#
# PC register write - instruction must set PC with PCLATH/PCL and perform branch operation
# Little-endian bit numbering
define token instr16(16)
op14 = (0,13)
op12 = (2,13)
op11 = (3,13)
op9 = (5,13)
op7 = (7,13)
op6 = (8,13)
op5 = (9,13)
op4 = (10,13)
op3 = (11,13)
d = (7,7)
b3 = (7,9)
IntConBits = (7,9)
StatusBit = (7,9)
f7 = (0,6)
lf7 = (0,3)
uf7 = (4,6)
fsr = (2,2)
fsrk = (6,6)
fregCore = (0,3)
k5 = (0,4)
k7 = (0,6)
k8 = (0,7)
sk9 = (0,8) signed
k11 = (0,10)
sk6 = (0,5) signed
l5 = (0,4) # low order 5-bits of instr16
mm = (0,1)
;
define register offset=0x100 size=4 contextreg;
define context contextreg
doPseudo = (0,0)
possibleSkip = (1,1) noflow
;
@if PROCESSOR == "PIC_16"
attach variables [ fregCore ] [
INDF TMR0 PCL STATUS FSR PORTA PORTB PORTC PORTD PORTE PCLATH INTCON _ _ _ _
];
@elif PROCESSOR == "PIC_16F"
attach variables [ fregCore ] [
INDF0 INDF1 PCL STATUS FSR0L FSR0H FSR1L FSR1H BSR W PCLATH INTCON _ _ _ _
];
attach names [IntConBits] [ IOCIF INTF TMR0IF IOCIE INTE TMR0IE PEIE GIE ];
attach variables [ fsr fsrk ] [ FSR0 FSR1 ];
@endif
#
# Unsupported Operations
#
define pcodeop clearWatchDogTimer;
define pcodeop sleep;
define pcodeop reset;
#
# MACROS
#
# Pack status bits into STATUS register
macro packStatus() {
# STATUS = (IRP << $(STATUS_IRP_BIT))
# | (RP << $(STATUS_RP0_BIT))
# | (Z << $(STATUS_Z_BIT))
# | (DC << $(STATUS_DC_BIT))
# | (C << $(STATUS_C_BIT));
}
# Unpack status bits from STATUS register
macro unpackStatus() {
# IRP = ((STATUS & $(STATUS_IRP_MASK)) != 0);
# RP = (STATUS & $(STATUS_RP_MASK)) >> $(STATUS_RP0_BIT);
# Z = ((STATUS & $(STATUS_Z_MASK)) != 0);
# DC = ((STATUS & $(STATUS_DC_MASK)) != 0);
# C = ((STATUS & $(STATUS_C_MASK)) != 0);
}
macro setResultFlags(result) {
$(Z) = (result == 0);
}
macro setAddCCarryFlag(op1,op2) {
local tc = $(C);
$(C) = (carry(op1,tc) || carry(op2,op1 + tc));
}
macro setAddCDigitCarryFlag(op1,op2) {
# op1 and op2 are assumed to be 8-bit values
local tmp1 = op1 << 4;
local tmp2 = op2 << 4;
local tdc = $(DC);
$(DC) = (carry(tmp1,tdc) || carry(tmp2,tmp1 + tdc));
}
macro setAddCFlags(op1,op2) {
setAddCCarryFlag(op1,op2);
setAddCDigitCarryFlag(op1,op2);
}
macro setAddFlags(op1,op2) {
$(C)= carry(op1,op2);
$(DC) = carry(op1<<4,op2<<4);
}
macro setSubtractCCarryFlag(op1,op2) {
local tc = $(C);
local notC = !tc;
$(C) = op2 >= !tc & op1 >= (op2 - !tc);
}
macro setSubtractCDigitCarryFlag(op1,op2) {
# op1 and op2 are assumed to be 8-bit values
local notDC = ~$(DC);
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);
}
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));
}
macro push(val) { # TODO: Uncertain about this !!
*[HWSTACK]:2 STKPTR = val;
STKPTR = STKPTR + 2;
}
macro pop(val) { # TODO: Uncertain about this !!
STKPTR = STKPTR - 2;
val = *[HWSTACK]:2 STKPTR;
}
#
# SUB-CONSTRUCTORS
#
# File register index (f7!=0): bank selection determined by RP bits in STATUS reg
@if PROCESSOR == "PIC_16"
srcREG: f7 is f7 {
addr:2 = (zext(RP) << 7) + f7;
export *[DATA]:1 addr;
}
@elif PROCESSOR == "PIC_16F"
srcREG: f7 is f7 {
addr:2 = (zext(BSR) << 7) + f7;
export *[DATA]:1 addr;
}
@endif
# Top 16 bytes are shared RAM on PIC16 and PIC16F
srcREG: fv is uf7=0x7 & lf7 [fv = 0x70 + lf7; ] {
addr:2 = fv;
export *[DATA]:1 addr;
}
# File register index (f7=0): INDF use implies indirect data access using FSR value and IRP bit in STATUS reg
@if PROCESSOR == "PIC_16"
srcREG: fregCore is f7=0 & fregCore {
addr:2 = (zext(IRP) << 8) + zext(FSR);
export *[DATA]:1 addr;
}
srcREG: fregCore is f7=1 & fregCore {
rpval:2 = zext(RP == 1) + zext(RP == 2);
addr:2 = (zext(rpval) << 7) + 1;
export *[DATA]:1 addr;
}
@elif PROCESSOR == "PIC_16F"
srcREG: fregCore is f7=0 & fregCore {
addr:2 = FSR0;
export *[DATA]:1 addr;
}
srcREG: fregCore is f7=1 & fregCore {
addr:2 = FSR1;
export *[DATA]:1 addr;
}
@endif
# Special File Registers always mapped to Bank-0
srcREG: fregCore is f7=0x02 & fregCore {
# PCL and PCLATH must be latched
addr:2 = inst_start >> 1; # Compensate for CODE wordsize
PCL = addr:1;
PCLATH = addr(1);
export PCL;
}
srcREG: fregCore is f7=0x03 & fregCore { export fregCore; }
srcREG: fregCore is f7=0x04 & fregCore { export fregCore; }
@if PROCESSOR == "PIC_16F"
srcREG: fregCore is f7=0x05 & fregCore { export fregCore; }
srcREG: fregCore is f7=0x06 & fregCore { export fregCore; }
srcREG: fregCore is f7=0x07 & fregCore { export fregCore; }
srcREG: fregCore is f7=0x08 & fregCore { export fregCore; }
srcREG: fregCore is f7=0x09 & fregCore { export fregCore; }
@endif
srcREG: fregCore is f7=0x0a & fregCore { export fregCore; }
srcREG: fregCore is f7=0x0b & fregCore { export fregCore; }
# Destination register (either srcREG or W)
destREG: "0" is d=0 { export W; }
# Destination register: bank selection determined by RP bits in STATUS reg
destREG: "1" is d=1 & f7 & srcREG { export srcREG; }
# Destination register: Special File Registers always mapped to Bank-0
destREG: "1" is d=1 & f7=0x02 & fregCore { export fregCore; } # PCL (special behavior reqd)
# Destination operand representation (w: W register is destination; f: specified srcREG is destination)
D: "w" is d=0 { }
D: "f" is d=1 { }
# Absolute address generated from k11 and PCLATH<4:3>
absAddr11: k11 is k11 {
addr:2 = ((zext(PCLATH) & 0x78) << 8) + k11;
export addr;
}
@if PROCESSOR == "PIC_16F"
# Absolute address generated from k11 and PCLATH<4:3>
relAddr9: addr is sk9 [ addr = inst_next + sk9; ] {
export *[CODE]:2 addr;
}
@endif
# Immediate Data (Literal operation)
imm8: "#"k8 is k8 { export *[const]:1 k8; }
@if PROCESSOR == "PIC_16F"
# Immediate Data (Literal operation)
imm7: "#"k7 is k7 { export *[const]:1 k7; }
# Immediate Data (Literal operation)
imm5: "#"k5 is k5 { export *[const]:1 k5; }
@endif
# Bit identifier
bit: "#"b3 is b3 { export *[const]:1 b3; }
# TRIS register (TODO: not sure if this TRIS mapping is correct - see TRIS instruction)
@if PROCESSOR == "PIC_16"
trisREG: "5" is l5=5 { local trl:2 = 0x89; export *[DATA]:1 trl; } # TRISA
trisREG: "6" is l5=6 { local trl:2 = 0x187; export *[DATA]:1 trl; } # TRISB
trisREG: "7" is l5=7 { local trl:2 = 0x188; export *[DATA]:1 trl; } # TRISC
@elif PROCESSOR == "PIC_16F"
trisREG: "5" is l5=5 { local trl:2 = 0x10C; export *[DATA]:1 trl; } # TRISA
trisREG: "6" is l5=6 { local trl:2 = 0x10D; export *[DATA]:1 trl; } # TRISB
trisREG: "7" is l5=7 { local trl:2 = 0x10E; export *[DATA]:1 trl; } # TRISC
@endif
:^instruction is possibleSkip=1 & instruction [ possibleSkip=0; ] {
if (SkipNext) goto inst_next;
build instruction;
}
#
# BYTE-ORIENTED FILE REGISTER OPERATIONS
#
@if PROCESSOR == "PIC_16F"
:ADD^fsrk sk6 is op7=0x62 & fsrk & sk6 {
fsrk = fsrk + sk6;
}
@endif
:ADDLW imm8 is op6=0x3e & imm8 {
# --11 111x kkkk kkkk
# 0011 1110 0001 0010 -> ADDLW #0x12
setAddFlags(W, imm8);
W = W + imm8;
setResultFlags(W);
}
:ADDWF srcREG, D is op6=0x07 & srcREG & D & destREG {
# --00 0111 dfff ffff
# 0000 0111 0000 0000 -> ADDWF INDF, 0
# 0000 0111 1000 0000 -> ADDWF INDF, 1
# 0000 0111 0010 0000 -> ADDWF 0x20, 0
# 0000 0111 1010 0000 -> ADDWF 0x20, 1
val:1 = srcREG;
setAddFlags(W, val);
val = W + val;
setResultFlags(val);
destREG = val;
}
:ADDWF PC, D is op6=0x07 & D & d=1 & f7=0x02 & PC {
# --00 0111 dfff ffff
# 0000 0111 1000 0010 -> ADDWF PCL, w, ACCESS
addr:2 = inst_start >> 1; # Compenstate for CODE wordsize
PCLATH = addr(1);
tmp:1 = addr:1;
setAddFlags(tmp, W);
tmp = tmp + W;
addr = (zext(PCLATH) << 8) + zext(tmp);
PCL = tmp;
setResultFlags(tmp);
goto [addr];
}
:ADDWFC srcREG, D is op6=0x3D & srcREG & D & destREG {
val:1 = srcREG;
local tmpC = $(C);
setAddFlags(W, val);
val = W + val;
local tc = $(C);
setAddFlags(val,tmpC);
$(C) = $(C) | tc;
val = val + tmpC;
setResultFlags(val);
destREG = val;
}
:ADDWFC PC, D is op6=0x3D & D & d=1 & f7=0x02 & PC {
# --00 0111 dfff ffff
# 0000 0111 1000 0010 -> ADDWF PCL, w, ACCESS
addr:2 = inst_start >> 1; # Compenstate for CODE wordsize
PCLATH = addr(1);
val:1 = addr:1;
local tmpC = $(C);
setAddFlags(W, val);
local tc = $(C);
val = W + val;
setAddFlags(val,tmpC);
$(C) = $(C) | tc;
val = val + tmpC;
addr = (zext(PCLATH) << 8) + zext(val);
PCL = val;
setResultFlags(val);
goto [addr];
}
:ANDLW imm8 is op6=0x39 & imm8 {
# --11 1001 kkkk kkkk
# 0011 1001 0001 0010 -> ANDLW #0x12
W = W & imm8;
setResultFlags(W);
}
:ANDWF srcREG, D is op6=0x05 & srcREG & D & destREG {
# --00 0101 dfff ffff
# 0000 0101 0000 0000 -> ANDWF INDF, 0
# 0000 0101 1000 0000 -> ANDWF INDF, 1
# 0000 0101 0010 0000 -> ANDWF 0x20, 0
# 0000 0101 1010 0000 -> ANDWF 0x20, 1
val:1 = srcREG;
val = W & val;
setResultFlags(val);
destREG = val;
}
:BCF srcREG, bit is op4=0x4 & srcREG & bit {
# --01 00bb bfff ffff
# 0001 0010 0000 0000 -> BCF INDF, #0x4
# 0001 0010 0010 0000 -> BCF 0x20, #0x4
local bitmask = ~(1 << bit);
srcREG = srcREG & bitmask;
}
:BCF srcREG, IntConBits is op4=0x4 & f7=0xb & bit & srcREG & IntConBits {
local bitmask = ~(1 << bit);
srcREG = srcREG & bitmask;
}
:BCF STATUS, "C" is op4=0x4 & b3=0 & f7=0x3 & STATUS {
# --01 00bb bfff ffff
# 0001 0000 0000 0011 -> BCF STATUS, #C
$(C) = 0;
}
:BCF STATUS, "DC" is op4=0x4 & b3=1 & f7=0x3 & STATUS & bit {
# --01 00bb bfff ffff
# 0001 0000 1000 0011 -> BCF STATUS, #DC
$(DC) = 0;
}
:BCF STATUS, "Z" is op4=0x4 & b3=2 & f7=0x3 & STATUS & bit {
# --01 00bb bfff ffff
# 0001 0001 0000 0011 -> BCF STATUS, #Z
$(Z) = 0;
}
:BCF STATUS, "RP0" is op4=0x4 & b3=5 & f7=0x3 & STATUS & bit {
# --01 00bb bfff ffff
# 0001 0010 1000 0011 -> BCF STATUS, #RP0
RP = RP & 0x2;
local bitmask = ~(1 << bit);
STATUS = STATUS & bitmask;
}
:BCF STATUS, "RP1" is op4=0x4 & b3=6 & f7=0x3 & STATUS & bit {
# --01 00bb bfff ffff
# 0001 0011 0000 0011 -> BCF STATUS, #RP1
RP = RP & 0x1;
local bitmask = ~(1 << bit);
STATUS = STATUS & bitmask;
}
:BCF STATUS, "IRP" is op4=0x4 & b3=7 & f7=0x3 & STATUS & bit {
# --01 00bb bfff ffff
# 0001 0011 1000 0011 -> BCF STATUS, #IRP
IRP = 0;
local bitmask = ~(1 << bit);
STATUS = STATUS & bitmask;
}
:BSF srcREG, bit is op4=0x5 & bit & srcREG {
# --01 01bb bfff ffff
# 0001 0110 0000 0000 -> BSF INDF, #0x4
# 0001 0110 0010 0000 -> BSF 0x20, #0x4
local bitmask = 1 << bit;
srcREG = srcREG | bitmask;
}
:BSF srcREG, IntConBits is op4=0x5 & f7=0xb & bit & srcREG & IntConBits {
local bitmask = 1 << bit;
srcREG = srcREG | bitmask;
}
:BSF STATUS, "C" is op4=0x5 & b3=0 & f7=0x3 & STATUS {
# --01 01bb bfff ffff
# 0001 0100 0000 0011 -> BSF STATUS, #C
$(C) = 1;
}
:BSF STATUS, "DC" is op4=0x5 & b3=1 & f7=0x3 & STATUS {
# --01 01bb bfff ffff
# 0001 0100 1000 0011 -> BSF STATUS, #DC
$(DC) = 1;
}
:BSF STATUS, "Z" is op4=0x5 & b3=2 & f7=0x3 & STATUS & bit {
# --01 01bb bfff ffff
# 0001 0111 0000 0011 -> BSF STATUS, #Z
$(Z) = 1;
}
:BSF STATUS, "RP0" is op4=0x5 & b3=5 & f7=0x3 & STATUS & bit {
# --01 01bb bfff ffff
# 0001 0110 1000 0011 -> BSF STATUS, #RP0
RP = RP | 0x1;
local bitmask = 1 << bit;
STATUS = STATUS | bitmask;
}
:BSF STATUS, "RP1" is op4=0x5 & b3=6 & f7=0x3 & STATUS & bit {
# --01 01bb bfff ffff
# 0001 0111 0000 0011 -> BSF STATUS, #RP1
RP = RP | 0x2;
local bitmask = 1 << bit;
STATUS = STATUS | bitmask;
}
:BSF STATUS, "IRP" is op4=0x5 & b3=7 & f7=0x3 & STATUS & bit {
# --01 01bb bfff ffff
# 0001 0111 1000 0011 -> BSF STATUS, #IRP
IRP = 1;
local bitmask = 1 << bit;
STATUS = STATUS | bitmask;
}
:BTFSC srcREG, bit is op4=0x6 & bit & srcREG [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 10bb bfff ffff
# 0001 1010 0000 0000 -> BTFSC INDF, #0x4
# 0001 1010 0010 0000 -> BTFSC 0x20, #0x4
local bitmask = 1 << bit;
local tmp = srcREG & bitmask;
SkipNext = (tmp == 0);
}
:BC absAddr11 is doPseudo=1 & op4=0x6 & b3=0 & bit & f7=0x3 ; op3=0x5 & absAddr11 {
if ($(C) == 0) goto inst_next;
goto [absAddr11];
}
@if PROCESSOR == "PIC_16F"
:BRA relAddr9 is op5=0x19 & relAddr9 {
goto [relAddr9];
}
:BRW is op14=0xb {
# inst_next is byte, not word offset, need to load PC with word offset
PC = (inst_next >> 1) + zext(W);
goto [PC];
}
@endif
:BTFSC STATUS, bit is op4=0x6 & b3=0 & bit & f7=0x3 & STATUS [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 10bb bfff ffff
# 0001 1000 0000 0011 -> BTFSC STATUS, #C
SkipNext = ($(C) == 0);
}
:SKPC is doPseudo=1 & op4=0x6 & b3=0 & bit & f7=0x3 [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
SkipNext = ($(C) == 1);
}
:SKPNC is doPseudo=1 & op4=0x7 & b3=0 & bit & f7=0x3 [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
SkipNext = ($(C) != 1);
}
:SKPZ is doPseudo=1 & op4=0x6 & b3=2 & bit & f7=0x3 [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
SkipNext = ($(Z) == 1);
}
:SKPNZ is doPseudo=1 & op4=0x7 & b3=2 & bit & f7=0x3 [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
SkipNext = ($(Z) != 1);
}
:BTFSC STATUS, bit is op4=0x6 & b3=1 & bit & f7=0x3 & STATUS [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 10bb bfff ffff
# 0001 1000 1000 0011 -> BTFSC STATUS, #DC
SkipNext = ($(DC) == 0);
}
:BZ absAddr11 is doPseudo=1 & op4=0x6 & b3=2 & bit & f7=0x3 ; op3=0x5 & absAddr11 {
if ($(Z) == 0) goto inst_next;
goto [absAddr11];
}
:BTFSC STATUS, bit is op4=0x6 & b3=2 & bit & f7=0x3 & STATUS [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 10bb bfff ffff
# 0001 1001 0000 0011 -> BTFSC STATUS, #Z
SkipNext = ($(Z) == 0);
}
:BTFSS srcREG, bit is op4=0x7 & bit & srcREG [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 11bb bfff ffff
# 0001 1110 0000 0000 -> BTFSS INDF, #0x4
# 0001 1110 0010 0000 -> BTFSS 0x20, #0x4
local bitmask = 1 << bit;
local tmp = srcREG & bitmask;
SkipNext = (tmp != 0);
}
:BNC absAddr11 is doPseudo=1 & op4=0x7 & b3=0 & bit & f7=0x3 ; op3=0x5 & absAddr11 {
if ($(C) != 0) goto inst_next;
goto [absAddr11];
}
:BTFSS STATUS, bit is op4=0x7 & b3=0 & bit & f7=0x3 & STATUS [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 11bb bfff ffff
# 0001 1100 0000 0011 -> BTFSS STATUS, #C
SkipNext = ($(C) != 0);
}
:BTFSS STATUS, bit is op4=0x7 & b3=1 & bit & f7=0x3 & STATUS [ possibleSkip = 1; globalset(inst_next,possibleSkip); ]{
# --01 11bb bfff ffff
# 0001 1100 1000 0011 -> BTFSS STATUS, #DC
SkipNext = ($(DC) != 0);
}
:BNZ absAddr11 is doPseudo=1 & op4=0x7 & b3=2 & bit & f7=0x3 ; op3=0x5 & absAddr11 {
if ($(Z) != 0) goto inst_next;
goto [absAddr11];
}
:BTFSS STATUS, bit is op4=0x7 & b3=2 & bit & f7=0x3 & STATUS [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --01 11bb bfff ffff
# 0001 1101 0000 0011 -> BTFSS STATUS, #Z
SkipNext = ($(Z) != 0);
}
:CALL absAddr11 is op3=0x4 & absAddr11 {
# --10 0kkk kkkk kkkk
# 0010 0001 0010 0011 -> CALL 0x123
# 0010 0000 0001 0000 -> CALL 0x10
push(&:2 inst_next);
call [absAddr11];
}
:CLRF srcREG is op6=0x01 & d=1 & srcREG {
# --00 0001 1fff ffff
# 0000 0001 1000 0000 -> CLRF INDF
# 0000 0001 1010 0000 -> CLRF 0x20
srcREG = 0;
$(Z) = 1;
}
:CLRF STATUS is op6=0x01 & d=1 & f7=0x3 & STATUS {
# --00 0001 1fff ffff
# 0000 0001 1000 0011 -> CLRF STATUS
STATUS = 0;
IRP = 0;
RP = 0;
$(Z) = 0;
$(DC) = 0;
$(C) = 0;
}
:CLRW is op12=0b000001000000 & mm {
# --00 0001 0xxx xxxx
# 0000 0001 0000 0000 -> CLRW
W = 0;
$(Z) = 1;
}
:CLRWDT is op14=0x0064 {
# --00 0000 0110 0100
# Clear Watchdog Timer - Not Implemented
clearWatchDogTimer();
}
:COMF srcREG, D is op6=0x09 & srcREG & D & destREG {
# --00 1001 dfff ffff
# 0000 1001 0000 0000 -> COMF INDF, 0
# 0000 1001 1000 0000 -> COMF INDF, 1
# 0000 1001 0010 0000 -> COMF 0x20, 0
# 0000 1001 1010 0000 -> COMF 0x20, 1
tmp:1 = ~srcREG;
destREG = tmp;
setResultFlags(tmp);
}
:DECF srcREG, D is op6=0x03 & srcREG & D & destREG {
# --00 0011 dfff ffff
# 0000 0011 0000 0000 -> DECF INDF, 0
# 0000 0011 1000 0000 -> DECF INDF, 1
# 0000 0011 0010 0000 -> DECF 0x20, 0
# 0000 0011 1010 0000 -> DECF 0x20, 1
val:1 = srcREG - 1;
destREG = val;
setResultFlags(val);
}
:DECFSZ srcREG, D is op6=0x0b & srcREG & D & destREG [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --00 1011 dfff ffff
# 0000 1011 0000 0000 -> DECFSZ INDF, 0
# 0000 1011 1000 0000 -> DECFSZ INDF, 1
# 0000 1011 0010 0000 -> DECFSZ 0x20, 0
# 0000 1011 1010 0000 -> DECFSZ 0x20, 1
val:1 = srcREG - 1;
destREG = val;
SkipNext = (val == 0);
}
:GOTO absAddr11 is op3=0x5 & absAddr11 {
# --10 1kkk kkkk kkkk
# 0010 1001 0010 0011 -> GOTO 0x123
# 0010 1000 0001 0000 -> GOTO 0x10
goto [absAddr11];
}
:INCF srcREG, D is op6=0x0a & srcREG & D & destREG {
# --00 1010 dfff ffff
# 0000 1010 0000 0000 -> INCF INDF, 0
# 0000 1010 1000 0000 -> INCF INDF, 1
# 0000 1010 0010 0000 -> INCF 0x20, 0
# 0000 1010 1010 0000 -> INCF 0x20, 1
val:1 = srcREG + 1;
destREG = val;
setResultFlags(val);
}
:INCFSZ srcREG, D is op6=0x0f & srcREG & D & destREG [ possibleSkip = 1; globalset(inst_next,possibleSkip); ] {
# --00 1111 dfff ffff
# 0000 1111 0000 0000 -> INCFSZ INDF, 0
# 0000 1111 1000 0000 -> INCFSZ INDF, 1
# 0000 1111 0010 0000 -> INCFSZ 0x20, 0
# 0000 1111 1010 0000 -> INCFSZ 0x20, 1
val:1 = srcREG + 1;
destREG = val;
SkipNext = (val == 0);
}
:IORLW imm8 is op6=0x38 & imm8 {
# --11 1000 kkkk kkkk
# 0011 1000 0001 0010 -> IORLW #0x12
W = W | imm8;
setResultFlags(W);
}
:IORWF srcREG, D is op6=0x04 & srcREG & D & destREG {
# --00 0100 dfff ffff
# 0000 0100 0000 0000 -> IORWF INDF, 0
# 0000 0100 1000 0000 -> IORWF INDF, 1
# 0000 0100 0010 0000 -> IORWF 0x20, 0
# 0000 0100 1010 0000 -> IORWF 0x20, 1
val:1 = W | srcREG;
destREG = val;
setResultFlags(val);
}
@if PROCESSOR == "PIC_16F"
srcFSR: "++"fsr is fsr & mm=0 { fsr = fsr + 1; addr:2 = fsr; export *[DATA]:1 addr; }
srcFSR: "--"fsr is fsr & mm=1 { fsr = fsr - 1; addr:2 = fsr; export *[DATA]:1 addr; }
srcFSR: fsr"++" is fsr & mm=2 { addr:2 = fsr; fsr = fsr + 1; export *[DATA]:1 addr; }
srcFSR: fsr"--" is fsr & mm=3 { addr:2 = fsr; fsr = fsr - 1; export *[DATA]:1 addr; }
srcFSRk: sk6"["fsrk"]" is fsrk & sk6 {
addr:2 = fsrk + sk6; export *[DATA]:1 addr;
}
:MOVIW srcFSR is op11=2 & srcFSR {
W = srcFSR;
setResultFlags(W);
}
:MOVIW srcFSRk is op7=0x7e & srcFSRk {
W = srcFSRk;
setResultFlags(W);
}
:MOVWI srcFSR is op11=3 & srcFSR {
srcFSR = W;
}
:MOVWI srcFSRk is op7=0x7f & srcFSRk {
srcFSRk = W;
}
:MOVLB imm5 is op9=0x1 & imm5 {
BSR = imm5;
}
:MOVLP imm7 is op7=0x63 & imm7 {
PCLATH = imm7;
}
@endif
:MOVLW imm8 is op6=0x30 & imm8 {
# --11 00xx kkkk kkkk
# 0011 0000 0001 0010 -> MOVLW #0x12
W = imm8;
}
:MOVF srcREG, D is op6=0x08 & srcREG & D & destREG {
# --00 1000 dfff ffff
# 0000 1000 0000 0000 -> MOVF INDF, 0
# 0000 1000 1000 0000 -> MOVF INDF, 1
# 0000 1000 0010 0000 -> MOVF 0x20, 0
# 0000 1000 1010 0000 -> MOVF 0x20, 1
val:1 = srcREG;
destREG = val;
setResultFlags(val);
}
:MOVWF srcREG is op6=0x00 & d=1 & srcREG {
# --00 0000 1fff ffff
# 0000 0000 1000 0000 -> MOVWF INDF
# 0000 0000 1010 0000 -> MOVWF 0x20
srcREG = W;
}
:MOVWF PC is op6=0x00 & d=1 & f7=0x02 & PC {
# --00 0000 1fff ffff
# 0000 0000 1000 0010 -> MOVWF PCL
PCL = W;
addr:2 = (zext(PCLATH) << 8) + zext(PCL);
goto [addr];
}
:NOP is op6=0 & d=0 & l5=0 {
# --00 0000 0xx0 0000
}
:OPTION is op14=0x0062 {
# --00 0000 0110 0010
OPTION = W;
}
:RESET is op14=0x0001 {
reset();
goto 0x0;
}
:RETFIE is op14=0x0009 {
# --00 0000 0000 1001
INTCON = 0x80 | INTCON; # set INTCON.GIE bit
retAddr:4 = 0;
pop(retAddr);
return [retAddr];
}
:RETLW imm8 is op4=0xd & imm8 {
# --11 01xx kkkk kkkk
# 0011 0100 0001 0010 -> RETLW #0x12
W = imm8;
retAddr:4 = 0;
pop(retAddr);
return [retAddr];
}
:RETURN is op14=0x0008 {
# --00 0000 0000 1000
retAddr:4 = 0;
pop(retAddr);
return [retAddr];
}
:RLF srcREG, D is op6=0x0d & srcREG & D & destREG {
# --00 1101 dfff ffff
# 0000 1101 0000 0000 -> RLF INDF, 0
# 0000 1101 1000 0000 -> RLF INDF, 1
# 0000 1101 0010 0000 -> RLF 0x20, 0
# 0000 1101 1010 0000 -> RLF 0x20, 1
local tmpC = $(C);
val:1 = srcREG;
$(C) = (val s< 0);
val = (val << 1) | tmpC;
destREG = val;
setResultFlags(val);
}
:RRF srcREG, D is op6=0x0c & srcREG & D & destREG {
# --00 1100 dfff ffff
# 0000 1100 0000 0000 -> RRF INDF, 0
# 0000 1100 1000 0000 -> RRF INDF, 1
# 0000 1100 0010 0000 -> RRF 0x20, 0
# 0000 1100 1010 0000 -> RRF 0x20, 1
local tmpC = $(C) << 7;
val:1 = srcREG;
$(C) = (val & 1) != 0;
val = (val >> 1) | tmpC;
destREG = val;
setResultFlags(val);
}
:SLEEP is op14=0x0063 {
# --00 0000 0110 0011
# Sleep - Not Implemented
sleep();
}
:SUBLW imm8 is op6=0x3c & imm8 {
# --11 110x kkkk kkkk
# 0011 1100 0001 0010 -> SUBLW #0x12
setSubtractFlags(imm8, W);
W = imm8 - W;
setResultFlags(W);
}
:SUBWF srcREG, D is op6=0x02 & srcREG & D & destREG {
# --00 0010 dfff ffff
# 0000 0010 0000 0000 -> SUBWF INDF, 0
# 0000 0010 1000 0000 -> SUBWF INDF, 1
# 0000 0010 0010 0000 -> SUBWF 0x20, 0
# 0000 0010 1010 0000 -> SUBWF 0x20, 1
val:1 = srcREG;
setSubtractFlags(val, W);
val = val - W;
setResultFlags(val);
destREG = val;
}
:SUBWFB srcREG, D is op6=0x3b & srcREG & D & destREG {
val:1 = srcREG;
bor:1 = !$(C);
setSubtractFlags(val, W);
val = val - W;
tb:1 = $(C);
setSubtractFlags(val,bor);
# first subtraction could cause borrow
$(C) = $(C) & tb; # borrow if C not set
val = val - bor;
setResultFlags(val);
destREG = val;
}
:SWAPF srcREG, D is op6=0x0e & srcREG & D & destREG {
# --00 1110 dfff ffff
# 0000 1110 0000 0000 -> SUBWF INDF, 0
# 0000 1110 1000 0000 -> SUBWF INDF, 1
# 0000 1110 0010 0000 -> SUBWF 0x20, 0
# 0000 1110 1010 0000 -> SUBWF 0x20, 1
val:1 = srcREG;
destREG = (val << 4) | (val >> 4);
}
:TRIS trisREG is op9=0x3 & trisREG {
# --00 0000 0110 0fff
# 0000 0000 0110 0101 -> TRIS 5
trisREG = W;
}
:XORLW imm8 is op6=0x3a & imm8 {
# --11 1010 kkkk kkkk
# 0011 1010 0001 0010 -> XORLW #0x12
W = imm8 ^ W;
setResultFlags(W);
}
:XORWF srcREG, D is op6=0x06 & srcREG & D & destREG {
# --00 0110 dfff ffff
# 0000 0110 0000 0000 -> XORWF INDF, 0
# 0000 0110 1000 0000 -> XORWF INDF, 1
# 0000 0110 0010 0000 -> XORWF 0x20, 0
# 0000 0110 1010 0000 -> XORWF 0x20, 1
val:1 = W ^ srcREG;
destREG = val;
setResultFlags(val);
}