diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index b97e5756a7..525f324584 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -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 ; - mask:4 = 1 << rt5; + shamt:4 = (rt5 << 25) s>> 25; + mask:4 = zext(shamt s>= 0) * (1 << shamt); Rd5 = rs5 ^ mask; - 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; } diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.slaspec b/Ghidra/Processors/Hexagon/data/languages/hexagon.slaspec index fa67708196..1d1e25f58e 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.slaspec +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.slaspec @@ -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, diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon_float.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon_float.sinc index 00d6e1de3b..0341fc56e1 100644 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon_float.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon_float.sinc @@ -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; } diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc index 46bdf98133..b2ba6592a3 100644 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc @@ -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); +} diff --git a/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonPacketCoverageTest.java b/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonPacketCoverageTest.java new file mode 100644 index 0000000000..ad83b4ab6e --- /dev/null +++ b/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonPacketCoverageTest.java @@ -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. + * + *

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. + * + *

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. + * + *

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. + * + *

The byte encodings below are LLVM canonical primaries (one per + * {@code def : HInst<>}) modified only to: + *

+ * + *

The 3-bit new-value field lives at: + *

+ */ +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": + * + * 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: [!]cmp.(R0.new,)," + // 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"); + } +} diff --git a/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonShiftEdgeCasesTest.java b/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonShiftEdgeCasesTest.java new file mode 100644 index 0000000000..775c88609a --- /dev/null +++ b/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonShiftEdgeCasesTest.java @@ -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. + * + *

These tests pin the encodings and disassembly text for the recently fixed + * decoder/pcode constructors: + * + *

    + *
  • 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"); + *
  • {@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"); + *
  • {@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"); + *
  • {@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"); + *
  • {@code sub(#-1,Rs)} canonicalization to {@code not(Rs)}: a long-standing + * pin to detect accidental decoder shadowing. + *
+ * + *

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. + * + *

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)<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. + * + *

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). + * + *

Unlike {@link HexagonAssemblyTest} this class does not 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"); + } +}