Merge branch 'GP-7267_ghidra1_PR-9163_shuffle2_HexagonFixes' into patch

(Closes #9163)
This commit is contained in:
ghidra1
2026-09-10 19:05:20 -04:00
7 changed files with 1451 additions and 177 deletions

View File

@@ -1,4 +1,4 @@
# Qualcomm Hexagon (V73) General Instruction Set
# Qualcomm Hexagon (V60-V81) General Instruction Set
#
# Custom pcode-op
@@ -2907,7 +2907,7 @@ VcmpbEq: "vcmpb.eq("^rss5,rtt5^")" is rss5 & rtt5 { tmp:1 = vcmpb.eq(rss5,rtt5)
# 1 0 0 0 1 1 0 0 0 0 0 s s s s s P P 0 i i i i i 0 1 1 d d d d d
:rol Rd5,rs5,Uimm8_0812 EndPacket is iclass=8 & op2127=0x60 & op13=0 & op0507=3 & Rd5 & rs5 & Uimm8_0812 & $(END_PACKET) {
Rd5 = (rs5 << Uimm8_0812) | zext((rs5 s< 0) * 1);
Rd5 = (rs5 << Uimm8_0812) | (rs5 >> (32 - Uimm8_0812));
build EndPacket;
}
@@ -2939,8 +2939,9 @@ define pcodeop aslSat;
# 1 1 0 0 0 1 1 0 0 1 - s s s s s P P - t t t t t 1 0 - d d d d d
:asl Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x19 & op0607=2 & Rd5 & rs5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
Rd5 = (zext(right) * (rs5 s>> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
Rd5 = (zext(right) * (rs5 s>> -shamt)) + (zext(!right) * (rs5 << shamt));
build EndPacket;
}
@@ -2970,7 +2971,7 @@ define pcodeop aslSat;
# 1 0 0 0 0 0 0 0 0 0 0 s s s s s P P i i i i i i 0 1 1 d d d d d
:rol Rdd5,rss5,Uimm8_0813 EndPacket is iclass=8 & op2227=0x0 & op21=0 & op0507=3 & Rdd5 & rss5 & Uimm8_0813 & $(END_PACKET) {
Rdd5 = (rss5 << Uimm8_0813) | zext((rss5 s< 0) * 1);
Rdd5 = (rss5 << Uimm8_0813) | (rss5 >> (64 - Uimm8_0813));
build EndPacket;
}
@@ -2980,8 +2981,9 @@ define pcodeop aslSat;
# 1 1 0 0 0 0 1 1 1 0 - s s s s s P P - t t t t t 1 0 - d d d d d
:asl Rdd5,rss5,rt5 EndPacket is iclass=12 & op2227=0xe & op0607=2 & Rdd5 & rss5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
Rdd5 = (zext(right) * (rss5 s>> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
Rdd5 = (zext(right) * (rss5 s>> -shamt)) + (zext(!right) * (rss5 << shamt));
build EndPacket;
}
@@ -3001,7 +3003,7 @@ define pcodeop aslSat;
# 1 0 0 0 1 1 1 0 0 1 - s s s s s P P 0 i i i i i 0 1 1 x x x x x
:rol&= Rd5,rs5,Uimm8_0812 EndPacket is iclass=8 & op2227=0x39 & op13=0 & op0507=3 & Rd5 & rd5 & rs5 & Uimm8_0812 & $(END_PACKET) {
Rd5 = rd5 & ((rs5 << Uimm8_0812) | zext((rs5 s<0) * 1));
Rd5 = rd5 & ((rs5 << Uimm8_0812) | (rs5 >> (32 - Uimm8_0812)));
build EndPacket;
}
@@ -3011,8 +3013,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 1 0 0 0 1 - s s s s s P P - t t t t t 1 0 - x x x x x
:asl&= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x31 & op0607=2 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 s>> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 s>> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 & result;
build EndPacket;
}
@@ -3033,7 +3036,7 @@ define pcodeop aslSat;
# 1 0 0 0 1 1 1 0 0 0 - s s s s s P P 0 i i i i i 1 1 1 x x x x x
:rol+= Rd5,rs5,Uimm8_0812 EndPacket is iclass=8 & op2227=0x38 & op13=0 & op0507=7 & Rd5 & rd5 & rs5 & Uimm8_0812 & $(END_PACKET) {
Rd5 = rd5 + ((rs5 << Uimm8_0812) | zext((rs5 s< 0) * 1));
Rd5 = rd5 + ((rs5 << Uimm8_0812) | (rs5 >> (32 - Uimm8_0812)));
build EndPacket;
}
@@ -3043,8 +3046,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 1 0 0 1 1 - s s s s s P P - t t t t t 1 0 - x x x x x
:asl+= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x33 & op0607=2 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 s>> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 s>> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 + result;
build EndPacket;
}
@@ -3065,7 +3069,7 @@ define pcodeop aslSat;
# 1 0 0 0 1 1 1 0 0 0 - s s s s s P P 0 i i i i i 0 1 1 x x x x x
:rol-= Rd5,rs5,Uimm8_0812 EndPacket is iclass=8 & op2227=0x38 & op13=0 & op0507=3 & Rd5 & rd5 & rs5 & Uimm8_0812 & $(END_PACKET) {
Rd5 = rd5 - ((rs5 << Uimm8_0812) | zext((rs5 s< 0) * 1));
Rd5 = rd5 - ((rs5 << Uimm8_0812) | (rs5 >> (32 - Uimm8_0812)));
build EndPacket;
}
@@ -3075,8 +3079,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 1 0 0 1 0 - s s s s s P P - t t t t t 1 0 - x x x x x
:asl-= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x32 & op0607=2 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 s>> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 s>> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 - result;
build EndPacket;
}
@@ -3097,7 +3102,7 @@ define pcodeop aslSat;
# 1 0 0 0 1 1 1 0 1 0 - s s s s s P P 0 i i i i i 0 1 1 x x x x x
:rol"^=" Rd5,rs5,Uimm8_0812 EndPacket is iclass=8 & op2227=0x3a & op13=0 & op0507=3 & Rd5 & rd5 & rs5 & Uimm8_0812 & $(END_PACKET) {
Rd5 = rd5 ^ ((rs5 << Uimm8_0812) | zext((rs5 s< 0) * 1));
Rd5 = rd5 ^ ((rs5 << Uimm8_0812) | (rs5 >> (32 - Uimm8_0812)));
build EndPacket;
}
@@ -3117,7 +3122,7 @@ define pcodeop aslSat;
# 1 0 0 0 1 1 1 0 0 1 - s s s s s P P 0 i i i i i 1 1 1 x x x x x
:rol|= Rd5,rs5,Uimm8_0812 EndPacket is iclass=8 & op2227=0x39 & op13=0 & op0507=7 & Rd5 & rd5 & rs5 & Uimm8_0812 & $(END_PACKET) {
Rd5 = rd5 | ((rs5 << Uimm8_0812) | zext((rs5 s< 0) * 1));
Rd5 = rd5 | ((rs5 << Uimm8_0812) | (rs5 >> (32 - Uimm8_0812)));
build EndPacket;
}
@@ -3127,8 +3132,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 1 0 0 0 0 - s s s s s P P - t t t t t 1 0 - x x x x x
:asl|= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x30 & op0607=2 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 s>> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 s>> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 | result;
build EndPacket;
}
@@ -3149,7 +3155,7 @@ define pcodeop aslSat;
# 1 0 0 0 0 0 1 0 0 1 - s s s s s P P i i i i i i 0 1 1 x x x x x
:rol&= Rdd5,rss5,Uimm8_0813 EndPacket is iclass=8 & op2227=0x9 & op0507=3 & Rdd5 & rdd5 & rss5 & Uimm8_0813 & $(END_PACKET) {
Rdd5 = rdd5 & ((rss5 << Uimm8_0813) | zext((rss5 s< 0) * 1));
Rdd5 = rdd5 & ((rss5 << Uimm8_0813) | (rss5 >> (64 - Uimm8_0813)));
build EndPacket;
}
@@ -3159,8 +3165,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 0 1 1 0 1 0 s s s s s P P - t t t t t 1 0 - x x x x x
:asl&= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5a & op0607=2 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 s>> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 s>> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 & result;
build EndPacket;
}
@@ -3181,7 +3188,7 @@ define pcodeop aslSat;
# 1 0 0 0 0 0 1 0 0 0 - s s s s s P P i i i i i i 1 1 1 x x x x x
:rol+= Rdd5,rss5,Uimm8_0813 EndPacket is iclass=8 & op2227=0x8 & op0507=7 & Rdd5 & rdd5 & rss5 & Uimm8_0813 & $(END_PACKET) {
Rdd5 = rdd5 + ((rss5 << Uimm8_0813) | zext((rss5 s< 0) * 1));
Rdd5 = rdd5 + ((rss5 << Uimm8_0813) | (rss5 >> (64 - Uimm8_0813)));
build EndPacket;
}
@@ -3191,8 +3198,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 0 1 1 1 1 0 s s s s s P P - t t t t t 1 0 - x x x x x
:asl+= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5e & op0607=2 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 s>> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 s>> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 + result;
build EndPacket;
}
@@ -3213,7 +3221,7 @@ define pcodeop aslSat;
# 1 0 0 0 0 0 1 0 0 0 - s s s s s P P i i i i i i 0 1 1 x x x x x
:rol-= Rdd5,rss5,Uimm8_0813 EndPacket is iclass=8 & op2227=0x8 & op0507=3 & Rdd5 & rdd5 & rss5 & Uimm8_0813 & $(END_PACKET) {
Rdd5 = rdd5 - ((rss5 << Uimm8_0813) | zext((rss5 s< 0) * 1));
Rdd5 = rdd5 - ((rss5 << Uimm8_0813) | (rss5 >> (64 - Uimm8_0813)));
build EndPacket;
}
@@ -3223,8 +3231,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 0 1 1 1 0 0 s s s s s P P - t t t t t 1 0 - x x x x x
:asl-= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5c & op0607=2 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 s>> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 s>> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 - result;
build EndPacket;
}
@@ -3245,7 +3254,7 @@ define pcodeop aslSat;
# 1 0 0 0 0 0 1 0 1 0 - s s s s s P P i i i i i i 0 1 1 x x x x x
:rol"^=" Rdd5,rss5,Uimm8_0813 EndPacket is iclass=8 & op2227=0xa & op0507=3 & Rdd5 & rdd5 & rss5 & Uimm8_0813 & $(END_PACKET) {
Rdd5 = rdd5 ^ ((rss5 << Uimm8_0813) | zext((rss5 s< 0) * 1));
Rdd5 = rdd5 ^ ((rss5 << Uimm8_0813) | (rss5 >> (64 - Uimm8_0813)));
build EndPacket;
}
@@ -3255,8 +3264,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 0 1 1 0 1 1 s s s s s P P - t t t t t 1 0 - x x x x x
:asl"^=" Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5b & op0607=2 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 s>> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 s>> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 ^ result;
build EndPacket;
}
@@ -3277,7 +3287,7 @@ define pcodeop aslSat;
# 1 0 0 0 0 0 1 0 0 1 - s s s s s P P i i i i i i 1 1 1 x x x x x
:rol|= Rdd5,rss5,Uimm8_0813 EndPacket is iclass=8 & op2227=0x9 & op0507=7 & Rdd5 & rdd5 & rss5 & Uimm8_0813 & $(END_PACKET) {
Rdd5 = rdd5 | ((rss5 << Uimm8_0813) | zext((rss5 s< 0) * 1));
Rdd5 = rdd5 | ((rss5 << Uimm8_0813) | (rss5 >> (64 - Uimm8_0813)));
build EndPacket;
}
@@ -3287,8 +3297,9 @@ define pcodeop aslSat;
# 1 1 0 0 1 0 1 1 0 0 0 s s s s s P P - t t t t t 1 0 - x x x x x
:asl|= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x58 & op0607=2 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 s>> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 s>> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 | result;
build EndPacket;
}
@@ -3374,8 +3385,9 @@ define pcodeop aslSat;
# 1 1 0 0 0 1 1 0 0 1 - s s s s s P P - t t t t t 0 0 - d d d d d
:asr Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x19 & op0607=0 & Rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
Rd5 = (zext(!left) * (rs5 s>> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
Rd5 = (zext(!left) * (rs5 s>> shamt)) + (zext(left) * (rs5 << -shamt));
build EndPacket;
}
@@ -3407,8 +3419,9 @@ define pcodeop asrSat;
# 1 1 0 0 0 0 1 1 1 0 - s s s s s P P - t t t t t 0 0 - d d d d d
:asr Rdd5,rss5,rt5 EndPacket is iclass=12 & op2227=0xe & op0607=0 & Rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
Rdd5 = (zext(!left) * (rss5 s>> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
Rdd5 = (zext(!left) * (rss5 s>> shamt)) + (zext(left) * (rss5 << -shamt));
build EndPacket;
}
@@ -3428,8 +3441,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 1 0 0 0 1 - s s s s s P P - t t t t t 0 0 - x x x x x
:asr&= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x31 & op0607=0 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 s>> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 s>> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 & result;
build EndPacket;
}
@@ -3450,8 +3464,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 1 0 0 1 1 - s s s s s P P - t t t t t 0 0 - x x x x x
:asr+= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x33 & op0607=0 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 s>> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 s>> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 + result;
build EndPacket;
}
@@ -3472,8 +3487,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 1 0 0 1 0 - s s s s s P P - t t t t t 0 0 - x x x x x
:asr-= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x32 & op0607=0 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 s>> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 s>> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 - result;
build EndPacket;
}
@@ -3494,8 +3510,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 1 0 0 0 0 - s s s s s P P - t t t t t 0 0 - x x x x x
:asr|= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x30 & op0607=0 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 s>> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 s>> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 | result;
build EndPacket;
}
@@ -3516,8 +3533,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 0 1 1 0 1 0 s s s s s P P - t t t t t 0 0 - x x x x x
:asr&= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5a & op0607=0 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 s>> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 s>> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 & result;
build EndPacket;
}
@@ -3538,8 +3556,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 0 1 1 1 1 0 s s s s s P P - t t t t t 0 0 - x x x x x
:asr+= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5e & op0607=0 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 s>> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 s>> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 + result;
build EndPacket;
}
@@ -3560,8 +3579,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 0 1 1 1 0 0 s s s s s P P - t t t t t 0 0 - x x x x x
:asr-= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5c & op0607=0 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 s>> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 s>> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 - result;
build EndPacket;
}
@@ -3572,8 +3592,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 0 1 1 0 1 1 s s s s s P P - t t t t t 0 0 - x x x x x
:asr"^=" Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5b & op0607=0 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 s>> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 s>> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 ^ result;
build EndPacket;
}
@@ -3594,8 +3615,9 @@ define pcodeop asrSat;
# 1 1 0 0 1 0 1 1 0 0 0 s s s s s P P - t t t t t 0 0 - x x x x x
:asr|= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x58 & op0607=0 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 s>> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 s>> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 | result;
build EndPacket;
}
@@ -4211,7 +4233,8 @@ define pcodeop clip;
# 1 1 0 0 0 1 1 0 1 0 - s s s s s P P - t t t t t 0 1 - d d d d d
:clrbit Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x1a & op0607=1 & Rd5 & rs5 & rt5 & $(END_PACKET) {
mask:4 = 1 << rt5;
shamt:4 = (rt5 << 25) s>> 25;
mask:4 = zext(shamt s>= 0) * (1 << shamt);
Rd5 = rs5 & ~mask;
build EndPacket;
}
@@ -4232,7 +4255,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 1 1 1 0 1 0 1 0 0 i s s s s s P P i i i i i i i i i 1 0 0 d d
:cmp.eq! Pd2,rs5,Simm32_21_0513x EndPacket is iclass=7 & op2227=0x14 & op0204=4 & rs5 & Simm32_21_0513x & Pd2 & $(END_PACKET) {
:"!cmp.eq" Pd2,rs5,Simm32_21_0513x EndPacket is iclass=7 & op2227=0x14 & op0204=4 & rs5 & Simm32_21_0513x & Pd2 & $(END_PACKET) {
bool:1 = (rs5 != Simm32_21_0513x);
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -4254,7 +4277,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 1 1 0 0 1 0 - 0 0 s s s s s P P - t t t t t - - - 1 0 0 d d
:cmp.eq! Pd2,rs5,rt5 EndPacket is iclass=15 & op2427=0x2 & op2122=0x0 & op0204=4 & rs5 & rt5 & Pd2 & $(END_PACKET) {
:"!cmp.eq" Pd2,rs5,rt5 EndPacket is iclass=15 & op2427=0x2 & op2122=0x0 & op0204=4 & rs5 & rt5 & Pd2 & $(END_PACKET) {
bool:1 = (rs5 != rt5);
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -4287,7 +4310,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 1 1 1 0 1 0 1 0 1 i s s s s s P P i i i i i i i i i 1 0 0 d d
:cmp.gt! Pd2,rs5,Simm32_21_0513x EndPacket is iclass=7 & op2227=0x15 & op0204=4 & rs5 & Simm32_21_0513x & Pd2 & $(END_PACKET) {
:"!cmp.gt" Pd2,rs5,Simm32_21_0513x EndPacket is iclass=7 & op2227=0x15 & op0204=4 & rs5 & Simm32_21_0513x & Pd2 & $(END_PACKET) {
bool:1 = (rs5 s<= Simm32_21_0513x);
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -4309,7 +4332,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 1 1 0 0 1 0 - 1 0 s s s s s P P - t t t t t - - - 1 0 0 d d
:cmp.gt! Pd2,rs5,rt5 EndPacket is iclass=15 & op2427=0x2 & op2122=0x2 & op0204=4 & rs5 & rt5 & Pd2 & $(END_PACKET) {
:"!cmp.gt" Pd2,rs5,rt5 EndPacket is iclass=15 & op2427=0x2 & op2122=0x2 & op0204=4 & rs5 & rt5 & Pd2 & $(END_PACKET) {
bool:1 = (rs5 s<= rt5);
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -4342,7 +4365,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 1 1 1 0 1 0 1 1 0 0 s s s s s P P i i i i i i i i i 1 0 0 d d
:cmp.gtu! Pd2,rs5,Uimm32_0513x EndPacket is iclass=7 & op2127=0x2c & op0204=4 & rs5 & Uimm32_0513x & Pd2 & $(END_PACKET) {
:"!cmp.gtu" Pd2,rs5,Uimm32_0513x EndPacket is iclass=7 & op2127=0x2c & op0204=4 & rs5 & Uimm32_0513x & Pd2 & $(END_PACKET) {
bool:1 = (rs5 <= Uimm32_0513x);
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -4364,7 +4387,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 1 1 0 0 1 0 - 1 1 s s s s s P P - t t t t t - - - 1 0 0 d d
:cmp.gtu! Pd2,rs5,rt5 EndPacket is iclass=15 & op2427=0x2 & op2122=0x3 & op0204=4 & rs5 & rt5 & Pd2 & $(END_PACKET) {
:"!cmp.gtu" Pd2,rs5,rt5 EndPacket is iclass=15 & op2427=0x2 & op2122=0x3 & op0204=4 & rs5 & rt5 & Pd2 & $(END_PACKET) {
bool:1 = (rs5 <= rt5);
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -4387,7 +4410,6 @@ define pcodeop clip;
# 0 1 1 1 0 0 1 1 - 1 0 s s s s s P P 1 i i i i i i i i d d d d d
:cmp.eq Rd5,rs5,Simm32_0512x EndPacket is iclass=7 & op2427=0x3 & op2122=0x2 & op13=1 & rs5 & Rd5 & Simm32_0512x & $(END_PACKET) {
# TODO: Verify output value - assuming 0/1 boolean
Rd5 = zext(rs5 == Simm32_0512x);
build EndPacket;
}
@@ -4397,8 +4419,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 1 1 1 0 0 1 1 - 1 1 s s s s s P P 1 i i i i i i i i d d d d d
:cmp.eq! Rd5,rs5,Simm32_0512x EndPacket is iclass=7 & op2427=0x3 & op2122=0x3 & op13=1 & rs5 & Rd5 & Simm32_0512x & $(END_PACKET) {
# TODO: Verify output value - assuming 0/1 boolean
:"!cmp.eq" Rd5,rs5,Simm32_0512x EndPacket is iclass=7 & op2427=0x3 & op2122=0x3 & op13=1 & rs5 & Rd5 & Simm32_0512x & $(END_PACKET) {
Rd5 = zext(rs5 != Simm32_0512x);
build EndPacket;
}
@@ -4418,7 +4439,7 @@ define pcodeop clip;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 1 1 0 0 1 1 0 1 1 s s s s s P P - t t t t t - - - d d d d d
:cmp.eq! Rd5,rs5,rt5 EndPacket is iclass=15 & op2127=0x1b & rs5 & rt5 & Rd5 & $(END_PACKET) {
:"!cmp.eq" Rd5,rs5,rt5 EndPacket is iclass=15 & op2127=0x1b & rs5 & rt5 & Rd5 & $(END_PACKET) {
Rd5 = zext(rs5 != rt5);
build EndPacket;
}
@@ -5843,7 +5864,7 @@ define pcodeop getimask;
# 0 1 0 1 0 0 1 0 1 0 1 s s s s s P P - - - - - - - - - - - - - -
:hintjr rs5 EndPacket is iclass=5 & op2127=0x15 & rs5 & $(END_PACKET) {
# TODO: appears in decomp compilation - not sure what it does
# branch hint - intentionally no-op
build EndPacket;
}
@@ -5950,7 +5971,7 @@ define pcodeop ictagr;
define pcodeop ictagw;
:ictagw rs5,rt5 EndPacket is iclass=5 & op2127=0x2e & op13=0 & op0007=0 & Rd5 & rs5 & rt5 & $(END_PACKET) {
:ictagw rs5,rt5 EndPacket is iclass=5 & op2127=0x2e & op13=0 & op0007=0 & rs5 & rt5 & $(END_PACKET) {
ictagw(rs5, rt5);
build EndPacket;
}
@@ -6922,7 +6943,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 0 1 1 0 1 0 - i i i i i P P - t t t t t 1 1 i d d d d d
:lsl Rd5,Simm8_1620_05,rt5 EndPacket is iclass=12 & op2227=0x1a & op0607=3 & Rd5 & rt5 & Simm8_1620_05 & $(END_PACKET) {
Rd5 = sext(Simm8_1620_05) << rt5;
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
Rd5 = (zext(right) * (sext(Simm8_1620_05) >> -shamt)) + (zext(!right) * (sext(Simm8_1620_05) << shamt));
build EndPacket;
}
@@ -6932,8 +6955,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 0 1 1 0 0 1 - s s s s s P P - t t t t t 1 1 - d d d d d
:lsl Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x19 & op0607=3 & Rd5 & rt5 & rs5 & $(END_PACKET) {
right:1 = rt5 s< 0;
Rd5 = (zext(right) * (rs5 >> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
Rd5 = (zext(right) * (rs5 >> -shamt)) + (zext(!right) * (rs5 << shamt));
build EndPacket;
}
@@ -6943,8 +6967,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 0 0 1 1 1 0 - s s s s s P P - t t t t t 1 1 - d d d d d
:lsl Rdd5,rss5,rt5 EndPacket is iclass=12 & op2227=0xe & op0607=3 & Rdd5 & rt5 & rss5 & $(END_PACKET) {
right:1 = rt5 s< 0;
Rdd5 = (zext(right) * (rss5 >> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
Rdd5 = (zext(right) * (rss5 >> -shamt)) + (zext(!right) * (rss5 << shamt));
build EndPacket;
}
@@ -6954,8 +6979,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 0 1 - s s s s s P P - t t t t t 1 1 - x x x x x
:lsl&= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x31 & op0607=3 & Rd5 & rd5 & rt5 & rs5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 >> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 >> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 & result;
build EndPacket;
}
@@ -6966,8 +6992,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 1 1 - s s s s s P P - t t t t t 1 1 - x x x x x
:lsl+= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x33 & op0607=3 & Rd5 & rd5 & rt5 & rs5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 >> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 >> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 + result;
build EndPacket;
}
@@ -6978,8 +7005,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 1 0 - s s s s s P P - t t t t t 1 1 - x x x x x
:lsl-= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x32 & op0607=3 & Rd5 & rd5 & rt5 & rs5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 >> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 >> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 - result;
build EndPacket;
}
@@ -6990,8 +7018,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 0 0 - s s s s s P P - t t t t t 1 1 - x x x x x
:lsl|= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x30 & op0607=3 & Rd5 & rd5 & rt5 & rs5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:4 = (zext(right) * (rs5 >> -rt5)) + (zext(!right) * (rs5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:4 = (zext(right) * (rs5 >> -shamt)) + (zext(!right) * (rs5 << shamt));
Rd5 = rd5 | result;
build EndPacket;
}
@@ -7002,7 +7031,10 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 0 1 0 s s s s s P P - t t t t t 1 1 - x x x x x
:lsl&= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5a & op0607=3 & Rdd5 & rdd5 & rt5 & rss5 & $(END_PACKET) {
Rdd5 = rdd5 & (rss5 << rt5);
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 >> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 & result;
build EndPacket;
}
@@ -7012,8 +7044,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 1 1 0 s s s s s P P - t t t t t 1 1 - x x x x x
:lsl+= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5e & op0607=3 & Rdd5 & rdd5 & rt5 & rss5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 >> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 >> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 + result;
build EndPacket;
}
@@ -7024,8 +7057,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 1 0 0 s s s s s P P - t t t t t 1 1 - x x x x x
:lsl-= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5c & op0607=3 & Rdd5 & rdd5 & rt5 & rss5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 >> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 >> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 - result;
build EndPacket;
}
@@ -7036,8 +7070,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 0 1 1 s s s s s P P - t t t t t 1 1 - x x x x x
:lsl"^=" Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5b & op0607=3 & Rdd5 & rdd5 & rt5 & rss5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 >> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 >> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 ^ result;
build EndPacket;
}
@@ -7048,8 +7083,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 0 0 0 s s s s s P P - t t t t t 1 1 - x x x x x
:lsl|= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x58 & op0607=3 & Rdd5 & rdd5 & rt5 & rss5 & $(END_PACKET) {
right:1 = rt5 s< 0;
result:8 = (zext(right) * (rss5 >> -rt5)) + (zext(!right) * (rss5 << rt5));
shamt:4 = (rt5 << 25) s>> 25;
right:1 = shamt s< 0;
result:8 = (zext(right) * (rss5 >> -shamt)) + (zext(!right) * (rss5 << shamt));
Rdd5 = rdd5 | result;
build EndPacket;
}
@@ -7070,8 +7106,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 0 1 1 0 0 1 - s s s s s P P - t t t t t 0 1 - d d d d d
:lsr Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x19 & op0607=1 & Rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
Rd5 = (zext(!left) * (rs5 >> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
Rd5 = (zext(!left) * (rs5 >> shamt)) + (zext(left) * (rs5 << -shamt));
build EndPacket;
}
@@ -7091,8 +7128,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 0 0 1 1 1 0 - s s s s s P P - t t t t t 0 1 - d d d d d
:lsr Rdd5,rss5,rt5 EndPacket is iclass=12 & op2227=0xe & op0607=1 & Rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
Rdd5 = (zext(!left) * (rss5 >> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
Rdd5 = (zext(!left) * (rss5 >> shamt)) + (zext(left) * (rss5 << -shamt));
build EndPacket;
}
@@ -7112,8 +7150,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 0 1 - s s s s s P P - t t t t t 0 1 - x x x x x
:lsr&= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x31 & op0607=1 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 >> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 >> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 & result;
build EndPacket;
}
@@ -7134,8 +7173,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 1 1 - s s s s s P P - t t t t t 0 1 - x x x x x
:lsr+= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x33 & op0607=1 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 >> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 >> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 + result;
build EndPacket;
}
@@ -7156,8 +7196,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 1 0 - s s s s s P P - t t t t t 0 1 - x x x x x
:lsr-= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x32 & op0607=1 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 >> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 >> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 - result;
build EndPacket;
}
@@ -7188,8 +7229,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 1 0 0 0 0 - s s s s s P P - t t t t t 0 1 - x x x x x
:lsr|= Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x30 & op0607=1 & Rd5 & rd5 & rs5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:4 = (zext(!left) * (rs5 >> rt5)) + (zext(left) * (rs5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:4 = (zext(!left) * (rs5 >> shamt)) + (zext(left) * (rs5 << -shamt));
Rd5 = rd5 | result;
build EndPacket;
}
@@ -7210,8 +7252,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 0 1 0 s s s s s P P - t t t t t 0 1 - x x x x x
:lsr&= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5a & op0607=1 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 >> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 >> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 & result;
build EndPacket;
}
@@ -7232,8 +7275,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 1 1 0 s s s s s P P - t t t t t 0 1 - x x x x x
:lsr+= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5e & op0607=1 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 >> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 >> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 + result;
build EndPacket;
}
@@ -7254,8 +7298,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 1 0 0 s s s s s P P - t t t t t 0 1 - x x x x x
:lsr-= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5c & op0607=1 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 >> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 >> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 - result;
build EndPacket;
}
@@ -7276,8 +7321,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 0 1 1 s s s s s P P - t t t t t 0 1 - x x x x x
:lsr"^=" Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x5b & op0607=1 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 >> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 >> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 ^ result;
build EndPacket;
}
@@ -7298,8 +7344,9 @@ LoopUimm10: "#"^val is i1620 & i0507 & i0001 [ val = (i1620 << 5) | (i0507 <<
# 1 1 0 0 1 0 1 1 0 0 0 s s s s s P P - t t t t t 0 1 - x x x x x
:lsr|= Rdd5,rss5,rt5 EndPacket is iclass=12 & op2127=0x58 & op0607=1 & Rdd5 & rdd5 & rss5 & rt5 & $(END_PACKET) {
left:1 = rt5 s< 0;
result:8 = (zext(!left) * (rss5 >> rt5)) + (zext(left) * (rss5 << -rt5));
shamt:4 = (rt5 << 25) s>> 25;
left:1 = shamt s< 0;
result:8 = (zext(!left) * (rss5 >> shamt)) + (zext(left) * (rss5 << -shamt));
Rdd5 = rdd5 | result;
build EndPacket;
}
@@ -11642,6 +11689,17 @@ define pcodeop memw_phys;
build EndPacket;
}
# (v68,9) memw_aq -- "Rd32 = memw_aq ( Rs32 )"
# _________________________________________________________________________________________________
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 0 0 1 0 0 1 0 0 0 0 s s s s s P P 0 0 1 0 0 0 0 0 0 d d d d d
define pcodeop memw_aq;
:memw_aq Rd5,rs5 EndPacket is iclass=9 & op2127=0x10 & op0513=0x40 & Rd5 & rs5 & $(END_PACKET) {
Rd5 = memw_aq(rs5);
}
# (v2,13) min -- "Rd32 = min ( Rt32 , Rs32 )"
# _________________________________________________________________________________________________
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
@@ -11649,7 +11707,7 @@ define pcodeop memw_phys;
define pcodeop min;
:min Rd5,rs5,rt5 EndPacket is iclass=13 & op2127=0x2d & op7=0 & rs5 & rt5 & Rd5 & $(END_PACKET) {
:min Rd5,rt5,rs5 EndPacket is iclass=13 & op2127=0x2d & op7=0 & rs5 & rt5 & Rd5 & $(END_PACKET) {
Rd5 = min(rt5,rs5);
build EndPacket;
}
@@ -11659,7 +11717,7 @@ define pcodeop min;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 0 1 0 0 1 1 1 0 1 s s s s s P P - t t t t t 1 1 0 d d d d d
:min Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=6 & rss5 & rtt5 & Rdd5 & $(END_PACKET) {
:min Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=6 & rss5 & rtt5 & Rdd5 & $(END_PACKET) {
Rdd5 = min(rtt5,rss5);
build EndPacket;
}
@@ -11671,7 +11729,7 @@ define pcodeop min;
define pcodeop minu;
:minu Rd5,rs5,rt5 EndPacket is iclass=13 & op2127=0x2d & op7=1 & rs5 & rt5 & Rd5 & $(END_PACKET) {
:minu Rd5,rt5,rs5 EndPacket is iclass=13 & op2127=0x2d & op7=1 & rs5 & rt5 & Rd5 & $(END_PACKET) {
Rd5 = minu(rt5,rs5);
build EndPacket;
}
@@ -11681,7 +11739,7 @@ define pcodeop minu;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 0 1 0 0 1 1 1 0 1 s s s s s P P - t t t t t 1 1 1 d d d d d
:minu Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=7 & rss5 & rtt5 & Rdd5 & $(END_PACKET) {
:minu Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=7 & rss5 & rtt5 & Rdd5 & $(END_PACKET) {
Rdd5 = minu(rtt5,rss5);
build EndPacket;
}
@@ -12639,7 +12697,7 @@ define pcodeop mpySatSub;
# 1 1 1 0 1 1 0 0 1 1 0 s s s s s P P - t t t t t 0 0 0 d d d d d
:mpyu^":<<1" Rd5,Rs5HL06,Rt5HL05 EndPacket is iclass=14 & op2127=0x66 & op7=0 & Rs5HL06 & Rt5HL05 & Rd5 & $(END_PACKET) {
Rd5 = zext(Rs5HL06) * zext(Rs5HL06);
Rd5 = zext(Rs5HL06) * zext(Rt5HL05);
Rd5 = Rd5 << 1;
build EndPacket;
}
@@ -12865,7 +12923,7 @@ define pcodeop mpySatSub;
# 1 1 1 0 0 1 1 0 1 1 0 s s s s s P P - t t t t t 0 0 0 x x x x x
:mpyu+=^":<<1" Rdd5,Rs5HL06,Rt5HL05 EndPacket is iclass=14 & op2127=0x36 & op7=0 & Rs5HL06 & Rt5HL05 & Rdd5 & rdd5 & $(END_PACKET) {
tmp:8 = zext(Rs5HL06) * zext(Rs5HL06);
tmp:8 = zext(Rs5HL06) * zext(Rt5HL05);
Rdd5 = rdd5 + (tmp << 1);
build EndPacket;
}
@@ -13622,7 +13680,8 @@ define pcodeop roundArithmeticPSat;
# 1 1 0 0 0 1 1 0 1 0 - s s s s s P P - t t t t t 0 0 - d d d d d
:setbit Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x1a & op0607=0 & Rd5 & rs5 & rt5 & $(END_PACKET) {
mask:4 = 1 << rt5;
shamt:4 = (rt5 << 25) s>> 25;
mask:4 = zext(shamt s>= 0) * (1 << shamt);
Rd5 = rs5 | mask;
build EndPacket;
}
@@ -13681,8 +13740,8 @@ define pcodeop shuffeh;
define pcodeop shuffob;
:shuffob Rdd5,rss5,rtt5 EndPacket is iclass=12 & op2227=0x4 & op0607=2 & Rdd5 & rss5 & rtt5 & $(END_PACKET) {
Rdd5 = shuffob(rss5,rtt5);
:shuffob Rdd5,rtt5,rss5 EndPacket is iclass=12 & op2227=0x4 & op0607=2 & Rdd5 & rss5 & rtt5 & $(END_PACKET) {
Rdd5 = shuffob(rtt5,rss5);
build EndPacket;
}
@@ -13693,8 +13752,8 @@ define pcodeop shuffob;
define pcodeop shuffoh;
:shuffoh Rdd5,rss5,rtt5 EndPacket is iclass=12 & op2227=0x6 & op0607=0 & op5=0 & Rdd5 & rss5 & rtt5 & $(END_PACKET) {
Rdd5 = shuffoh(rss5,rtt5);
:shuffoh Rdd5,rtt5,rss5 EndPacket is iclass=12 & op2227=0x6 & op0607=0 & op5=0 & Rdd5 & rss5 & rtt5 & $(END_PACKET) {
Rdd5 = shuffoh(rtt5,rss5);
build EndPacket;
}
@@ -14387,10 +14446,9 @@ define pcodeop tlbw;
# 1 1 0 0 0 1 1 0 1 0 - s s s s s P P - t t t t t 1 0 - d d d d d
:togglebit Rd5,rs5,rt5 EndPacket is iclass=12 & op2227=0x1a & op0607=2 & Rd5 & rs5 & rt5 & $(END_PACKET) {
if (rt5 > 31) goto <end>;
mask:4 = 1 << rt5;
shamt:4 = (rt5 << 25) s>> 25;
mask:4 = zext(shamt s>= 0) * (1 << shamt);
Rd5 = rs5 ^ mask;
<end>
build EndPacket;
}
@@ -14487,7 +14545,8 @@ define pcodeop getTrap1Vector;
# 1 1 0 0 0 1 1 1 0 0 0 s s s s s P P - t t t t t - - - - - - d d
:tstbit Pd2,rs5,rt5 EndPacket is iclass=12 & op2127=0x38 & rs5 & rt5 & Pd2 & $(END_PACKET) {
mask:4 = 1 << rt5;
shamt:4 = (rt5 << 25) s>> 25;
mask:4 = zext(shamt s>= 0) * (1 << shamt);
bool:1 = (rs5 & mask) != 0;
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -14499,7 +14558,8 @@ define pcodeop getTrap1Vector;
# 1 1 0 0 0 1 1 1 0 0 1 s s s s s P P - t t t t t - - - - - - d d
:"!tstbit" Pd2,rs5,rt5 EndPacket is iclass=12 & op2127=0x39 & rs5 & rt5 & Pd2 & $(END_PACKET) {
mask:4 = 1 << rt5;
shamt:4 = (rt5 << 25) s>> 25;
mask:4 = zext(shamt s>= 0) * (1 << shamt);
bool:1 = (rs5 & mask) == 0;
Pd2 = Pd2 & (bool * 0xff);
build EndPacket;
@@ -14749,10 +14809,10 @@ define pcodeop vaddubSat;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 0 1 0 0 1 1 0 0 0 s s s s s P P - t t t t t 1 0 1 d d d d d
:vaddw Rdd5,rtt5,rss5 EndPacket is iclass=0xd & op2127=0x18 & op0507=5 & rss5 & rtt5 & Rdd5 & $(END_PACKET)
:vaddw Rdd5,rss5,rtt5 EndPacket is iclass=0xd & op2127=0x18 & op0507=5 & rss5 & rtt5 & Rdd5 & $(END_PACKET)
{
Rdd5[0,32] = rtt5[0,32] + rss5[0,32];
Rdd5[32,32] = rtt5[32,32] + rss5[32,32];
Rdd5[0,32] = rss5[0,32] + rtt5[0,32];
Rdd5[32,32] = rss5[32,32] + rtt5[32,32];
build EndPacket;
}
@@ -14761,12 +14821,12 @@ define pcodeop vaddubSat;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 1 1 0 1 0 0 1 1 0 0 0 s s s s s P P - t t t t t 1 1 0 d d d d d
:vaddw":sat" Rdd5,rtt5,rss5 EndPacket is iclass=0xd & op2127=0x18 & op0507=6 & rss5 & rtt5 & Rdd5 & $(END_PACKET)
:vaddw":sat" Rdd5,rss5,rtt5 EndPacket is iclass=0xd & op2127=0x18 & op0507=6 & rss5 & rtt5 & Rdd5 & $(END_PACKET)
{
w:4 = 0;
addSat32(w, rtt5[0,32], rss5[0,32]);
addSat32(w, rss5[0,32], rtt5[0,32]);
Rdd5[0,32] = w;
addSat32(w, rtt5[32,32], rss5[32,32]);
addSat32(w, rss5[32,32], rtt5[32,32]);
Rdd5[32,32] = w;
build EndPacket;
}
@@ -15757,8 +15817,8 @@ define pcodeop vlsrw;
define pcodeop vmaxb;
:vmaxb Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1e & op0507=6 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxb(rss5, rtt5);
:vmaxb Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1e & op0507=6 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxb(rtt5, rss5);
build EndPacket;
}
@@ -15769,8 +15829,8 @@ define pcodeop vmaxb;
define pcodeop vmaxh;
:vmaxh Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1e & op0507=1 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxh(rss5, rtt5);
:vmaxh Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1e & op0507=1 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxh(rtt5, rss5);
build EndPacket;
}
@@ -15781,8 +15841,8 @@ define pcodeop vmaxh;
define pcodeop vmaxub;
:vmaxub Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1e & op0507=0 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxub(rss5, rtt5);
:vmaxub Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1e & op0507=0 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxub(rtt5, rss5);
build EndPacket;
}
@@ -15793,8 +15853,8 @@ define pcodeop vmaxub;
define pcodeop vmaxuh;
:vmaxuh Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1e & op0507=2 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxuh(rss5, rtt5);
:vmaxuh Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1e & op0507=2 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxuh(rtt5, rss5);
build EndPacket;
}
@@ -15805,8 +15865,8 @@ define pcodeop vmaxuh;
define pcodeop vmaxuw;
:vmaxuw Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=5 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxuw(rss5, rtt5);
:vmaxuw Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=5 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxuw(rtt5, rss5);
build EndPacket;
}
@@ -15817,8 +15877,8 @@ define pcodeop vmaxuw;
define pcodeop vmaxw;
:vmaxw Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1e & op0507=3 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxw(rss5, rtt5);
:vmaxw Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1e & op0507=3 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vmaxw(rtt5, rss5);
build EndPacket;
}
@@ -15829,8 +15889,8 @@ define pcodeop vmaxw;
define pcodeop vminb;
:vminb Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1e & op0507=7 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminb(rss5, rtt5);
:vminb Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1e & op0507=7 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminb(rtt5, rss5);
build EndPacket;
}
@@ -15841,8 +15901,8 @@ define pcodeop vminb;
define pcodeop vminh;
:vminh Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=1 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminh(rss5, rtt5);
:vminh Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=1 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminh(rtt5, rss5);
build EndPacket;
}
@@ -15853,8 +15913,8 @@ define pcodeop vminh;
define pcodeop vminub;
:vminub Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=0 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminub(rss5, rtt5);
:vminub Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=0 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminub(rtt5, rss5);
build EndPacket;
}
@@ -15864,9 +15924,9 @@ define pcodeop vminub;
# 1 1 1 0 1 0 1 0 1 1 1 s s s s s P P 0 t t t t t 0 e e d d d d d
define pcodeop vminubPred; # per-byte predicate bits: Pe[i] = (first.ub[i] > second.ub[i])
:vminub Rdd5,Pd0506,rss5,rtt5 EndPacket is iclass=14 & op2127=0x57 & op13=0 & op7=0 & Rdd5 & Pd0506 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminub(rss5, rtt5);
Pd0506 = vminubPred(rss5, rtt5);
:vminub Rdd5,Pd0506,rtt5,rss5 EndPacket is iclass=14 & op2127=0x57 & op13=0 & op7=0 & Rdd5 & Pd0506 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminub(rtt5, rss5);
Pd0506 = vminubPred(rtt5, rss5);
build EndPacket;
}
@@ -15877,8 +15937,8 @@ define pcodeop vminubPred; # per-byte predicate bits: Pe[i] = (first.ub[i] > sec
define pcodeop vminuh;
:vminuh Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=2 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminuh(rss5, rtt5);
:vminuh Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=2 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminuh(rtt5, rss5);
build EndPacket;
}
@@ -15889,8 +15949,8 @@ define pcodeop vminuh;
define pcodeop vminuw;
:vminuw Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=4 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminuw(rss5, rtt5);
:vminuw Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=4 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminuw(rtt5, rss5);
build EndPacket;
}
@@ -15901,8 +15961,8 @@ define pcodeop vminuw;
define pcodeop vminw;
:vminw Rdd5,rss5,rtt5 EndPacket is iclass=13 & op2127=0x1d & op0507=3 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminw(rss5, rtt5);
:vminw Rdd5,rtt5,rss5 EndPacket is iclass=13 & op2127=0x1d & op0507=3 & Rdd5 & rtt5 & rss5 & $(END_PACKET) {
Rdd5 = vminw(rtt5, rss5);
build EndPacket;
}

View File

@@ -1,12 +1,14 @@
# Qualcomm Hexagon (V79) and HVX (V79)
## KNOWN ISSUES
# 1. Shift amounts may be positive or negative, however in some cases no special handling
# is provided for negative shift amounts.
# 1. Shift amounts may be positive or negative. The register-form shifts model the
# 7-bit signed shift amount explicitly; other forms may still assume a positive amount.
# 2. There are many complex instructions with unimplemented pcode or simple custom pcodeops
#
## NOTES
# 1. Implementation includes V73 system registers, instruction set may be incomplete
# 1. Implementation includes V73 system registers, instruction set may be incomplete.
# Decode additionally covers the V66 ZReg matrix extension and V81 valign4 as
# decode-only stubs (unimpl pcode).
# 2. HVX register pairs may be access with a vector-swap mode (lsb of 5-bit field is 1)
# introduced with Hexagon v67.
# 3. HVX vector register size is 128-bytes (see defines below), paired size is 256-bytes,

View File

@@ -438,7 +438,7 @@ define pcodeop sfinvsqrtaPred; # Pe = exponent class bits of the approximation
# 1 1 0 1 0 1 1 0 0 1 i - - - - - P P i i i i i i i i i d d d d d
:sfmake^":neg" Rd5,Uimm16_21_0513 EndPacket is iclass=13 & op2227=0x19 & Uimm16_21_0513 & Rd5 & $(END_PACKET) {
Rd5 = int2float(-Uimm16_21_0513); # TODO: assumed functionality
Rd5 = (1 << 31) | (((127 - 6) << 23) + (zext(Uimm16_21_0513) << 17));
build EndPacket;
}
@@ -448,7 +448,7 @@ define pcodeop sfinvsqrtaPred; # Pe = exponent class bits of the approximation
# 1 1 0 1 0 1 1 0 0 0 i - - - - - P P i i i i i i i i i d d d d d
:sfmake^":pos" Rd5,Uimm16_21_0513 EndPacket is iclass=13 & op2227=0x18 & Uimm16_21_0513 & Rd5 & $(END_PACKET) {
Rd5 = int2float(Uimm16_21_0513); # TODO: assumed functionality
Rd5 = ((127 - 6) << 23) + (zext(Uimm16_21_0513) << 17);
build EndPacket;
}
@@ -628,7 +628,7 @@ define pcodeop sfinvsqrtaPred; # Pe = exponent class bits of the approximation
# 1 1 0 1 1 0 0 1 0 1 i - - - - - P P i i i i i i i i i d d d d d
:dfmake^":neg" Rdd5,Uimm16_21_0513 EndPacket is iclass=13 & op2227=0x25 & Uimm16_21_0513 & Rdd5 & $(END_PACKET) {
Rdd5 = int2float(-Uimm16_21_0513); # TODO: assumed functionality
Rdd5 = (1:8 << 63) | (((1023:8 - 6) << 52) + (zext(Uimm16_21_0513) << 46));
build EndPacket;
}
@@ -638,7 +638,7 @@ define pcodeop sfinvsqrtaPred; # Pe = exponent class bits of the approximation
# 1 1 0 1 1 0 0 1 0 0 i - - - - - P P i i i i i i i i i d d d d d
:dfmake^":pos" Rdd5,Uimm16_21_0513 EndPacket is iclass=13 & op2227=0x24 & Uimm16_21_0513 & Rdd5 & $(END_PACKET) {
Rdd5 = int2float(Uimm16_21_0513); # TODO: assumed functionality
Rdd5 = ((1023:8 - 6) << 52) + (zext(Uimm16_21_0513) << 46);
build EndPacket;
}

View File

@@ -1,7 +1,7 @@
# Qualcomm Hexagon HVX Instruction Set
# NOTES:
# - HVX implementation has been updated through V79
# - HVX implementation has been updated through V81
# - HVX hardware supports either 64-byte or 128-byte vector lengths. See hexagon.slaspec for
# default length of 128-bytes.
@@ -1625,8 +1625,8 @@ define pcodeop vsub_VwVw_carryResult;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 0 0 1 1 1 1 0 - - 0 - - 0 1 1 P P 1 u u u u u 1 1 1 d d d d d
:assign Vd5,Vu_0812 EndPacket is iclass=0x1 & op2427=0xe & op21=0x0 & op18=0x0 & op1617=0x3 & op13=0x1 & op0507=0x7 & Vd5 & Vu_0812 & $(END_PACKET) [ cond=0; ] {
Vd5 = Vu_0812; # Vd5 handles unconditional commit
:assign Vd5,Vu_0812 EndPacket is iclass=0x1 & op2427=0xe & op2123=0x0 & op1620=0x3 & op13=0x1 & op0507=0x7 & Vd5 & Vu_0812 & $(END_PACKET) [ cond=0; ] {
Vd5 = Vu_0812; # Vd5 handles unconditional commit
build EndPacket;
}
@@ -1635,7 +1635,7 @@ define pcodeop vsub_VwVw_carryResult;
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 0 0 1 1 1 1 0 - - 0 - - - 0 1 P P 0 u u u u u 1 1 0 d d d d d
:assign Vd5tmp,Vu_0812 EndPacket is iclass=0x1 & op2427=0xe & op21=0x0 & op1617=0x1 & op13=0x0 & op0507=0x6 & Vd5tmp & Vu_0812 & $(END_PACKET) {
:assign Vd5tmp,Vu_0812 EndPacket is iclass=0x1 & op2427=0xe & op2123=0x0 & op1620=0x1 & op13=0x0 & op0507=0x6 & Vd5tmp & Vu_0812 & $(END_PACKET) {
Vd5tmp = Vu_0812;
build EndPacket;
}
@@ -6028,7 +6028,7 @@ define pcodeop Vub_vasr_WuhVub_rnd_sat;
define pcodeop Vsf_equals_Vqf32;
:assign VdSF_0004,VuQF32_0812 EndPacket is iclass=0x1 & op2427=0xe & op21=0x0 & op18=0x1 & op1617=0x0 & op13=0x1 & op0507=0x0 & VdSF_0004 & VuQF32_0812 & $(END_PACKET) {
:assign VdSF_0004,VuQF32_0812 EndPacket is iclass=0x1 & op2427=0xe & op2123=0x0 & op1620=0x4 & op13=0x1 & op0507=0x0 & VdSF_0004 & VuQF32_0812 & $(END_PACKET) {
VdSF_0004 = Vsf_equals_Vqf32(VuQF32_0812);
build EndPacket;
}
@@ -6040,7 +6040,7 @@ define pcodeop Vsf_equals_Vqf32;
define pcodeop Vhf_equals_Vqf16;
:assign VdHF_0004,VuQF16_0812 EndPacket is iclass=0x1 & op2427=0xe & op21=0x0 & op18=0x1 & op1617=0x0 & op13=0x1 & op0507=0x3 & VdHF_0004 & VuQF16_0812 & $(END_PACKET) {
:assign VdHF_0004,VuQF16_0812 EndPacket is iclass=0x1 & op2427=0xe & op2123=0x0 & op1620=0x4 & op13=0x1 & op0507=0x3 & VdHF_0004 & VuQF16_0812 & $(END_PACKET) {
VdHF_0004 = Vhf_equals_Vqf16(VuQF16_0812);
build EndPacket;
}
@@ -6052,7 +6052,7 @@ define pcodeop Vhf_equals_Vqf16;
define pcodeop Vhf_equals_Wqf32;
:assign VdHF_0004,VuuQF32_0812 EndPacket is iclass=0x1 & op2427=0xe & op21=0x0 & op18=0x1 & op1617=0x0 & op13=0x1 & op0507=0x6 & VdHF_0004 & VuuQF32_0812 & $(END_PACKET) {
:assign VdHF_0004,VuuQF32_0812 EndPacket is iclass=0x1 & op2427=0xe & op2123=0x0 & op1620=0x4 & op13=0x1 & op0507=0x6 & VdHF_0004 & VuuQF32_0812 & $(END_PACKET) {
VdHF_0004 = Vhf_equals_Wqf32(VuuQF32_0812);
build EndPacket;
}
@@ -6877,4 +6877,13 @@ define pcodeop scatter_release;
scatter_release(VAlignMemAddrRxAIMu);
}
# (hvx,1) valign4 -- "Vd = valign4(Vu, Vv, Rt8)"
# _________________________________________________________________________________________________
# |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
# 0 0 0 1 1 0 0 0 0 0 0 z z t t t P P 0 u u u u u 1 0 1 d d d d d
define pcodeop valign4;
:valign4 Vd5,Vu_0812,Vz_1923,rt1618 EndPacket is iclass=0x1 & op2427=0x8 & op2123=0x0 & op13=0x0 & op0507=0x5 & Vd5 & Vu_0812 & Vz_1923 & rt1618 & $(END_PACKET) {
Vd5 = valign4(Vu_0812,Vz_1923,rt1618);
}

View File

@@ -0,0 +1,419 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import org.junit.Test;
import ghidra.app.plugin.assembler.sleigh.sem.AssemblyPatternBlock;
import ghidra.app.util.PseudoInstruction;
import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.lang.RegisterValue;
/**
* Packet-context regression-pin coverage test for the Hexagon SLEIGH spec.
*
* <p>Many Hexagon instruction families (NV-cmp-jumps, NV-stores, HVX
* V6_vS32b_new_*, dealloc_return:new, ...) only decode in the context of a
* non-zero packet position with prior-slot register tracking. The mainline
* canonical-byte oracle test (compare_3way.json) decodes each instruction
* standalone and so reports these families as DECODE_FAILED -- but that is a
* methodology artifact, not a real spec gap.
*
* <p>This class constructs the required {@code packetOffset} /
* {@code packetBits} context by hand and disassembles the second-or-later
* instruction in the packet, asserting the resulting mnemonic and operand
* text. The pattern follows
* {@code HexagonAssemblyTest#testAssemble_memw_mSP_n0x4_R0new}, which already
* exercises packet-context for {@code R0.new} stores.
*
* <p>Each assertion pins the current spec output for one representative
* encoding of one packet-context-dependent family; if the constructor
* disappears or its rendering changes the assertion fires.
*
* <p>The byte encodings below are LLVM canonical primaries (one per
* {@code def : HInst<>}) modified only to:
* <ul>
* <li>set the 3-bit {@code Ns8} / {@code Os8} / {@code Nt8} new-register field
* to encoded value {@code 0b010} (= 2). With
* {@code nregSlot = packetOffset - xreg - (field >> 1)} and
* {@code packetOffset == 1, xreg == 0}, this resolves to
* {@code nregSlot = 0} (i.e. the writer was at slot 0);
* <li>leave parse bits at the canonical {@code 11} (end-of-packet) since the
* reader instruction is the last in the packet.
* </ul>
*
* <p>The 3-bit new-value field lives at:
* <ul>
* <li>bits 16..18 (Ns8) for NV-cmp-jumps; setting bit 17 of the word lifts
* it from {@code 000} to {@code 010};
* <li>bits 8..10 (Nt8) for NV-stores; setting bit 9;
* <li>bits 0..2 (Os8) for HVX V6_vS32b_new; setting bit 1.
* </ul>
*/
public class HexagonPacketCoverageTest extends AbstractAssemblyTest {
@Override
protected LanguageID getLanguageID() {
return new LanguageID("Hexagon:LE:32:default");
}
/**
* Build a context byte string with the given {@code packetOffset} and
* {@code packetBits} sub-register values. Mirrors the helper in
* {@link HexagonAssemblyTest}.
*
* @param packetOffset slot index within the packet (0..3)
* @param packetBits raw value of the {@code packetBits} sub-register; the
* high 2 bits are {@code parse1} (slot-0 parse), the
* next 2 are {@code parse2} (slot-1 parse), then 5-bit
* {@code nreg0}, {@code nreg1}, {@code nreg2}, etc.
*/
private String makeCtx(int packetOffset, long packetBits) {
RegisterValue ctxVal = new RegisterValue(lang.getContextBaseRegister());
ctxVal = ctxVal.assign(lang.getRegister("packetOffset"),
BigInteger.valueOf(packetOffset));
ctxVal = ctxVal.assign(lang.getRegister("packetBits"),
BigInteger.valueOf(packetBits));
return AssemblyPatternBlock.fromRegisterValue(ctxVal).fillMask().toString();
}
/**
* Decode a single 4-byte little-endian Hexagon word at packet position
* {@code packetOffset} with the given prior-slot {@code packetBits} and
* assert the disassembly text.
*
* @param hexBytes 8 hex chars representing the 4 bytes in
* little-endian order as they appear in memory
* @param packetOffset slot index within the packet (0..3)
* @param packetBits raw {@code packetBits} sub-register value
* @param expected expected disassembly text, trimmed
*/
protected void assertPacketDecode(String hexBytes, int packetOffset, long packetBits,
String expected) {
if (hexBytes.length() != 8) {
throw new IllegalArgumentException(
"expected 4-byte hex word (8 chars), got: " + hexBytes);
}
byte[] bytes = new byte[4];
for (int i = 0; i < 4; i++) {
bytes[i] = (byte) Integer.parseInt(hexBytes.substring(i * 2, i * 2 + 2), 16);
}
String ctxStr = makeCtx(packetOffset, packetBits);
byte[] ctx = AssemblyPatternBlock.fromString(ctxStr).fillMask().getVals();
PseudoInstruction pi;
try {
pi = disassemble(DEFAULT_ADDR, bytes, ctx);
}
catch (Exception e) {
throw new AssertionError(
"disassembly threw for bytes " + hexBytes + " ctx=" + ctxStr +
" (expected: " + expected + ")",
e);
}
String actual = pi.toString().trim();
assertEquals("bytes " + hexBytes + " offset=" + packetOffset + " packetBits=" +
Long.toHexString(packetBits), expected, actual);
}
/**
* Common context for "slot 1 reads slot 0's writer of R0":
* <ul>
* <li>parse1 = 01 (slot 0 was a normal middle instruction)
* <li>nreg0 = 0 (slot 0 wrote to R0; encoded directly into the 5-bit
* {@code nreg0} sub-field of {@code packetBits})
* </ul>
* packetBits = parse1 in high 2 bits = 0b01_00_00000_00000_00000_00000_00000_000
* = 0x40000000.
*/
private static final long PB_S1_NREG0_R0 = 0x40000000L;
// ---------------------------------------------------------------------
// NV cmp-jump families (J4_cmp{eq,gt,gtu}{,i,n1}_{t,f}_jumpnv_{nt,t})
// ---------------------------------------------------------------------
//
// Encoding layout:
// 31..28 : iclass = 0010
// 27..22 : opcode bits selecting cmp.{eq,gt,gtu} and t/f
// 18..16 : Ns8 (3-bit new-value source)
// 15..14 : parse bits
// 13 : taken hint (1=jump:t, 0=jump:nt)
// 12..8 : Rt32 (or U5 immediate)
// 7..1 : i7 immediate
//
// Canonical sets Ns8 = 000; we set bit 17 -> Ns8 = 010. In LE memory
// order byte2 (bits 16..23) gets bit 1 set: byte2 |= 0x02.
//
// Mainline display order:
// "jump.if:<t|nt> [!]cmp.<eq|gt|gtu>(R0.new,<rhs>),<target>"
// Jump target = inst_start - 4*packetOffset + sext(imm)*4. With
// DEFAULT_ADDR = 0x40000000, packetOffset=1, imm=0: 0x40000000 - 4 = 0x3ffffffc.
/** Pin the J4_cmpeq*_*_jumpnv_* families. */
@Test
public void testPacketCoverage_NVCmpJump_eq() {
// J4_cmpeq_t_jumpnv_t (canonical 00e00020)
assertPacketDecode("00e00220", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.eq(R0.new,R0),0x3ffffffc");
// J4_cmpeq_t_jumpnv_nt (canonical 00c00020)
assertPacketDecode("00c00220", 1, PB_S1_NREG0_R0,
"jump.if:nt cmp.eq(R0.new,R0),0x3ffffffc");
// J4_cmpeq_f_jumpnv_t (canonical 00e04020)
assertPacketDecode("00e04220", 1, PB_S1_NREG0_R0,
"jump.if:t !cmp.eq(R0.new,R0),0x3ffffffc");
// J4_cmpeqi_t_jumpnv_t (canonical 00e00024)
assertPacketDecode("00e00224", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.eq(R0.new,#0x0),0x3ffffffc");
// J4_cmpeqi_f_jumpnv_t (canonical 00e04024)
assertPacketDecode("00e04224", 1, PB_S1_NREG0_R0,
"jump.if:t !cmp.eq(R0.new,#0x0),0x3ffffffc");
// J4_cmpeqn1_t_jumpnv_t (canonical 00e00026) -- #-1 literal renders as "#-1"
assertPacketDecode("00e00226", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.eq(R0.new,#-1),0x3ffffffc");
// J4_cmpeqn1_f_jumpnv_t (canonical 00e04026)
assertPacketDecode("00e04226", 1, PB_S1_NREG0_R0,
"jump.if:t !cmp.eq(R0.new,#-1),0x3ffffffc");
}
/** Pin the J4_cmpgt*_*_jumpnv_* families. */
@Test
public void testPacketCoverage_NVCmpJump_gt() {
// J4_cmpgt_t_jumpnv_t (canonical 00e08020)
assertPacketDecode("00e08220", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.gt(R0.new,R0),0x3ffffffc");
// J4_cmpgt_t_jumpnv_nt
assertPacketDecode("00c08220", 1, PB_S1_NREG0_R0,
"jump.if:nt cmp.gt(R0.new,R0),0x3ffffffc");
// J4_cmpgt_f_jumpnv_t (canonical 00e0c020)
assertPacketDecode("00e0c220", 1, PB_S1_NREG0_R0,
"jump.if:t !cmp.gt(R0.new,R0),0x3ffffffc");
// J4_cmpgti_t_jumpnv_t (canonical 00e08024)
assertPacketDecode("00e08224", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.gt(R0.new,#0x0),0x3ffffffc");
// J4_cmpgtn1_t_jumpnv_t (canonical 00e08026) -- #-1 literal
assertPacketDecode("00e08226", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.gt(R0.new,#-1),0x3ffffffc");
}
/** Pin the J4_cmpgtu*_*_jumpnv_* families. */
@Test
public void testPacketCoverage_NVCmpJump_gtu() {
// J4_cmpgtu_t_jumpnv_t (canonical 00e00021)
assertPacketDecode("00e00221", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.gtu(R0.new,R0),0x3ffffffc");
// J4_cmpgtu_t_jumpnv_nt (canonical 00c00021)
assertPacketDecode("00c00221", 1, PB_S1_NREG0_R0,
"jump.if:nt cmp.gtu(R0.new,R0),0x3ffffffc");
// J4_cmpgtu_f_jumpnv_t (canonical 00e04021)
assertPacketDecode("00e04221", 1, PB_S1_NREG0_R0,
"jump.if:t !cmp.gtu(R0.new,R0),0x3ffffffc");
// J4_cmpgtui_t_jumpnv_t (canonical 00e00025)
assertPacketDecode("00e00225", 1, PB_S1_NREG0_R0,
"jump.if:t cmp.gtu(R0.new,#0x0),0x3ffffffc");
// J4_cmpgtui_f_jumpnv_t (canonical 00e04025)
assertPacketDecode("00e04225", 1, PB_S1_NREG0_R0,
"jump.if:t !cmp.gtu(R0.new,#0x0),0x3ffffffc");
}
// ---------------------------------------------------------------------
// NV-store families (S2_storer{b,h,i}new_*, S4_storer{b,h,i}new_*)
// ---------------------------------------------------------------------
//
// Encoding layout (S2_storerXnew_io, _pi, _pci, _rr):
// 31..28 : iclass = 1010 (0xa) for S2_*; 0011_1011 etc. for S4_*
// 27..22 : subclass selecting size & addressing mode
// 21..16 : Rs32 (base reg)
// 15..14 : parse bits
// 13..11 : 000
// 10..8 : Nt8 (3-bit new-value source)
// 7..3 : Ii immediate
//
// Canonical Nt8 = 000; we set bit 9 of word -> Nt8 = 010. In LE memory
// order, byte1 |= 0x02. With imm=0 the rendering omits the offset:
// "memb (R0),R0.new" not "memb (R0+#0x0),R0.new".
/** Pin S2_storerbnew_io / S2_storerbnew_pi / S4_storerbnew_rr. */
@Test
public void testPacketCoverage_NVStore_byte() {
// S2_storerbnew_io (canonical 00c0a0a1) imm=0 -> "(R0)" only
assertPacketDecode("00c2a0a1", 1, PB_S1_NREG0_R0,
"memb (R0),R0.new");
// S2_storerbnew_pi (canonical 00c0a0ab)
assertPacketDecode("00c2a0ab", 1, PB_S1_NREG0_R0,
"memb (R0++#0x0),R0.new");
// S4_storerbnew_rr (canonical 00c0a03b)
// Note: this constructor uses Nreg0002 (Nt8 at bits 0..2), NOT Nreg0810,
// so we set bit 1 (byte0 |= 0x02) rather than bit 9.
// With shift = 0 the rendering omits the "<<#0x0" suffix.
assertPacketDecode("02c0a03b", 1, PB_S1_NREG0_R0,
"memb (R0+R0),R0.new");
}
/** Pin S2_storerhnew_io / S2_storerhnew_pi / S4_storerhnew_rr. */
@Test
public void testPacketCoverage_NVStore_half() {
// S2_storerhnew_io (canonical 00c8a0a1)
assertPacketDecode("00caa0a1", 1, PB_S1_NREG0_R0,
"memh (R0),R0.new");
// S2_storerhnew_pi (canonical 00c8a0ab)
assertPacketDecode("00caa0ab", 1, PB_S1_NREG0_R0,
"memh (R0++#0x0),R0.new");
// S4_storerhnew_rr (canonical 08c0a03b) -- Nreg0002 -> set bit 1
assertPacketDecode("0ac0a03b", 1, PB_S1_NREG0_R0,
"memh (R0+R0),R0.new");
}
/** Pin S2_storerinew_io / S2_storerinew_pi / S4_storerinew_rr. */
@Test
public void testPacketCoverage_NVStore_word() {
// S2_storerinew_io (canonical 00d0a0a1)
assertPacketDecode("00d2a0a1", 1, PB_S1_NREG0_R0,
"memw (R0),R0.new");
// S2_storerinew_pi (canonical 00d0a0ab)
assertPacketDecode("00d2a0ab", 1, PB_S1_NREG0_R0,
"memw (R0++#0x0),R0.new");
// S4_storerinew_rr (canonical 10c0a03b) -- Nreg0002 -> set bit 1
assertPacketDecode("12c0a03b", 1, PB_S1_NREG0_R0,
"memw (R0+R0),R0.new");
}
// ---------------------------------------------------------------------
// HVX V6_vS32b_new_* (vector NV stores)
// ---------------------------------------------------------------------
//
// Encoding for V6_vS32b_new_ai (canonical 20c02028 -> word 0x2820c020):
// 31..28 : iclass = 0010
// 27..21 : 1010_000 (vS32b family subclass)
// ...
// 2..0 : Os8 (3-bit new vector reg, via VNreg0002 sub-constructor)
//
// Canonical Os8 = 0; we set bit 1 of word -> Os8 = 010.
// In LE memory order, byte0 |= 0x02.
// ---------------------------------------------------------------------
// Predicated NV-store families (S4_pstorer{b,h,i}new{t,f}{,new}_*)
// ---------------------------------------------------------------------
//
// Encoding for S4_pstorerbnewt_io (predicated NV store):
// 31..28 : iclass = 0100 (0x4) [for the io form]
// ...
// 10..8 : Nt8 (Nreg0810)
// We set Nt8 = 010 -> bit 9 of word, byte1 |= 0x02.
//
// For S4_pstorerXnewtnew_rr / S4_pstorerXnewfnew_rr (P.new + register
// indexed) the canonical bytes from JSON include the
// {@code <<#0x0} shift = 0; we set bit 1 (Nreg0002) on those.
/** Pin S4 predicated NV-store family. */
@Test
public void testPacketCoverage_PStoreNew_pred() {
// S4_pstorerbnewt_rr (canonical 00c0a034) -- if (P0) memb(...) = R0.new
// Uses Nreg0002, set bit 1
assertPacketDecode("02c0a034", 1, PB_S1_NREG0_R0,
"memb.if(P0) (R0+R0),R0.new");
// S4_pstorerbnewf_rr (canonical 00c0a035) -- if (!P0)
assertPacketDecode("02c0a035", 1, PB_S1_NREG0_R0,
"memb.if(!P0) (R0+R0),R0.new");
// S4_pstorerinewtnew_rr (canonical 10c0a036) -- if (P0.new)
assertPacketDecode("12c0a036", 1, PB_S1_NREG0_R0,
"memw.if(P0.new) (R0+R0),R0.new");
// S4_pstorerhnewfnew_rr (canonical 08c0a037) -- if (!P0.new)
assertPacketDecode("0ac0a037", 1, PB_S1_NREG0_R0,
"memh.if(!P0.new) (R0+R0),R0.new");
}
// ---------------------------------------------------------------------
// L4_return_*new_p* (dealloc_return predicated by P.new)
// ---------------------------------------------------------------------
//
// Encoding for "if (Ps4.new) dealloc_return:t" (LLVM L4_return_tnew_pt):
// 31..28 : 1001 (iclass=9)
// 27..21 : 0110000 (op2127=0x30)
// 20..16 : 11110 (op1620=0x1e -- fixed pattern, NOT a register
// field; this distinguishes the form from
// "Rdd32 = dealloc_return(Rs32)" which puts an
// rs5 register here)
// 15..14 : PP (parse bits)
// 13 : 0/1 = jump:t/jump:nt (DRTaken12)
// 12..11 : 11 (selects "if (..new)" path)
// 10..9 : 10/01 selecting P.new and/or "!"
// 7..1 : (zero in our test)
// 4..0 : 11110 (op0007=0x1e fixed)
//
// Note: LLVM canonical encoding sets the 5 bits at op1620 and the low 5
// bits of op0007 to 0 (these encode placeholder operands like Rs32 and
// Rdd32 in LLVM's view). Mainline matches the predicated-with-rs5 form
// (which has rs5 at bits 16..20 and op0007=0x1e fixed), so canonical
// bytes 00d80096 from compare_3way.json don't decode in mainline:
// the low-5 bits 0x00 don't match op0007=0x1e. We supply byte0=0x1e.
//
// rs5 = 0 (R0) -> byte2 bits 0..4 = 0; byte2 bits 5..7 = 0 (op2127 low).
// byte3 bits 0..3 = 0110 (op2127 high), bits 4..7 = 1001 (iclass=9) ->
// byte3 = 0x96. So bytes for "if (P0.new) dealloc_return:t R0":
// byte0 = 0x1e, byte1 = 0xd8, byte2 = 0x00, byte3 = 0x96 -> "1ed80096".
// NOTE: a non-canonical dealloc_return renders with its explicit destination
// pair (":raw Rdd,Rs"); the bare "dealloc_return" spelling is reserved for the
// canonical Rs=R30 / Rdd=R31:30 encoding. These use rs5=R0, so they decode as
// ":raw R31R30,R0".
/** Pin L4_return_*new_p* (dealloc_return predicated by P.new) family. */
@Test
public void testPacketCoverage_DeallocReturnNew() {
// L4_return_tnew_pt -- "if (P0.new) dealloc_return:t" rs5=R0
// byte1: parse=11, bit13=0, bit12=1, bit11=1, bit10=0, bits9..8=00 = 0xd8
assertPacketDecode("1ed80096", 1, PB_S1_NREG0_R0,
"dealloc_return.if(P0.new):t:raw R31R30,R0");
// L4_return_tnew_pnt -- "if (P0.new) dealloc_return:nt"
// bit12=0 -> byte1 = 11_0_0_1_0_00 = 0xc8
assertPacketDecode("1ec80096", 1, PB_S1_NREG0_R0,
"dealloc_return.if(P0.new):nt:raw R31R30,R0");
// L4_return_fnew_pt -- "if (!P0.new) dealloc_return:t"
// bit13=1 -> byte1 = 11_1_1_1_0_00 = 0xf8
assertPacketDecode("1ef80096", 1, PB_S1_NREG0_R0,
"dealloc_return.if(!P0.new):t:raw R31R30,R0");
// L4_return_fnew_pnt -- "if (!P0.new) dealloc_return:nt"
// bit13=1, bit12=0 -> byte1 = 11_1_0_1_0_00 = 0xe8
assertPacketDecode("1ee80096", 1, PB_S1_NREG0_R0,
"dealloc_return.if(!P0.new):nt:raw R31R30,R0");
}
/** Pin HVX V6_vS32b_new_* family. */
@Test
public void testPacketCoverage_HVX_VS32bNew() {
// V6_vS32b_new_ai (canonical 20c02028) -> set bit 1: byte0 = 0x22
assertPacketDecode("22c02028", 1, PB_S1_NREG0_R0,
"vmem (R0),V0.new");
// V6_vS32b_new_pi (canonical 20c02029)
assertPacketDecode("22c02029", 1, PB_S1_NREG0_R0,
"vmem (R0++#0x0),V0.new");
// V6_vS32b_new_pred_ai (canonical 40c0a028) -- mainline renders as
// "vmem.if(P0)" rather than "if (P0) vmem".
assertPacketDecode("42c0a028", 1, PB_S1_NREG0_R0,
"vmem.if(P0) (R0),V0.new");
// V6_vS32b_new_npred_ai (canonical 68c0a028)
assertPacketDecode("6ac0a028", 1, PB_S1_NREG0_R0,
"vmem.if(!P0) (R0),V0.new");
// V6_vS32b_new_ppu (canonical 20c0202b) -- Mu2 post-increment
assertPacketDecode("22c0202b", 1, PB_S1_NREG0_R0,
"vmem (R0++M0),V0.new");
// V6_vS32b_new_pred_pi (canonical 40c0a029) -- predicated post-inc imm
assertPacketDecode("42c0a029", 1, PB_S1_NREG0_R0,
"vmem.if(P0) (R0++#0x0),V0.new");
}
}

View File

@@ -0,0 +1,538 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import ghidra.app.util.PseudoInstruction;
import ghidra.program.model.lang.LanguageID;
/**
* Edge-case regression tests for Hexagon shift, rotate, multiply and float-make
* pcode behavior.
*
* <p>These tests pin the encodings and disassembly text for the recently fixed
* decoder/pcode constructors:
*
* <ul>
* <li>scalar register-form shifts (asl, asr, lsl, lsr, setbit, togglebit,
* clrbit) under sxt7 of the Rt register: shift amounts above bit 6 must
* decode as right-shifts (commit "model sxt7 shift amount in
* register-form shifts");
* <li>{@code mpyu(Rs.h,Rt.h):<<1} and its accumulating sibling: the prior
* constructor squared Rs (commit "fix M2_mpyu_*_s1 typo squaring Rs
* instead of Rs*Rt");
* <li>{@code rol} 32-bit and 64-bit immediate forms: must rotate by N rather
* than fold the sign bit (commit "fix rol pcode to compute true rotate");
* <li>{@code sfmake} / {@code dfmake}: must build the IEEE-754 bit pattern
* from {@code (bias-6)<<23 | imm<<17} per V73 spec (commit "build
* sfmake/dfmake from bit pattern per V73");
* <li>{@code sub(#-1,Rs)} canonicalization to {@code not(Rs)}: a long-standing
* pin to detect accidental decoder shadowing.
* </ul>
*
* <p>The HVX vector shift family (vasl/vasr/vlsr) is decode-only -- its pcode
* is a single opaque pcodeop -- but we pin a representative encoding regardless
* of the Rt value to confirm the disasm mnemonic is stable.
*
* <p>The class follows the same disassemble-and-assert pattern as
* {@link HexagonStubCoverageTest}: round-trip tests that don't require the
* assembler grammar, just byte-to-text decode.
*/
public class HexagonShiftEdgeCasesTest extends AbstractAssemblyTest {
@Override
protected LanguageID getLanguageID() {
return new LanguageID("Hexagon:LE:32:default");
}
/**
* Decode a single 4-byte little-endian Hexagon word and assert the
* disassembly text (trimmed) matches {@code expected}.
*/
protected void assertDecode(String hexBytes, String expected) {
if (hexBytes.length() != 8) {
throw new IllegalArgumentException(
"expected 4-byte hex word (8 chars), got: " + hexBytes);
}
byte[] bytes = new byte[4];
for (int i = 0; i < 4; i++) {
bytes[i] = (byte) Integer.parseInt(hexBytes.substring(i * 2, i * 2 + 2), 16);
}
byte[] ctx = context.getDefaultAt(lang.getDefaultSpace().getAddress(DEFAULT_ADDR))
.fillMask()
.getVals();
PseudoInstruction pi;
try {
pi = disassemble(DEFAULT_ADDR, bytes, ctx);
}
catch (Exception e) {
throw new AssertionError(
"disassembly threw for bytes " + hexBytes + " (expected: " + expected + ")", e);
}
String actual = pi.toString().trim();
assertEquals("bytes " + hexBytes, expected, actual);
}
// ---------------------------------------------------------------------
// Scalar register-form shifts -- sxt7 negative shift handling
// ---------------------------------------------------------------------
//
// Encoding for the 32-bit register-form shifts:
// 31..28 : iclass = 1100
// 27..21 : op2127 = 0x32 (asl/asr/lsl/lsr) or 0x34 (setbit/clrbit/togglebit)
// 20..16 : Rs5 (source reg)
// 15..14 : parse bits = 11 (end of packet)
// 13 : op13 = 0
// 12..8 : Rt5 (shift-count reg)
// 7..5 : op0507 = function code
// asl = 4 (100)
// asr = 0 (000)
// lsr = 2 (010)
// lsl = 6 (110)
// setbit = 0 (000) [op2127=0x34 distinguishes]
// clrbit = 2 (010) [op2127=0x34]
// togglebit = 4 (100) [op2127=0x34]
// 4..0 : Rd5 (dest reg)
//
// Disassembly is opaque to Rt's runtime value (the Rt5 field names a
// register, not a shift count), so the mnemonic is identical regardless
// of whether the runtime value is positive or has bit 6 set. We pin the
// encodings with several Rd/Rs/Rt register triples to detect accidental
// constructor shadowing.
/** asl Rd,Rs,Rt -- register-form, op2127=0x32, op0507=4. */
@Test
public void testShiftEdge_asl_register_form() {
// asl R3,R2,R1
assertDecode("83c142c6", "asl R3,R2,R1");
// asl R0,R0,R0
assertDecode("80c040c6", "asl R0,R0,R0");
// asl R5,R6,R7 (Rs=R6, Rt=R7, Rd=R5)
assertDecode("85c746c6", "asl R5,R6,R7");
// asl R31,R31,R31 (max scalar regs -> LR per attach table)
assertDecode("9fdf5fc6", "asl LR,LR,LR");
}
/** asr Rd,Rs,Rt -- register-form, op2127=0x32, op0507=0. */
@Test
public void testShiftEdge_asr_register_form() {
// asr R3,R2,R1 -- bits 7..5 = 000 so byte0 = 0000 0011 = 0x03
assertDecode("03c142c6", "asr R3,R2,R1");
// asr R0,R0,R0
assertDecode("00c040c6", "asr R0,R0,R0");
// asr R5,R6,R7
assertDecode("05c746c6", "asr R5,R6,R7");
}
/** lsr Rd,Rs,Rt -- register-form, op2127=0x32, op0507=2 (010). */
@Test
public void testShiftEdge_lsr_register_form() {
// lsr R3,R2,R1 -- byte0 = 0100 0011 = 0x43
assertDecode("43c142c6", "lsr R3,R2,R1");
// lsr R0,R0,R0
assertDecode("40c040c6", "lsr R0,R0,R0");
}
/** lsl Rd,Rs,Rt -- register-form, op2127=0x32, op0507=6 (110). */
@Test
public void testShiftEdge_lsl_register_form() {
// lsl R3,R2,R1 -- byte0 = 1100 0011 = 0xC3
assertDecode("c3c142c6", "lsl R3,R2,R1");
// lsl R0,R0,R0
assertDecode("c0c040c6", "lsl R0,R0,R0");
}
// ---------------------------------------------------------------------
// 64-bit scalar register-form shifts -- (Rdd5 = asl/asr/lsl/lsr Rss5, rt5)
// ---------------------------------------------------------------------
//
// Encoding for the 64-bit register-form shifts:
// 31..28 : iclass = 1100
// 27..21 : op2127 = 0x1c
// 20..16 : Rss5 (paired-low source reg)
// 15..14 : parse = 11
// 13 : op13 = 0
// 12..8 : Rt5 (32-bit shift-count reg)
// 7..5 : op0507 = function code (asl=4, asr=0, lsl=6, lsr=2)
// 4..0 : Rdd5 (paired-low dest reg)
//
// op2127=0x1c = 0011100 (bits 27..21 MSB..LSB). For Rss=R1R0, Rdd=R1R0,
// Rt=R0: bits 27..21 = 0011100, rs=00000, rt=00000. With parse=11:
// nibble 31..28 = C
// nibble 27..24 = 0011 = 3
// nibble 23..20 = 1000 = 8 (b23=1, 22=0, 21=0, 20=0)
// nibble 19..16 = 0
// nibble 15..12 = 1100 = C
// nibble 11..8 = 0
// nibble 7..4 = depends on op0507 + bit 4 = 0 (Rdd5 bit 4 = 0)
// nibble 3..0 = 0
// Word for asl R1R0,R1R0,R0 (op0507=4): 0xC380C080. Bytes "80c080c3".
// Word for asr R1R0,R1R0,R0 (op0507=0): 0xC380C000. Bytes "00c080c3".
// Word for lsr R1R0,R1R0,R0 (op0507=2): 0xC380C040. Bytes "40c080c3".
// Word for lsl R1R0,R1R0,R0 (op0507=6): 0xC380C0C0. Bytes "c0c080c3".
/** asl Rdd,Rss,Rt -- 64-bit register-form. */
@Test
public void testShiftEdge_asl64_register_form() {
// asl R1R0,R1R0,R0
assertDecode("80c080c3", "asl R1R0,R1R0,R0");
// asl R3R2,R5R4,R6 -- Rdd=2, Rss=4, Rt=6 -> bits 4..0=2 (low byte=
// 1000 0010=0x82), 12..8=6 (byte1=11 0 00110=0xC6), 20..16=4 (bit
// 24..20 nibble updates: bits 23..20 = 1000 ohh wait let me redo).
// For Rss=R5R4 (low reg index 4), bits 20..16 = 00100. Bits 23..20
// from op2127=0x1c -> bits 23,22,21 = 1,0,0; bit 20 = 0 (Rss MSB) ->
// nibble 23..20 = 1000 = 8. Bits 19..16 = 100 (Rss low 3 bits) plus
// bit 19=0... wait let me redo. Rss = 4 = 00100 in 5 bits. Bits
// 20..16 = 0,0,1,0,0. nibble 19..16 = 0100 = 4, nibble 23..20 has
// bit 20 = 0 -> nibble 23..20 = 1000 = 8. So byte2 = 1000_0100 = 0x84.
// byte1: parse=11, bit13=0, Rt=R6=00110, bits 12..8 = 00110, byte1
// = 11_0_0_0_1_1_0 = 1100 0110 = 0xC6.
// byte0: op0507=4 (100), bit 4 = Rdd MSB = 0, Rdd=R3R2 -> low reg=2,
// bits 4..0 = 00010, byte0 = 1000 0010 = 0x82.
// byte3: iclass=1100, op2127 high bits = 0011, byte3 = 1100 0011 = 0xC3.
assertDecode("82c684c3", "asl R3R2,R5R4,R6");
}
/** asr Rdd,Rss,Rt -- 64-bit register-form. */
@Test
public void testShiftEdge_asr64_register_form() {
// asr R1R0,R1R0,R0
assertDecode("00c080c3", "asr R1R0,R1R0,R0");
}
/** lsr Rdd,Rss,Rt -- 64-bit register-form. */
@Test
public void testShiftEdge_lsr64_register_form() {
// lsr R1R0,R1R0,R0
assertDecode("40c080c3", "lsr R1R0,R1R0,R0");
}
/** lsl Rdd,Rss,Rt -- 64-bit register-form. */
@Test
public void testShiftEdge_lsl64_register_form() {
// lsl R1R0,R1R0,R0
assertDecode("c0c080c3", "lsl R1R0,R1R0,R0");
}
// ---------------------------------------------------------------------
// setbit / clrbit / togglebit -- op2127 = 0x34
// ---------------------------------------------------------------------
//
// op2127=0x34 = 0110100 (bits 27..21 MSB..LSB). vs 0x32 = 0110010 used
// by asl/asr/lsl/lsr above. The two differ only at bit 21: 0x32 has
// bit 21 clear, 0x34 has bit 21 set. Combined with rs5=0 the nibble at
// 23..20 is 0x4 vs 0x6 respectively.
/** setbit Rd,Rs,Rt -- op2127=0x34, op0507=0. */
@Test
public void testShiftEdge_setbit_register_form() {
// setbit R0,R0,R0: word = 1100 0110 1000 0000 1100 0000 0000 0000
// = 0xC680 C000
assertDecode("00c080c6", "setbit R0,R0,R0");
// setbit R3,R2,R1
assertDecode("03c182c6", "setbit R3,R2,R1");
}
/** clrbit Rd,Rs,Rt -- op2127=0x34, op0507=2. */
@Test
public void testShiftEdge_clrbit_register_form() {
// clrbit R0,R0,R0: byte0 = 0100 0000 = 0x40
assertDecode("40c080c6", "clrbit R0,R0,R0");
// clrbit R3,R2,R1
assertDecode("43c182c6", "clrbit R3,R2,R1");
}
/** togglebit Rd,Rs,Rt -- op2127=0x34, op0507=4. */
@Test
public void testShiftEdge_togglebit_register_form() {
// togglebit R0,R0,R0: byte0 = 1000 0000 = 0x80
assertDecode("80c080c6", "togglebit R0,R0,R0");
// togglebit R3,R2,R1
assertDecode("83c182c6", "togglebit R3,R2,R1");
}
// ---------------------------------------------------------------------
// Accumulating asl Rd, Rs, Rt -- pinned to detect the sxt7 fix on each
// accumulator family (the sxt7 commit edited each variant separately).
// ---------------------------------------------------------------------
//
// Encoding for "asl&= Rd,Rs,Rt" (and siblings):
// 31..28 : iclass = 1100
// 27..21 : op2127 selects accumulator op
// asl&= -> 0x62, asl+= -> 0x66, asl-= -> 0x64, asl|= -> 0x60
// 20..16 : Rs5
// 15..14 : parse = 11
// 13 : op13 = 0
// 12..8 : Rt5
// 7..5 : op0507 = 4 (asl)
// 4..0 : Rd5 (accumulating - same as Rx5)
//
// All four use bit 22 = 1 (different from the plain register-form 0x32),
// and they only differ in bits 27..23. We pin one canonical encoding
// per accumulator family.
/** asl&= Rd,Rs,Rt -- accumulating-AND form. */
@Test
public void testShiftEdge_asl_acc_and() {
// op2127=0x62 = 1100010. Bits 27..21 = 1,1,0,0,0,1,0.
// nibble 27..24 = 1100 = C, nibble 23..20 = 0100 = 4 (b23=0,22=1,
// 21=0, 20=0 with rs=0). Word: 0xCC40C080. Bytes "80c040cc".
// Wait: iclass=12=1100 nibble 31..28 = C. nibble 27..24 = 1100 = C.
// nibble 23..20 with rs=0: bits 23,22,21,20 = 0,1,0,0 -> 0100 = 4.
// Hmm but op2127=0x62 = 1100010 in 7 bits. Bits 27..21:
// 27=1, 26=1, 25=0, 24=0, 23=0, 22=1, 21=0.
// nibble 27..24 = 1100 = C, nibble 23..20 = 0100 = 4 (b23=0,22=1,
// 21=0, 20=0). So word = 0xCC40_C080. Bytes "80c040cc".
assertDecode("80c040cc", "asl&= R0,R0,R0");
}
/** asl+= Rd,Rs,Rt -- accumulating-add form. */
@Test
public void testShiftEdge_asl_acc_plus() {
// op2127=0x66 = 1100110. Bits 27..21 = 1,1,0,0,1,1,0.
// nibble 27..24 = 1100 = C, nibble 23..20 = 1100 = C (b23=1,22=1,
// 21=0, 20=0). Word = 0xCCC0_C080. Bytes "80c0c0cc".
assertDecode("80c0c0cc", "asl+= R0,R0,R0");
}
/** asl-= Rd,Rs,Rt -- accumulating-sub form. */
@Test
public void testShiftEdge_asl_acc_minus() {
// op2127=0x64 = 1100100. Bits 27..21 = 1,1,0,0,1,0,0.
// nibble 27..24 = 1100, nibble 23..20 = 1000 (b23=1,22=0,21=0,20=0).
// Word = 0xCC80_C080. Bytes "80c080cc".
assertDecode("80c080cc", "asl-= R0,R0,R0");
}
/** asl|= Rd,Rs,Rt -- accumulating-OR form. */
@Test
public void testShiftEdge_asl_acc_or() {
// op2127=0x60 = 1100000. Bits 27..21 = 1,1,0,0,0,0,0.
// nibble 27..24 = 1100, nibble 23..20 = 0000 (b23=0,22=0,21=0,20=0).
// Word = 0xCC00_C080. Bytes "80c000cc".
assertDecode("80c000cc", "asl|= R0,R0,R0");
}
// ---------------------------------------------------------------------
// rol Rd,Rs,#u5 -- 32-bit immediate rotate
// ---------------------------------------------------------------------
//
// Encoding:
// 31..28 : iclass = 1000
// 27..21 : op2127 = 0x60 (1100000)
// 20..16 : Rs5
// 15..14 : parse = 11
// 13 : op13 = 0
// 12..8 : Uimm8_0812 (5-bit shift count)
// 7..5 : op0507 = 3 (011)
// 4..0 : Rd5
//
// Per the recent commit, the pcode now correctly emits
// Rd = (Rs << N) | (Rs >> (32 - N))
// rather than the prior "fold sign bit into bit 0". We pin the
// disassembly for several N values to ensure all rol constructors
// continue to decode at boundary values.
/** rol Rd,Rs,#N -- pin N=1, 5, 16, 31 decode. */
@Test
public void testShiftEdge_rol32_imm() {
// rol R0,R0,#1
assertDecode("60c1008c", "rol R0,R0,#0x1");
// rol R0,R0,#5
assertDecode("60c5008c", "rol R0,R0,#0x5");
// rol R0,R0,#16
assertDecode("60d0008c", "rol R0,R0,#0x10");
// rol R0,R0,#31 (max valid 5-bit value)
assertDecode("60df008c", "rol R0,R0,#0x1f");
}
// ---------------------------------------------------------------------
// rol Rdd,Rss,#u6 -- 64-bit immediate rotate
// ---------------------------------------------------------------------
//
// Encoding:
// 31..28 : iclass = 1000
// 27..21 : op2127 = 0x00 (0000000)
// 20..16 : Rss5 (paired register, low)
// 15..14 : parse = 11
// 13..8 : Uimm8_0813 (6-bit shift count)
// 7..5 : op0507 = 3 (011)
// 4..0 : Rdd5
//
// The fixed pcode is (Rss << N) | (Rss >> (64 - N)). Pin N=1, 5, 32, 63.
/** rol Rdd,Rss,#N -- pin N=1, 5, 32, 63 decode. */
@Test
public void testShiftEdge_rol64_imm() {
// rol R1R0,R1R0,#1
assertDecode("60c10080", "rol R1R0,R1R0,#0x1");
// rol R1R0,R1R0,#5
assertDecode("60c50080", "rol R1R0,R1R0,#0x5");
// rol R1R0,R1R0,#32 (high bit of 6-bit imm set; bits 13..8 = 100000)
assertDecode("60e00080", "rol R1R0,R1R0,#0x20");
// rol R1R0,R1R0,#63 (max valid 6-bit value)
assertDecode("60ff0080", "rol R1R0,R1R0,#0x3f");
}
// ---------------------------------------------------------------------
// mpyu :<<1 -- ensure Rs and Rt are distinct after fix
// ---------------------------------------------------------------------
//
// Encoding for M2_mpyu_hh_s1 ("Rd32 = mpyu(Rs.h,Rt.h):<<1"):
// 31..28 : iclass = 1110
// 27..21 : op2127 = 0x66
// 20..16 : Rs5
// 15..14 : parse = 11
// 13 : op13 = 0
// 12..8 : Rt5
// 7 : op7 = 0
// 6 : op6 = 1 -> Rs.H
// 5 : op5 = 1 -> Rt.H
// 4..0 : Rd5
//
// Pre-fix the constructor squared Rs (zext(Rs)*zext(Rs)). After fix it
// multiplies by Rt. Pin a few register triples; the disasm doesn't
// reflect the buggy semantics, but the fact that we have distinct Rs and
// Rt operands in the rendered text confirms the constructor is in fact
// the two-operand form.
/** mpyu(Rs.h,Rt.h):<<1 -- pin distinct Rs/Rt registers. */
@Test
public void testShiftEdge_mpyu_hh_s1() {
// mpyu(R0.H,R0.H):<<1 -> R0
assertDecode("60c0c0ec", "mpyu:<<1 R0,R0.H,R0.H");
// mpyu(R6.H,R7.H):<<1 -> R5 -- Rs=R6 (bits 20..16=00110), Rt=R7
// (bits 12..8=00111), Rd=R5 (bits 4..0=00101)
assertDecode("65c7c6ec", "mpyu:<<1 R5,R6.H,R7.H");
}
// Encoding for the accumulating M2_mpyu_acc_hh_s1 ("Rxx32 += mpyu(...)"):
// 31..28 : iclass = 1110
// 27..21 : op2127 = 0x36
// 20..16 : Rs5
// 15..14 : parse = 11
// 13 : op13 = 0
// 12..8 : Rt5
// 7 : op7 = 0
// 6 : op6 = 1 (Rs.H)
// 5 : op5 = 1 (Rt.H)
// 4..0 : Rxx5 (paired -- Rxx low reg encoded as Rxx5/2)
@Test
public void testShiftEdge_mpyu_hh_s1_acc() {
// R1R0 += mpyu(R0.H,R0.H):<<1
assertDecode("60c0c0e6", "mpyu+=:<<1 R1R0,R0.H,R0.H");
// R3R2 += mpyu(R6.H,R7.H):<<1 -- Rxx5 = 2 (R3R2 in the dpair table)
assertDecode("62c7c6e6", "mpyu+=:<<1 R3R2,R6.H,R7.H");
}
// ---------------------------------------------------------------------
// sfmake / dfmake -- IEEE-754 bit pattern construction
// ---------------------------------------------------------------------
//
// Encoding for sfmake:pos:
// 31..28 : iclass = 1101
// 27..22 : op2227 = 0x18 (011000)
// 21 : i (high bit of imm, becomes bit 9 after concat)
// 20..16 : op1620 = 0
// 15..14 : parse = 11
// 13..5 : i0513 (low 9 bits of imm)
// 4..0 : Rd5
//
// :neg uses op2227 = 0x19 (011001).
//
// The fixed pcode emits
// Rd = ((bias-6)<<exp_shift) + (zext(imm) << mantissa_shift)
// rather than int2float of the imm. Pin the disassembly for a couple of
// imm values; the mnemonic is "sfmake:pos" / "sfmake:neg".
@Test
public void testShiftEdge_sfmake() {
// sfmake:pos R0,#0
assertDecode("00c000d6", "sfmake:pos R0,#0x0");
// sfmake:neg R0,#0
assertDecode("00c040d6", "sfmake:neg R0,#0x0");
}
@Test
public void testShiftEdge_dfmake() {
// dfmake:pos R1R0,#0
assertDecode("00c000d9", "dfmake:pos R1R0,#0x0");
// dfmake:neg R1R0,#0
assertDecode("00c040d9", "dfmake:neg R1R0,#0x0");
}
// ---------------------------------------------------------------------
// not Rd, Rs -- canonicalized from sub(#-1, Rs)
// ---------------------------------------------------------------------
//
// Encoding (special case of sub Rd,#i,Rs with imm = -1, immexted=0):
// 31..28 : iclass = 0111
// 27..22 : op2227 = 0x19 (011001)
// 21 : s21 = 1 (sign bit of imm)
// 20..16 : Rs5
// 15..14 : parse = 11
// 13..5 : i0513 = 0x1ff (all-ones)
// 4..0 : Rd5
//
// Pin so that a constructor reorder elsewhere in the decoder doesn't
// silently shadow the special case (which would turn "not R0,R0" back
// into "sub R0,#-1,R0" in the output).
@Test
public void testShiftEdge_not_from_sub_neg1() {
// not R0, R0
assertDecode("e0ff6076", "not R0,R0");
// not R5, R6 -- bits 20..16 = R6 = 00110, bits 4..0 = R5 = 00101
// byte0 = (1,1,1,0,0,1,0,1) = 0xE5
// byte1 = (1,1,1,1,1,1,1,1) = 0xFF
// byte2 = (0,1,1,0,0,1,1,0) = 0x66
// byte3 = (0,1,1,1,0,1,1,0) = 0x76
assertDecode("e5ff6676", "not R5,R6");
}
// ---------------------------------------------------------------------
// HVX vasl/vasr/vlsr -- decode-only pin
// ---------------------------------------------------------------------
//
// HVX vector shifts are implemented as opaque pcodeops; semantics are
// known-issue. We just pin that the mnemonic continues to decode for
// representative encodings.
@Test
public void testShiftEdge_hvx_vshifts_decode_only() {
// V6_vaslw -- iclass=1, op2127=0x4b, op0507=7
// Word: 0001 1001 0110 0000 1100 0000 1110 0000 = 0x1960C0E0
assertDecode("e0c06019", "vasl V0.w,V0.w,R0");
// V6_vasrw -- iclass=1, op2127=0x4b, op0507=5
// Word: 0001 1001 0110 0000 1100 0000 1010 0000 = 0x1960C0A0
assertDecode("a0c06019", "vasr V0.w,V0.w,R0");
// V6_vasrh -- iclass=1, op2127=0x4b, op0507=6
// Word: 0001 1001 0110 0000 1100 0000 1100 0000 = 0x1960C0C0
assertDecode("c0c06019", "vasr V0.h,V0.h,R0");
// V6_vaslh -- iclass=1, op2127=0x4c, op0507=0
// Word: 0001 1001 1000 0000 1100 0000 0000 0000 = 0x1980C000
assertDecode("00c08019", "vasl V0.h,V0.h,R0");
// V6_vlsruw -- iclass=1, op2127=0x4c, op0507=1
// Word: 0001 1001 1000 0000 1100 0000 0010 0000 = 0x1980C020
assertDecode("20c08019", "vlsr V0.uw,V0.uw,R0");
// V6_vlsruh -- iclass=1, op2127=0x4c, op0507=2
// Word: 0001 1001 1000 0000 1100 0000 0100 0000 = 0x1980C040
assertDecode("40c08019", "vlsr V0.uh,V0.uh,R0");
}
}

View File

@@ -0,0 +1,246 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import ghidra.app.util.PseudoInstruction;
import ghidra.program.model.lang.LanguageID;
/**
* Regression-pin coverage test for recently added decoder stubs.
*
* <p>Each assertion records, as a baseline, the disassembly text produced by
* the current Hexagon SLEIGH spec for a representative encoding of one stub
* family. The intent is purely to detect silent behavioral regressions
* (e.g. a future edit that accidentally removes or shadows a decoder
* constructor): if the decoded mnemonic changes for any pinned encoding,
* the corresponding assertion will fail and force a deliberate review.
*
* <p>Encodings are taken from real LLVM-MC sample bytes for V69/V73 HVX and
* system instructions; the expected text is what the spec currently emits
* (which for some families is a deliberately simplified or stubbed form).
*
* <p>Unlike {@link HexagonAssemblyTest} this class does <em>not</em> exercise
* the assembler -- many of the stubbed mnemonics use punctuation
* (e.g. {@code |=}, {@code &=}, {@code ^=}, {@code +=}, {@code :rnd:sat})
* that does not necessarily round-trip through the assembler grammar.
* We only assert byte-to-text disassembly via {@link #disassemble}.
*/
public class HexagonStubCoverageTest extends AbstractAssemblyTest {
@Override
protected LanguageID getLanguageID() {
return new LanguageID("Hexagon:LE:32:default");
}
/**
* Decode a single 4-byte little-endian Hexagon word and assert the
* disassembly text (trimmed) matches {@code expected}.
*
* @param hexBytes 8 hex chars representing the 4 bytes in little-endian
* order as they appear in memory (the same form that the
* LLVM-MC corpus prints)
* @param expected the expected disassembly, without trailing whitespace
*/
protected void assertDecode(String hexBytes, String expected) {
if (hexBytes.length() != 8) {
throw new IllegalArgumentException(
"expected 4-byte hex word (8 chars), got: " + hexBytes);
}
byte[] bytes = new byte[4];
for (int i = 0; i < 4; i++) {
bytes[i] = (byte) Integer.parseInt(hexBytes.substring(i * 2, i * 2 + 2), 16);
}
// Default context for a single-instruction packet; the parse-bits
// in the encoding itself mark end-of-packet.
byte[] ctx = context.getDefaultAt(lang.getDefaultSpace().getAddress(DEFAULT_ADDR))
.fillMask()
.getVals();
PseudoInstruction pi;
try {
pi = disassemble(DEFAULT_ADDR, bytes, ctx);
}
catch (Exception e) {
throw new AssertionError(
"disassembly threw for bytes " + hexBytes + " (expected: " + expected + ")", e);
}
String actual = pi.toString().trim();
assertEquals("bytes " + hexBytes, expected, actual);
}
@Test
public void testStubCoverage_HVX_vmpy_integer() {
// V6_vmpyhus
assertDecode("40c0201c", "vmpy V1V0.w,V0.h,V0.uh");
// V6_vmpyhus_acc
assertDecode("20e0201c", "vmpy+= V1V0.w,V0.h,V0.uh");
// V6_vmpyhv
assertDecode("e0c0001c", "vmpy V1V0.w,V0.h,V0.h");
// V6_vmpyhv_acc
assertDecode("e0e0001c", "vmpy+= V1V0.w,V0.h,V0.h");
// V6_vmpyhvsrs
assertDecode("20c0201c", "vmpy:<<1:rnd:sat V0.h,V0.h,V0.h");
}
@Test
public void testStubCoverage_HVX_vrmpy_rtt() {
// V6_vrmpybub_rtt
assertDecode("a0c0c019", "vrmpy V1V0.w,V0.b,R1R0.ub");
// V6_vrmpybub_rtt_acc
assertDecode("00e0a019", "vrmpy+= V1V0.w,V0.b,R1R0.ub");
// V6_vrmpyub_rtt
assertDecode("80c0c019", "vrmpy V1V0.uw,V0.ub,R1R0.ub");
// V6_vrmpyub_rtt_acc
assertDecode("e0e0a019", "vrmpy+= V1V0.uw,V0.ub,R1R0.ub");
}
@Test
public void testStubCoverage_HVX_hf_sf_arith() {
// V6_vdmpy_sf_hf_acc
assertDecode("60e0401c", "vdmpy+= V0.sf,V0.hf,V0.hf");
// V6_vmpy_hf_hf_acc
assertDecode("40e0401c", "vmpy+= V0.hf,V0.hf,V0.hf");
// V6_vmpy_sf_hf_acc
assertDecode("20e0401c", "vmpy+= V1V0.sf,V0.hf,V0.hf");
// V6_vfmax_hf
assertDecode("40e0601c", "vfmax V0.hf,V0.hf,V0.hf");
// V6_vfmax_sf
assertDecode("60e0601c", "vfmax V0.sf,V0.sf,V0.sf");
// V6_vfmin_hf
assertDecode("00e0601c", "vfmin V0.hf,V0.hf,V0.hf");
// V6_vfmin_sf
assertDecode("20e0601c", "vfmin V0.sf,V0.sf,V0.sf");
}
@Test
public void testStubCoverage_HVX_bf_arith() {
// V6_vadd_sf_bf
assertDecode("c0e0401d", "vadd V1V0.sf,V0.bf,V0.bf");
// V6_vsub_sf_bf
assertDecode("a0e0401d", "vsub V1V0.sf,V0.bf,V0.bf");
// V6_vmpy_sf_bf
assertDecode("80e0401d", "vmpy V1V0.sf,V0.bf,V0.bf");
// V6_vmpy_sf_bf_acc
assertDecode("00e0001d", "vmpy+= V1V0.sf,V0.bf,V0.bf");
// V6_vmax_bf
assertDecode("e0e0401d", "vmax V0.bf,V0.bf,V0.bf");
// V6_vmin_bf
assertDecode("00e0401d", "vmin V0.bf,V0.bf,V0.bf");
// V6_vcvt_bf_sf
assertDecode("60e0401d", "vcvt V0.bf,V0.sf,V0.sf");
}
@Test
public void testStubCoverage_HVX_bf_compare() {
// V6_vgtbf
assertDecode("78e0801c", "vcmp.gt Q0,V0.bf,V0.bf");
// V6_vgtbf_and
assertDecode("d0e0801c", "vcmp.gt&= Q0,V0.bf,V0.bf");
// V6_vgtbf_or
assertDecode("38e0801c", "vcmp.gt|= Q0,V0.bf,V0.bf");
// V6_vgtbf_xor
assertDecode("f0e0801c", "vcmp.gt^= Q0,V0.bf,V0.bf");
}
@Test
public void testStubCoverage_HVX_hf_sf_eq_compare() {
// V6_veqhf_and
assertDecode("1ce0801c", "vcmp.eq&= Q0,V0.hf,V0.hf");
// V6_veqhf_or
assertDecode("5ce0801c", "vcmp.eq|= Q0,V0.hf,V0.hf");
// V6_veqhf_xor
assertDecode("9ce0801c", "vcmp.eq^= Q0,V0.hf,V0.hf");
// V6_veqsf_and
assertDecode("0ce0801c", "vcmp.eq&= Q0,V0.sf,V0.sf");
// V6_veqsf_or
assertDecode("4ce0801c", "vcmp.eq|= Q0,V0.sf,V0.sf");
// V6_veqsf_xor
assertDecode("8ce0801c", "vcmp.eq^= Q0,V0.sf,V0.sf");
}
@Test
public void testStubCoverage_HVX_f8_and_cvt2() {
// V6_vcvt2_b_hf
assertDecode("c0e0c01a", "vcvt2 V0.b,V0.hf,V0.hf");
// V6_vcvt2_ub_hf
assertDecode("e0e0c01a", "vcvt2 V0.ub,V0.hf,V0.hf");
// V6_vfmax_f8
assertDecode("a0e0601c", "vfmax V0.f8,V0.f8,V0.f8");
// V6_vfmin_f8
assertDecode("80e0601c", "vfmin V0.f8,V0.f8,V0.f8");
// V6_vabs_f8 -- previously broken (typo bug), now decoded
assertDecode("c0e0661c", "vabs V0.f8,V0.f8");
// V6_vfneg_f8 -- previously broken (typo bug), now decoded
assertDecode("e0e0661c", "vfneg V0.f8,V0.f8");
}
@Test
public void testStubCoverage_HVX_vhist() {
// V6_vhist -- previously broken (typo bug), now decoded
assertDecode("80e0001e", "vhist");
// V6_vhistq -- previously broken (typo bug), now decoded
assertDecode("80e0021e", "vhist Q0");
}
@Test
public void testStubCoverage_HVX_qfext_and_align() {
// V6_get_qfext
assertDecode("e0c0c019", "vgetqfext V0,V0.x,R0");
// V6_get_qfext_oracc
assertDecode("c0c0c019", "vgetqfext|= V0,V0.x,R0");
// V6_set_qfext
assertDecode("60c0c019", "vsetqfext V0.x,V0,R0");
// V6_valign4
assertDecode("a0c00018", "valign4 V0,V0,V0,R0");
}
@Test
public void testStubCoverage_scalar_and_pair() {
// A6_vminub_RdP
assertDecode("00c0e0ea", "vminub R1R0,P0,R1R0,R1R0");
// L2_loadw_aq
assertDecode("00c80092", "memw_aq R0,R0");
// L6_memcpy
assertDecode("40c00092", "memcpy R0,R0,M0");
// S6_vtrunehb_ppp -- previously broken (typo bug), now decoded
assertDecode("60c080c1", "vtrunehb R1R0,R1R0,R1R0");
// S6_vtrunohb_ppp -- previously broken (typo bug), now decoded
assertDecode("a0c080c1", "vtrunohb R1R0,R1R0,R1R0");
}
@Test
public void testStubCoverage_system_and_dma() {
// Y2_icdataw
assertDecode("00e0c055", "icdataw R0,R0");
// Y2_tlbpp
assertDecode("00c0606c", "tlbp R0,R1R0");
// Y6_dmlink
assertDecode("40c000a6", "dmlink R0,R0");
// Y6_dmpause
assertDecode("60c000a8", "dmpause R0");
// Y6_dmpoll
assertDecode("40c000a8", "dmpoll R0");
// Y6_dmresume
assertDecode("80c000a6", "dmresume R0");
// Y6_dmstart
assertDecode("20c000a6", "dmstart R0");
// Y6_dmwait
assertDecode("20c000a8", "dmwait R0");
}
}