940 lines
23 KiB
Plaintext
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);
|
|
}
|