From ed3cbae4aa8eeb5b0c13fece3be9d0c01bc44564 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:49:46 -0700 Subject: [PATCH 01/17] hexagon: fix rol pcode to compute true rotate The rol* constructors were emitting (rs << N) | zext(rs s< 0) which only folds the sign bit into bit 0 instead of rotating the high bits back into the low. Use the standard (x << N) | (x >> (W - N)) pattern so the single-shot, accumulating, and bitwise variants all match the ISA. --- .../Hexagon/data/languages/hexagon.sinc | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index b97e5756a7..301c9a755b 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -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; } @@ -2970,7 +2970,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; } @@ -3001,7 +3001,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; } @@ -3033,7 +3033,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; } @@ -3065,7 +3065,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; } @@ -3097,7 +3097,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 +3117,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; } @@ -3149,7 +3149,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; } @@ -3181,7 +3181,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; } @@ -3213,7 +3213,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; } @@ -3245,7 +3245,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; } @@ -3277,7 +3277,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; } From b8bcbac047639b969249b2d32bab40b9011614a7 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:50:06 -0700 Subject: [PATCH 02/17] hexagon: prefix !cmp.eq/gt/gtu rather than suffix LLVM disassembles the negated cmp constructors as "!cmp.eq Pd, Rs, Rt" not "cmp.eq! Pd, Rs, Rt". Quote the bang into the head token so the display matches; pcode is unchanged. --- .../Hexagon/data/languages/hexagon.sinc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 301c9a755b..ed7da8b221 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -4232,7 +4232,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 +4254,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 +4287,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 +4309,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 +4342,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 +4364,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; @@ -4397,7 +4397,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) { +:"!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 Rd5 = zext(rs5 != Simm32_0512x); build EndPacket; @@ -4418,7 +4418,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; } From 80c5e9d07f0f5f6635ac4d17e52dfe1237ed05b6 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:50:15 -0700 Subject: [PATCH 03/17] hexagon: fix M2_mpyu_*_s1 typo squaring Rs instead of Rs*Rt Both the plain and accumulating M2_mpyu :<<1 forms had zext(Rs)*zext(Rs). Multiply by Rt as the encoding intends. --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index ed7da8b221..a134aa325d 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -12639,7 +12639,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 +12865,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; } From 51685f00ff3c7a5a88dd551b0c7338d84e5119c3 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:50:24 -0700 Subject: [PATCH 04/17] hexagon: drop spurious Rd5 from ictagw match list ictagw has no destination register; Rd5 was listed in the constructor's operand expression but never used. Remove it so the constructor only binds the operands it actually consumes. --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index a134aa325d..c9080c532f 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -5950,7 +5950,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; } From 0740f82ce453678071e0d83f9c494cb14d18ee63 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:50:50 -0700 Subject: [PATCH 05/17] hexagon: swap min/minu operand display to match LLVM LLVM prints min as "min(Rt, Rs)" not "min(Rs, Rt)". Reorder the display tokens for the four scalar/pair min and minu constructors; pcode already evaluates min(rt, rs). --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index c9080c532f..8b05f67b7e 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -11649,7 +11649,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 +11659,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 +11671,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 +11681,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; } From 8215297c8377399b976b399c2ae5f6d2f2de5079 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:53:35 -0700 Subject: [PATCH 06/17] hexagon: add V68 memw_aq decode-only stub Acquire-load form L2_loadw_aq from V68; same iclass/op2127 family as the existing memw_phys constructor but distinguished by op0513=0x40. --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 8b05f67b7e..8beaf84cb2 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -11642,6 +11642,14 @@ 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 + +:memw_aq Rd5,rs5 EndPacket is iclass=9 & op2127=0x10 & op0513=0x40 & Rd5 & rs5 & $(END_PACKET) +unimpl + # (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| From 42ea4784b2d34525f605c6ba9fea4cb7a81fddda Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 15:54:42 -0700 Subject: [PATCH 07/17] hexagon_hvx: tighten vassign bit constraints Replace the open-ended op21/op1617 patterns on the existing vassign and Vsf/Vhf-from-qf32/qf16 constructors with the full op2123/op1620 fields, matching the LLVM encodings exactly so neighbouring stubs don't decode ambiguously. --- .../Hexagon/data/languages/hexagon_hvx.sinc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc index 46bdf98133..045754cd4d 100644 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc @@ -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; } From 671add87ab4b5a3aeb5583a226703ea00850979d Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 16:03:00 -0700 Subject: [PATCH 08/17] hexagon_hvx: add V81 valign4 stub Adds a decode-only stub for V6_valign4. The six veqhf/veqsf qfloat-accumulating predicate forms that originally accompanied this are not added: upstream's hexagon_hvx2.sinc implements all of them with real p-code. --- Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc index 045754cd4d..43509bb90b 100644 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc @@ -6877,4 +6877,10 @@ 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 + +: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) unimpl From 9d4c191a46076d2bc0d3631ad39bf763a6a2a2dc Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 16:04:06 -0700 Subject: [PATCH 09/17] Hexagon: add stub- and packet-coverage regression-pin tests Two new JUnit tests pin the disassembly text emitted for representative encodings of the recently added decoder stubs (HexagonStubCoverageTest) and packet-context decoding (HexagonPacketCoverageTest), so a future edit that accidentally drops or shadows a constructor will surface as a deliberate review point rather than a silent regression. --- .../sleigh/HexagonPacketCoverageTest.java | 419 ++++++++++++++++++ .../sleigh/HexagonStubCoverageTest.java | 246 ++++++++++ 2 files changed, 665 insertions(+) create mode 100644 Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonPacketCoverageTest.java create mode 100644 Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonStubCoverageTest.java 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: + *

    + *
  • set the 3-bit {@code Ns8} / {@code Os8} / {@code Nt8} new-register field + * to encoded value {@code 0b010} (= 2). With + * {@code nregSlot = packetOffset - xreg - (field >> 1)} and + * {@code packetOffset == 1, xreg == 0}, this resolves to + * {@code nregSlot = 0} (i.e. the writer was at slot 0); + *
  • leave parse bits at the canonical {@code 11} (end-of-packet) since the + * reader instruction is the last in the packet. + *
+ * + *

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

    + *
  • bits 16..18 (Ns8) for NV-cmp-jumps; setting bit 17 of the word lifts + * it from {@code 000} to {@code 010}; + *
  • bits 8..10 (Nt8) for NV-stores; setting bit 9; + *
  • bits 0..2 (Os8) for HVX V6_vS32b_new; setting bit 1. + *
+ */ +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": + *
    + *
  • parse1 = 01 (slot 0 was a normal middle instruction) + *
  • nreg0 = 0 (slot 0 wrote to R0; encoded directly into the 5-bit + * {@code nreg0} sub-field of {@code packetBits}) + *
+ * 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/HexagonStubCoverageTest.java b/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonStubCoverageTest.java new file mode 100644 index 0000000000..6d038db5bf --- /dev/null +++ b/Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonStubCoverageTest.java @@ -0,0 +1,246 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.assembler.sleigh; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import ghidra.app.util.PseudoInstruction; +import ghidra.program.model.lang.LanguageID; + +/** + * Regression-pin coverage test for recently added decoder stubs. + * + *

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"); + } +} From 0402ed5476f84d3d1c1feda39789b0498916e816 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 18:45:46 -0700 Subject: [PATCH 10/17] hexagon: drop redundant togglebit shift-count guard --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 2 -- 1 file changed, 2 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 8beaf84cb2..222de6ed07 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -14395,10 +14395,8 @@ 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; Rd5 = rs5 ^ mask; - build EndPacket; } From d29b9c718fbf951de19cc3b88211565c9e2a6e4f Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 18:56:59 -0700 Subject: [PATCH 11/17] hexagon: model sxt7 shift amount in register-form shifts --- .../Hexagon/data/languages/hexagon.sinc | 239 +++++++++++------- 1 file changed, 146 insertions(+), 93 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 222de6ed07..3437c42c8c 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -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; } @@ -6922,7 +6945,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 +6957,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 +6969,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 +6981,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 +6994,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 +7007,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 +7020,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 +7033,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 +7046,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 +7059,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 +7072,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 +7085,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 +7108,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 +7130,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 +7152,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 +7175,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 +7198,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 +7231,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 +7254,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 +7277,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 +7300,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 +7323,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 +7346,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; } @@ -13630,7 +13679,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; } @@ -14395,7 +14445,8 @@ 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) { - mask:4 = 1 << rt5; + shamt:4 = (rt5 << 25) s>> 25; + mask:4 = zext(shamt s>= 0) * (1 << shamt); Rd5 = rs5 ^ mask; build EndPacket; } @@ -14493,7 +14544,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; @@ -14505,7 +14557,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; From 0345ff83cfd8ac3aa48bd2df5b1e6f97b0aee2d1 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Fri, 28 Aug 2026 21:55:29 -0700 Subject: [PATCH 12/17] hexagon: refresh comments to reflect current support Records the decode coverage this branch adds (V66 ZReg matrix extension and V81 valign4, both decode-only stubs) and narrows the shift-amount KNOWN ISSUE to what is actually fixed: register-form shifts now model the 7-bit signed shift amount, other forms may still assume positive. --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 2 +- Ghidra/Processors/Hexagon/data/languages/hexagon.slaspec | 8 +++++--- Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 3437c42c8c..00d90c7820 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 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_hvx.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc index 43509bb90b..35a3daf4a8 100644 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc @@ -2,6 +2,8 @@ # NOTES: # - HVX implementation has been updated through V79 +# - Decode additionally covers the V66 ZReg matrix family (vrmpyz / vr8mpyz / vr16mpyz +# and the z-register loads) plus V81 valign4, as decode-only stubs (unimpl pcode). # - HVX hardware supports either 64-byte or 128-byte vector lengths. See hexagon.slaspec for # default length of 128-bytes. From ce95d4edb3226e8f8e61b3918a18be3208e6ede0 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 19:23:56 -0700 Subject: [PATCH 13/17] hexagon_float: build sfmake/dfmake from bit pattern per V73 --- .../Processors/Hexagon/data/languages/hexagon_float.sinc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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; } From 55f425223b446b2fd5844472c5ccb6558071b10f Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 19:27:21 -0700 Subject: [PATCH 14/17] hexagon: drop stale TODOs that no longer apply --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 00d90c7820..1e8436921c 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -4410,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; } @@ -4421,7 +4420,6 @@ define pcodeop clip; # 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 Rd5 = zext(rs5 != Simm32_0512x); build EndPacket; } @@ -5866,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; } From daf46c9777718230cb23d1eb5131ac7575c80a71 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 May 2026 20:28:16 -0700 Subject: [PATCH 15/17] Hexagon: expand tests for shift edge cases and recent fixes --- .../sleigh/HexagonShiftEdgeCasesTest.java | 538 ++++++++++++++++++ 1 file changed, 538 insertions(+) create mode 100644 Ghidra/Processors/Hexagon/src/test/java/ghidra/app/plugin/assembler/sleigh/HexagonShiftEdgeCasesTest.java 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)< Date: Fri, 28 Aug 2026 21:59:33 -0700 Subject: [PATCH 16/17] hexagon: swap vmin/vmax/shuffo/vaddw operand display to match LLVM Same class of bug as the earlier min/minu fix: the displayed source operand order contradicts the instruction syntax recorded in each constructor's own doc comment (and LLVM/the PRM). vminb/vminh/vminub/vminuh/vminuw/vminw, vmaxb/vmaxh/vmaxub/vmaxuh/ vmaxuw/vmaxw and shuffob/shuffoh are documented as "f ( Rtt32 , Rss32 )" but displayed Rss before Rtt. vaddw and vaddw:sat are documented as "vaddw ( Rss32 , Rtt32 )" but displayed Rtt before Rss. Includes the V62 "Rdd32,Pe4 = vminub ( Rtt32 , Rss32 )" form. The pcodeop / inline arguments are swapped to match, so the emitted call argument order still follows the displayed operand order. For the min, max and add forms this is semantically neutral (all commutative); it matters for vminubPred, whose result is defined relative to the first operand, and for the opaque shuffob/shuffoh, whose operand roles are positional. Verified: SleighCompile clean, all 60 Hexagon unit tests pass. No test expectations change (the one test pinning vminub uses R1R0 for both sources). --- .../Hexagon/data/languages/hexagon.sinc | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 1e8436921c..2977629dbd 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -13737,8 +13737,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; } @@ -13749,8 +13749,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; } @@ -14806,10 +14806,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; } @@ -14818,12 +14818,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; } @@ -15814,8 +15814,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; } @@ -15826,8 +15826,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; } @@ -15838,8 +15838,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; } @@ -15850,8 +15850,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; } @@ -15862,8 +15862,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; } @@ -15874,8 +15874,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; } @@ -15886,8 +15886,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; } @@ -15898,8 +15898,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; } @@ -15910,8 +15910,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; } @@ -15921,9 +15921,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; } @@ -15934,8 +15934,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; } @@ -15946,8 +15946,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; } @@ -15958,8 +15958,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; } From dbec68725c3005a91e8b9b753a5669152be44161 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 10 Sep 2026 19:02:19 -0400 Subject: [PATCH 17/17] GP-7267 Minor revision to Hexagon pcode --- Ghidra/Processors/Hexagon/data/languages/hexagon.sinc | 7 +++++-- .../Processors/Hexagon/data/languages/hexagon_hvx.sinc | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc index 2977629dbd..525f324584 100755 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon.sinc @@ -11694,8 +11694,11 @@ define pcodeop memw_phys; # |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 -:memw_aq Rd5,rs5 EndPacket is iclass=9 & op2127=0x10 & op0513=0x40 & Rd5 & rs5 & $(END_PACKET) -unimpl +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 )" # _________________________________________________________________________________________________ diff --git a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc index 35a3daf4a8..b2ba6592a3 100644 --- a/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc +++ b/Ghidra/Processors/Hexagon/data/languages/hexagon_hvx.sinc @@ -1,9 +1,7 @@ # Qualcomm Hexagon HVX Instruction Set # NOTES: -# - HVX implementation has been updated through V79 -# - Decode additionally covers the V66 ZReg matrix family (vrmpyz / vr8mpyz / vr16mpyz -# and the z-register loads) plus V81 valign4, as decode-only stubs (unimpl pcode). +# - 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. @@ -6884,5 +6882,8 @@ define pcodeop scatter_release; # |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 -: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) unimpl +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); +}