From 3d1b865543b5b91976c8ddad9ab78ecc2d1e939b Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Fri, 3 Nov 2023 12:30:51 -0400 Subject: [PATCH] GP-3879: Implemented lzcount in several instructions --- .../68000/data/languages/68000.sinc | 25 +-- .../AARCH64/data/languages/AARCH64base.sinc | 63 +------ .../data/languages/avr32a_bit_operations.sinc | 162 +----------------- .../HCS12/data/languages/XGATE.sinc | 6 +- .../tricore/data/languages/tricore.sinc | 17 +- 5 files changed, 33 insertions(+), 240 deletions(-) diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 504b1deb0f..c33f4be592 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -1065,21 +1065,25 @@ with : extGUARD=1 { # f_off and f_wd specify the offset and width of the field of the source to consider. # If f_off=0 and f_wd=0 then this means the full 32-bit source is examined (implemented here). # - tmp:4 = e2l; + local tmp:4 = e2l; NF = (tmp & 0x80000000) != 0; ZF = (tmp == 0); VF = 0; CF = 0; - tmp2:4 = lzcount(tmp); - # NB- it seems the MSB left most bit is really at offset 0, - # and the right LSB is at offset 31 - tmp3:4 = (tmp2 % 32); # need mod for when there are all zeros, when tmp2 would = 32 - f_reg = tmp3; + f_reg = zext(tmp != 0) * lzcount(tmp); } -# TODO: complete bfffo for when f_off or f_wd !=0, and for when f_off and f_wd are in registers -:bfffo e2l{f_off:f_wd},f_reg is opbig=0xed & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd & f_reg ; e2l - [ savmod2=savmod1; regtsan=regtfan; ] unimpl +:bfffo e2l{f_off:f_wd},f_reg is opbig=0xed & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd & f_reg ; e2l [ savmod2=savmod1; regtsan=regtfan; ] { + local tmp:4 = e2l; + tmp = (tmp << f_off) >> (32 - f_wd); + tmp = (tmp << (32 - f_wd)); + local offw = f_off + f_wd; + NF = (tmp & 0x80000000) != 0; + ZF = (tmp == 0); + VF = 0; + CF = 0; + f_reg = (zext(tmp != 0) * lzcount(tmp)) + (zext(tmp == 0) * zext(offw)); +} :bfins f_reg,e2l{f_off:f_wd} is opbig=0xef & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd & f_reg; e2l [ savmod2=savmod1; regtsan=regtfan; ] { @@ -2930,10 +2934,9 @@ accreg: ACC1 is ACC1 & acclsb=1 ; accmsb=0 { export ACC1; } accreg: ACC2 is ACC2 & acclsb=0 ; accmsb=1 { export ACC2; } accreg: ACC3 is ACC3 & acclsb=1 ; accmsb=1 { export ACC3; } -define pcodeop findFirstOne; :ff1 regdn is reg315=0x98 & regdn { - regdn = findFirstOne(regdn); + regdn = lzcount(regdn); VF = 0; CF = 0; resflags(regdn); diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc index b9c0ccb649..6fb9d2e799 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc @@ -1445,19 +1445,8 @@ is b_2431=0xd5 & b_2223=0 & l=0 & Op0=0 & Op1=3 & CRn=0x3 & CRm_uimm4_def15 & Op is sf=0 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x5 & Rn_GPR32 & Rd_GPR32 & Rd_GPR64 { local tmp:4 = (Rn_GPR32 ^ (Rn_GPR32<<1))|0x1; - # first make all lower bits =1 - tmp = tmp | (tmp >> 1); - tmp = tmp | (tmp >> 2); - tmp = tmp | (tmp >> 4); - tmp = tmp | (tmp >> 8); - tmp = tmp | (tmp >> 16); - # now add the 1 bits together, voila - tmp = ((tmp & 0xaaaaaaaa)>>1) + (tmp & 0x55555555); - tmp = ((tmp & 0xcccccccc)>>2) + (tmp & 0x33333333); - tmp = ((tmp & 0xf0f0f0f0)>>4) + (tmp & 0x0f0f0f0f); - tmp = ((tmp & 0xff00ff00)>>8) + (tmp & 0x00ff00ff); - tmp = ((tmp & 0xffff0000)>>16) + (tmp & 0x0000ffff); - Rd_GPR64 = zext(32 - (tmp & 0x3f)); + + Rd_GPR64 = lzcount(tmp); } # C6.2.57 CLS page C6-1243 line 72939 MATCH x5ac01400/mask=x7ffffc00 @@ -1468,21 +1457,8 @@ is sf=0 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x5 is sf=1 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x5 & Rn_GPR64 & Rd_GPR64 { local tmp:8 = (Rn_GPR64 ^ (Rn_GPR64<<1))|0x1; - # first make all lower bits =1 - tmp = tmp | (tmp >> 1); - tmp = tmp | (tmp >> 2); - tmp = tmp | (tmp >> 4); - tmp = tmp | (tmp >> 8); - tmp = tmp | (tmp >> 16); - tmp = tmp | (tmp >> 32); - # now add the 1 bits together, voila - tmp = ((tmp & 0xaaaaaaaaaaaaaaaa)>>1) + (tmp & 0x5555555555555555); - tmp = ((tmp & 0xcccccccccccccccc)>>2) + (tmp & 0x3333333333333333); - tmp = ((tmp & 0xf0f0f0f0f0f0f0f0)>>4) + (tmp & 0x0f0f0f0f0f0f0f0f); - tmp = ((tmp & 0xff00ff00ff00ff00)>>8) + (tmp & 0x00ff00ff00ff00ff); - tmp = ((tmp & 0xffff0000ffff0000)>>16) + (tmp & 0x0000ffff0000ffff); - tmp = ((tmp & 0xffffffff00000000)>>32) + (tmp & 0x00000000ffffffff); - Rd_GPR64 = 64 - (tmp & 0x7f); + + Rd_GPR64 = lzcount(tmp); } # C6.2.58 CLZ page C6-1245 line 73022 MATCH x5ac01000/mask=x7ffffc00 @@ -1493,19 +1469,7 @@ is sf=1 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x5 is sf=0 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x4 & Rn_GPR32 & Rd_GPR32 & Rd_GPR64 { local tmp:4 = Rn_GPR32; - # first make all lower bits =1 - tmp = tmp | (tmp >> 1); - tmp = tmp | (tmp >> 2); - tmp = tmp | (tmp >> 4); - tmp = tmp | (tmp >> 8); - tmp = tmp | (tmp >> 16); - # now add the 1 bits together, voila - tmp = ((tmp & 0xaaaaaaaa)>>1) + (tmp & 0x55555555); - tmp = ((tmp & 0xcccccccc)>>2) + (tmp & 0x33333333); - tmp = ((tmp & 0xf0f0f0f0)>>4) + (tmp & 0x0f0f0f0f); - tmp = ((tmp & 0xff00ff00)>>8) + (tmp & 0x00ff00ff); - tmp = ((tmp & 0xffff0000)>>16) + (tmp & 0x0000ffff); - Rd_GPR64 = zext(32 - (tmp & 0x3f)); + Rd_GPR64 = lzcount(tmp); } # C6.2.58 CLZ page C6-1245 line 73022 MATCH x5ac01000/mask=x7ffffc00 @@ -1516,21 +1480,8 @@ is sf=0 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x4 is sf=1 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x4 & Rn_GPR64 & Rd_GPR64 { local tmp:8 = Rn_GPR64; - # first make all lower bits =1 - tmp = tmp | (tmp >> 1); - tmp = tmp | (tmp >> 2); - tmp = tmp | (tmp >> 4); - tmp = tmp | (tmp >> 8); - tmp = tmp | (tmp >> 16); - tmp = tmp | (tmp >> 32); - # now add the 1 bits together, voila - tmp = ((tmp & 0xaaaaaaaaaaaaaaaa)>>1) + (tmp & 0x5555555555555555); - tmp = ((tmp & 0xcccccccccccccccc)>>2) + (tmp & 0x3333333333333333); - tmp = ((tmp & 0xf0f0f0f0f0f0f0f0)>>4) + (tmp & 0x0f0f0f0f0f0f0f0f); - tmp = ((tmp & 0xff00ff00ff00ff00)>>8) + (tmp & 0x00ff00ff00ff00ff); - tmp = ((tmp & 0xffff0000ffff0000)>>16) + (tmp & 0x0000ffff0000ffff); - tmp = ((tmp & 0xffffffff00000000)>>32) + (tmp & 0x00000000ffffffff); - Rd_GPR64 = 64 - (tmp & 0x7f); + + Rd_GPR64 = lzcount(tmp); } # C6.2.59 CMN (extended register) page C6-1246 line 73092 MATCH x2b20001f/mask=x7fe0001f diff --git a/Ghidra/Processors/Atmel/data/languages/avr32a_bit_operations.sinc b/Ghidra/Processors/Atmel/data/languages/avr32a_bit_operations.sinc index df6b05c04b..7b74ff4543 100644 --- a/Ghidra/Processors/Atmel/data/languages/avr32a_bit_operations.sinc +++ b/Ghidra/Processors/Atmel/data/languages/avr32a_bit_operations.sinc @@ -231,167 +231,7 @@ CSBRH: off is bp9_4 & bp4_1 :CLZ rd0, RS9A is op13_3=0x7 & op4_5=0x0 & rd0 & RS9A ; eop0_16=0x1200 { - continueloop:4 = 1; - count:4 = 0; - mask:4 = 0x80000000; - - test:4 = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - count = count + test * continueloop; - continueloop = continueloop * test; - mask = mask >> 1; - - test = zext((mask & RS9A) == 0); - rd0 = count + test * continueloop; + rd0 = lzcount(RS9A); Z = (rd0 == 0); C = (rd0 == 32); diff --git a/Ghidra/Processors/HCS12/data/languages/XGATE.sinc b/Ghidra/Processors/HCS12/data/languages/XGATE.sinc index c03f63b6a0..fb41da5c59 100644 --- a/Ghidra/Processors/HCS12/data/languages/XGATE.sinc +++ b/Ghidra/Processors/HCS12/data/languages/XGATE.sinc @@ -54,7 +54,6 @@ attach variables [reg8_hi ] [R0.H R1.H R2.H R3.H R4.H R5.H R6.H R7.H]; # Pseudo Instructions ################################################################ -define pcodeop findFirstOne; define pcodeop leftShiftCarry; define pcodeop rightShiftCarry; define pcodeop parity; @@ -277,9 +276,8 @@ rd_hi: reg8 is reg8 & reg8_hi { export reg8_hi; } { # 15 - count leading zeros tmp:2 = rs1; - $(XC) = (rd == 0); - #TODO: implement findFirstOne behavior - rd = findFirstOne(tmp); + $(XC) = (rs1 == 0); + rd = zext(tmp != 0) * (15 - lzcount(tmp)); default_flags(rd); } diff --git a/Ghidra/Processors/tricore/data/languages/tricore.sinc b/Ghidra/Processors/tricore/data/languages/tricore.sinc index 1c20278230..adffa29601 100644 --- a/Ghidra/Processors/tricore/data/languages/tricore.sinc +++ b/Ghidra/Processors/tricore/data/languages/tricore.sinc @@ -490,7 +490,6 @@ define pcodeop cache_index_ivld; define pcodeop cache_index_wb; define pcodeop cache_index_wi; define pcodeop round16; -define pcodeop leading_signs; define pcodeop crc32; # float @@ -1844,8 +1843,8 @@ SC: [a10]const0815Z10zz is PCPMode=0 & a10 & const0815Z10zz & op0003=8 & op0404= # CLO.H D[c], D[a] (RR) :clo.h Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x7d0 { - local tmp1:4 = zext(Rd0811[16,16]); - local tmp0:4 = zext(Rd0811[0,16]); + local tmp1:2 = Rd0811[16,16]; + local tmp0:2 = Rd0811[0,16]; Rd2831[16,16] = lzcount(~tmp1); Rd2831[0,16] = lzcount(~tmp0); } @@ -1853,16 +1852,18 @@ SC: [a10]const0815Z10zz is PCPMode=0 & a10 & const0815Z10zz & op0003=8 & op0404= # CLS D[c], D[a] (RR) :cls Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x1d0 { - Rd2831 = leading_signs(Rd0811) - 1; + local tmp:4 = (Rd0811 ^ (Rd0811<<1))|0x1; + + Rd2831 = lzcount(tmp); } # CLS.H D[c], D[a] (RR) :cls.h Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x7e0 { - local tmp1:4 = zext(Rd0811[16,16]); - local tmp0:4 = zext(Rd0811[0,16]); - Rd2831[16,16] = leading_signs(tmp1) - 1; - Rd2831[0,16] = leading_signs(tmp0) - 1; + local tmp1:2 = (Rd0811[16,16] ^ (Rd0811[16,16]<<1))|0x1; + local tmp0:2 = (Rd0811[0,16] ^ (Rd0811[0,16]<<1))|0x1; + Rd2831[16,16] = lzcount(tmp1); + Rd2831[0,16] = lzcount(tmp0); } # CLZ D[c], D[a] (RR)