2316 lines
73 KiB
Plaintext
2316 lines
73 KiB
Plaintext
# This module defines CR16C
|
|
|
|
|
|
# NOTE: Have assumed for now CFG.SR = 0
|
|
|
|
# sizes:
|
|
# B = byte = 1 byte
|
|
# W = word = 2 bytes
|
|
# D = doubleword = 4 bytes
|
|
|
|
|
|
# Basic =====================================================================
|
|
|
|
define alignment=2;
|
|
|
|
define space ram type=ram_space size=4 default;
|
|
define space register type=register_space size=2;
|
|
|
|
# Registers ==================================================================
|
|
|
|
# - When CFG.SR is not set, register pairs are defined as follows:
|
|
# (R1,R0), (R2,R1) ... (R11,R10), (R12_L, R11)
|
|
# R12, R13, RA and SP are double-word registers for direct storage of
|
|
# addresses greater than 16 bits.
|
|
#
|
|
# - The most significant 8 bits of ISP and the least significant bit of ISP
|
|
# are forced to 0
|
|
|
|
# General purpose registers
|
|
# NOTE: RA_L==RA and SP_L==SP
|
|
# NOTE: R12_H, R13_H, RA_H don't actually exist as named registers
|
|
# (name needed for push/pop instructions implementation only)
|
|
define register offset=0 size=2 [
|
|
R0 R1 R2 R3 R4 R5 R6 R7
|
|
R8 R9 R10 R11 R12_L R12_H R13_L R13_H
|
|
RA_L RA_H SP_L SP_H
|
|
];
|
|
|
|
define register offset=0 size=4 [
|
|
R1R0 R3R2 R5R4 R7R6 R9R8 R11R10 R12 R13 RA SP
|
|
];
|
|
|
|
define register offset=2 size=4 [
|
|
R2R1 R4R3 R6R5 R8R7 R10R9 R12LR11
|
|
];
|
|
|
|
# Dedicated address registers
|
|
define register offset=50 size=4 [ PC ];
|
|
define register offset=60 size=2 [ ISPH ISPL USPH USPL INTBASEH INTBASEL ];
|
|
define register offset=60 size=4 [ ISP USP INTBASE ];
|
|
|
|
# Processor Status register
|
|
define register offset=80 size=2 [ PSR ];
|
|
#define register offset=90 size=1 [ C T L U F Z N E P I ]; # cond flags
|
|
@define C "PSR[0,1]"
|
|
@define T "PSR[1,1]"
|
|
@define L "PSR[2,1]"
|
|
@define U "PSR[3,1]"
|
|
@define F "PSR[5,1]"
|
|
@define Z "PSR[6,1]"
|
|
@define N "PSR[7,1]"
|
|
@define E "PSR[9,1]"
|
|
@define P "PSR[10,1]"
|
|
@define I "PSR[11,1]"
|
|
|
|
# Configuration register
|
|
define register offset=100 size=2 [ CFG ];
|
|
|
|
# Debug registers
|
|
define register offset=110 size=2 [ DBS DSR DCRH DCRL CAR0H CAR0L CAR1H CAR1L ];
|
|
define register offset=114 size=4 [ DCR CAR0 CAR1 ];
|
|
|
|
# these don't actually exist - they are for prd definition (size=4)
|
|
define register offset=130 size=4 [ DBS_1 DSR_1 CFG_1 PSR_1 ];
|
|
|
|
|
|
# Fields ======================================================================
|
|
|
|
define token word1(16)
|
|
hi = (8,15) # opcode8
|
|
lo = (0,7) #
|
|
op = (0,15) # opcode16
|
|
op12 = (4,15) # opcode12
|
|
op9 = (7,15) # opcode9
|
|
op7 = (9,15) # opcode7
|
|
op7p3 = (8,8) # p3 for opcode7
|
|
# op10 = (6,15) # opcode10
|
|
op4 = (12,15) # opcode4
|
|
lo1 = (0,3)
|
|
op13 = (3,15) # opcode13
|
|
op11 = (5,15)
|
|
|
|
dst = (0,3) # register
|
|
src = (4,7)
|
|
src1 = (0,3)
|
|
reg0 = (0,3)
|
|
reg1 = (0,3)
|
|
reg2 = (0,3)
|
|
reg3 = (0,3)
|
|
reg4 = (0,3)
|
|
reg5 = (0,3)
|
|
reg6 = (0,3)
|
|
reg7 = (0,3)
|
|
dst1 = (4,7)
|
|
|
|
rp_dst = (0,3) # register pair
|
|
rp_src = (4,7)
|
|
rp_dst2 = (4,7)
|
|
rp_src2 = (0,3)
|
|
|
|
prp_src1 = (0,3)
|
|
prp_dst1 = (0,3)
|
|
|
|
cond = (4,7)
|
|
|
|
x4 = (12,15) # generic, nibble 4
|
|
x3 = (8,11)
|
|
x2 = (4,7)
|
|
x1 = (0,3)
|
|
|
|
x2s = (4,6)
|
|
x3s = (8,11) signed
|
|
b4_8 = (4,8)
|
|
b4_7 = (4,7)
|
|
b4_6 = (4,6)
|
|
b_ra = (7,7) # RA bit for push/pop, fmt 14
|
|
b_prp = (3,3) # prp bit, fmt 18
|
|
b0_2 = (0,2) # fmt 6
|
|
;
|
|
|
|
define token word2(16)
|
|
w2 = (0,15)
|
|
n4 = (12,15) # nibble 4, sometimes an opcode extension
|
|
n3 = (8,11)
|
|
n2 = (4,7)
|
|
n1 = (0,3)
|
|
w2_b0 = (0,0)
|
|
w2_b1_15 = (1,15) signed
|
|
w2_hi = (8,15)
|
|
|
|
prd = (4,7) # processor registers
|
|
pr = (4,7)
|
|
|
|
rp_src3 = (0,3) # register pairs
|
|
rp_dst3 = (0,3)
|
|
rp_src6 = (4,7)
|
|
rp_dst6 = (4,7)
|
|
rp_dst7 = (8,11)
|
|
|
|
src2 = (0,3) # registers
|
|
dst2 = (0,3)
|
|
src5 = (4,7)
|
|
;
|
|
|
|
define token word3(16)
|
|
w3 = (0,15)
|
|
w3_b0 = (0,0)
|
|
w3_b1_15 = (1,15)
|
|
;
|
|
|
|
# used this token when operands spanned across 2 words
|
|
# | byte1 byte0 byte3 byte2 |
|
|
define token doubleword(32)
|
|
dw = (0,31)
|
|
dw_w1 = (0,15) signed
|
|
dw_w2 = (16,31)
|
|
n8 = (12,15) # nibble 4, sometimes an opcode extension
|
|
n7 = (8,11)
|
|
n6 = (4,7) # (cond)
|
|
n5 = (0,3)
|
|
n5s = (0,3) signed
|
|
b1_15 = (17,31)
|
|
b0_15 = (16,31)
|
|
dw_lo = (0,7) signed # for fmt 5
|
|
dw_hi = (8,15) # (op8)
|
|
dw_op7 = (9,15) # (op7)
|
|
dw_op9 = (7,15) # (op9)
|
|
op10 = (6,15) # (opcode 10)
|
|
b_rs = (8,8) # for fmt 13
|
|
dw_b4_6 = (4,6)
|
|
dw_b_prp = (3,3) # for fmt 17
|
|
f17a = (16,19) # for fmt 17 p3
|
|
f17b = (4,5)
|
|
f17c = (30,31)
|
|
f17d = (24,29)
|
|
dw_n2 = (20,23) # fmt 17, p2, 4-bits
|
|
dw_n2b = (20,22) # fmt 17, p2, 3-bit version
|
|
|
|
rp_dst4 = (4,7)
|
|
rp_src4 = (4,7)
|
|
rp_dst5 = (0,3)
|
|
rp_src5 = (0,3)
|
|
dst3 = (4,7)
|
|
src3 = (4,7)
|
|
dst4 = (0,3)
|
|
src4 = (0,3)
|
|
prp_dst = (0,3)
|
|
prp_src = (0,3)
|
|
;
|
|
|
|
|
|
# Attach variables =====================================================
|
|
|
|
# normal registers
|
|
attach variables [ src dst src1 dst1 src2 dst2 src3 dst3 src4 dst4 src5 ] [
|
|
R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12_L R13_L RA_L SP_L
|
|
];
|
|
|
|
# register pairs
|
|
attach variables [ rp_src rp_dst rp_src2 rp_dst2 rp_src3 rp_dst3
|
|
rp_src4 rp_dst4 rp_src5 rp_dst5 rp_src6 rp_dst6 rp_dst7 ] [
|
|
R1R0 R2R1 R3R2 R4R3 R5R4 R6R5 R7R6 R8R7
|
|
R9R8 R10R9 R11R10 R12LR11 R12 R13 RA SP
|
|
];
|
|
|
|
attach variables [ prp_src prp_dst prp_src1 prp_dst1 ] [ # rrp
|
|
R1R0 R3R2 R5R4 R7R6 R9R8 R11R10 R4R3 R6R5
|
|
R1R0 R3R2 R5R4 R7R6 R9R8 R11R10 R4R3 R6R5
|
|
];
|
|
|
|
# processor registers
|
|
attach variables [ pr ] [
|
|
DBS DSR DCRL DCRH CAR0L CAR0H CAR1L CAR1H CFG PSR INTBASEL INTBASEH ISPL ISPH USPL USPH
|
|
];
|
|
|
|
attach variables [ prd ] [
|
|
DBS_1 DSR_1 DCR _ CAR0 _ CAR1 _ CFG_1 PSR_1 INTBASE _ ISP _ USP _
|
|
];
|
|
|
|
# Pseudo instructions =================================================
|
|
|
|
define pcodeop trap;
|
|
define pcodeop suspend;
|
|
|
|
# Macros ==============================================================
|
|
|
|
# Flags set by add instructions
|
|
macro addflags(op1, op2) {
|
|
$(C) = (carry(op1, op2)); # Check for carry
|
|
$(F) = (scarry(op1, op2)); # Check for overflow
|
|
}
|
|
# Flags set by add instructions (3 operands)
|
|
macro addflags2(op1, op2, op3) {
|
|
local tmp = (carry(op1,op2)); # Check for carry
|
|
$(C) = (carry(zext(tmp), op3));
|
|
tmp = (scarry(op1,op2)); # Check for overflow
|
|
$(F) = (scarry(zext(tmp), op3));
|
|
}
|
|
# Flags set by sub instructions
|
|
macro subflags(op1, op2) {
|
|
$(C) = (op1 < op2); # Check for borrow
|
|
$(F) = sborrow(op1, op2); # Check for overflow
|
|
}
|
|
# Flags set by sub instructions (3 operands)
|
|
macro subflags2(op1, op2, op3) {
|
|
$(C) = (op1 < (op2 + op3)); # Check for borrow
|
|
local tmp = sborrow(op1, op2); # Check for overflow
|
|
$(F) = sborrow(zext(tmp), op3);
|
|
}
|
|
|
|
# Flags set by the compare instructions
|
|
macro compflags(op1, op2) {
|
|
$(Z) = (op1 == op2); # Equal comparison
|
|
$(N) = (op2 s< op1); # Signed comparison
|
|
$(L) = (op2 < op1); # Unsigned comparison
|
|
}
|
|
|
|
# Operand Display ====================================================
|
|
|
|
imm20: "$"tmp is n5 & dw_w2 [ tmp = (n5 << 16) + dw_w2; ] { export *[const]:3 tmp; }
|
|
imm32: "$"tmp is dw_w1 & dw_w2 [ tmp = (dw_w1 << 16) + dw_w2; ] { export *[const]:4 tmp; }
|
|
imm4: "$"x2 is x2 { export *[const]:1 x2; } # imm src
|
|
imm4: "$"tmp is x2=9 [ tmp = -1; ] { export *[const]:1 tmp; }
|
|
imm4a: "$"x2 is x2 { export *[const]:1 x2; } # imm pos
|
|
imm4b: "$"n6 is n6 { export *[const]:1 n6; }
|
|
imm4c: "$"dw_n2 is dw_n2 { export *[const]:1 dw_n2; }
|
|
imm4d: "$"b4_7 is b4_7 { export *[const]:1 b4_7; } # for ash and lsh (signed count)
|
|
imm16: "$"w2 is w2 { export *[const]:2 w2; }
|
|
imm5: "$"b4_8 is b4_8 { export *[const]:1 b4_8; } # for ash and lsh (signed count)
|
|
imm3: "$"b4_6 is b4_6 { export *[const]:1 b4_6; }
|
|
imm3b: "$"dw_b4_6 is dw_b4_6 { export *[const]:1 dw_b4_6; }
|
|
imm3c: "$"dw_n2b is dw_n2b { export *[const]:1 dw_n2b; }
|
|
imm3d: "$"x2s is x2s { export *[const]:1 x2s; } # for ash and lsh (signed count)
|
|
|
|
cnt3: "$"tmp is b4_6 [ tmp = b4_6 + 1; ] { export *[const]:1 tmp; }
|
|
cnt3b: "$"tmp is b0_2 [ tmp = b0_2 + 1; ] { export *[const]:1 tmp; }
|
|
|
|
# If (abs20 > 0xEFFFF) the resulting address is logically ORed with 0xF00000
|
|
# i.e. addresses from 1M-64k to 1M are re-mapped by the core to 16M-64k to 16M.
|
|
abs20: tmp is n5=0xf & dw_w2 [ tmp = 0xff0000 | dw_w2; ] {
|
|
export *[const]:3 tmp;
|
|
}
|
|
|
|
abs20: tmp is n5 & dw_w2 [ tmp = (n5 << 16) + dw_w2; ] {
|
|
export *[const]:3 tmp;
|
|
}
|
|
|
|
abs24: "*"tmp is n5 & n7 & b0_15
|
|
[ tmp = (n5 << 20) + (n7 << 16) + (b0_15); ] { export *[const]:4 tmp; }
|
|
|
|
# NOTE: disp24 is sign extended to 25 bits - hopefully that doesn't matter here
|
|
# TODO: display *+/*- relative to PC?
|
|
disp8: "*"tmp is x1 & x3s
|
|
[ tmp = (x3s << 5) + (x1 << 1) + inst_start; ] { export *[ram]:4 tmp; } # fmt 21
|
|
disp16: "*"tmp is w2_b1_15
|
|
[ tmp = (w2_b1_15 << 1) + inst_start; ] { export *[ram]:4 tmp; } # fmt 5, 22
|
|
disp24: "*"tmp is n5s & n7 & b1_15
|
|
[ tmp = (n5s << 20) + (n7 << 16) + (b1_15 << 1) + inst_start; ] { export *[ram]:4 tmp; }
|
|
disp24b:"*"tmp is dw_lo & b1_15
|
|
[ tmp = (dw_lo << 16) + (b1_15 << 1) + inst_start; ] { export *[ram]:4 tmp; }
|
|
disp4c: "*"tmp is x2
|
|
[ tmp = ((x2 + 1) << 1) + inst_start; ] { export *[ram]:4 tmp; }
|
|
|
|
# disps not relative to PC
|
|
disp4: "*"tmp is x3 [ tmp = (x3 << 1); ] { export *[const]:3 tmp; }
|
|
disp4b: "*"x3 is x3 { export *[const]:3 x3; }
|
|
disp16b:"*"w2 is w2 { export *[const]:2 w2; }
|
|
disp20: "*"tmp is n7 & dw_w2
|
|
[ tmp = (n7 << 16) + dw_w2; ] { export *[const]:3 tmp; }
|
|
disp14: "*"tmp is f17a & f17b & f17c & f17d
|
|
[ tmp = (f17d << 8) + (f17c << 6) + (f17b << 4) + f17a; ] { export *[const]:3 tmp; }
|
|
|
|
|
|
cc: "eq" is cond=0 { local tmp = $(Z); export tmp; }
|
|
cc: "ne" is cond=1 { local tmp = !$(Z); export tmp; }
|
|
cc: "cs" is cond=2 { local tmp = $(C); export tmp; }
|
|
cc: "cc" is cond=3 { local tmp = !$(C); export tmp; }
|
|
cc: "hi" is cond=4 { local tmp = $(L); export tmp; }
|
|
cc: "ls" is cond=5 { local tmp = !$(L); export tmp; }
|
|
cc: "gt" is cond=6 { local tmp = $(N); export tmp; }
|
|
cc: "le" is cond=7 { local tmp = !$(N); export tmp; }
|
|
cc: "fs" is cond=8 { local tmp = $(F); export tmp; }
|
|
cc: "fc" is cond=9 { local tmp = !$(F); export tmp; }
|
|
cc: "lo" is cond=10 { local tmp = !$(Z) && !$(L); export tmp; }
|
|
cc: "hs" is cond=11 { local tmp = $(Z) || $(L); export tmp; }
|
|
cc: "lt" is cond=12 { local tmp = !$(Z) && !$(N); export tmp; }
|
|
cc: "ge" is cond=13 { local tmp = $(Z) || $(N); export tmp; }
|
|
COND: cc is cc { if (!cc) goto inst_next; }
|
|
|
|
cc2: "eq" is n6=0 { local tmp = $(Z); export tmp; }
|
|
cc2: "ne" is n6=1 { local tmp = !$(Z); export tmp; }
|
|
cc2: "cs" is n6=2 { local tmp = $(C); export tmp; }
|
|
cc2: "cc" is n6=3 { local tmp = !$(C); export tmp; }
|
|
cc2: "hi" is n6=4 { local tmp = $(L); export tmp; }
|
|
cc2: "ls" is n6=5 { local tmp = !$(L); export tmp; }
|
|
cc2: "gt" is n6=6 { local tmp = $(N); export tmp; }
|
|
cc2: "le" is n6=7 { local tmp = !$(N); export tmp; }
|
|
cc2: "fs" is n6=8 { local tmp = $(F); export tmp; }
|
|
cc2: "fc" is n6=9 { local tmp = !$(F); export tmp; }
|
|
cc2: "lo" is n6=10 { local tmp = !($(Z) && $(L)); export tmp; }
|
|
cc2: "hs" is n6=11 { local tmp = $(Z) || $(L); export tmp; }
|
|
cc2: "lt" is n6=12 { local tmp = !($(Z) && $(N)); export tmp; }
|
|
cc2: "ge" is n6=13 { local tmp = $(Z) || $(N); export tmp; }
|
|
COND2: cc2 is cc2 { if (!cc2) goto inst_next; }
|
|
|
|
|
|
ra: "RA" is epsilon { }
|
|
const1: "0x0" is epsilon { }
|
|
|
|
rs: "[R12]" is b_rs=0 { export R12; }
|
|
rs: "[R13]" is b_rs=1 { export R13; }
|
|
|
|
prp2: "[R12]" is dw_b_prp=0 { export R12; }
|
|
prp2: "[R13]" is dw_b_prp=1 { export R13; }
|
|
|
|
prp: "[R12]" is b_prp=0 { export R12; }
|
|
prp: "[R13]" is b_prp=1 { export R13; }
|
|
|
|
cinv1: "[i]" is epsilon { }
|
|
cinv2: "[i,u]" is epsilon { }
|
|
cinv3: "[d]" is epsilon { }
|
|
cinv4: "[d,u]" is epsilon { }
|
|
cinv5: "[d,i]" is epsilon { }
|
|
cinv6: "[d,i,u]" is epsilon { }
|
|
|
|
|
|
|
|
# Constructors ===============================================================
|
|
|
|
# MOVES
|
|
|
|
# MOVB - move low-order byte only
|
|
:MOVB imm4, dst is hi=0x58 & dst & imm4 {
|
|
dst = (dst & 0xff00) | (zext(imm4) & 0x00ff);
|
|
}
|
|
:MOVB imm16, dst is hi=0x58 & x2=11 & dst ; imm16 {
|
|
dst = (dst & 0xff00) | (imm16 & 0x00ff);
|
|
}
|
|
:MOVB src, dst is hi=0x59 & src & dst {
|
|
dst = (dst & 0xff00) | (zext(src:1) & 0x00ff);
|
|
}
|
|
|
|
# MOVD - move doubleword
|
|
:MOVD imm20, rp_dst4 is dw_hi=0x05 & rp_dst4 & imm20 {
|
|
rp_dst4 = zext(imm20);
|
|
}
|
|
:MOVD imm32, rp_dst is op12=0x007 & rp_dst ; imm32 {
|
|
rp_dst = imm32;
|
|
}
|
|
:MOVD imm4, rp_dst is hi=0x54 & rp_dst & imm4 {
|
|
rp_dst = sext(imm4);
|
|
}
|
|
:MOVD imm16, rp_dst is hi=0x54 & x2=11 & rp_dst ; imm16 {
|
|
rp_dst = sext(imm16);
|
|
}
|
|
:MOVD rp_src, rp_dst is hi=0x55 & rp_dst & rp_src {
|
|
rp_dst = rp_src;
|
|
}
|
|
|
|
# MOVW - move word
|
|
:MOVW imm4, dst is hi=0x5a & dst & imm4 {
|
|
dst = sext(imm4);
|
|
}
|
|
:MOVW imm16, dst is hi=0x5a & x2=11 & dst ; imm16 {
|
|
dst = imm16;
|
|
}
|
|
:MOVW src, dst is hi=0x5b & src & dst {
|
|
dst = src;
|
|
}
|
|
|
|
# MOVXB - move low-order byte of src to word dst with sign extension
|
|
:MOVXB src, dst is hi=0x5c & src & dst {
|
|
dst = sext(src:1);
|
|
}
|
|
# MOVXW - move word src to doubleword dst with sign extension
|
|
:MOVXW src, rp_dst is hi=0x5e & src & rp_dst {
|
|
rp_dst = sext(src);
|
|
}
|
|
|
|
# MOVZB - move low-order byte of src to word dst with zero extension
|
|
:MOVZB src, dst is hi=0x5d & src & dst {
|
|
dst = zext(src:1);
|
|
}
|
|
# MOVZW - move word src to doubleword dst with zero extension
|
|
:MOVZW src, rp_dst is hi=0x5f & src & rp_dst {
|
|
rp_dst = zext(src);
|
|
}
|
|
|
|
|
|
# ARITHMETIC
|
|
|
|
# ADDB - add low-order byte only
|
|
:ADDB imm4, dst is hi=0x30 & dst & imm4 {
|
|
addflags(dst:1, imm4);
|
|
tmp:1 = dst:1 + imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ADDB imm16, dst is hi=0x30 & x2=11 & dst ; imm16 {
|
|
addflags(dst:1, imm16:1);
|
|
tmp:1 = dst:1 + imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ADDB src, dst is hi=0x31 & src & dst {
|
|
addflags(dst:1, src:1);
|
|
tmp:1 = dst:1 + src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# ADDCB - add with carry low-order byte only
|
|
:ADDCB imm4, dst is hi=0x34 & dst & imm4 {
|
|
addflags2(dst:1, imm4, $(C));
|
|
tmp:1 = dst:1 + imm4 + $(C);
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ADDCB imm16, dst is hi=0x34 & x2=11 & dst ; imm16 {
|
|
addflags2(dst:1, imm16:1, $(C));
|
|
tmp:1 = dst:1 + imm16:1 + $(C);
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ADDCB src, dst is hi=0x35 & src & dst {
|
|
addflags2(dst:1, src:1, $(C));
|
|
tmp:1 = dst:1 + src:1 + $(C);
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# ADDCW - add word with carry
|
|
:ADDCW imm4, dst is hi=0x36 & dst & imm4 {
|
|
tmp2:2 = sext(imm4);
|
|
tmp3:2 = zext($(C));
|
|
addflags2(dst, tmp2, tmp3);
|
|
dst = dst + tmp2 + tmp3;
|
|
}
|
|
:ADDCW imm16, dst is hi=0x36 & x2=11 & dst ; imm16 {
|
|
tmp3:2 = zext($(C));
|
|
addflags2(dst, imm16, tmp3);
|
|
dst = dst + imm16 + tmp3;
|
|
}
|
|
:ADDCW src, dst is hi=0x37 & src & dst {
|
|
tmp3:2 = zext($(C));
|
|
addflags2(dst, src, tmp3);
|
|
dst = dst + src + tmp3;
|
|
}
|
|
|
|
# ADDD - add doubleword
|
|
:ADDD imm20, rp_dst4 is dw_hi=0x04 & rp_dst4 & imm20 {
|
|
tmp:4 = zext(imm20);
|
|
addflags(tmp, rp_dst4);
|
|
rp_dst4 = rp_dst4 + tmp;
|
|
}
|
|
:ADDD imm32, rp_dst is op12=0x002 & rp_dst ; imm32 {
|
|
addflags(imm32, rp_dst);
|
|
rp_dst = rp_dst + imm32;
|
|
}
|
|
:ADDD imm4, rp_dst is hi=0x60 & rp_dst & imm4 {
|
|
tmp:4 = sext(imm4);
|
|
addflags(tmp, rp_dst);
|
|
rp_dst = rp_dst + tmp;
|
|
}
|
|
:ADDD imm16, rp_dst is hi=0x60 & x2=11 & rp_dst ; imm16 {
|
|
tmp:4 = sext(imm16);
|
|
addflags(tmp, rp_dst);
|
|
rp_dst = rp_dst + tmp;
|
|
}
|
|
:ADDD rp_src, rp_dst is hi=0x61 & rp_dst & rp_src {
|
|
addflags(rp_src, rp_dst);
|
|
rp_dst = rp_dst + rp_src;
|
|
}
|
|
|
|
# ADDUB - add low-order byte only, PSR flags unaffected
|
|
:ADDUB imm4, dst is hi=0x2c & dst & imm4 {
|
|
tmp:1 = dst:1 + imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:NOP is hi=0x2c & dst=0 & x2=0 {
|
|
|
|
}
|
|
:ADDUB imm16, dst is hi=0x2c & x2=11 & dst ; imm16 {
|
|
tmp:1 = dst:1 + imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ADDUB src, dst is hi=0x2d & src & dst {
|
|
tmp:1 = dst:1 + src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# ADDUW - add word, PSR flags unaffected
|
|
:ADDUW imm4, dst is hi=0x2e & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
dst = dst + tmp;
|
|
}
|
|
:ADDUW imm16, dst is hi=0x2e & x2=11 & dst ; imm16 {
|
|
dst = dst + imm16;
|
|
}
|
|
:ADDUW src, dst is hi=0x2f & src & dst {
|
|
dst = dst + src;
|
|
}
|
|
|
|
# ADDW - add word
|
|
:ADDW imm4, dst is hi=0x32 & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
addflags(tmp, dst);
|
|
dst = dst + tmp;
|
|
}
|
|
:ADDW imm16, dst is hi=0x32 & x2=11 & dst ; imm16 {
|
|
addflags(imm16, dst);
|
|
dst = dst + imm16;
|
|
}
|
|
:ADDW src, dst is hi=0x33 & src & dst {
|
|
addflags(src, dst);
|
|
dst = dst + src;
|
|
}
|
|
|
|
# Multiply Signed Q15 Word and Accumulate Long Result
|
|
:MACQW src2, src5, rp_dst7 is op=0x0014 ; n4=13 & src2 & src5 & rp_dst7 {
|
|
tmp:4 = sext(src2) * sext(src5); # TODO based on what Q15 is, this sext may not be right
|
|
rp_dst7 = rp_dst7 + tmp;
|
|
|
|
# if (!scarry(rp_dst7, tmp)) goto <macqw_next>;
|
|
# rp_dst7 = 0x7fffffff; # overflowed, set to max
|
|
# goto <macqw_end>;
|
|
#<macqw_next>
|
|
# if (!sborrow(rp_dst7, tmp)) goto <macqw_end>;
|
|
# rp_dst7 = 0x80000000; # underflowed, set to min
|
|
#<macqw_end>
|
|
|
|
# TODO: if scarry(rp_dst7, tmp) then rp_dst7 = 0x? TODO what is Q15 signed fractional format
|
|
# if sborrow(rp_dst7, tmp) then rp_dst7 = 0x?
|
|
}
|
|
|
|
# Unsigned Multiply Word and Accumulate Long Result
|
|
:MACUW src2, src5, rp_dst7 is op=0x0014 ; n4=14 & src2 & src5 & rp_dst7 {
|
|
tmp:4 = zext(src2) * zext(src5);
|
|
rp_dst7 = rp_dst7 + tmp;
|
|
|
|
# if scarry(rp_dst7, tmp) then rp_dst7 = 0xffffffff
|
|
if (!scarry(rp_dst7, tmp)) goto <macuw_end>;
|
|
rp_dst7 = 0xffffffff; # overflowed, set to max
|
|
<macuw_end>
|
|
}
|
|
|
|
# Signed Multiply Word and Add Long Result
|
|
:MACSW src2, src5, rp_dst7 is op=0x0014 ; n4=15 & src2 & src5 & rp_dst7 {
|
|
tmp:4 = sext(src2) * sext(src5);
|
|
rp_dst7 = rp_dst7 + tmp;
|
|
|
|
# if scarry(rp_dst7, tmp) then rp_dst7 = 0x7fffffff
|
|
if (!scarry(rp_dst7, tmp)) goto <macsw_next>;
|
|
rp_dst7 = 0x7fffffff; # overflowed, set to max
|
|
goto <macsw_end>;
|
|
<macsw_next>
|
|
# if sborrow(rp_dst7, tmp) then rp_dst7 = 0x80000000
|
|
if (!sborrow(rp_dst7, tmp)) goto <macsw_end>;
|
|
rp_dst7 = 0x80000000; # underflowed, set to min
|
|
<macsw_end>
|
|
}
|
|
|
|
# MULB - multiply byte
|
|
:MULB imm4, dst is hi=0x64 & dst & imm4 {
|
|
tmp:1 = dst:1 * imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:MULB imm16, dst is hi=0x64 & x2=11 & dst ; imm16 {
|
|
tmp:1 = dst:1 * imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);}
|
|
:MULB src, dst is hi=0x65 & src & dst{
|
|
tmp:1 = dst:1 * src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# Signed Multiply Byte, Word Result
|
|
:MULSB src, dst is hi=0x0b & src & dst {
|
|
dst = sext(src:1) * sext(dst:1);
|
|
}
|
|
|
|
# Signed Multiply Word, Long Result
|
|
:MULSW src, rp_dst is hi=0x62 & src & rp_dst {
|
|
rp_dst = sext(src) * sext(rp_dst:2);
|
|
}
|
|
|
|
# Unsigned Multiply Word, Long Result
|
|
:MULUW src, rp_dst is hi=0x63 & src & rp_dst {
|
|
rp_dst = zext(src) * zext(rp_dst:2);
|
|
}
|
|
|
|
# MULW - multiply word
|
|
:MULW imm4, dst is hi=0x66 & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
dst = dst * tmp;
|
|
}
|
|
:MULW imm16, dst is hi=0x66 & x2=11 & dst ; imm16 {
|
|
dst = dst * imm16;
|
|
}
|
|
:MULW src, dst is hi=0x67 & src & dst {
|
|
dst = dst * src;
|
|
}
|
|
|
|
# SUBB - subtract low-order byte only
|
|
:SUBB imm4, dst is hi=0x38 & dst & imm4 {
|
|
subflags(dst:1, imm4);
|
|
tmp:1 = dst:1 - imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:SUBB imm16, dst is hi=0x38 & x2=11 & dst ; imm16 {
|
|
subflags(dst:1, imm16:1);
|
|
tmp:1 = dst:1 - imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:SUBB src, dst is hi=0x39 & src & dst {
|
|
subflags(dst:1, src:1);
|
|
tmp:1 = dst:1 - src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# SUBCB - subtract with carry low-order byte only
|
|
:SUBCB imm4, dst is hi=0x3c & dst & imm4 {
|
|
subflags2(dst:1, imm4, $(C));
|
|
tmp:1 = dst:1 - imm4 - $(C);
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:SUBCB imm16, dst is hi=0x3c & x2=11 & dst ; imm16 {
|
|
subflags2(dst:1, imm16:1, $(C));
|
|
tmp:1 = dst:1 - imm16:1 - $(C);
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:SUBCB src, dst is hi=0x3d & src & dst {
|
|
subflags2(dst:1, src:1, $(C));
|
|
tmp:1 = dst:1 - src:1 - $(C);
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# SUBCW - subtract word with carry
|
|
:SUBCW imm4, dst is hi=0x3e & dst & imm4 {
|
|
tmp2:2 = sext(imm4);
|
|
tmp3:2 = zext($(C));
|
|
subflags2(dst, tmp2, tmp3);
|
|
dst = dst - tmp2 - tmp3;
|
|
}
|
|
:SUBCW imm16, dst is hi=0x3e & x2=11 & dst ; imm16 {
|
|
tmp3:2 = zext($(C));
|
|
subflags2(dst, imm16, tmp3);
|
|
dst = dst - imm16 - tmp3;
|
|
}
|
|
:SUBCW src, dst is hi=0x3f & src & dst {
|
|
tmp3:2 = zext($(C));
|
|
subflags2(dst, src, tmp3);
|
|
dst = dst - src - tmp3;
|
|
}
|
|
|
|
# SUBD - subtract doubleword
|
|
:SUBD rp_src6, rp_dst3 is op=0x0014 ; n4=12 & n3=0 & rp_src6 & rp_dst3 { # fmt 1
|
|
subflags(rp_dst3, rp_src6);
|
|
rp_dst3 = rp_dst3 - rp_src6;
|
|
}
|
|
:SUBD imm32, rp_dst is op12=0x003 & rp_dst ; imm32 {
|
|
subflags(imm32, rp_dst);
|
|
rp_dst = rp_dst - imm32;
|
|
}
|
|
|
|
# SUBW - subtract word
|
|
:SUBW imm4, dst is hi=0x3a & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
subflags(tmp, dst);
|
|
dst = dst - tmp;
|
|
}
|
|
:SUBW imm16, dst is hi=0x3a & x2=11 & dst ; imm16 {
|
|
subflags(imm16, dst);
|
|
dst = dst - imm16;
|
|
}
|
|
:SUBW src, dst is hi=0x3b & src & dst {
|
|
subflags(src, dst);
|
|
dst = dst - src;
|
|
}
|
|
|
|
|
|
# INTEGER COMPARISON
|
|
|
|
# CMPB - compare low-order byte only
|
|
:CMPB imm4, src1 is hi=0x50 & src1 & imm4 {
|
|
compflags(imm4, src1:1);
|
|
}
|
|
:CMPB imm16, src1 is hi=0x50 & x2=11 & src1 ; imm16 {
|
|
compflags(imm16:1, src1:1);
|
|
}
|
|
:CMPB src, src1 is hi=0x51 & src & src1 {
|
|
compflags(src:1, src1:1);
|
|
}
|
|
|
|
# CMPD - compare doubleword
|
|
:CMPD imm32, rp_src2 is op12=0x009 & rp_src2 ; imm32 {
|
|
compflags(imm32, rp_src2);
|
|
}
|
|
:CMPD imm4, rp_src2 is hi=0x56 & rp_src2 & imm4 {
|
|
tmp:4 = sext(imm4);
|
|
compflags(tmp, rp_src2);
|
|
}
|
|
:CMPD imm16, rp_src2 is hi=0x56 & x2=11 & rp_src2 ; imm16 {
|
|
tmp:4 = sext(imm16);
|
|
compflags(tmp, rp_src2);
|
|
}
|
|
:CMPD rp_src, rp_src2 is hi=0x57 & rp_src & rp_src2 {
|
|
compflags(rp_src, rp_src2);
|
|
}
|
|
|
|
# CMPW - compare word
|
|
:CMPW imm4, src1 is hi=0x52 & src1 & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
compflags(tmp, src1);
|
|
}
|
|
:CMPW imm16, src1 is hi=0x52 & x2=11 & src1 ; imm16 {
|
|
compflags(imm16, src1);
|
|
}
|
|
:CMPW src, src1 is hi=0x53 & src & src1 {
|
|
compflags(src, src1);
|
|
}
|
|
|
|
|
|
# LOGICAL / BOOLEAN
|
|
|
|
# ANDB - and low-order byte only
|
|
:ANDB imm4, dst is hi=0x20 & dst & imm4 {
|
|
tmp:1 = dst:1 & imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ANDB imm16, dst is hi=0x20 & x2=11 & dst ; imm16 {
|
|
tmp:1 = dst:1 & imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ANDB src, dst is hi=0x21 & src & dst {
|
|
tmp:1 = dst:1 & src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# ANDW - and word
|
|
:ANDW imm4, dst is hi=0x22 & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
dst = dst & tmp;
|
|
}
|
|
:ANDW imm16, dst is hi=0x22 & x2=11 & dst ; imm16 {
|
|
dst = dst & imm16;
|
|
}
|
|
:ANDW src, dst is hi=0x23 & src & dst {
|
|
dst = dst & src;
|
|
}
|
|
|
|
# ANDD - and doubleword
|
|
:ANDD imm32, rp_dst is op12=0x004 & rp_dst ; imm32 {
|
|
rp_dst = rp_dst & imm32;
|
|
}
|
|
:ANDD rp_src6, rp_dst3 is op=0x0014 ; n4=11 & rp_src6 & rp_dst3 { # fmt 1
|
|
rp_dst3 = rp_dst3 & rp_src6;
|
|
}
|
|
|
|
# ORB - or low-order byte only
|
|
:ORB imm4, dst is hi=0x24 & dst & imm4 {
|
|
tmp:1 = dst:1 | imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ORB imm16, dst is hi=0x24 & x2=11 & dst ; imm16 {
|
|
tmp:1 = dst:1 | imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:ORB src, dst is hi=0x25 & src & dst {
|
|
tmp:1 = dst:1 | src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# ORW - or word
|
|
:ORW imm4, dst is hi=0x26 & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
dst = dst | tmp;
|
|
}
|
|
:ORW imm16, dst is hi=0x26 & x2=11 & dst ; imm16 {
|
|
dst = dst | imm16;
|
|
}
|
|
:ORW src, dst is hi=0x27 & src & dst {
|
|
dst = dst | src;
|
|
}
|
|
|
|
# ORD - or doubleword
|
|
:ORD imm32, rp_dst is op12=0x005 & rp_dst ; imm32 {
|
|
rp_dst = rp_dst | imm32;
|
|
}
|
|
:ORD rp_src6, rp_dst3 is op=0x0014 ; n4=9 & rp_src6 & rp_dst3 { # fmt 1
|
|
rp_dst3 = rp_dst3 | rp_src6;
|
|
}
|
|
|
|
# S - save condition as boolean
|
|
:S^COND dst is hi=0x08 & COND & dst {
|
|
dst = 0;
|
|
build COND;
|
|
dst = 1;
|
|
}
|
|
:S dst is hi=0x08 & cond=14 & dst {
|
|
dst = 1;
|
|
}
|
|
:S dst is hi=0x08 & cond=15 & dst {
|
|
dst = 1;
|
|
}
|
|
|
|
# XORB - xor low-order byte only
|
|
:XORB imm4, dst is hi=0x28 & dst & imm4 {
|
|
tmp:1 = dst:1 ^ imm4;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:XORB imm16, dst is hi=0x28 & x2=11 & dst ; imm16 {
|
|
tmp:1 = dst:1 ^ imm16:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
:XORB src, dst is hi=0x29 & src & dst {
|
|
tmp:1 = dst:1 ^ src:1;
|
|
dst = (dst & 0xff00) + zext(tmp);
|
|
}
|
|
|
|
# XORW - xor word
|
|
:XORW imm4, dst is hi=0x2a & dst & imm4 {
|
|
tmp:2 = sext(imm4);
|
|
dst = dst ^ tmp;
|
|
}
|
|
:XORW imm16, dst is hi=0x2a & x2=11 & dst ; imm16 {
|
|
dst = dst ^ imm16;
|
|
}
|
|
:XORW src, dst is hi=0x2b & src & dst {
|
|
dst = dst ^ src;
|
|
}
|
|
|
|
# XORD - xor doubleword
|
|
:XORD imm32, rp_dst is op12=0x006 & rp_dst ; imm32 {
|
|
rp_dst = rp_dst ^ imm32;
|
|
}
|
|
:XORD rp_src6, rp_dst3 is op=0x0014 ; n4=10 & rp_src6 & rp_dst3 { # fmt 1
|
|
rp_dst3 = rp_dst3 ^ rp_src6;
|
|
}
|
|
|
|
|
|
# SHIFTS
|
|
|
|
# TODO: left shift displays "+", right shift displays "-"
|
|
|
|
macro do_ash(count, dest) {
|
|
local shift = count:1;
|
|
local lf = ( shift) * zext(shift s> 0);
|
|
local rt = (-shift) * zext(shift s< 0);
|
|
dest = dest << lf;
|
|
dest = dest s>> rt;
|
|
}
|
|
|
|
macro do_ashb(count, dest) {
|
|
local tmp = dest & 0xff;
|
|
do_ash(count, tmp);
|
|
dest = (dest & 0xff00) | (tmp & 0x00ff);
|
|
}
|
|
|
|
macro do_lsh(count, dest) {
|
|
local shift = count:1;
|
|
local lf = ( shift) * zext(shift s> 0);
|
|
local rt = (-shift) * zext(shift s< 0);
|
|
dest = dest << lf;
|
|
dest = dest >> rt;
|
|
}
|
|
|
|
macro do_lshb(count, dest) {
|
|
local tmp = dest & 0xff;
|
|
do_lsh(count, tmp);
|
|
dest = (dest & 0xff00) | (tmp & 0x00ff);
|
|
}
|
|
|
|
# ASHUB - Arithmetic shift low-order byte only
|
|
:ASHUB imm3d, dst is op9=0b010000000 & imm3d & dst { do_ashb(imm3d, dst); }
|
|
:ASHUB imm3d, dst is op9=0b010000001 & imm3d & dst { do_ashb(imm3d-8, dst); }
|
|
:ASHUB src, dst is hi=0x41 & src & dst { do_ashb(src, dst); }
|
|
|
|
# ASHUD - Arithmetic shift doubleword
|
|
:ASHUD imm5, rp_dst is op7=0b0100110 & imm5 & rp_dst { do_ash(imm5, rp_dst); }
|
|
:ASHUD imm5, rp_dst is op7=0b0100111 & imm5 & rp_dst { do_ash(imm5-32, rp_dst); }
|
|
:ASHUD src, rp_dst is hi=0x48 & src & rp_dst { do_ash(src, rp_dst); }
|
|
|
|
# ASHUW - Arithmetic shift word
|
|
:ASHUW imm4d, dst is hi=0x42 & imm4d & dst { do_ash(imm4d, dst); }
|
|
:ASHUW imm4d, dst is hi=0x43 & imm4d & dst { do_ash(imm4d-16, dst); }
|
|
:ASHUW src, dst is hi=0x45 & src & dst { do_ash(src, dst); }
|
|
|
|
# LSHB - Logical shift low-order byte only
|
|
:LSHB imm3d, dst is op9=0b000010011 & imm3d & dst { do_lshb(imm3d-8, dst); }
|
|
:LSHB src, dst is hi=0x44 & src & dst { do_lshb(src, dst); }
|
|
|
|
# LSHD - Logical shift doubleword
|
|
:LSHD imm5, rp_dst is op7=0b0100101 & imm5 & rp_dst { do_lsh(imm5-32, rp_dst); }
|
|
:LSHD src, rp_dst is hi=0x47 & src & rp_dst { do_lsh(src, rp_dst); }
|
|
|
|
# LSHW - Logical shift word
|
|
:LSHW imm4d, dst is hi=0x49 & imm4d & dst { do_lsh(imm4d-16, dst); }
|
|
:LSHW src, dst is hi=0x46 & src & dst { do_lsh(src, dst); }
|
|
|
|
# BITS
|
|
# - for bit ops, dsp(n) is always unsigned
|
|
|
|
# CBITB - clear bit in low-order byte
|
|
:CBITB imm3c, prp2 disp14(prp_dst) is op10=0x1aa & imm3c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3c;
|
|
$(F) = (val & mask) >> imm3c; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3b, disp20(dst4) is op=0x0010 ; n8=4 & imm3b & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3, const1(rp_dst) is op9=0x0d4 & imm3 & rp_dst & const1 { # fmt 9
|
|
tmp:4 = rp_dst:4;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3;
|
|
$(F) = (val & mask) >> imm3; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3, disp16b(rp_dst) is op9=0x0d6 & imm3 & rp_dst ; disp16b { # fmt 10
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3;
|
|
$(F) = (val & mask) >> imm3; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3b, disp20(rp_dst5) is op=0x0010 ; n8=5 & imm3b & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3b, disp20(prp_dst) is op=0x0010 ; n8=6 & imm3b & disp20 & prp_dst { # fmt 2
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3b, abs20 is dw_op9=0x0d7 & imm3b & abs20 { # fmt 7
|
|
tmp:4 = zext(abs20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3b, rs abs20 is dw_hi=0x68 & imm3b & rs & abs20 { # fmt 8
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITB imm3b, abs24 is op=0x0010 ; n8=7 & imm3b & abs24 { # fmt 3
|
|
tmp:4 = abs24;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
mask = ~mask;
|
|
*:1 tmp = val & mask; # clear bit, store
|
|
}
|
|
|
|
# CBITW - clear bit in word
|
|
:CBITW imm4c, prp2 disp14(prp_dst) is op10=0x1ab & imm4c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4c;
|
|
bit:2 = (val & mask) >> imm4c;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4b, disp20(dst4) is op=0x0011 ; n8=4 & imm4b & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4a, const1(rp_dst) is hi=0x6e & imm4a & rp_dst & const1 {
|
|
tmp:4 = rp_dst:4;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4a, disp16b(rp_dst) is hi=0x69 & imm4a & rp_dst ; disp16b {
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4b, disp20(rp_dst5) is op=0x0011 ; n8=5 & rp_dst5 & imm4b & disp20 {
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4b, disp20(prp_dst) is op=0x0011 ; n8=6 & imm4b & disp20 & prp_dst { # fmt 2
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4b, abs20 is dw_hi=0x6f & imm4b & abs20 { # fmt 12
|
|
tmp:4 = zext(abs20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4b, rs abs20 is dw_op7=0x36 & imm4b & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
:CBITW imm4b, abs24 is op=0x0011 ; n8=7 & imm4b & abs24 { # fmt 3
|
|
tmp:4 = abs24;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
mask = ~mask;
|
|
*:2 tmp = val & mask; # clear bit, store
|
|
}
|
|
|
|
# SBITB - set bit in low-order byte
|
|
:SBITB imm3c, prp2 disp14(prp_dst) is op10=0x1ca & imm3c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3c;
|
|
$(F) = (val & mask) >> imm3c; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3b, disp20(dst4) is op=0x0010 ; n8=8 & imm3b & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3, const1(rp_dst) is op9=0x0e4 & imm3 & rp_dst & const1 { # fmt 9
|
|
tmp:4 = rp_dst:4;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3;
|
|
$(F) = (val & mask) >> imm3; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3, disp16b(rp_dst) is op9=0x0e6 & imm3 & rp_dst ; disp16b { # fmt 10
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3;
|
|
$(F) = (val & mask) >> imm3; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3b, disp20(rp_dst5) is op=0x0010 ; n8=9 & imm3b & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3b, disp20(prp_dst) is op=0x0010 ; n8=10 & imm3b & disp20 & prp_dst { # fmt 2
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3b, abs20 is dw_op9=0x0e7 & imm3b & abs20 { # fmt 7
|
|
tmp:4 = zext(abs20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3b, rs abs20 is dw_hi=0x70 & imm3b & rs & abs20 { # fmt 8
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
:SBITB imm3b, abs24 is op=0x0010 ; n8=11 & imm3b & abs24 { # fmt 3
|
|
tmp:4 = abs24;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
*:1 tmp = val | mask; # set bit, store
|
|
}
|
|
|
|
# SBITW - set bit in word
|
|
:SBITW imm4c, prp2 disp14(prp_dst) is op10=0x1cb & imm4c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4c;
|
|
bit:2 = (val & mask) >> imm4c;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4b, disp20(dst4) is op=0x0011 ; n8=8 & imm4b & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4a, const1(rp_dst) is hi=0x76 & imm4a & const1 & rp_dst { # fmt 15
|
|
tmp:4 = rp_dst:4;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4a, disp16b(rp_dst) is hi=0x71 & imm4a & rp_dst ; disp16b { # fmt 16
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4b, disp20(rp_dst5) is op=0x0011 ; n8=9 & rp_dst5 & imm4b & disp20 {
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4b, disp20(prp_dst) is op=0x0011 ; n8=10 & imm4b & disp20 & prp_dst {
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4b, abs20 is dw_hi=0x77 & imm4b & abs20 { # fmt 12
|
|
tmp:4 = zext(abs20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4b, rs abs20 is dw_op7=0x3a & imm4b & rs & abs20 {
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
:SBITW imm4b, abs24 is op=0x0011 ; n8=11 & imm4b & abs24 { # fmt 3
|
|
tmp:4 = abs24;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
*:2 tmp = val | mask; # clear bit, store
|
|
}
|
|
|
|
# TBIT - test bit
|
|
:TBIT imm4a, src1 is hi=0x06 & imm4a & src1 {
|
|
tmp:4 = zext(src1);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBIT src, src1 is hi=0x07 & src & src1 {
|
|
tmp:4 = zext(src1);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << src;
|
|
bit:2 = (val & mask) >> src;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
|
|
# TBITB - test bit in low-order byte
|
|
:TBITB imm3c, prp2 disp14(prp_dst) is op10=0x1ea & imm3c & prp2 & disp14 & prp_dst { # fmt 17 (affected by CFG.SR)
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3c;
|
|
$(F) = (val & mask) >> imm3c; # save bit
|
|
}
|
|
:TBITB imm3b, disp20(dst4) is op=0x0010 ; n8=12 & imm3b & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
}
|
|
:TBITB imm3, const1(rp_dst) is op9=0x0f4 & imm3 & rp_dst & const1 { # fmt 9
|
|
tmp:4 = rp_dst:4;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3;
|
|
$(F) = (val & mask) >> imm3; # save bit
|
|
}
|
|
:TBITB imm3, disp16b(rp_dst) is op9=0x0f6 & imm3 & rp_dst ; disp16b { # fmt 10
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3;
|
|
$(F) = (val & mask) >> imm3; # save bit
|
|
}
|
|
:TBITB imm3b, disp20(rp_dst5) is op=0x0010 ; n8=13 & imm3b & disp20 & rp_dst5 {
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
}
|
|
:TBITB imm3b, disp20(prp_dst) is op=0x0010 ; n8=14 & imm3b & disp20 & prp_dst {
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
}
|
|
:TBITB imm3b, abs20 is dw_op9=0x0f7 & imm3b & abs20 { # fmt 7
|
|
tmp:4 = zext(abs20);
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
}
|
|
:TBITB imm3b, rs abs20 is dw_hi=0x78 & imm3b & rs & abs20 { # fmt 8
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
}
|
|
:TBITB imm3b, abs24 is op=0x0010 ; n8=15 & imm3b & abs24 { # fmt 3
|
|
tmp:4 = abs24;
|
|
val:1 = *:1 tmp; # load dst operand
|
|
local mask = 1 << imm3b;
|
|
$(F) = (val & mask) >> imm3b; # save bit
|
|
}
|
|
|
|
# TBITW - test bit in word
|
|
:TBITW imm4c, prp2 disp14(prp_dst) is op10=0x1eb & imm4c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4c;
|
|
bit:2 = (val & mask) >> imm4c;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4b, disp20(dst4) is op=0x0011 ; n8=12 & imm4b & disp20 & dst4 {
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4a, const1(rp_dst) is hi=0x7e & imm4a & const1 & rp_dst { # fmt 15
|
|
tmp:4 = rp_dst:4;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4a, disp16b(rp_dst) is hi=0x79 & imm4a & rp_dst ; disp16b { # fmt 16
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4a;
|
|
bit:2 = (val & mask) >> imm4a;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4b, disp20(rp_dst5) is op=0x0011 ; n8=13 & rp_dst5 & imm4b & disp20 {
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4b, disp20(prp_dst) is op=0x0011 ; n8=14 & imm4b & disp20 & prp_dst {
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4b, abs20 is dw_hi=0x7f & imm4b & abs20 {
|
|
tmp:4 = zext(abs20);
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4b, rs abs20 is dw_op7=0x3e & imm4b & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
:TBITW imm4b, abs24 is op=0x0011 ; n8=15 & imm4b & abs24 {
|
|
tmp:4 = abs24;
|
|
val:2 = *:2 tmp; # load dst operand
|
|
mask:2 = 1 << imm4b;
|
|
bit:2 = (val & mask) >> imm4b;
|
|
$(F) = bit:1; # save bit
|
|
}
|
|
|
|
|
|
# PROCESSOR REGISTER MANIPULATION
|
|
|
|
# TODO:
|
|
# For the LPR instruction, if dest is ISPL or INTBASEL the least significant
|
|
# bit (bit 0) of the address is 0. If dest is INTBASEH, ISPH, USPH, CAR0H,
|
|
# or CAR1H bits 8 through 15 are always written as 0.
|
|
# For the LPRD instruction, if dest is ISP or INTBASE the least significant
|
|
# bit (bit 0) of the address is 0. If dest is INTBASE, ISP, USP, CAR0, or
|
|
# CAR1 bits 24 through 31 are always written as 0.
|
|
|
|
# Load Processor Register (word)
|
|
:LPR src2, pr is op=0x0014 ; n4=0 & n3=0 & pr & src2 {
|
|
pr = src2;
|
|
}
|
|
|
|
# Load Processor Register (doubleword)
|
|
:LPRD rp_src3, prd is op=0x0014 ; n4=1 & n3=0 & prd & rp_src3 {
|
|
prd = rp_src3;
|
|
}
|
|
|
|
# Store Processor Register (word)
|
|
:SPR pr, dst2 is op=0x0014 ; n4=2 & n3=0 & pr & dst2 {
|
|
dst2 = pr;
|
|
}
|
|
|
|
# Store Processor Register (doubleword)
|
|
:SPRD prd, rp_dst3 is op=0x0014 ; n4=3 & n3=0 & prd & rp_dst3 {
|
|
rp_dst3 = prd;
|
|
}
|
|
|
|
|
|
# JUMPS AND LINKS
|
|
|
|
# BAL - Branch and Link
|
|
:BAL (RA), disp24b is dw_hi=0xc0 & disp24b & RA {
|
|
RA = inst_next >> 1; # save bits 1 to 23 in link reg RA
|
|
PC = &disp24b; # PC = PC + sext25(disp) TODO: 25 bits?
|
|
call disp24b;
|
|
}
|
|
:BAL rp_dst4, disp24 is op=0x0010 ; n8=2 & disp24 & rp_dst4 {
|
|
# rp link is at word2 (4,7)
|
|
rp_dst4 = inst_next >> 1; # save bits 1 to 23 in link reg
|
|
PC = &disp24; # PC = PC + sext25(disp) TODO: 25 bits?
|
|
call disp24;
|
|
}
|
|
|
|
# BEQ0B - branch if low byte equals 0
|
|
:BEQ0B src1, disp4c is hi=0x0c & src1 & disp4c {
|
|
if (src1:1 != 0) goto inst_next; # don't branch if not equal
|
|
PC = &disp4c; # branch
|
|
goto disp4c;
|
|
}
|
|
# BEQ0W - branch if word equals 0
|
|
:BEQ0W src1, disp4c is hi=0x0e & src1 & disp4c {
|
|
if (src1 != 0) goto inst_next; # don't branch if not equal
|
|
PC = &disp4c; # branch
|
|
goto disp4c;
|
|
}
|
|
# BNE0B - branch if low byte does not equal 0
|
|
:BNE0B src1, disp4c is hi=0x0d & src1 & disp4c {
|
|
if (src1:1 == 0) goto inst_next; # don't branch if equal
|
|
PC = &disp4c; # branch
|
|
goto disp4c;
|
|
}
|
|
:BNE0W src1, disp4c is hi=0x0f & src1 & disp4c {
|
|
if (src1 == 0) goto inst_next; # don't branch if equal
|
|
PC = &disp4c; # branch
|
|
goto disp4c;
|
|
}
|
|
|
|
# BR - branch (conditional and unconditional)
|
|
:BR^COND disp8 is op4=1 & COND & disp8 { # BR (conditional)
|
|
build COND;
|
|
PC = &disp8;
|
|
goto disp8;
|
|
}
|
|
:BR disp8 is op4=1 & cond=14 & disp8 { # BR cond=14 (always)
|
|
PC = &disp8;
|
|
goto disp8;
|
|
}
|
|
:BR disp8 is op4=1 & cond=15 & disp8 { # BR cond=15 (unconditional)
|
|
PC = &disp8;
|
|
goto disp8;
|
|
}
|
|
|
|
:BR^COND disp16 is hi=0x18 & lo1=0 & COND ; disp16 { # BR (conditional)
|
|
build COND;
|
|
PC = &disp16;
|
|
goto disp16;
|
|
}
|
|
:BR disp16 is hi=0x18 & lo1=0 & cond=14 ; disp16 { # BR cond=14 (always)
|
|
PC = &disp16;
|
|
goto disp16;
|
|
}
|
|
:BR disp16 is hi=0x18 & lo1=0 & cond=15 ; disp16 { # BR cond=15 (unconditional)
|
|
PC = &disp16;
|
|
goto disp16;
|
|
}
|
|
|
|
:BR^COND2 disp24 is op=0x0010 ; n8=0 & COND2 & disp24 { # BR (conditional)
|
|
build COND2;
|
|
PC = &disp24;
|
|
goto disp24;
|
|
}
|
|
:BR disp24 is op=0x0010 ; n8=0 & n6=14 & disp24 { # BR cond=14 (always)
|
|
PC = &disp24;
|
|
goto disp24;
|
|
}
|
|
:BR disp24 is op=0x0010 ; n8=0 & n6=15 & disp24 { # BR cond=15 (unconditional)
|
|
PC = &disp24;
|
|
goto disp24;
|
|
}
|
|
|
|
# EXCP - Exception
|
|
:EXCP x1 is op12=0x00c & x1 {
|
|
# *:4(ISP:3) = zext(inst_start);
|
|
*:2(ISP:4) = PSR; # push PSR onto interrupt stack
|
|
ISP = ISP - 2;
|
|
*:4(ISP:4) = inst_start; # push ret addr (current instruction) onto interrupt stack
|
|
ISP = ISP - 4;
|
|
trap();
|
|
}
|
|
|
|
# JAL - Jump and Link
|
|
:JAL rp_dst is op12=0x00d & rp_dst {
|
|
RA = inst_next >> 1;
|
|
local tmp = rp_dst << 1;
|
|
PC = tmp:4;
|
|
call [PC];
|
|
}
|
|
:JAL rp_dst6 is op=0x0014 ; n4=8 & n3=0 & rp_dst6 & rp_dst3 {
|
|
# rp link is at word2 (0,3)
|
|
rp_dst3 = inst_next >> 1;
|
|
local tmp = rp_dst6 << 1;
|
|
PC = tmp:4;
|
|
call [PC];
|
|
}
|
|
|
|
# J - Jump - special case jumping through link register
|
|
:J^COND RA is hi=0x0a & COND & rp_dst=14 & RA { # conditional
|
|
build COND;
|
|
local tmp = RA << 1;
|
|
PC = tmp:4;
|
|
return [PC];
|
|
}
|
|
:JUMP RA is hi=0xa & cond=14 & rp_dst=14 & RA { # always
|
|
local tmp = RA << 1;
|
|
PC = tmp:4;
|
|
return [PC];
|
|
}
|
|
:JUSR RA is hi=0xa & cond=15 & rp_dst=14 & RA { # unconditional
|
|
$(U) = 1;
|
|
local tmp = RA << 1;
|
|
PC = tmp:4;
|
|
return [PC];
|
|
}
|
|
|
|
# J - Jump (conditional and unconditional)
|
|
:J^COND rp_dst is hi=0x0a & COND & rp_dst { # conditional
|
|
build COND;
|
|
local tmp = rp_dst << 1;
|
|
PC = tmp:4;
|
|
goto [PC];
|
|
}
|
|
:JUMP rp_dst is hi=0xa & cond=14 & rp_dst { # always
|
|
local tmp = rp_dst << 1;
|
|
PC = tmp:4;
|
|
goto [PC];
|
|
}
|
|
:JUSR rp_dst is hi=0xa & cond=15 & rp_dst { # unconditional
|
|
$(U) = 1;
|
|
local tmp = rp_dst << 1;
|
|
PC = tmp:4;
|
|
goto [PC];
|
|
}
|
|
|
|
attach variables [ reg0 ] [ R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12_L R13_L RA_L SP_L ];
|
|
attach variables [ reg1 ] [ R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12_L R12_H R13_H RA_H SP_H ];
|
|
attach variables [ reg2 ] [ R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12_L R12_H R13_L RA_L SP_L R0 ];
|
|
attach variables [ reg3 ] [ R3 R4 R5 R6 R7 R8 R9 R10 R11 R12_L R12_H R13_L R13_H RA_H SP_H R1 ];
|
|
attach variables [ reg4 ] [ R4 R5 R6 R7 R8 R9 R10 R11 R12_L R12_H R13_L R13_H RA_L SP_L R0 R3 ];
|
|
attach variables [ reg5 ] [ R5 R6 R7 R8 R9 R10 R11 R12_L R12_H R13_L R13_H RA_L RA_H SP_H R1 R4 ];
|
|
attach variables [ reg6 ] [ R6 R7 R8 R9 R10 R11 R12_L R12_H R13_L R13_H RA_L RA_H SP_L R0 R2 R5 ];
|
|
attach variables [ reg7 ] [ R7 R8 R9 R10 R11 R12_L R12_H R13_L R13_H RA_L RA_H SP_L SP_H R1 R3 R6 ];
|
|
|
|
macro push_one(reg) {
|
|
SP = SP - 2;
|
|
*SP = reg;
|
|
}
|
|
|
|
macro pop_one(reg) {
|
|
reg = *SP;
|
|
SP = SP + 2;
|
|
}
|
|
|
|
macro push_ra() {
|
|
SP = SP - 4;
|
|
*SP = RA;
|
|
}
|
|
|
|
macro pop_ra() {
|
|
RA = *SP;
|
|
SP = SP + 4;
|
|
}
|
|
macro do_pop_ret() {
|
|
tmp:4 = RA << 1;
|
|
PC = tmp;
|
|
return [PC];
|
|
}
|
|
|
|
push_args: "$"tmp, reg0 is b_ra=0 & b4_6 & reg0 [ tmp = b4_6 + 1; ] { }
|
|
push_args: "$"tmp, reg0, "ra" is b_ra=1 & b4_6 & reg0 [ tmp = b4_6 + 1; ] { push_ra(); }
|
|
|
|
pop_args: "$"tmp, reg0 is b_ra=0 & b4_6 & reg0 [ tmp = b4_6 + 1; ] { }
|
|
pop_args: "$"tmp, reg0, "ra" is b_ra=1 & b4_6 & reg0 [ tmp = b4_6 + 1; ] { pop_ra(); }
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=0 & reg0 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg0);
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=1 & reg0 & reg1 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=2 & reg0 & reg1 & reg2 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg2);
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=3 & reg0 & reg1 & reg2 & reg3 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg3);
|
|
push_one(reg2);
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=4 & reg0 & reg1 & reg2 & reg3 & reg4 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg4);
|
|
push_one(reg3);
|
|
push_one(reg2);
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=5 & reg0 & reg1 & reg2 & reg3 & reg4 & reg5 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg5);
|
|
push_one(reg4);
|
|
push_one(reg3);
|
|
push_one(reg2);
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=6 & reg0 & reg1 & reg2 & reg3 & reg4 & reg5 & reg6 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg6);
|
|
push_one(reg5);
|
|
push_one(reg4);
|
|
push_one(reg3);
|
|
push_one(reg2);
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
|
|
}
|
|
|
|
:push push_args
|
|
is hi=1 & b4_6=7 & reg0 & reg1 & reg2 & reg3 & reg4 & reg5 & reg6 & reg7 & push_args
|
|
{
|
|
build push_args;
|
|
push_one(reg7);
|
|
push_one(reg6);
|
|
push_one(reg5);
|
|
push_one(reg4);
|
|
push_one(reg3);
|
|
push_one(reg2);
|
|
push_one(reg1);
|
|
push_one(reg0);
|
|
}
|
|
|
|
pop_ret: "ret" is hi=3 { do_pop_ret(); }
|
|
pop_ret: "" is hi=2 { }
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=0 & reg0
|
|
{
|
|
pop_one(reg0);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=1 & reg0 & reg1
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=2 & reg0 & reg1 & reg2
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
pop_one(reg2);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=3 & reg0 & reg1 & reg2 & reg3
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
pop_one(reg2);
|
|
pop_one(reg3);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=4 & reg0 & reg1 & reg2 & reg3 & reg4
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
pop_one(reg2);
|
|
pop_one(reg3);
|
|
pop_one(reg4);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=5 & reg0 & reg1 & reg2 & reg3 & reg4 & reg5
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
pop_one(reg2);
|
|
pop_one(reg3);
|
|
pop_one(reg4);
|
|
pop_one(reg5);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=6 & reg0 & reg1 & reg2 & reg3 & reg4 & reg5 & reg6
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
pop_one(reg2);
|
|
pop_one(reg3);
|
|
pop_one(reg4);
|
|
pop_one(reg5);
|
|
pop_one(reg6);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
:pop^pop_ret pop_args
|
|
is pop_ret & pop_args & op7=1 & b4_6=7 & reg0 & reg1 & reg2 & reg3 & reg4 & reg5 & reg6 & reg7
|
|
{
|
|
pop_one(reg0);
|
|
pop_one(reg1);
|
|
pop_one(reg2);
|
|
pop_one(reg3);
|
|
pop_one(reg4);
|
|
pop_one(reg5);
|
|
pop_one(reg6);
|
|
pop_one(reg7);
|
|
build pop_args;
|
|
build pop_ret;
|
|
}
|
|
|
|
# RETX - Return from Exception
|
|
:RETX is op=0x0003 {
|
|
PC = *(ISP:4) << 1; # PC equals bits 0 to 22 popped from stack shifted left 1
|
|
ISP = ISP + 4;
|
|
PSR = *(ISP:4); # PSR popped/restored from interrupt stack
|
|
ISP = ISP + 2;
|
|
return [PC];
|
|
}
|
|
|
|
|
|
# LOAD / STORE
|
|
# - for loads and stores, dsp(n) is always unsigned
|
|
|
|
# LOADB - Load low-order byte only
|
|
:LOADB prp const1(prp_src1), dst1 is hi=0xbe & prp & const1 & prp_src1 & dst1 { # fmt 18
|
|
tmp:4 = prp_src1:4 + prp:4;
|
|
dst1 = (dst1 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB prp2 disp14(prp_src), dst3 is op10=0x219 & prp2 & disp14 & prp_src & dst3 { # fmt 17
|
|
tmp:4 = prp_src:4 + prp2:4 + zext(disp14);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB disp20(src4), dst3 is op=0x0012 ; n8=4 & disp20 & src4 & dst3 { # fmt 2
|
|
tmp:4 = zext(src4) + zext(disp20);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB -disp20(src4), dst3 is op=0x0018 ; n8=4 & disp20 & src4 & dst3 {
|
|
tmp:4 = zext(src4) - zext(disp20);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB disp16b(rp_src2), dst1 is hi=0xbf & rp_src2 & dst1 ; disp16b { # fmt 19
|
|
tmp:4 = rp_src2:4 + zext(disp16b);
|
|
dst1 = (dst1 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB disp20(rp_src5), dst3 is op=0x0012 ; n8=5 & disp20 & rp_src5 & dst3 { # fmt 2
|
|
tmp:4 = rp_src5:4 + zext(disp20);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB -disp20(rp_src5), dst3 is op=0x0018 ; n8=5 & disp20 & rp_src5 & dst3 {
|
|
tmp:4 = rp_src5:4 - zext(disp20);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB disp4b(rp_src2), dst1 is op4=0xb & dst1 & disp4b & rp_src2 { # fmt 18
|
|
tmp:4 = rp_src2:4 + zext(disp4b);
|
|
dst1 = (dst1 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB disp20(prp_src), dst3 is op=0x0012 ; n8=6 & disp20 & prp_src & dst3 { # fmt 2
|
|
tmp:4 = prp_src:4 + zext(disp20);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB abs20, dst3 is dw_hi=0x88 & abs20 & dst3 { # fmt 12
|
|
tmp:4 = zext(abs20);
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB rs abs20, dst3 is dw_op7=0x45 & dst3 & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 tmp );
|
|
}
|
|
:LOADB abs24, dst3 is op=0x0012 ; n8=7 & dst3 & abs24 { # fmt 3
|
|
dst3 = (dst3 & 0xff00) + zext( *:1 abs24 );
|
|
}
|
|
|
|
# LOADD - load doubleword
|
|
:LOADD prp const1(prp_src1), rp_dst2 is hi=0xae & prp & const1 & prp_src1 & rp_dst2 { # fmt 18
|
|
tmp:4 = prp_src1:4 + prp:4;
|
|
rp_dst2 = *tmp;
|
|
}
|
|
:LOADD prp2 disp14(prp_src), rp_dst4 is op10=0x21a & prp2 & disp14 & prp_src & rp_dst4 { # fmt 17
|
|
tmp:4 = prp_src:4 + prp2:4 + zext(disp14);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD disp20(src4), rp_dst4 is op=0x0012 ; n8=8 & disp20 & src4 & rp_dst4 { # fmt 2
|
|
tmp:4 = zext(src4) + zext(disp20);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD -disp20(src4), rp_dst4 is op=0x0018 ; n8=8 & disp20 & src4 & rp_dst4 {
|
|
tmp:4 = zext(src4) - zext(disp20);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD disp16b(rp_src2), rp_dst2 is hi=0xaf & rp_dst2 & rp_src2 ; disp16b { # fmt 19
|
|
tmp:4 = rp_src2:4 + zext(disp16b);
|
|
rp_dst2 = *tmp;
|
|
}
|
|
:LOADD disp20(rp_src5), rp_dst4 is op=0x0012 ; n8=9 & disp20 & rp_src5 & rp_dst4 { # fmt 2
|
|
tmp:4 = rp_src5:4 + zext(disp20);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD -disp20(rp_src5), rp_dst4 is op=0x0018 ; n8=9 & disp20 & rp_src5 & rp_dst4 {
|
|
tmp:4 = rp_src5:4 - zext(disp20);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD disp4(rp_src2), rp_dst2 is op4=0xa & disp4 & rp_src2 & rp_dst2 {
|
|
tmp:4 = rp_src2:4 + zext(disp4);
|
|
rp_dst2 = *tmp;
|
|
}
|
|
:LOADD disp20(prp_src), rp_dst4 is op=0x0012 ; n8=10 & disp20 & prp_src & rp_dst4 { # fmt 2
|
|
tmp:4 = prp_src:4 + zext(disp20);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD abs20, rp_dst4 is dw_hi=0x87 & abs20 & rp_dst4 {
|
|
tmp:4 = zext(abs20);
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD rs abs20, rp_dst4 is dw_op7=0x46 & rs & abs20 & rp_dst4 {
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
rp_dst4 = *tmp;
|
|
}
|
|
:LOADD abs24, rp_dst4 is op=0x0012 ; n8=11 & rp_dst4 & abs24 { # fmt 3
|
|
rp_dst4 = *abs24;
|
|
}
|
|
|
|
macro load_one_1(rd) {
|
|
addr:4 = zext(R0);
|
|
rd = *addr;
|
|
R0 = R0 + 2;
|
|
}
|
|
|
|
macro load_one_2(rd) {
|
|
addr:4 = R1R0:4;
|
|
rd = *addr;
|
|
R1R0 = R1R0 + 2;
|
|
}
|
|
|
|
# LOADM/LOADMP - Load Multiple Registers from Memory
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=0 & cnt3b { load_one_1(R2); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=1 & cnt3b { load_one_1(R2); load_one_1(R3); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=2 & cnt3b { load_one_1(R2); load_one_1(R3); load_one_1(R4); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=3 & cnt3b { load_one_1(R2); load_one_1(R3); load_one_1(R4); load_one_1(R5); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=4 & cnt3b { load_one_1(R2); load_one_1(R3); load_one_1(R4); load_one_1(R5); load_one_1(R8); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=5 & cnt3b { load_one_1(R2); load_one_1(R3); load_one_1(R4); load_one_1(R5); load_one_1(R8); load_one_1(R9); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=6 & cnt3b { load_one_1(R2); load_one_1(R3); load_one_1(R4); load_one_1(R5); load_one_1(R8); load_one_1(R9); load_one_1(R10); }
|
|
:LOADM cnt3b is op13=0x0014 & b0_2=7 & cnt3b { load_one_1(R2); load_one_1(R3); load_one_1(R4); load_one_1(R5); load_one_1(R8); load_one_1(R9); load_one_1(R10); load_one_1(R11); }
|
|
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=0 & cnt3b { load_one_2(R2); load_one_2(R3); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=1 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=2 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=3 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); load_one_2(R5); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=4 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); load_one_2(R5); load_one_2(R8); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=5 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); load_one_2(R5); load_one_2(R8); load_one_2(R9); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=6 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); load_one_2(R5); load_one_2(R8); load_one_2(R9); load_one_2(R10); }
|
|
:LOADMP cnt3b is op13=0x0015 & b0_2=7 & cnt3b { load_one_2(R2); load_one_2(R3); load_one_2(R4); load_one_2(R5); load_one_2(R8); load_one_2(R9); load_one_2(R10); load_one_2(R11); }
|
|
|
|
# LOADW - load word
|
|
:LOADW prp const1(prp_src1), dst1 is hi=0x9e & prp & const1 & prp_src1 & dst1 { # fmt 18
|
|
tmp:4 = prp_src1:4 + prp:4;
|
|
dst1 = *tmp;
|
|
}
|
|
:LOADW prp2 disp14(prp_src), dst3 is op10=0x21b & prp2 & disp14 & prp_src & dst3 { # fmt 17
|
|
tmp:4 = prp_src:4 + prp2:4 + zext(disp14);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW disp20(src4), dst3 is op=0x0012 ; n8=12 & disp20 & src4 & dst3 { # fmt 2
|
|
tmp:4 = zext(src4) + zext(disp20);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW -disp20(src4), dst3 is op=0x0018 ; n8=12 & disp20 & src4 & dst3 {
|
|
tmp:4 = zext(src4) - zext(disp20);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW disp16b(rp_src2), dst1 is hi=0x9f & rp_src2 & dst1 ; disp16b { # fmt 19
|
|
tmp:4 = rp_src2:4 + zext(disp16b);
|
|
dst1 = *tmp;
|
|
}
|
|
:LOADW disp20(rp_src5), dst3 is op=0x0012 ; n8=13 & disp20 & rp_src5 & dst3 { # fmt 2
|
|
tmp:4 = rp_src5:4 + zext(disp20);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW -disp20(rp_src5), dst3 is op=0x0018 ; n8=13 & disp20 & rp_src5 & dst3 {
|
|
tmp:4 = rp_src5:4 - zext(disp20);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW disp4(rp_src2), dst1 is op4=0x9 & disp4 & rp_src2 & dst1 { # fmt 18
|
|
tmp:4 = rp_src2:4 + zext(disp4);
|
|
dst1 = *tmp;
|
|
}
|
|
:LOADW disp20(prp_src), dst3 is op=0x0012 ; n8=14 & disp20 & prp_src & dst3 { # fmt 2
|
|
tmp:4 = prp_src:4 + zext(disp20);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW abs20, dst3 is dw_hi=0x89 & abs20 & dst3 {
|
|
tmp:4 = zext(abs20);
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW rs abs20, dst3 is dw_op7=0x47 & dst3 & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
dst3 = *tmp;
|
|
}
|
|
:LOADW abs24, dst3 is op=0x0012 ; n8=15 & dst3 & abs24 { # fmt 3
|
|
dst3 = *abs24;
|
|
}
|
|
|
|
# STORB - store low-order byte only
|
|
:STORB src, prp const1(prp_dst1) is hi=0xfe & src & prp & const1 & prp_dst1 { # fmt 18
|
|
tmp:4 = prp_dst1:4 + prp:4;
|
|
*tmp = src:1;
|
|
}
|
|
:STORB src3, prp2 disp14(prp_dst) is op10=0x319 & src3 & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src3, disp20(dst4) is op=0x0013 ; n8=4 & src3 & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src3, -disp20(dst4) is op=0x0019 ; n8=4 & src3 & disp20 & dst4 {
|
|
tmp:4 = zext(dst4) - zext(disp20);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src, disp16b(rp_dst) is hi=0xff & src & rp_dst ; disp16b { # fmt 19
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
*tmp = src:1;
|
|
}
|
|
:STORB src3, disp20(rp_dst5) is op=0x0013 ; n8=5 & src3 & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src3, -disp20(rp_dst5) is op=0x0019 ; n8=5 & src3 & disp20 & rp_dst5 {
|
|
tmp:4 = rp_dst5:4 - zext(disp20);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src, disp4b(rp_dst) is op4=0xf & src & disp4b & rp_dst { # fmt 18 <---
|
|
tmp:4 = rp_dst:4 + zext(disp4b);
|
|
*tmp = src:1;
|
|
}
|
|
:STORB src3, disp20(prp_dst) is op=0x0013 ; n8=6 & src3 & disp20 & prp_dst { # fmt 2
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src3, abs20 is dw_hi=0xc8 & abs20 & src3 {
|
|
tmp:4 = zext(abs20);
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src3, rs abs20 is dw_op7=0x65 & src3 & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
*tmp = src3:1;
|
|
}
|
|
:STORB src3, abs24 is op=0x0013 ; n8=7 & src3 & abs24 { # fmt 3
|
|
*abs24 = src3:1;
|
|
}
|
|
|
|
:STORB imm4c, prp2 disp14(prp_dst) is op10=0x218 & imm4c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
*tmp = imm4c;
|
|
}
|
|
:STORB imm4c, disp20(dst4) is op=0x0012 ; n8=0 & imm4c & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
*tmp = imm4c;
|
|
}
|
|
:STORB imm4a, const1(rp_dst) is hi=0x82 & imm4a & const1 & rp_dst { # fmt 15
|
|
*rp_dst:4 = imm4a;
|
|
}
|
|
:STORB imm4a, disp16b(rp_dst) is hi=0x83 & imm4a & rp_dst ; disp16b { # fmt 16
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
*tmp = imm4a;
|
|
}
|
|
:STORB imm4c, disp20(rp_dst5) is op=0x0012 ; n8=1 & imm4c & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
*tmp = imm4c;
|
|
}
|
|
:STORB imm4c, disp20(prp_dst) is op=0x0012 ; n8=2 & imm4c & disp20 & prp_dst {
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
*tmp = imm4c;
|
|
}
|
|
:STORB imm4b, abs20 is dw_hi=0x81 & imm4b & abs20 { # fmt 12
|
|
tmp:4 = zext(abs20);
|
|
*tmp = imm4b;
|
|
}
|
|
:STORB imm4b, rs abs20 is dw_op7=0x42 & imm4b & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
*tmp = imm4b;
|
|
}
|
|
:STORB imm4b, abs24 is op=0x0012 ; n8=3 & imm4b & abs24 { # fmt 3
|
|
*abs24 = imm4b;
|
|
}
|
|
|
|
# STORD - store doubleword
|
|
:STORD rp_src, prp const1(prp_dst1) is hi=0xee & rp_src & prp & const1 & prp_dst1 { # fmt 18
|
|
tmp:4 = prp_dst1:4 + prp:4;
|
|
*tmp = rp_src;
|
|
}
|
|
:STORD rp_src4, prp2 disp14(prp_dst) is op10=0x31a & rp_src4 & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src4, disp20(dst4) is op=0x0013 ; n8=8 & rp_src4 & dst4 & disp20 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src4, -disp20(dst4) is op=0x0019 ; n8=8 & rp_src4 & dst4 & disp20 {
|
|
tmp:4 = zext(dst4) - zext(disp20);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src, disp16b(rp_dst) is hi=0xef & rp_src & rp_dst ; disp16b { # fmt 19
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
*tmp = rp_src;
|
|
}
|
|
:STORD rp_src4, disp20(rp_dst5) is op=0x0013 ; n8=9 & rp_src4 & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src4, -disp20(rp_dst5) is op=0x0019 ; n8=9 & rp_src4 & disp20 & rp_dst5 {
|
|
tmp:4 = rp_dst5:4 - zext(disp20);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src, disp4(rp_dst) is op4=0xe & disp4 & rp_src & rp_dst { # fmt 18
|
|
tmp:4 = rp_dst:4 + zext(disp4);
|
|
*tmp = rp_src;
|
|
}
|
|
:STORD rp_src4, disp20(prp_dst) is op=0x0013 ; n8=10 & rp_src4 & disp20 & prp_dst { # fmt 2
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src4, abs20 is dw_hi=0xc7 & abs20 & rp_src4 {
|
|
tmp:4 = zext(abs20);
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src4, rs abs20 is dw_op7=0x66 & rp_src4 & rs & abs20 {
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
*tmp = rp_src4;
|
|
}
|
|
:STORD rp_src4, abs24 is op=0x0013 ; n8=11 & rp_src4 & abs24 { # fmt 3
|
|
*abs24 = rp_src4;
|
|
}
|
|
|
|
macro store_one_1(rd) {
|
|
addr:4 = zext(R1);
|
|
*addr = rd;
|
|
R1 = R1 + 2;
|
|
}
|
|
|
|
macro store_one_2(rd) {
|
|
addr:4 = R7R6:4;
|
|
*addr = rd;
|
|
R7R6 = R7R6 + 2;
|
|
}
|
|
|
|
# STORM/STORMP - Store Multiple Registers to Memory
|
|
:STORM cnt3b is op13=0x0016 & b0_2=0 & cnt3b { store_one_1(R2); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=1 & cnt3b { store_one_1(R2); store_one_1(R3); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=2 & cnt3b { store_one_1(R2); store_one_1(R3); store_one_1(R4); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=3 & cnt3b { store_one_1(R2); store_one_1(R3); store_one_1(R4); store_one_1(R5); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=4 & cnt3b { store_one_1(R2); store_one_1(R3); store_one_1(R4); store_one_1(R5); store_one_1(R8); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=5 & cnt3b { store_one_1(R2); store_one_1(R3); store_one_1(R4); store_one_1(R5); store_one_1(R8); store_one_1(R9); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=6 & cnt3b { store_one_1(R2); store_one_1(R3); store_one_1(R4); store_one_1(R5); store_one_1(R8); store_one_1(R9); store_one_1(R10); }
|
|
:STORM cnt3b is op13=0x0016 & b0_2=7 & cnt3b { store_one_1(R2); store_one_1(R3); store_one_1(R4); store_one_1(R5); store_one_1(R8); store_one_1(R9); store_one_1(R10); store_one_1(R11); }
|
|
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=0 & cnt3b { store_one_2(R2); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=1 & cnt3b { store_one_2(R2); store_one_2(R3); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=2 & cnt3b { store_one_2(R2); store_one_2(R3); store_one_2(R4); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=3 & cnt3b { store_one_2(R2); store_one_2(R3); store_one_2(R4); store_one_2(R5); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=4 & cnt3b { store_one_2(R2); store_one_2(R3); store_one_2(R4); store_one_2(R5); store_one_2(R8); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=5 & cnt3b { store_one_2(R2); store_one_2(R3); store_one_2(R4); store_one_2(R5); store_one_2(R8); store_one_2(R9); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=6 & cnt3b { store_one_2(R2); store_one_2(R3); store_one_2(R4); store_one_2(R5); store_one_2(R8); store_one_2(R9); store_one_2(R10); }
|
|
:STORMP cnt3b is op13=0x0017 & b0_2=7 & cnt3b { store_one_2(R2); store_one_2(R3); store_one_2(R4); store_one_2(R5); store_one_2(R8); store_one_2(R9); store_one_2(R10); store_one_2(R11); }
|
|
|
|
# STORW - store word
|
|
:STORW src, prp const1(prp_dst1) is hi=0xde & src & prp & const1 & prp_dst1 { # fmt 18
|
|
tmp:4 = prp_dst1:4 + prp:4;
|
|
*tmp = src;
|
|
}
|
|
:STORW src3, prp2 disp14(prp_dst) is op10=0x31b & prp2 & disp14 & src3 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src3, disp20(dst4) is op=0x0013 ; n8=12 & src3 & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src3, -disp20(dst4) is op=0x0019 ; n8=12 & src3 & disp20 & dst4 {
|
|
tmp:4 = zext(dst4) - zext(disp20);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src, disp16b(rp_dst) is hi=0xdf & src & rp_dst ; disp16b {
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
*tmp = src;
|
|
}
|
|
:STORW src3, disp20(rp_dst5) is op=0x0013 ; n8=13 & src3 & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src3, -disp20(rp_dst5) is op=0x0019 ; n8=13 & src3 & disp20 & rp_dst5 {
|
|
tmp:4 = rp_dst5:4 - zext(disp20);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src, disp4(rp_dst) is op4=0xd & disp4 & src & rp_dst { # fmt 18
|
|
tmp:4 = rp_dst:4 + zext(disp4);
|
|
*tmp = src;
|
|
}
|
|
:STORW src3, disp20(prp_dst) is op=0x0013 ; n8=14 & src3 & disp20 & prp_dst { # fmt 2
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src3, abs20 is dw_hi=0xc9 & abs20 & src3 {
|
|
tmp:4 = zext(abs20);
|
|
*tmp = src3;
|
|
}
|
|
:STORW src3, rs abs20 is dw_op7=0x67 & src3 & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
*tmp = src3;
|
|
}
|
|
:STORW src3, abs24 is op=0x0013 ; n8=15 & src3 & abs24 { # fmt 3
|
|
*abs24 = src3;
|
|
}
|
|
|
|
:STORW imm4c, prp2 disp14(prp_dst) is op10=0x318 & imm4c & prp2 & disp14 & prp_dst { # fmt 17
|
|
tmp:4 = prp_dst:4 + prp2:4 + zext(disp14);
|
|
*:2 tmp = sext(imm4c);
|
|
}
|
|
:STORW imm4c, disp20(dst4) is op=0x0013 ; n8=0 & imm4c & disp20 & dst4 { # fmt 2
|
|
tmp:4 = zext(dst4) + zext(disp20);
|
|
*:2 tmp = sext(imm4c);
|
|
}
|
|
:STORW imm4a, const1(rp_dst) is hi=0xc2 & imm4a & const1 & rp_dst { # fmt 15
|
|
*:2 rp_dst:4 = sext(imm4a);
|
|
}
|
|
:STORW imm4a, disp16b(rp_dst) is hi=0xc3 & imm4a & rp_dst ; disp16b { # fmt 16
|
|
tmp:4 = rp_dst:4 + zext(disp16b);
|
|
*:2 tmp = sext(imm4a);
|
|
}
|
|
:STORW imm4c, disp20(rp_dst5) is op=0x0013 ; n8=1 & imm4c & disp20 & rp_dst5 { # fmt 2
|
|
tmp:4 = rp_dst5:4 + zext(disp20);
|
|
*:2 tmp = sext(imm4c);
|
|
}
|
|
:STORW imm4c, disp20(prp_dst) is op=0x0013 ; n8=2 & imm4c & disp20 & prp_dst {
|
|
tmp:4 = prp_dst:4 + zext(disp20);
|
|
*:2 tmp = sext(imm4c);
|
|
}
|
|
:STORW imm4b, abs20 is dw_hi=0xc1 & imm4b & abs20 {
|
|
tmp:4 = zext(abs20);
|
|
*:2 tmp = sext(imm4b);
|
|
}
|
|
:STORW imm4b, rs abs20 is dw_op7=0x62 & imm4b & rs & abs20 { # fmt 13
|
|
tmp:4 = zext(abs20) + rs:4;
|
|
*:2 tmp = sext(imm4b);
|
|
}
|
|
:STORW imm4b, abs24 is op=0x0013 ; n8=3 & imm4b & abs24 { # fmt 3
|
|
*:2 abs24 = sext(imm4b);
|
|
}
|
|
|
|
|
|
# MISC
|
|
|
|
# CINV - Cache Invalidate
|
|
:CINV cinv1 is op=0x000a & cinv1 {
|
|
}
|
|
:CINV cinv2 is op=0x000b & cinv2 {
|
|
}
|
|
:CINV cinv3 is op=0x000c & cinv3 {
|
|
}
|
|
:CINV cinv4 is op=0x000d & cinv4 {
|
|
}
|
|
:CINV cinv5 is op=0x000e & cinv5 {
|
|
}
|
|
:CINV cinv6 is op=0x000f & cinv6 {
|
|
}
|
|
|
|
# Disable Maskable Interrupts
|
|
:DI is op=0x0004 {
|
|
$(E) = 0;
|
|
}
|
|
# Enable Maskable Interrupts
|
|
:EI is op=0x0005 {
|
|
$(E) = 1;
|
|
}
|
|
# Wait for Interrupt
|
|
:WAIT is op=0x0006 {
|
|
suspend();
|
|
}
|
|
# Enable Interrupt and Wait for Interrupt
|
|
:EIWAIT is op=0x0007 {
|
|
$(E) = 1;
|
|
suspend();
|
|
}
|
|
|
|
|
|
# Reserved
|
|
|
|
:undef is op=0x0000 {
|
|
}
|
|
:undef is op=0x0001 {
|
|
}
|
|
|
|
:undef is op=0x0002 {
|
|
}
|
|
|
|
:undef is op=0x0008 {
|
|
}
|
|
:undef is op=0x0009 {
|
|
}
|
|
|
|
:undef is op=0x0010 ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x0011 ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x0014 ; w2 {
|
|
}
|
|
:undef is op=0x0015 ; w2 {
|
|
}
|
|
:undef is op=0x0016 ; w2 {
|
|
}
|
|
:undef is op=0x0017 ; w2 {
|
|
}
|
|
|
|
:undef is op=0x0018 ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x0019 ; w2 ; w3 {
|
|
}
|
|
|
|
:undef is op=0x001a ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x001b ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x001c ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x001d ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x001e ; w2 ; w3 {
|
|
}
|
|
:undef is op=0x001f ; w2 ; w3 {
|
|
}
|
|
|
|
:undef is op12=0x008 ; w2 ; w3 {
|
|
}
|
|
|
|
:undef is op11=0x007 {
|
|
}
|
|
|
|
:undef is op9=0x012 ; w2 {
|
|
}
|
|
|
|
:undef is hi=0x80 {
|
|
}
|
|
|
|
#:undef is hi=0xc0 {
|
|
#}
|
|
|
|
:undef is op=0xffff {
|
|
}
|
|
|